├── TP1 ├── correction │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── next.config.mjs │ ├── package-lock.json │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ │ ├── next.svg │ │ └── vercel.svg │ ├── src │ │ └── app │ │ │ ├── blog │ │ │ ├── [id] │ │ │ │ └── page.tsx │ │ │ └── page.tsx │ │ │ ├── datas.ts │ │ │ ├── favicon.ico │ │ │ ├── globals.css │ │ │ ├── layout.tsx │ │ │ ├── page.tsx │ │ │ └── types.ts │ ├── tailwind.config.ts │ └── tsconfig.json └── enonce │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── next.config.mjs │ ├── package-lock.json │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ ├── next.svg │ └── vercel.svg │ ├── src │ └── app │ │ ├── data.ts │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── types.ts │ ├── tailwind.config.ts │ └── tsconfig.json └── tp2 ├── .eslintrc.json ├── .gitignore ├── README.md ├── components.json ├── next.config.mjs ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── public ├── minerals.png └── vitamins.png ├── src ├── app │ ├── api │ │ └── foods │ │ │ ├── [name] │ │ │ └── route.ts │ │ │ └── all │ │ │ └── route.ts │ ├── favicon.ico │ ├── food │ │ └── [name] │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── components │ └── ui │ │ ├── button.tsx │ │ ├── command.tsx │ │ ├── dialog.tsx │ │ └── popover.tsx ├── data.ts ├── lib │ └── utils.ts └── types │ └── index.ts ├── tailwind.config.ts └── tsconfig.json /TP1/correction/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /TP1/correction/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /TP1/correction/README.md: -------------------------------------------------------------------------------- 1 | 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). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | 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. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /TP1/correction/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /TP1/correction/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "next": "14.2.3", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^20", 18 | "@types/react": "^18", 19 | "@types/react-dom": "^18", 20 | "eslint": "^8", 21 | "eslint-config-next": "14.2.3", 22 | "postcss": "^8", 23 | "tailwindcss": "^3.4.1", 24 | "typescript": "^5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TP1/correction/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /TP1/correction/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TP1/correction/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TP1/correction/src/app/blog/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { articles } from "@/app/datas"; 2 | import { Metadata } from "next"; 3 | 4 | export function generateMetadata({ params }: { params: { id: string }}): Metadata { 5 | const article = articles.find((element) => element.id === parseInt(params.id)); 6 | return { 7 | title: article?.title, 8 | description: article?.description 9 | } 10 | } 11 | 12 | export default function ArticlePage({ params }: { params: { id: string }}) { 13 | const article = articles.find((element) => element.id === parseInt(params.id)); 14 | return ( 15 | <> 16 | {article && 17 |
20 |

{article.title} le {article.date} par {article.author}

21 |
{article.description}
22 |
23 | } 24 | 25 | ) 26 | } -------------------------------------------------------------------------------- /TP1/correction/src/app/blog/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link" 2 | import { articles } from "../datas" 3 | import { Article } from "../types" 4 | import type { Metadata } from "next"; 5 | 6 | export const metadata: Metadata = { 7 | title: "Ben BK - Le Blog", 8 | description: "Randonneur à ses heures perdues.", 9 | }; 10 | 11 | export default function BlogPage() { 12 | return ( 13 | <> 14 | {articles.map((article: Article) => { 15 | const link = `blog/${article.id}` 16 | return ( 17 |
20 |

{article.title} le {article.date} par {article.author}

