Début du projet, création du comportement de base + structure du site / du projet

This commit is contained in:
Sonny
2022-01-07 01:58:57 +01:00
parent 716f9758bb
commit 41f7eaa553
19 changed files with 11739 additions and 73 deletions

7
.env Normal file
View File

@@ -0,0 +1,7 @@
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server and MongoDB (Preview).
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"

3
.eslintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

100
.gitignore vendored
View File

@@ -1,76 +1,34 @@
# Logs
logs
*.log
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# FuseBox cache
.fusebox/
# vercel
.vercel

View File

@@ -1,2 +1,34 @@
# superpipo-v2
V2 de Superpipo sous Next et Prisma
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View File

@@ -0,0 +1,31 @@
import styles from '../../styles/categories.module.scss';
export default function Categories({ categories, favorites, handleSelectCategory, categoryActive }) {
return (<div className={styles['categories-wrapper']}>
<div className={styles['block-wrapper']}>
<h4>Favoris</h4>
<ul className={styles['favorites']}>
{favorites.map(({ name, category }, key) => {
const catName = categories.find(c => c.id === category).name;
return <li key={key} className={styles['item']}>
{name} <span className={styles['category']}>- {catName}</span>
</li>;
})}
</ul>
</div>
<div className={styles['block-wrapper']}>
<h4>Catégories</h4>
<ul className={styles['categories']}>
{categories.map(({ id, name }, key) => (
<li
key={key}
className={id === categoryActive ? styles['active'] : null}
onClick={() => handleSelectCategory(id)}
>
{name} {id === categoryActive ? '(active)' : ''}
</li>
))}
</ul>
</div>
</div>);
}

28
components/Links/Link.js Normal file
View File

@@ -0,0 +1,28 @@
import { useEffect, useCallback } from 'react';
import { useInView } from 'react-intersection-observer';
import styles from '../../styles/links.module.scss';
export default function Link({ category, setCategoryActive, refCategoryActive }) {
const { ref, inView } = useInView({ threshold: .5 });
const { id, name, links, ref: refCategory } = category;
useEffect(() => inView ? setCategoryActive(id) : null, [id, inView, setCategoryActive]);
const setRefs = useCallback((node) => {
refCategory.current = node;
refCategoryActive.current = node;
ref(node);
}, [ref, refCategoryActive, refCategory]);
return (
<div className={styles['link-block']} ref={setRefs}>
<h2>{name}</h2>
<ul className={styles['links']}>
{links.map(({ name }, key2) => (
<li key={key2} className={styles['item']}>{name}</li>
))}
</ul>
</div>
);
}

16
components/Links/Links.js Normal file
View File

@@ -0,0 +1,16 @@
import Link from './Link';
import styles from '../../styles/links.module.scss';
export default function Links({ categories, setCategoryActive, refCategoryActive }) {
return (<div className={styles['links-wrapper']}>
{categories.map((category, key) => (
<Link
key={key}
category={category}
setCategoryActive={setCategoryActive}
refCategoryActive={refCategoryActive}
/>
))}
</div>);
}

3
next.config.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
reactStrictMode: true,
}

8412
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "superpipo-v2",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "12.0.7",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-intersection-observer": "^8.33.1",
"sass": "^1.46.0"
},
"devDependencies": {
"eslint": "7",
"eslint-config-next": "12.0.7"
}
}

7
pages/_app.js Normal file
View File

@@ -0,0 +1,7 @@
import '../styles/globals.scss';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;

76
pages/index.js Normal file
View File

@@ -0,0 +1,76 @@
import styles from '../styles/Home.module.scss';
import Categories from '../components/Categories/Categories';
import Links from '../components/Links/Links';
import { createRef, useRef, useState } from 'react';
export default function Home({ categories, favorites }) {
const [categoryActive, setCategoryActive] = useState(categories?.[0]?.id);
const refCategoryActive = useRef();
const handleSelectCategory = (id) => {
if (!refCategoryActive?.current) return;
const { ref } = categories.find(c => c.id === id);
ref?.current?.scrollIntoView({
block: 'end',
behavior: 'smooth'
});
}
return (
<div className={styles.App}>
<Categories
categories={categories}
favorites={favorites}
handleSelectCategory={handleSelectCategory}
categoryActive={categoryActive}
/>
<Links
categories={categories}
setCategoryActive={setCategoryActive}
refCategoryActive={refCategoryActive}
/>
</div>
)
}
export async function getStaticProps(context) {
const categories = [];
for (let i = 0; i < 20; i++) {
const links = [];
for (let y = 0; y < randomIntFromInterval(5, 25); y++) {
links.push({
id: y,
name: 'Lien #' + (y + 1),
category: i
});
}
categories.push({
id: i,
name: 'Catégorie #' + (i + 1),
links,
ref: createRef()
});
}
const favorites = [];
for (let i = 0; i < 5; i++) {
const category = categories[Math.floor(Math.random() * categories.length)];
const link = category.links[Math.floor(Math.random() * category.links.length)]
favorites.push(link);
}
console.log(favorites);
return {
props: {
categories,
favorites
}
}
}
function randomIntFromInterval(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}

17
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,17 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model user {
id Int @id @default(autoincrement())
email String @unique
password String
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

7
styles/Home.module.scss Normal file
View File

@@ -0,0 +1,7 @@
.App {
height: 100%;
width: 1280px;
padding: 10px;
display: flex;
justify-content: center;
}

View File

@@ -0,0 +1,32 @@
.categories-wrapper {
border: 1px solid red;
height: 100%;
width: 300px;
padding: 10px;
margin-right: 15px;
display: flex;
align-items: center;
flex-direction: column;
overflow-x: auto;
& .block-wrapper {
height: auto;
width: 100%;
margin-bottom: 15px;
& h4 {
text-transform: uppercase;
font-size: .85em;
color: #dadce0;
}
& .favorites .item .category {
color: #dadce0;
}
& .categories .active {
color: red;
}
}
}

31
styles/globals.scss Normal file
View File

@@ -0,0 +1,31 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,600;1,300;1,600&display=swap');
* {
box-sizing: border-box;
outline: 0;
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
width: 100%;
font-family: Poppins, sans-serif;
padding: 0;
margin: 0;
overflow: hidden;
}
#__next {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
ul, li {
list-style: none;
}

25
styles/links.module.scss Normal file
View File

@@ -0,0 +1,25 @@
.links-wrapper {
border: 1px solid red;
height: 100%;
padding: 10px;
flex: 1;
overflow-x: auto;
scroll-snap-type: y mandatory;
& .link-block {
min-height: 100%;
width: 100%;
margin-bottom: 10px;
flex: 1;
display: flex;
flex-direction: column;
scroll-snap-align: center;
& .links {
width: 100%;
display: flex;
flex-direction: column;
}
}
}

2960
yarn.lock Normal file

File diff suppressed because it is too large Load Diff