21 | Voir l'article 22 |
23 | ) 24 | })} 25 | 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /TP1/correction/src/app/datas.ts: -------------------------------------------------------------------------------- 1 | export const articles = [ 2 | { 3 | "id": 1, 4 | "title": "Les merveilles de la randonnée en montagne", 5 | "description": "Découvrez les paysages époustouflants des montagnes et les bienfaits de la randonnée en altitude.", 6 | "date": "2024-05-01", 7 | "author": "Jean Dupont" 8 | }, 9 | { 10 | "id": 2, 11 | "title": "Randonnée en forêt : conseils et astuces", 12 | "description": "Tout ce qu'il faut savoir pour une randonnée réussie en forêt, des équipements aux itinéraires.", 13 | "date": "2024-05-03", 14 | "author": "Marie Martin" 15 | }, 16 | { 17 | "id": 3, 18 | "title": "Les plus belles randonnées côtières", 19 | "description": "Partez à la découverte des sentiers côtiers et admirez les vues imprenables sur l'océan.", 20 | "date": "2024-05-05", 21 | "author": "Luc Leroy" 22 | }, 23 | { 24 | "id": 4, 25 | "title": "Randonnée et bien-être : les bénéfices pour la santé", 26 | "description": "Explorons les nombreux bienfaits de la randonnée sur la santé physique et mentale.", 27 | "date": "2024-05-07", 28 | "author": "Sophie Petit" 29 | }, 30 | { 31 | "id": 5, 32 | "title": "Les randonnées en famille : des moments inoubliables", 33 | "description": "Des idées de randonnées adaptées pour toute la famille, des plus petits aux plus grands.", 34 | "date": "2024-05-09", 35 | "author": "Pierre Blanc" 36 | }, 37 | { 38 | "id": 6, 39 | "title": "Préparer sa randonnée : les indispensables à emporter", 40 | "description": "Liste des équipements et provisions à ne pas oublier pour partir en randonnée en toute sérénité.", 41 | "date": "2024-05-11", 42 | "author": "Elise Dupuis" 43 | }, 44 | { 45 | "id": 7, 46 | "title": "Randonnées insolites : explorez des lieux méconnus", 47 | "description": "Partez à l'aventure et découvrez des sentiers de randonnée hors des sentiers battus.", 48 | "date": "2024-05-13", 49 | "author": "Nicolas Moreau" 50 | }, 51 | { 52 | "id": 8, 53 | "title": "Randonnée en hiver : les précautions à prendre", 54 | "description": "Conseils pour randonner en toute sécurité pendant la saison hivernale.", 55 | "date": "2024-05-15", 56 | "author": "Claire Richard" 57 | }, 58 | { 59 | "id": 9, 60 | "title": "Les applications utiles pour les randonneurs", 61 | "description": "Découvrez les meilleures applications pour planifier vos randonnées et vous orienter en chemin.", 62 | "date": "2024-05-17", 63 | "author": "Julien Fabre" 64 | }, 65 | { 66 | "id": 10, 67 | "title": "Randonnée et photographie : capturer la beauté de la nature", 68 | "description": "Astuces pour réussir vos photos de randonnée et immortaliser des paysages spectaculaires.", 69 | "date": "2024-05-19", 70 | "author": "Laura Moulin" 71 | } 72 | ] -------------------------------------------------------------------------------- /TP1/correction/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenBktech/Formation-NextJS/89897f3e60e9c6303da0c38184790324d37dc506/TP1/correction/src/app/favicon.ico -------------------------------------------------------------------------------- /TP1/correction/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | @layer utilities { 20 | .text-balance { 21 | text-wrap: balance; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TP1/correction/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Ben BK", 9 | description: "Randonneur à ses heures perdues.", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | 20 |
Ben BK Blog
24 |
27 | {children} 28 |
29 | 35 | 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /TP1/correction/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function Home() { 4 | return ( 5 | <> 6 |

Bienvenue sur mon site !

7 | Accéder au blog 8 | 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /TP1/correction/src/app/types.ts: -------------------------------------------------------------------------------- 1 | export interface Article { 2 | id: number; 3 | title: string; 4 | description: string; 5 | date: string; 6 | author: string; 7 | } -------------------------------------------------------------------------------- /TP1/correction/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /TP1/correction/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /TP1/enonce/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /TP1/enonce/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /TP1/enonce/README.md: -------------------------------------------------------------------------------- 1 | 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). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | 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. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /TP1/enonce/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /TP1/enonce/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "enonce", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "next": "14.2.3", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^20", 18 | "@types/react": "^18", 19 | "@types/react-dom": "^18", 20 | "eslint": "^8", 21 | "eslint-config-next": "14.2.3", 22 | "postcss": "^8", 23 | "tailwindcss": "^3.4.1", 24 | "typescript": "^5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TP1/enonce/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /TP1/enonce/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TP1/enonce/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TP1/enonce/src/app/data.ts: -------------------------------------------------------------------------------- 1 | export const articles = [ 2 | { 3 | "id": 1, 4 | "title": "Les merveilles de la randonnée en montagne", 5 | "description": "Découvrez les paysages époustouflants des montagnes et les bienfaits de la randonnée en altitude.", 6 | "date": "2024-05-01", 7 | "author": "Jean Dupont" 8 | }, 9 | { 10 | "id": 2, 11 | "title": "Randonnée en forêt : conseils et astuces", 12 | "description": "Tout ce qu'il faut savoir pour une randonnée réussie en forêt, des équipements aux itinéraires.", 13 | "date": "2024-05-03", 14 | "author": "Marie Martin" 15 | }, 16 | { 17 | "id": 3, 18 | "title": "Les plus belles randonnées côtières", 19 | "description": "Partez à la découverte des sentiers côtiers et admirez les vues imprenables sur l'océan.", 20 | "date": "2024-05-05", 21 | "author": "Luc Leroy" 22 | }, 23 | { 24 | "id": 4, 25 | "title": "Randonnée et bien-être : les bénéfices pour la santé", 26 | "description": "Explorons les nombreux bienfaits de la randonnée sur la santé physique et mentale.", 27 | "date": "2024-05-07", 28 | "author": "Sophie Petit" 29 | }, 30 | { 31 | "id": 5, 32 | "title": "Les randonnées en famille : des moments inoubliables", 33 | "description": "Des idées de randonnées adaptées pour toute la famille, des plus petits aux plus grands.", 34 | "date": "2024-05-09", 35 | "author": "Pierre Blanc" 36 | }, 37 | { 38 | "id": 6, 39 | "title": "Préparer sa randonnée : les indispensables à emporter", 40 | "description": "Liste des équipements et provisions à ne pas oublier pour partir en randonnée en toute sérénité.", 41 | "date": "2024-05-11", 42 | "author": "Elise Dupuis" 43 | }, 44 | { 45 | "id": 7, 46 | "title": "Randonnées insolites : explorez des lieux méconnus", 47 | "description": "Partez à l'aventure et découvrez des sentiers de randonnée hors des sentiers battus.", 48 | "date": "2024-05-13", 49 | "author": "Nicolas Moreau" 50 | }, 51 | { 52 | "id": 8, 53 | "title": "Randonnée en hiver : les précautions à prendre", 54 | "description": "Conseils pour randonner en toute sécurité pendant la saison hivernale.", 55 | "date": "2024-05-15", 56 | "author": "Claire Richard" 57 | }, 58 | { 59 | "id": 9, 60 | "title": "Les applications utiles pour les randonneurs", 61 | "description": "Découvrez les meilleures applications pour planifier vos randonnées et vous orienter en chemin.", 62 | "date": "2024-05-17", 63 | "author": "Julien Fabre" 64 | }, 65 | { 66 | "id": 10, 67 | "title": "Randonnée et photographie : capturer la beauté de la nature", 68 | "description": "Astuces pour réussir vos photos de randonnée et immortaliser des paysages spectaculaires.", 69 | "date": "2024-05-19", 70 | "author": "Laura Moulin" 71 | } 72 | ] -------------------------------------------------------------------------------- /TP1/enonce/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenBktech/Formation-NextJS/89897f3e60e9c6303da0c38184790324d37dc506/TP1/enonce/src/app/favicon.ico -------------------------------------------------------------------------------- /TP1/enonce/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TP1/enonce/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /TP1/enonce/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 |
7 |

8 | Get started by editing  9 | src/app/page.tsx 10 |

11 |
12 | 18 | By{" "} 19 | Vercel Logo 27 | 28 |
29 |
30 | 31 |
32 | Next.js Logo 40 |
41 | 42 |
43 | 49 |

50 | Docs{" "} 51 | 52 | -> 53 | 54 |

55 |

56 | Find in-depth information about Next.js features and API. 57 |

58 |
59 | 60 | 66 |

67 | Learn{" "} 68 | 69 | -> 70 | 71 |

72 |

73 | Learn about Next.js in an interactive course with quizzes! 74 |

75 |
76 | 77 | 83 |

84 | Templates{" "} 85 | 86 | -> 87 | 88 |

89 |

90 | Explore starter templates for Next.js. 91 |

92 |
93 | 94 | 100 |

101 | Deploy{" "} 102 | 103 | -> 104 | 105 |

106 |

107 | Instantly deploy your Next.js site to a shareable URL with Vercel. 108 |

109 |
110 |
111 |
112 | ); 113 | } 114 | -------------------------------------------------------------------------------- /TP1/enonce/src/app/types.ts: -------------------------------------------------------------------------------- 1 | export interface Article { 2 | id: number; 3 | title: string; 4 | description: string; 5 | date: string; 6 | author: string; 7 | } -------------------------------------------------------------------------------- /TP1/enonce/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /TP1/enonce/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /tp2/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /tp2/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /tp2/README.md: -------------------------------------------------------------------------------- 1 | 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). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | 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. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /tp2/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /tp2/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /tp2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tp2", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@radix-ui/react-dialog": "^1.0.5", 13 | "@radix-ui/react-popover": "^1.0.7", 14 | "@radix-ui/react-slot": "^1.0.2", 15 | "class-variance-authority": "^0.7.0", 16 | "clsx": "^2.1.1", 17 | "cmdk": "^1.0.0", 18 | "lucide-react": "^0.395.0", 19 | "next": "14.2.4", 20 | "react": "^18", 21 | "react-dom": "^18", 22 | "recharts": "^2.12.7", 23 | "tailwind-merge": "^2.3.0", 24 | "tailwindcss-animate": "^1.0.7" 25 | }, 26 | "devDependencies": { 27 | "@types/node": "^20", 28 | "@types/react": "^18", 29 | "@types/react-dom": "^18", 30 | "eslint": "^8", 31 | "eslint-config-next": "14.2.4", 32 | "postcss": "^8", 33 | "tailwindcss": "^3.4.1", 34 | "typescript": "^5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tp2/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /tp2/public/minerals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenBktech/Formation-NextJS/89897f3e60e9c6303da0c38184790324d37dc506/tp2/public/minerals.png -------------------------------------------------------------------------------- /tp2/public/vitamins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenBktech/Formation-NextJS/89897f3e60e9c6303da0c38184790324d37dc506/tp2/public/vitamins.png -------------------------------------------------------------------------------- /tp2/src/app/api/foods/[name]/route.ts: -------------------------------------------------------------------------------- 1 | import { foods } from "@/data"; 2 | 3 | export async function GET( 4 | request: Request, 5 | { params }: { params: { name: string }} 6 | ) { 7 | console.log('ok'); 8 | console.log(params.name); 9 | const index = foods.findIndex( 10 | (food) => food.name.toLowerCase().replace(/ /g, '-') === params.name 11 | ) 12 | console.log(foods[index]); 13 | if(index !== -1) { 14 | return new Response(JSON.stringify(foods[index]), { 15 | headers: { 16 | "Content-Type": "application/json" 17 | }, 18 | status: 200 19 | }) 20 | } 21 | else { 22 | return new Response("Food not found.", { 23 | headers: { 24 | "Content-Type": "application/json" 25 | }, 26 | status: 404 27 | }); 28 | } 29 | } -------------------------------------------------------------------------------- /tp2/src/app/api/foods/all/route.ts: -------------------------------------------------------------------------------- 1 | import { foods } from "@/data"; 2 | 3 | export async function GET() { 4 | return Response.json(foods); 5 | } -------------------------------------------------------------------------------- /tp2/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenBktech/Formation-NextJS/89897f3e60e9c6303da0c38184790324d37dc506/tp2/src/app/favicon.ico -------------------------------------------------------------------------------- /tp2/src/app/food/[name]/layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; // Ajoutez cet import 2 | import type { Metadata } from "next"; 3 | 4 | export function generateMetadata({ params }: { params: { name: string }}): Metadata { 5 | const title = `Discover ${params.name} - NutriSpark`; 6 | const description = `Learn all about the nutritional values of ${params.name} on NutriTech. Explore now!`; 7 | return { 8 | title, 9 | description, 10 | }; 11 | } 12 | 13 | export default function FoodLayout({ 14 | children, 15 | }: Readonly<{ 16 | children: React.ReactNode; 17 | }>) { 18 | return ( 19 |
20 | {children} 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /tp2/src/app/food/[name]/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import Image from "next/image"; 3 | import { useState, useEffect } from "react"; 4 | import { IFood, IMacronutrientData } from "@/types"; 5 | import { PieChart, Pie, Cell, ResponsiveContainer } from 'recharts'; 6 | import { useRouter } from "next/navigation"; 7 | import { Undo2 } from 'lucide-react'; 8 | 9 | const FoodPage = ({ params }: { params: { name: string }}) => { 10 | 11 | const router = useRouter(); 12 | 13 | const [food, setFood] = useState(null); 14 | const [isLoading, setIsLoading] = useState(true); 15 | const [macronutriments, setMacronutriments] = useState([]); 16 | 17 | const COLORS = ['#F28907', '#5079F2', '#F2220F']; 18 | 19 | const fetchFood = async() => { 20 | try { 21 | const APIQueryURL = `/api/foods/${params.name}`; 22 | const response = await fetch(APIQueryURL); 23 | const data = await response.json(); 24 | 25 | // Macronutriments 26 | const macronutrimentsDatas: IMacronutrientData[] = [ 27 | { name: 'carbohydrates', value: data.carbohydrates }, 28 | { name: 'protein', value: data.protein }, 29 | { name: 'fat', value: data.fat }, 30 | ]; 31 | 32 | setMacronutriments(macronutrimentsDatas); 33 | 34 | // Food General Informations 35 | setFood(data); 36 | console.log(data); 37 | } 38 | catch(error) { 39 | console.log("Error fetching Food:", error); 40 | } 41 | finally { 42 | setIsLoading(false); 43 | } 44 | } 45 | 46 | useEffect(() => { 47 | const initialize = async() => { 48 | await fetchFood(); 49 | } 50 | initialize(); 51 | }, [params.name]); 52 | 53 | return ( 54 | <> 55 | {(!isLoading && food && macronutriments) ? ( 56 |
57 | router.back()} /> 58 |

59 | {food.name} 60 |

61 |
62 |
63 | 64 | 65 | 75 | {macronutriments.map((entry, index) => ( 76 | 77 | ))} 78 | 79 | 80 | 81 |
82 | Carbohydrates 83 | Protein 84 | Fat 85 |
86 |
87 |
88 |
Nutritional Information per 100 grams:
89 |
90 |
91 |
92 |
Carbohydrates: {food.carbohydrates}g
93 |
94 |
95 |
96 |
Protein: {food.protein}g
97 |
98 |
99 |
100 |
Fat: {food.fat}g
101 |
102 |
103 |
104 |
105 | Vitamins 106 |
107 | Vitamins: {food.vitamins?.join(', ')} 108 |
109 |
110 |
111 | Minerals 112 |
113 | Minerals: {food.minerals?.join(', ')} 114 |
115 |
116 |
117 |
118 |
119 |
120 | ) : ( 121 |
122 |

Loading...

123 |
124 | )} 125 | 126 | ); 127 | } 128 | 129 | export default FoodPage; 130 | -------------------------------------------------------------------------------- /tp2/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .colorInfo { 6 | @apply w-5 h-5 border mr-2; 7 | } 8 | 9 | .colorInfo.carbohydrates { 10 | @apply bg-[#F28907]; 11 | } 12 | 13 | .colorInfo.protein { 14 | @apply bg-[#5079F2]; 15 | } 16 | 17 | .colorInfo.fat { 18 | @apply bg-[#F2220F]; 19 | } 20 | 21 | .title_colored { 22 | @apply bg-gradient-to-r from-[#75fd38] to-[#e1f3ab] bg-clip-text text-transparent; 23 | } 24 | 25 | @layer base { 26 | :root { 27 | --background: 0 0% 100%; 28 | --foreground: 222.2 84% 4.9%; 29 | 30 | --card: 0 0% 100%; 31 | --card-foreground: 222.2 84% 4.9%; 32 | 33 | --popover: 0 0% 100%; 34 | --popover-foreground: 222.2 84% 4.9%; 35 | 36 | --primary: 222.2 47.4% 11.2%; 37 | --primary-foreground: 210 40% 98%; 38 | 39 | --secondary: 210 40% 96.1%; 40 | --secondary-foreground: 222.2 47.4% 11.2%; 41 | 42 | --muted: 210 40% 96.1%; 43 | --muted-foreground: 215.4 16.3% 46.9%; 44 | 45 | --accent: 210 40% 96.1%; 46 | --accent-foreground: 222.2 47.4% 11.2%; 47 | 48 | --destructive: 0 84.2% 60.2%; 49 | --destructive-foreground: 210 40% 98%; 50 | 51 | --border: 214.3 31.8% 91.4%; 52 | --input: 214.3 31.8% 91.4%; 53 | --ring: 222.2 84% 4.9%; 54 | 55 | --radius: 0.5rem; 56 | } 57 | 58 | .dark { 59 | --background: 222.2 84% 4.9%; 60 | --foreground: 210 40% 98%; 61 | 62 | --card: 222.2 84% 4.9%; 63 | --card-foreground: 210 40% 98%; 64 | 65 | --popover: 222.2 84% 4.9%; 66 | --popover-foreground: 210 40% 98%; 67 | 68 | --primary: 210 40% 98%; 69 | --primary-foreground: 222.2 47.4% 11.2%; 70 | 71 | --secondary: 217.2 32.6% 17.5%; 72 | --secondary-foreground: 210 40% 98%; 73 | 74 | --muted: 217.2 32.6% 17.5%; 75 | --muted-foreground: 215 20.2% 65.1%; 76 | 77 | --accent: 217.2 32.6% 17.5%; 78 | --accent-foreground: 210 40% 98%; 79 | 80 | --destructive: 0 62.8% 30.6%; 81 | --destructive-foreground: 210 40% 98%; 82 | 83 | --border: 217.2 32.6% 17.5%; 84 | --input: 217.2 32.6% 17.5%; 85 | --ring: 212.7 26.8% 83.9%; 86 | } 87 | } 88 | 89 | @layer base { 90 | * { 91 | @apply border-border; 92 | } 93 | body { 94 | @apply bg-background text-foreground; 95 | } 96 | } -------------------------------------------------------------------------------- /tp2/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import "./globals.css"; 3 | 4 | import { Inter as FontSans } from "next/font/google" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const fontSans = FontSans({ 9 | subsets: ["latin"], 10 | variable: "--font-sans", 11 | }) 12 | 13 | export const metadata: Metadata = { 14 | title: "Welcome to NutriSpark", 15 | description: "Discover the nutritional values of your favorite foods. Use the search below to get started.", 16 | }; 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: Readonly<{ 21 | children: React.ReactNode; 22 | }>) { 23 | return ( 24 | 25 | 26 | 32 | {children} 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /tp2/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { useState, useEffect } from "react"; 3 | import { IFood, IFoodReduced } from "@/types"; 4 | import { Check, ChevronsUpDown } from "lucide-react"; 5 | import { cn } from "@/lib/utils"; 6 | import { Button } from "@/components/ui/button"; 7 | import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; 8 | import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; 9 | import { useRouter } from "next/navigation"; 10 | 11 | export default function Home() { 12 | 13 | const router = useRouter(); 14 | const [foods, setFoods] = useState([]); 15 | const [open, setOpen] = useState(false); 16 | const [value, setValue] = useState(""); 17 | const [isLoading, setIsLoading] = useState(true); 18 | 19 | const fetchFoods = async() => { 20 | try { 21 | const response = await fetch('/api/foods/all'); 22 | const data = await response.json(); 23 | const foodsReduced: IFoodReduced[] = data.map((food: IFood) => ({ 24 | value: food.name.toLowerCase().replace(/ /g, '-'), 25 | label: food.name 26 | })); 27 | setFoods(foodsReduced); 28 | } 29 | catch(error) { 30 | console.log(error); 31 | } 32 | } 33 | 34 | useEffect(() => { 35 | const initialize = async() => { 36 | await fetchFoods(); 37 | setIsLoading(false); 38 | } 39 | initialize(); 40 | }, []) 41 | 42 | useEffect(() => { 43 | if(value.length > 0) { 44 | router.push(`/food/${value}`); 45 | } 46 | }, [value]); 47 | 48 | return ( 49 | <> 50 | {!isLoading ? ( 51 |
52 |

Welcome to NutriSpark

53 |

54 | Discover the nutritional values of your favorite foods. Use the search below to get started. 55 |

56 | 57 | 58 | 69 | 70 | 71 | 72 | 73 | No food found. 74 | 75 | {foods.map((food) => ( 76 | { 80 | setValue(currentValue === value ? "" : currentValue); 81 | setOpen(false); 82 | }} 83 | className="hover:bg-gray-700" 84 | > 85 | 91 | {food.label} 92 | 93 | ))} 94 | 95 | 96 | 97 | 98 |
99 | ) : ( 100 |
101 |

Loading...

102 |
103 | )} 104 | 105 | ); 106 | } 107 | -------------------------------------------------------------------------------- /tp2/src/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | } 34 | ) 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button" 45 | return ( 46 | 51 | ) 52 | } 53 | ) 54 | Button.displayName = "Button" 55 | 56 | export { Button, buttonVariants } 57 | -------------------------------------------------------------------------------- /tp2/src/components/ui/command.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { type DialogProps } from "@radix-ui/react-dialog" 5 | import { Command as CommandPrimitive } from "cmdk" 6 | import { Search } from "lucide-react" 7 | 8 | import { cn } from "@/lib/utils" 9 | import { Dialog, DialogContent } from "@/components/ui/dialog" 10 | 11 | const Command = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef 14 | >(({ className, ...props }, ref) => ( 15 | 23 | )) 24 | Command.displayName = CommandPrimitive.displayName 25 | 26 | interface CommandDialogProps extends DialogProps {} 27 | 28 | const CommandDialog = ({ children, ...props }: CommandDialogProps) => { 29 | return ( 30 | 31 | 32 | 33 | {children} 34 | 35 | 36 | 37 | ) 38 | } 39 | 40 | const CommandInput = React.forwardRef< 41 | React.ElementRef, 42 | React.ComponentPropsWithoutRef 43 | >(({ className, ...props }, ref) => ( 44 |
45 | 46 | 54 |
55 | )) 56 | 57 | CommandInput.displayName = CommandPrimitive.Input.displayName 58 | 59 | const CommandList = React.forwardRef< 60 | React.ElementRef, 61 | React.ComponentPropsWithoutRef 62 | >(({ className, ...props }, ref) => ( 63 | 68 | )) 69 | 70 | CommandList.displayName = CommandPrimitive.List.displayName 71 | 72 | const CommandEmpty = React.forwardRef< 73 | React.ElementRef, 74 | React.ComponentPropsWithoutRef 75 | >((props, ref) => ( 76 | 81 | )) 82 | 83 | CommandEmpty.displayName = CommandPrimitive.Empty.displayName 84 | 85 | const CommandGroup = React.forwardRef< 86 | React.ElementRef, 87 | React.ComponentPropsWithoutRef 88 | >(({ className, ...props }, ref) => ( 89 | 97 | )) 98 | 99 | CommandGroup.displayName = CommandPrimitive.Group.displayName 100 | 101 | const CommandSeparator = React.forwardRef< 102 | React.ElementRef, 103 | React.ComponentPropsWithoutRef 104 | >(({ className, ...props }, ref) => ( 105 | 110 | )) 111 | CommandSeparator.displayName = CommandPrimitive.Separator.displayName 112 | 113 | const CommandItem = React.forwardRef< 114 | React.ElementRef, 115 | React.ComponentPropsWithoutRef 116 | >(({ className, ...props }, ref) => ( 117 | 125 | )) 126 | 127 | CommandItem.displayName = CommandPrimitive.Item.displayName 128 | 129 | const CommandShortcut = ({ 130 | className, 131 | ...props 132 | }: React.HTMLAttributes) => { 133 | return ( 134 | 141 | ) 142 | } 143 | CommandShortcut.displayName = "CommandShortcut" 144 | 145 | export { 146 | Command, 147 | CommandDialog, 148 | CommandInput, 149 | CommandList, 150 | CommandEmpty, 151 | CommandGroup, 152 | CommandItem, 153 | CommandShortcut, 154 | CommandSeparator, 155 | } 156 | -------------------------------------------------------------------------------- /tp2/src/components/ui/dialog.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as DialogPrimitive from "@radix-ui/react-dialog" 5 | import { X } from "lucide-react" 6 | 7 | import { cn } from "@/lib/utils" 8 | 9 | const Dialog = DialogPrimitive.Root 10 | 11 | const DialogTrigger = DialogPrimitive.Trigger 12 | 13 | const DialogPortal = DialogPrimitive.Portal 14 | 15 | const DialogClose = DialogPrimitive.Close 16 | 17 | const DialogOverlay = React.forwardRef< 18 | React.ElementRef, 19 | React.ComponentPropsWithoutRef 20 | >(({ className, ...props }, ref) => ( 21 | 29 | )) 30 | DialogOverlay.displayName = DialogPrimitive.Overlay.displayName 31 | 32 | const DialogContent = React.forwardRef< 33 | React.ElementRef, 34 | React.ComponentPropsWithoutRef 35 | >(({ className, children, ...props }, ref) => ( 36 | 37 | 38 | 46 | {children} 47 | 48 | 49 | Close 50 | 51 | 52 | 53 | )) 54 | DialogContent.displayName = DialogPrimitive.Content.displayName 55 | 56 | const DialogHeader = ({ 57 | className, 58 | ...props 59 | }: React.HTMLAttributes) => ( 60 |
67 | ) 68 | DialogHeader.displayName = "DialogHeader" 69 | 70 | const DialogFooter = ({ 71 | className, 72 | ...props 73 | }: React.HTMLAttributes) => ( 74 |
81 | ) 82 | DialogFooter.displayName = "DialogFooter" 83 | 84 | const DialogTitle = React.forwardRef< 85 | React.ElementRef, 86 | React.ComponentPropsWithoutRef 87 | >(({ className, ...props }, ref) => ( 88 | 96 | )) 97 | DialogTitle.displayName = DialogPrimitive.Title.displayName 98 | 99 | const DialogDescription = React.forwardRef< 100 | React.ElementRef, 101 | React.ComponentPropsWithoutRef 102 | >(({ className, ...props }, ref) => ( 103 | 108 | )) 109 | DialogDescription.displayName = DialogPrimitive.Description.displayName 110 | 111 | export { 112 | Dialog, 113 | DialogPortal, 114 | DialogOverlay, 115 | DialogClose, 116 | DialogTrigger, 117 | DialogContent, 118 | DialogHeader, 119 | DialogFooter, 120 | DialogTitle, 121 | DialogDescription, 122 | } 123 | -------------------------------------------------------------------------------- /tp2/src/components/ui/popover.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as PopoverPrimitive from "@radix-ui/react-popover" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Popover = PopoverPrimitive.Root 9 | 10 | const PopoverTrigger = PopoverPrimitive.Trigger 11 | 12 | const PopoverContent = React.forwardRef< 13 | React.ElementRef, 14 | React.ComponentPropsWithoutRef 15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( 16 | 17 | 27 | 28 | )) 29 | PopoverContent.displayName = PopoverPrimitive.Content.displayName 30 | 31 | export { Popover, PopoverTrigger, PopoverContent } 32 | -------------------------------------------------------------------------------- /tp2/src/data.ts: -------------------------------------------------------------------------------- 1 | import { IFood } from "./types"; 2 | 3 | export const foods: IFood[] = [ 4 | { name: "Apple", calories: 52, carbohydrates: 14, protein: 0.3, fat: 0.2, fiber: 2.4, sugar: 10.4, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium"] }, 5 | { name: "Banana", calories: 96, carbohydrates: 23, protein: 1.3, fat: 0.3, fiber: 2.6, sugar: 12.2, vitamins: ["Vitamin B6", "Vitamin C"], minerals: ["Potassium", "Magnesium"] }, 6 | { name: "Chicken", calories: 165, carbohydrates: 0, protein: 31, fat: 3.6, vitamins: ["Vitamin B6", "Vitamin B12"], minerals: ["Phosphorus", "Selenium"] }, 7 | { name: "Salmon", calories: 206, carbohydrates: 0, protein: 22, fat: 12, vitamins: ["Vitamin D", "Vitamin B12"], minerals: ["Selenium", "Phosphorus"] }, 8 | { name: "White Rice", calories: 130, carbohydrates: 28, protein: 2.4, fat: 0.3, fiber: 0.4, vitamins: ["Thiamine", "Niacin"], minerals: ["Magnesium", "Phosphorus"] }, 9 | { name: "Almonds", calories: 173, carbohydrates: 6.1, protein: 6, fat: 15, fiber: 3.5, sugar: 1.2, vitamins: ["Vitamin E", "Riboflavin"], minerals: ["Magnesium", "Calcium"] }, 10 | { name: "Whole Milk", calories: 149, carbohydrates: 11.7, protein: 7.7, fat: 8, vitamins: ["Vitamin D", "Vitamin B12"], minerals: ["Calcium", "Phosphorus"] }, 11 | { name: "Egg", calories: 72, carbohydrates: 0.4, protein: 6.3, fat: 4.8, vitamins: ["Vitamin A", "Vitamin D"], minerals: ["Iron", "Zinc"] }, 12 | { name: "Broccoli", calories: 34, carbohydrates: 6.6, protein: 2.8, fat: 0.4, fiber: 2.6, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Calcium", "Iron"] }, 13 | { name: "Carrot", calories: 41, carbohydrates: 9.6, protein: 0.9, fat: 0.2, fiber: 2.8, vitamins: ["Vitamin A", "Vitamin K"], minerals: ["Potassium", "Calcium"] }, 14 | { name: "Tomato", calories: 18, carbohydrates: 3.9, protein: 0.9, fat: 0.2, fiber: 1.2, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Iron"] }, 15 | { name: "Spinach", calories: 23, carbohydrates: 3.6, protein: 2.9, fat: 0.4, fiber: 2.2, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Iron", "Calcium"] }, 16 | { name: "Sweet Potato", calories: 86, carbohydrates: 20, protein: 1.6, fat: 0.1, fiber: 3, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Potassium", "Magnesium"] }, 17 | { name: "Plain Yogurt", calories: 59, carbohydrates: 3.6, protein: 10, fat: 0.4, vitamins: ["Vitamin B12", "Vitamin B2"], minerals: ["Calcium", "Phosphorus"] }, 18 | { name: "Cheddar Cheese", calories: 403, carbohydrates: 1.3, protein: 24, fat: 33, vitamins: ["Vitamin A", "Vitamin B12"], minerals: ["Calcium", "Phosphorus"] }, 19 | { name: "Tofu", calories: 76, carbohydrates: 1.9, protein: 8, fat: 4.8, vitamins: ["Vitamin B1", "Vitamin B2"], minerals: ["Calcium", "Iron"] }, 20 | { name: "Chickpeas", calories: 164, carbohydrates: 27.4, protein: 8.9, fat: 2.6, fiber: 7.6, vitamins: ["Folate", "Vitamin B6"], minerals: ["Iron", "Magnesium"] }, 21 | { name: "Quinoa", calories: 120, carbohydrates: 21.3, protein: 4.1, fat: 1.9, fiber: 2.8, vitamins: ["Folate", "Vitamin B1"], minerals: ["Iron", "Magnesium"] }, 22 | { name: "Avocado", calories: 160, carbohydrates: 8.5, protein: 2, fat: 14.7, fiber: 6.7, vitamins: ["Vitamin K", "Vitamin E"], minerals: ["Potassium", "Magnesium"] }, 23 | { name: "Blueberries", calories: 57, carbohydrates: 14.5, protein: 0.7, fat: 0.3, fiber: 2.4, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Manganese", "Copper"] }, 24 | { name: "Oats", calories: 389, carbohydrates: 66.3, protein: 16.9, fat: 6.9, fiber: 10.6, vitamins: ["Vitamin B1", "Vitamin B5"], minerals: ["Magnesium", "Zinc"] }, 25 | { name: "Lentils", calories: 116, carbohydrates: 20.1, protein: 9, fat: 0.4, fiber: 7.9, vitamins: ["Folate", "Vitamin B6"], minerals: ["Iron", "Manganese"] }, 26 | { name: "Red Bell Pepper", calories: 31, carbohydrates: 6, protein: 1, fat: 0.3, fiber: 2.1, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Potassium", "Manganese"] }, 27 | { name: "Oranges", calories: 47, carbohydrates: 11.8, protein: 0.9, fat: 0.1, fiber: 2.4, sugar: 9.4, vitamins: ["Vitamin C", "Folate"], minerals: ["Calcium", "Potassium"] }, 28 | { name: "Kiwi", calories: 61, carbohydrates: 14.7, protein: 1.1, fat: 0.5, fiber: 3, sugar: 8.9, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Magnesium"] }, 29 | { name: "Potato", calories: 77, carbohydrates: 17.6, protein: 2, fat: 0.1, fiber: 2.2, vitamins: ["Vitamin C", "Vitamin B6"], minerals: ["Potassium", "Phosphorus"] }, 30 | { name: "Celery", calories: 16, carbohydrates: 3, protein: 0.7, fat: 0.2, fiber: 1.6, vitamins: ["Vitamin K", "Vitamin A"], minerals: ["Calcium", "Potassium"] }, 31 | { name: "Cauliflower", calories: 25, carbohydrates: 4.9, protein: 1.9, fat: 0.3, fiber: 2, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Calcium", "Potassium"] }, 32 | { name: "Strawberries", calories: 32, carbohydrates: 7.7, protein: 0.7, fat: 0.3, fiber: 2, sugar: 4.9, vitamins: ["Vitamin C", "Folate"], minerals: ["Manganese", "Potassium"] }, 33 | { name: "Pineapple", calories: 50, carbohydrates: 13.1, protein: 0.5, fat: 0.1, fiber: 1.4, sugar: 9.9, vitamins: ["Vitamin C", "Vitamin B6"], minerals: ["Manganese", "Potassium"] }, 34 | { name: "Mango", calories: 60, carbohydrates: 15, protein: 0.8, fat: 0.4, fiber: 1.6, sugar: 13.7, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Potassium", "Magnesium"] }, 35 | { name: "Grapes", calories: 69, carbohydrates: 18.1, protein: 0.7, fat: 0.2, fiber: 0.9, sugar: 15.5, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Copper"] }, 36 | { name: "Grapefruit", calories: 42, carbohydrates: 10.7, protein: 0.8, fat: 0.1, fiber: 1.6, sugar: 7, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Potassium", "Calcium"] }, 37 | { name: "Cantaloupe", calories: 34, carbohydrates: 8.2, protein: 0.8, fat: 0.2, fiber: 0.9, sugar: 7.9, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Potassium", "Magnesium"] }, 38 | { name: "Zucchini", calories: 17, carbohydrates: 3.1, protein: 1.2, fat: 0.3, fiber: 1, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Potassium", "Magnesium"] }, 39 | { name: "Cucumber", calories: 16, carbohydrates: 3.6, protein: 0.7, fat: 0.1, fiber: 0.5, vitamins: ["Vitamin K", "Vitamin C"], minerals: ["Potassium", "Magnesium"] }, 40 | { name: "Pear", calories: 57, carbohydrates: 15.2, protein: 0.4, fat: 0.1, fiber: 3.1, sugar: 9.8, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Copper"] }, 41 | { name: "Peach", calories: 39, carbohydrates: 9.5, protein: 0.9, fat: 0.3, fiber: 1.5, sugar: 8.4, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Potassium", "Manganese"] }, 42 | { name: "Apricot", calories: 48, carbohydrates: 11.1, protein: 1.4, fat: 0.4, fiber: 2, sugar: 9.2, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Potassium", "Copper"] }, 43 | { name: "Plum", calories: 46, carbohydrates: 11.4, protein: 0.7, fat: 0.3, fiber: 1.4, sugar: 9.9, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Copper"] }, 44 | { name: "Cherry", calories: 50, carbohydrates: 12, protein: 1, fat: 0.3, fiber: 1.6, sugar: 8.5, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Potassium", "Manganese"] }, 45 | { name: "Pomegranate", calories: 83, carbohydrates: 18.7, protein: 1.7, fat: 1.2, fiber: 4, sugar: 13.7, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Copper"] }, 46 | { name: "Papaya", calories: 43, carbohydrates: 10.8, protein: 0.5, fat: 0.3, fiber: 1.7, sugar: 7.8, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 47 | { name: "Watermelon", calories: 30, carbohydrates: 7.6, protein: 0.6, fat: 0.2, fiber: 0.4, sugar: 6.2, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Potassium", "Magnesium"] }, 48 | { name: "Lettuce", calories: 15, carbohydrates: 2.9, protein: 1.4, fat: 0.2, fiber: 1.3, vitamins: ["Vitamin A", "Vitamin K"], minerals: ["Potassium", "Calcium"] }, 49 | { name: "Cabbage", calories: 25, carbohydrates: 5.8, protein: 1.3, fat: 0.1, fiber: 2.5, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Calcium"] }, 50 | { name: "Brussels Sprouts", calories: 43, carbohydrates: 8.9, protein: 3.4, fat: 0.3, fiber: 3.8, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Magnesium"] }, 51 | { name: "Eggplant", calories: 25, carbohydrates: 5.9, protein: 1, fat: 0.2, fiber: 3, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Magnesium"] }, 52 | { name: "Leek", calories: 61, carbohydrates: 14.2, protein: 1.5, fat: 0.3, fiber: 1.8, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Potassium", "Magnesium"] }, 53 | { name: "Turnip", calories: 28, carbohydrates: 6.2, protein: 0.9, fat: 0.1, fiber: 1.8, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Calcium"] }, 54 | { name: "Radish", calories: 16, carbohydrates: 3.4, protein: 0.7, fat: 0.1, fiber: 1.6, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 55 | { name: "Beetroot", calories: 43, carbohydrates: 9.6, protein: 1.6, fat: 0.2, fiber: 2.8, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 56 | { name: "Corn", calories: 86, carbohydrates: 19, protein: 3.2, fat: 1.2, fiber: 2.7, vitamins: ["Vitamin B3", "Vitamin B5"], minerals: ["Potassium", "Magnesium"] }, 57 | { name: "Artichoke", calories: 47, carbohydrates: 10.5, protein: 3.3, fat: 0.2, fiber: 5.4, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 58 | { name: "Watercress", calories: 11, carbohydrates: 1.3, protein: 2.3, fat: 0.1, fiber: 0.5, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Calcium", "Potassium"] }, 59 | { name: "Swiss Chard", calories: 19, carbohydrates: 3.7, protein: 1.8, fat: 0.2, fiber: 1.6, vitamins: ["Vitamin A", "Vitamin K"], minerals: ["Calcium", "Potassium"] }, 60 | { name: "Squash", calories: 26, carbohydrates: 6.5, protein: 1, fat: 0.1, fiber: 0.5, vitamins: ["Vitamin A", "Vitamin C"], minerals: ["Calcium", "Potassium"] }, 61 | { name: "Fennel", calories: 31, carbohydrates: 7.3, protein: 1.2, fat: 0.2, fiber: 3.1, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 62 | { name: "Green Beans", calories: 31, carbohydrates: 7, protein: 1.8, fat: 0.1, fiber: 2.7, vitamins: ["Vitamin C", "Vitamin A"], minerals: ["Calcium", "Potassium"] }, 63 | { name: "Romaine Lettuce", calories: 17, carbohydrates: 3.3, protein: 1.2, fat: 0.3, fiber: 2.1, vitamins: ["Vitamin A", "Vitamin K"], minerals: ["Calcium", "Potassium"] }, 64 | { name: "Onion", calories: 40, carbohydrates: 9.3, protein: 1.1, fat: 0.1, fiber: 1.7, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 65 | { name: "Shallot", calories: 72, carbohydrates: 16.8, protein: 2.5, fat: 0.1, fiber: 3.2, vitamins: ["Vitamin C", "Vitamin B6"], minerals: ["Potassium", "Magnesium"] }, 66 | { name: "Red Cabbage", calories: 31, carbohydrates: 7.4, protein: 1.4, fat: 0.2, fiber: 2.1, vitamins: ["Vitamin C", "Vitamin K"], minerals: ["Potassium", "Calcium"] }, 67 | { name: "Peas", calories: 81, carbohydrates: 14.5, protein: 5.4, fat: 0.4, fiber: 5.1, vitamins: ["Vitamin C", "Folate"], minerals: ["Potassium", "Magnesium"] }, 68 | { name: "Black Beans", calories: 132, carbohydrates: 23.7, protein: 8.9, fat: 0.5, fiber: 8.7, vitamins: ["Folate", "Vitamin B6"], minerals: ["Iron", "Magnesium"] }, 69 | { name: "White Fish", calories: 84, carbohydrates: 0, protein: 18.8, fat: 1.2, vitamins: ["Vitamin D", "Vitamin B12"], minerals: ["Selenium", "Phosphorus"] }, 70 | { name: "Tuna", calories: 132, carbohydrates: 0, protein: 28, fat: 1, vitamins: ["Vitamin B12", "Vitamin B6"], minerals: ["Selenium", "Phosphorus"] }, 71 | { name: "Shrimp", calories: 99, carbohydrates: 0.2, protein: 24, fat: 0.3, vitamins: ["Vitamin B12", "Vitamin E"], minerals: ["Selenium", "Phosphorus"] }, 72 | { name: "Oysters", calories: 68, carbohydrates: 3.9, protein: 7, fat: 2.5, vitamins: ["Vitamin B12", "Vitamin D"], minerals: ["Zinc", "Selenium"] }, 73 | { name: "Beef", calories: 250, carbohydrates: 0, protein: 26, fat: 15, vitamins: ["Vitamin B12", "Vitamin B6"], minerals: ["Iron", "Zinc"] }, 74 | { name: "Pork", calories: 242, carbohydrates: 0, protein: 27, fat: 14, vitamins: ["Vitamin B12", "Vitamin B6"], minerals: ["Phosphorus", "Zinc"] }, 75 | { name: "Lamb", calories: 294, carbohydrates: 0, protein: 25, fat: 21, vitamins: ["Vitamin B12", "Vitamin B6"], minerals: ["Iron", "Zinc"] }, 76 | { name: "Duck", calories: 337, carbohydrates: 0, protein: 19, fat: 28, vitamins: ["Vitamin B12", "Vitamin B6"], minerals: ["Iron", "Zinc"] }, 77 | { name: "Rabbit", calories: 173, carbohydrates: 0, protein: 33, fat: 3.5, vitamins: ["Vitamin B12", "Vitamin B3"], minerals: ["Phosphorus", "Selenium"] }, 78 | { name: "Turkey", calories: 189, carbohydrates: 0, protein: 29, fat: 7.4, vitamins: ["Vitamin B12", "Vitamin B6"], minerals: ["Phosphorus", "Selenium"] }, 79 | { name: "Butter", calories: 717, carbohydrates: 0.1, protein: 0.9, fat: 81, vitamins: ["Vitamin A", "Vitamin D"], minerals: ["Calcium", "Phosphorus"] }, 80 | { name: "Sour Cream", calories: 292, carbohydrates: 2.9, protein: 2.1, fat: 30, vitamins: ["Vitamin A", "Vitamin D"], minerals: ["Calcium", "Phosphorus"] }, 81 | { name: "Olive Oil", calories: 884, carbohydrates: 0, protein: 0, fat: 100, vitamins: ["Vitamin E", "Vitamin K"], minerals: ["Iron"] }, 82 | { name: "White Bread", calories: 265, carbohydrates: 49, protein: 9, fat: 3.2, fiber: 2.7, vitamins: ["Vitamin B1", "Vitamin B3"], minerals: ["Iron", "Calcium"] }, 83 | { name: "Pasta", calories: 131, carbohydrates: 25, protein: 5.2, fat: 1.1, fiber: 1.4, vitamins: ["Vitamin B1", "Vitamin B3"], minerals: ["Iron", "Magnesium"] }, 84 | { name: "Walnuts", calories: 196, carbohydrates: 3.9, protein: 4.3, fat: 20, fiber: 2, sugar: 1.1, vitamins: ["Vitamin E", "Folate"], minerals: ["Magnesium", "Phosphorus"] }, 85 | { name: "Hazelnuts", calories: 178, carbohydrates: 4.7, protein: 4.2, fat: 17, fiber: 2.7, sugar: 1.2, vitamins: ["Vitamin E", "Thiamine"], minerals: ["Magnesium", "Copper"] }, 86 | { name: "Pistachios", calories: 159, carbohydrates: 7.7, protein: 5.8, fat: 12.9, fiber: 3, sugar: 2.2, vitamins: ["Vitamin B6", "Thiamine"], minerals: ["Magnesium", "Phosphorus"] }, 87 | { name: "Cashews", calories: 155, carbohydrates: 8.6, protein: 5.2, fat: 12.3, fiber: 1, sugar: 1.7, vitamins: ["Vitamin K", "Thiamine"], minerals: ["Magnesium", "Phosphorus"] } 88 | ]; -------------------------------------------------------------------------------- /tp2/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /tp2/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface IFood { 2 | name: string; 3 | calories: number; 4 | carbohydrates: number; // in grams 5 | protein: number; // in grams 6 | fat: number; // in grams 7 | fiber?: number; // in grams, optional 8 | sugar?: number; // in grams, optional 9 | vitamins?: string[]; // array of vitamins, optional 10 | minerals?: string[]; // array of minerals, optional 11 | } 12 | 13 | export interface IFoodReduced { 14 | value: string; 15 | label: string; 16 | } 17 | 18 | export interface IMacronutrientData { 19 | name: 'carbohydrates' | 'protein' | 'fat'; 20 | value: number; 21 | } -------------------------------------------------------------------------------- /tp2/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss" 2 | const { fontFamily } = require("tailwindcss/defaultTheme") 3 | 4 | const config = { 5 | darkMode: ["class"], 6 | content: [ 7 | './pages/**/*.{ts,tsx}', 8 | './components/**/*.{ts,tsx}', 9 | './app/**/*.{ts,tsx}', 10 | './src/**/*.{ts,tsx}', 11 | ], 12 | prefix: "", 13 | theme: { 14 | container: { 15 | center: true, 16 | padding: "2rem", 17 | screens: { 18 | "2xl": "1400px", 19 | }, 20 | }, 21 | extend: { 22 | fontFamily: { 23 | sans: ["var(--font-sans)", ...fontFamily.sans], 24 | }, 25 | colors: { 26 | border: "hsl(var(--border))", 27 | input: "hsl(var(--input))", 28 | ring: "hsl(var(--ring))", 29 | background: "hsl(var(--background))", 30 | foreground: "hsl(var(--foreground))", 31 | primary: { 32 | DEFAULT: "hsl(var(--primary))", 33 | foreground: "hsl(var(--primary-foreground))", 34 | }, 35 | secondary: { 36 | DEFAULT: "hsl(var(--secondary))", 37 | foreground: "hsl(var(--secondary-foreground))", 38 | }, 39 | destructive: { 40 | DEFAULT: "hsl(var(--destructive))", 41 | foreground: "hsl(var(--destructive-foreground))", 42 | }, 43 | muted: { 44 | DEFAULT: "hsl(var(--muted))", 45 | foreground: "hsl(var(--muted-foreground))", 46 | }, 47 | accent: { 48 | DEFAULT: "hsl(var(--accent))", 49 | foreground: "hsl(var(--accent-foreground))", 50 | }, 51 | popover: { 52 | DEFAULT: "hsl(var(--popover))", 53 | foreground: "hsl(var(--popover-foreground))", 54 | }, 55 | card: { 56 | DEFAULT: "hsl(var(--card))", 57 | foreground: "hsl(var(--card-foreground))", 58 | }, 59 | }, 60 | borderRadius: { 61 | lg: "var(--radius)", 62 | md: "calc(var(--radius) - 2px)", 63 | sm: "calc(var(--radius) - 4px)", 64 | }, 65 | keyframes: { 66 | "accordion-down": { 67 | from: { height: "0" }, 68 | to: { height: "var(--radix-accordion-content-height)" }, 69 | }, 70 | "accordion-up": { 71 | from: { height: "var(--radix-accordion-content-height)" }, 72 | to: { height: "0" }, 73 | }, 74 | }, 75 | animation: { 76 | "accordion-down": "accordion-down 0.2s ease-out", 77 | "accordion-up": "accordion-up 0.2s ease-out", 78 | }, 79 | }, 80 | }, 81 | plugins: [require("tailwindcss-animate")], 82 | } satisfies Config 83 | 84 | export default config -------------------------------------------------------------------------------- /tp2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | --------------------------------------------------------------------------------