diff --git a/.gitignore b/.gitignore index 4614f33..fd3dbb5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,36 @@ -node_modules -pnpm-lock.yaml -yarn.lock -.parcel-cache -dist +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..a3c6b7b --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5ac0021 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/toolbox.iml b/.idea/toolbox.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/toolbox.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.parcelrc b/.parcelrc deleted file mode 100644 index 28d2587..0000000 --- a/.parcelrc +++ /dev/null @@ -1,34 +0,0 @@ -{ - "compressors": { - "*.{html,css,js,svg,map}": [ - "...", - "@parcel/compressor-gzip", - "@parcel/compressor-brotli" - ] - }, - "validators": { - "*.{ts,tsx}": ["@parcel/validator-typescript"] - }, - "transformers": { - "*.{ts,tsx}": [ - "@parcel/transformer-typescript-tsc" - ], - "bundle-text:*": [ - "...", - "@parcel/transformer-inline-string" - ], - "data-url:*": [ - "...", - "@parcel/transformer-inline-string" - ] - }, - "optimizers": { - "*.{jpg,jpeg,png}": [], - "data-url:*": [ - "...", - "@parcel/optimizer-data-url" - ] - }, - "extends": "@parcel/config-default", - "reporters": ["...", "parcel-reporter-clean-dist"] -} \ No newline at end of file diff --git a/.postcssrc b/.postcssrc deleted file mode 100644 index d42c370..0000000 --- a/.postcssrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "plugins": { - "tailwindcss": {} - } -} \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 2c961a3..0000000 --- a/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) 2024 NOBODY - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 684cffe..c403366 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,36 @@ -# template-basic-front +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). -Template pour les projets d'études 'frontend' HTML/SCSS/TS \ No newline at end of file +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## 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. diff --git a/components.json b/components.json new file mode 100644 index 0000000..2bf7f55 --- /dev/null +++ b/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "stone", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs new file mode 100644 index 0000000..4678774 --- /dev/null +++ b/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/package.json b/package.json index 4abfe92..28aed84 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,55 @@ { - "name": "template-basic-front", - "version": "1.0.0", - "description": "Template pour les projets d'études 'frontend' HTML/SCSS/TS", - "browserslist": "> 0.5%, last 2 versions, not dead", + "name": "toolbox", + "version": "0.1.0", "private": true, - "source": "./src/scripts/main.ts", - "module": "./dist/index.js", "scripts": { - "check": "tsc --noEmit", - "dev": "parcel serve -p 3000 'src/index.html' --lazy" - }, - "keywords": [], - "author": "Mathis H", - "license": "MIT", - "devDependencies": { - "@parcel/bundler-default": "^2.12.0", - "@parcel/compressor-brotli": "^2.12.0", - "@parcel/compressor-gzip": "^2.12.0", - "@parcel/config-default": "^2.12.0", - "@parcel/transformer-sass": "^2.12.0", - "@parcel/transformer-typescript-tsc": "^2.12.0", - "@parcel/validator-typescript": "^2.12.0", - "parcel": "latest", - "parcel-reporter-clean-dist": "^1.0.4", - "postcss": "^8.4.38", - "tailwindcss": "^3.4.3", - "typescript": ">=3.0.0" + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" }, "dependencies": { - "@fontsource/viga": "^5.0.12" + "@fontsource/ubuntu": "^5.0.12", + "@heroicons/react": "^2.1.3", + "@hookform/resolvers": "^3.3.4", + "@radix-ui/react-accordion": "^1.1.2", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-menubar": "^1.0.4", + "@radix-ui/react-navigation-menu": "^1.1.4", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-tooltip": "^1.0.7", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "date-fns": "^3.6.0", + "framer-motion": "^11.0.25", + "i18next": "^23.11.0", + "idb": "^8.0.0", + "lucide-react": "^0.356.0", + "mini-svg-data-uri": "^1.4.4", + "next": "latest", + "next-i18next": "latest", + "next-themes": "^0.2.1", + "react": "^18.2.0", + "react-day-picker": "^8.10.1", + "react-dom": "^18.2.0", + "react-hook-form": "^7.51.3", + "react-i18next": "^14.1.0", + "react-loader-spinner": "^6.1.6", + "store2": "^2.14.3", + "tailwind-merge": "^2.2.2", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.12.5", + "@types/react": "^18.2.74", + "@types/react-dom": "^18.2.24", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.3", + "typescript": "^5.4.4" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/public/logo-yidhra.svg b/public/logo-yidhra.svg new file mode 100644 index 0000000..6286a62 --- /dev/null +++ b/public/logo-yidhra.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/account/page.tsx b/src/app/account/page.tsx new file mode 100644 index 0000000..198d849 --- /dev/null +++ b/src/app/account/page.tsx @@ -0,0 +1,22 @@ +"use client" + +import { ThemeSelector } from "@/components/theme-selector"; +import { TextGenerateEffect } from "@/components/ui/text-generate-effect"; + + +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { cn } from "@/utils/cn"; +import {Header} from "@/components/Header"; + +export default function AccountPage() { + + return ( + <> +
+
+
+ + ); +} diff --git a/src/app/events/new/page.tsx b/src/app/events/new/page.tsx new file mode 100644 index 0000000..34d7fc7 --- /dev/null +++ b/src/app/events/new/page.tsx @@ -0,0 +1,25 @@ +"use client" + +import { ThemeSelector } from "@/components/theme-selector"; +import { TextGenerateEffect } from "@/components/ui/text-generate-effect"; + + +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { cn } from "@/utils/cn"; +import {Header} from "@/components/Header"; +import NewEventForm from "@/components/NewEventForm"; + +export default function EventsPage() { + + return ( + <> +
+
+ +
+
+ + ); +} diff --git a/src/app/events/page.tsx b/src/app/events/page.tsx new file mode 100644 index 0000000..deed56f --- /dev/null +++ b/src/app/events/page.tsx @@ -0,0 +1,37 @@ +"use client" + +import { ThemeSelector } from "@/components/theme-selector"; +import { TextGenerateEffect } from "@/components/ui/text-generate-effect"; + + +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { cn } from "@/utils/cn"; +import {Header} from "@/components/Header"; +import {EventCard} from "@/components/EventCard"; + +export default function EventsPage() { + + return ( + <> +
+
+
+ +
+
+
+ + ); +} diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..fa80b23 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,63 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + + + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 346.8 77.2% 49.8%; + --radius: 0.5rem; + } + + .dark { + --background: 20 14.3% 4.1%; + --foreground: 0 0% 95%; + --card: 24 9.8% 10%; + --card-foreground: 0 0% 95%; + --popover: 0 0% 9%; + --popover-foreground: 0 0% 95%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 15%; + --muted-foreground: 240 5% 64.9%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 346.8 77.2% 49.8%; + } +} + + + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..8604214 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,47 @@ +import type { Metadata } from "next"; +import { ThemeProvider } from "@/components/theme-provider" +import { + TooltipProvider, +} from "@/components/ui/tooltip" + +import { Toaster } from "@/components/ui/toaster" + +import '@fontsource/ubuntu'; +import "./globals.css"; +import React from "react"; + +export const metadata: Metadata = { + title: "Yidhra ToolBox", + description: "Generated and modify your project", +}; + +export interface RootLayoutProps { + children: React.ReactNode; +} + +const BODY_CLASS_NAME = "flex min-h-screen w-screen"; +const DIV_CLASS_NAME = "min-h-full w-full dark:bg-grid-small-white/[0.4] bg-grid-small-black/[0.6] relative flex flex-col justify-between items-center dark:bg-stone-950 text-primary transition-all duration-200 ease-in-out"; + +export default function RootLayout({children}: RootLayoutProps) { + return ( + + + + +
+ {/* Radial gradient for the container to give a faded look */} + {/*
*/} + {children} +
+ +
+
+ + + ); +} diff --git a/src/app/loading.tsx b/src/app/loading.tsx new file mode 100644 index 0000000..332cb2a --- /dev/null +++ b/src/app/loading.tsx @@ -0,0 +1,14 @@ +"use client" +import { Triangle } from 'react-loader-spinner' +export default function Loading() { + // You can add any UI inside Loading, including a Skeleton. + return
; +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..f3f85c3 --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,24 @@ +"use client" + +import { ThemeSelector } from "@/components/theme-selector"; +import { TextGenerateEffect } from "@/components/ui/text-generate-effect"; + + +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import { cn } from "@/utils/cn"; +import {Header} from "@/components/Header"; + +export default function Home() { + + return ( + <> +
+
+ +

Brief 04 - Educational purpose only

+
+ + ); +} diff --git a/src/assets/fonts/viga/400.css b/src/assets/fonts/viga/400.css deleted file mode 100644 index 8a70035..0000000 --- a/src/assets/fonts/viga/400.css +++ /dev/null @@ -1,19 +0,0 @@ -/* viga-latin-ext-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-ext-400-normal.woff2) format('woff2'), url(./files/viga-latin-ext-400-normal.woff) format('woff'); - unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; -} - -/* viga-latin-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-400-normal.woff2) format('woff2'), url(./files/viga-latin-400-normal.woff) format('woff'); - unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; -} \ No newline at end of file diff --git a/src/assets/fonts/viga/CHANGELOG.md b/src/assets/fonts/viga/CHANGELOG.md deleted file mode 100644 index e798685..0000000 --- a/src/assets/fonts/viga/CHANGELOG.md +++ /dev/null @@ -1,2 +0,0 @@ -# Changelog -See the [Fontsource CHANGELOG.md](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md). \ No newline at end of file diff --git a/src/assets/fonts/viga/LICENSE b/src/assets/fonts/viga/LICENSE deleted file mode 100644 index ec720ac..0000000 --- a/src/assets/fonts/viga/LICENSE +++ /dev/null @@ -1,93 +0,0 @@ -Copyright (c) 2011 Fontstage (info@fontstage.com), with Reserved Font Name "Viga" - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/assets/fonts/viga/README.md b/src/assets/fonts/viga/README.md deleted file mode 100644 index 5ae6441..0000000 --- a/src/assets/fonts/viga/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Fontsource Viga - -[![npm (scoped)](https://img.shields.io/npm/v/@fontsource/viga?color=brightgreen)](https://www.npmjs.com/package/@fontsource/viga) [![Generic badge](https://img.shields.io/badge/fontsource-passing-brightgreen)](https://github.com/fontsource/fontsource) [![Monthly downloads](https://badgen.net/npm/dm/@fontsource/viga)](https://github.com/fontsource/fontsource) [![Total downloads](https://badgen.net/npm/dt/@fontsource/viga)](https://github.com/fontsource/fontsource) [![GitHub stars](https://img.shields.io/github/stars/fontsource/fontsource.svg?style=social&label=Star)](https://github.com/fontsource/fontsource/stargazers) - -The CSS and web font files to easily self-host the “Viga” font. Please visit the main [Fontsource website](https://fontsource.org/fonts/viga) to view more details on this package. - -## Quick Installation - -Fontsource offers multiple methods to import the CSS, including using a bundler like Vite or using SASS. You can find full documentation [here](https://fontsource.org/docs/getting-started/introduction). - -```javascript -npm install @fontsource/viga -``` - -Within your app entry file or site component, import it in. - -```javascript -import "@fontsource/viga"; // Defaults to weight 400 -import "@fontsource/viga/400.css"; // Specify weight -import "@fontsource/viga/400-italic.css"; // Specify weight and style -``` - -Supported variables: -- Weights: `[400]` -- Styles: `[normal]` -- Subsets: `[latin,latin-ext]` - -> Note: `italic` may not be supported by all fonts. To learn more about what weights and styles are supported, please visit the [Fontsource website](https://fontsource.org/fonts/viga). - -Finally, you can reference the font name in a CSS stylesheet, CSS Module, or CSS-in-JS. - -```css -body { - font-family: "Viga"; -} -``` - -## Licensing -Always make sure to read the license for each font you use. Most of the fonts in the collection use the SIL Open Font License, v1.1. Some fonts use the Apache 2 license. The Ubuntu fonts use the Ubuntu Font License v1.0. - -Copyright (c) 2011 Fontstage (info@fontstage.com), with Reserved Font Name "Viga" -[OFL-1.1](http://scripts.sil.org/OFL) - -## Other Notes -Font version (provided by source): `v14`. - -If you have any suggestions or ideas to improve the performance of font loading or expand the existing library, feel free to star and contribute to this repository. You can share your suggestions or ideas by creating an [issue](https://github.com/fontsource/fontsource/issues). \ No newline at end of file diff --git a/src/assets/fonts/viga/files/viga-latin-400-normal.woff b/src/assets/fonts/viga/files/viga-latin-400-normal.woff deleted file mode 100644 index 15f36cb..0000000 Binary files a/src/assets/fonts/viga/files/viga-latin-400-normal.woff and /dev/null differ diff --git a/src/assets/fonts/viga/files/viga-latin-400-normal.woff2 b/src/assets/fonts/viga/files/viga-latin-400-normal.woff2 deleted file mode 100644 index fe752af..0000000 Binary files a/src/assets/fonts/viga/files/viga-latin-400-normal.woff2 and /dev/null differ diff --git a/src/assets/fonts/viga/files/viga-latin-ext-400-normal.woff b/src/assets/fonts/viga/files/viga-latin-ext-400-normal.woff deleted file mode 100644 index 8bf4b78..0000000 Binary files a/src/assets/fonts/viga/files/viga-latin-ext-400-normal.woff and /dev/null differ diff --git a/src/assets/fonts/viga/files/viga-latin-ext-400-normal.woff2 b/src/assets/fonts/viga/files/viga-latin-ext-400-normal.woff2 deleted file mode 100644 index 200513e..0000000 Binary files a/src/assets/fonts/viga/files/viga-latin-ext-400-normal.woff2 and /dev/null differ diff --git a/src/assets/fonts/viga/index.css b/src/assets/fonts/viga/index.css deleted file mode 100644 index 8a70035..0000000 --- a/src/assets/fonts/viga/index.css +++ /dev/null @@ -1,19 +0,0 @@ -/* viga-latin-ext-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-ext-400-normal.woff2) format('woff2'), url(./files/viga-latin-ext-400-normal.woff) format('woff'); - unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; -} - -/* viga-latin-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-400-normal.woff2) format('woff2'), url(./files/viga-latin-400-normal.woff) format('woff'); - unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; -} \ No newline at end of file diff --git a/src/assets/fonts/viga/latin-400.css b/src/assets/fonts/viga/latin-400.css deleted file mode 100644 index e2c66cd..0000000 --- a/src/assets/fonts/viga/latin-400.css +++ /dev/null @@ -1,8 +0,0 @@ -/* viga-latin-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-400-normal.woff2) format('woff2'), url(./files/viga-latin-400-normal.woff) format('woff'); -} \ No newline at end of file diff --git a/src/assets/fonts/viga/latin-ext-400.css b/src/assets/fonts/viga/latin-ext-400.css deleted file mode 100644 index fff62a0..0000000 --- a/src/assets/fonts/viga/latin-ext-400.css +++ /dev/null @@ -1,8 +0,0 @@ -/* viga-latin-ext-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-ext-400-normal.woff2) format('woff2'), url(./files/viga-latin-ext-400-normal.woff) format('woff'); -} \ No newline at end of file diff --git a/src/assets/fonts/viga/latin-ext.css b/src/assets/fonts/viga/latin-ext.css deleted file mode 100644 index fff62a0..0000000 --- a/src/assets/fonts/viga/latin-ext.css +++ /dev/null @@ -1,8 +0,0 @@ -/* viga-latin-ext-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-ext-400-normal.woff2) format('woff2'), url(./files/viga-latin-ext-400-normal.woff) format('woff'); -} \ No newline at end of file diff --git a/src/assets/fonts/viga/latin.css b/src/assets/fonts/viga/latin.css deleted file mode 100644 index e2c66cd..0000000 --- a/src/assets/fonts/viga/latin.css +++ /dev/null @@ -1,8 +0,0 @@ -/* viga-latin-400-normal */ -@font-face { - font-family: 'Viga'; - font-style: normal; - font-display: swap; - font-weight: 400; - src: url(./files/viga-latin-400-normal.woff2) format('woff2'), url(./files/viga-latin-400-normal.woff) format('woff'); -} \ No newline at end of file diff --git a/src/assets/fonts/viga/metadata.json b/src/assets/fonts/viga/metadata.json deleted file mode 100644 index 9671bed..0000000 --- a/src/assets/fonts/viga/metadata.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "id": "viga", - "family": "Viga", - "subsets": ["latin", "latin-ext"], - "weights": [400], - "styles": ["normal"], - "defSubset": "latin", - "variable": false, - "lastModified": "2022-09-22", - "version": "v14", - "category": "sans-serif", - "license": { - "type": "OFL-1.1", - "url": "http://scripts.sil.org/OFL", - "attribution": "Copyright (c) 2011 Fontstage (info@fontstage.com), with Reserved Font Name \"Viga\"" - }, - "source": "https://github.com/google/fonts", - "type": "google" -} \ No newline at end of file diff --git a/src/assets/fonts/viga/package.json b/src/assets/fonts/viga/package.json deleted file mode 100644 index 5d9b9ea..0000000 --- a/src/assets/fonts/viga/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@fontsource/viga", - "version": "5.0.12", - "description": "Self-host the Viga font in a neatly bundled NPM package.", - "main": "index.css", - "publishConfig": {"access": "public"}, - "keywords": [ - "fontsource", - "font", - "font family", - "google fonts", - "viga", - "Viga", - "css", - "sass", - "front-end", - "web", - "typeface", - "variable" - ], - "author": "Google Inc.", - "license": "OFL-1.1", - "homepage": "https://fontsource.org/fonts/viga", - "repository": { - "type": "git", - "url": "https://github.com/fontsource/font-files.git", - "directory": "fonts/google/viga" - }, - "publishHash": "c2b9bb905b377a60" -} \ No newline at end of file diff --git a/src/assets/fonts/viga/scss/metadata.scss b/src/assets/fonts/viga/scss/metadata.scss deleted file mode 100644 index 1b97b32..0000000 --- a/src/assets/fonts/viga/scss/metadata.scss +++ /dev/null @@ -1,17 +0,0 @@ -$id: 'viga' !default; -$family: 'Viga' !default; -$category: sans-serif !default; -$subsets: (latin, latin-ext) !default; -$weights: (400) !default; -$styles: (normal) !default; -$axes: null !default; -$defaults: ( - subset: latin, - weight: 400, - style: normal, - axis: null, -) !default; -$unicode: ( - latin-ext: (U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF), - latin: (U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD), -) !default; diff --git a/src/assets/fonts/viga/scss/mixins.scss b/src/assets/fonts/viga/scss/mixins.scss deleted file mode 100644 index 4d1c6c3..0000000 --- a/src/assets/fonts/viga/scss/mixins.scss +++ /dev/null @@ -1,184 +0,0 @@ -@use 'sass:list'; -@use 'sass:map'; -@use 'sass:math'; -@use 'sass:meta'; -@use 'sass:string'; - -@use 'metadata'; - -$metadata: meta.module-variables(metadata) !default; -$directory: null !default; - -$family: null !default; -$display: null !default; -$formats: null !default; -$subsets: null !default; -$weights: null !default; -$styles: null !default; -$axes: null !default; - -// Deprecated -$displayVar: null !default; - -@mixin generator( - $metadata: $metadata, - $directory: $directory, - $family: $family, - $display: $display, - $formats: $formats, - $subsets: $subsets, - $weights: $weights, - $styles: $styles, - $axes: $axes, - - // Deprecated - $displayVar: $displayVar -) { - @if $displayVar != null { - @warn "$displayVar is deprecated due to the limitation of using css variables in @font-face (https://github.com/fontsource/fontsource/issues/726)."; - } - - $isVariable: map.get($metadata, axes) != null; - - $directory: if( - $directory, - $directory, - '~@fontsource#{if($isVariable, '-variable', '')}/#{map.get($metadata, id)}/files' - ); - - $family: if($family, $family, map.get($metadata, family) + if($isVariable, ' Variable', '')); - $display: if($display, $display, swap); - $formats: if(not $formats or $formats == all, if($isVariable, woff2, (woff2, woff)), $formats); - $subsets: if( - $subsets, - if($subsets == all, map.get($metadata, subsets), $subsets), - map.get($metadata, defaults, subset) - ); - $weights: if( - $weights, - if($weights == all, map.get($metadata, weights), $weights), - map.get($metadata, defaults, weight) - ); - $styles: if( - $styles, - if($styles == all, map.get($metadata, styles), $styles), - map.get($metadata, defaults, style) - ); - $axes: if( - $axes, - if($axes == all, full, $axes), - if($isVariable, if(map.has-key($metadata, axes, wght), wght, full), null) - ); - - @each $subset in $subsets { - @each $unicodeSubset, $unicodeRange in map.get($metadata, unicode) { - @if ( - ($subset == $unicodeSubset) or - ( - // Is numeric subset - ($subset == map.get($metadata, defaults, subset)) and not - list.index(map.get($metadata, subsets), $unicodeSubset) - ) - ) { - @each $weight in if($axes, null, $weights) { - @each $axis in $axes { - @each $style in $styles { - $variant: '#{map.get($metadata, id)}-#{if($unicodeSubset, $unicodeSubset, $subset)}-#{if($axis, $axis, $weight)}-#{$style}'; - - $src: (); - @each $format in $formats { - $src: append( - $src, - url('#{$directory}/#{$variant}.#{$format}') - format('#{$format}#{if($axis, '-variations', '')}'), - comma - ); - } - - @content (( - metadata: $metadata, - directory: $directory, - family: $family, - display: $display, - formats: $formats, - subsets: $subsets, - weights: $weights, - styles: $styles, - axes: $axes, - - variant: $variant, - subset: $subset, - unicodeSubset: $unicodeSubset, - unicodeRange: $unicodeRange, - weight: $weight, - axis: $axis, - style: $style, - - font-family: string.quote($family), - font-style: if( - (($axis == full) or ($axis == slnt)) and map.has-key($metadata, axes, slnt), - oblique map.get($metadata, axes, slnt, min) + deg map.get($metadata, axes, slnt, max) + deg, - $style - ), - font-display: $display, - font-weight: if( - (($axis == full) or ($axis == wght)) and map.has-key($metadata, axes, wght), - map.get($metadata, axes, wght, min) map.get($metadata, axes, wght, max), - $weight - ), - font-stretch: if( - (($axis == full) or ($axis == wdth)) and map.has-key($metadata, axes, wdth), - '#{map.get($metadata, axes, wdth, min)}% #{map.get($metadata, axes, wdth, max)}%', - null - ), - src: $src, - unicode-range: $unicodeRange, - )); - } - } - } - } - } - } -} - -@mixin faces( - $metadata: $metadata, - $directory: $directory, - $family: $family, - $display: $display, - $formats: $formats, - $subsets: $subsets, - $weights: $weights, - $styles: $styles, - $axes: $axes, - - // Deprecated - $displayVar: $displayVar -) { - @include generator( - $metadata: $metadata, - $directory: $directory, - $family: $family, - $display: $display, - $formats: $formats, - $subsets: $subsets, - $weights: $weights, - $styles: $styles, - $axes: $axes, - - $displayVar: $displayVar - ) - using ($props) { - /* #{map.get($props, variant)} */ - @font-face { - font-family: map.get($props, font-family); - font-style: map.get($props, font-style); - font-display: map.get($props, font-display); - font-weight: map.get($props, font-weight); - font-stretch: map.get($props, font-stretch); - unicode-range: map.get($props, unicode-range); - src: map.get($props, src); - } - } -} diff --git a/src/assets/fonts/viga/unicode.json b/src/assets/fonts/viga/unicode.json deleted file mode 100644 index d317a27..0000000 --- a/src/assets/fonts/viga/unicode.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "latin-ext": "U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF", - "latin": "U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD" -} \ No newline at end of file diff --git a/src/components/EventCard.tsx b/src/components/EventCard.tsx new file mode 100644 index 0000000..07a4cea --- /dev/null +++ b/src/components/EventCard.tsx @@ -0,0 +1,23 @@ +'use client' +import React from 'react' +import {IEvent} from "@/types/response"; +import {Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle} from "@/components/ui/card"; +import Image from "next/image"; +export const EventCard = (props: IEvent) => { + return ( + <> + + + {props.title} + + {props.title} + {props.desc} + + +

{props.date}

+
+
+
+ + ) +} \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..d875666 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,17 @@ +import React from 'react' +import {Button} from "@/components/ui/button"; +import HeaderAccountContainer from "@/components/HeaderAccountContainer"; +import {ThemeSelector} from "@/components/theme-selector"; + +export const Header = () => { + return ( +
+
+

Rendez vous !

+
+ + +
+ ) +} +export default Header; \ No newline at end of file diff --git a/src/components/HeaderAccountContainer.tsx b/src/components/HeaderAccountContainer.tsx new file mode 100644 index 0000000..160061e --- /dev/null +++ b/src/components/HeaderAccountContainer.tsx @@ -0,0 +1,173 @@ +'use client' +import React, {useState, useEffect} from 'react' +import {Button} from "@/components/ui/button"; +import { + Menubar, + MenubarCheckboxItem, + MenubarContent, + MenubarItem, + MenubarMenu, + MenubarRadioGroup, + MenubarRadioItem, + MenubarSeparator, + MenubarShortcut, + MenubarSub, + MenubarSubContent, + MenubarSubTrigger, + MenubarTrigger, +} from "@/components/ui/menubar" +import store from "store2"; +import {IResMeData} from "@/types/response"; +import { + CalendarDays, + CalendarFold, + CalendarHeart, + CalendarPlus, + CalendarRange, + Server, + Loader2, + Unplug, + User, + UserCog +} from "lucide-react"; +import { toNamespacedPath } from 'path'; + +import { useToast } from "@/components/ui/use-toast" + +function HeaderAccountContainer() { + const { toast } = useToast() + const [userData, setUserData] = useState(null) + const [isLoggedIn, setLoggedIn] = useState(true) + store.set('jwt', 'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI5Yzg0MzQyYS1lNWQwLTQyYTAtYmE0Yy03OTBhN2E5ODQ2ZDMiLCJpYXQiOjE3MTM1MTcyMjUsImlzcyI6IkJyaWVmIDAzIC0gTWF0aGlzIEhFUlJJT1QiLCJhdWQiOiJ1c2VyIiwiZXhwIjoxNzEzNjAzNjI1fQ.uDXaO4DqcFab5TF0tnDm5FQHhUypXbLH8OQ8U45UUaQ_0zkWZxTO06k4GYCZvGS6qXJ9KW1M8K_BnpgaKyvcGg') + const token = store.get('jwt') + + useEffect(() => { + fetch('http://localhost:3333/auth/me', { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + } + }) + .then((res) => { + console.log(res.status) + if (res.status !== 200) { + toast({ + title: "User not found", + variant: "destructive" + }) + setLoggedIn(false) + return null + } + return res.json() + }) + .then((data: IResMeData | never) => { + // @ts-ignore + setUserData(data) + if (!userData) return; + // @ts-ignore + if (userData?.displayName) setLoggedIn(true) + }) + }, []) + + if (!isLoggedIn && !userData) { + return ( + <> +
+ + +
+ + ) + } + + if (isLoggedIn && userData) { + return ( + <> +
+ + + + + Êvenements + + + { + window.location.href = "/events/new" + }}> + + Créer un êvenement + + { + window.location.href = "/events/subscribed" + }}> + + Mes inscriptions + + { + window.location.href = "/events/owned" + }}> + + Mes êvenements + + + { + window.location.href = "/events" + }}> + + Explorer... + + + + + + + { + //@ts-ignore + userData.displayName + } + + + { + window.location.href = "/account" + }}> + + Mon profil + + { + window.location.href = "/admin" + }}> + + Administration + + + { + store.remove('jwt') + setLoggedIn(false) + setTimeout(()=>{window.location.reload()}, 1_500) + }} className={'gap-1'}> + + Déconnexion + + + + +
+ + ) + } + + return ( + <> + + + ) + +} +export default HeaderAccountContainer; diff --git a/src/components/NewEventForm.tsx b/src/components/NewEventForm.tsx new file mode 100644 index 0000000..500613b --- /dev/null +++ b/src/components/NewEventForm.tsx @@ -0,0 +1,183 @@ +'use client' +import React from 'react' +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import { z } from "zod" +import { Button } from "@/components/ui/button" +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" + +import { Input } from "@/components/ui/input" +import {Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle} from "@/components/ui/card"; + +const formSchema = z.object({ + title: z.string().min(4).max(32), + subTitle: z.string().min(4).max(64), + base64Banner: z.any() + .refine((file: File)=> file?.size < 1_024_000, "Le fichier fait plus de 1Mo"), + desc: z.string().max(128), + date: z.date().min(new Date()), + were: z.string(), + maxMembers: z.number().int() + +}) + +export const NewEventForm = () => { + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + title: "Mon êvenement", + subTitle: "Lorem ipsum dolor..." + }, + }) + function onSubmit(values: z.infer) { + console.log("submit") + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values) + } + return ( + <> + + + Créer un nouvel êvènement + Veuillez saissir tout les champs. + + +
+ { + event.preventDefault() + console.log('p') + form.handleSubmit(onSubmit, ()=>{ + console.log('Invalid')}) + }} className="space-y-8"> + ( + + Titre + + + + + Titre de votre êvenement. + + + + )} + /> + ( + + Sous-titre + + + + + Sous-titre de votre êvenement. + + + + )} + /> + ( + + Bannière + + + + + Image de bannière (1Mo max en jpg) + + + + )} + /> + ( + + Description + + + + + Description de votre êvenement. + + + + )} + /> + ( + + Description + + + + + Date de votre êvenement. + + + + )} + /> +
+ ( + + Lieu + + + + + Lieu de votre êvenement. + + + + )} + /> + ( + + Nb de places + + + + + Lieu de votre êvenement. + + + + )} + /> +
+ + + +
+
+ + ) +} +export default NewEventForm; \ No newline at end of file diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx new file mode 100644 index 0000000..8c90fbc --- /dev/null +++ b/src/components/theme-provider.tsx @@ -0,0 +1,9 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" +import { type ThemeProviderProps } from "next-themes/dist/types" + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} diff --git a/src/components/theme-selector.tsx b/src/components/theme-selector.tsx new file mode 100644 index 0000000..a49687e --- /dev/null +++ b/src/components/theme-selector.tsx @@ -0,0 +1,63 @@ +"use client" + +import * as React from "react" +import { Moon, Sun } from "lucide-react" +import { useTheme } from "next-themes" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip" + +export function ThemeSelector() { + const { setTheme } = useTheme() + //TODO i18n + return ( + + + + + + Theme de couleur + + + setTheme("system")}> + Theme du système + + setTheme("dark")}> + Theme sombre + + setTheme("light")}> + Theme clair + + + + {/* + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + */} + + ) +} \ No newline at end of file diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx new file mode 100644 index 0000000..24c788c --- /dev/null +++ b/src/components/ui/accordion.tsx @@ -0,0 +1,58 @@ +"use client" + +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) + +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..0ba4277 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "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", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx new file mode 100644 index 0000000..2f02434 --- /dev/null +++ b/src/components/ui/calendar.tsx @@ -0,0 +1,66 @@ +"use client" + +import * as React from "react" +import { ChevronLeft, ChevronRight } from "lucide-react" +import { DayPicker } from "react-day-picker" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +export type CalendarProps = React.ComponentProps + +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { + return ( + , + IconRight: ({ ...props }) => , + }} + {...props} + /> + ) +} +Calendar.displayName = "Calendar" + +export { Calendar } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..afa13ec --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..f69a0d6 --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx new file mode 100644 index 0000000..4603f8b --- /dev/null +++ b/src/components/ui/form.tsx @@ -0,0 +1,176 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" +import { + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext, +} from "react-hook-form" + +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" + +const Form = FormProvider + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName +} + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue +) + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +>({ + ...props +}: ControllerProps) => { + return ( + + + + ) +} + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within ") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +} + +type FormItemContextValue = { + id: string +} + +const FormItemContext = React.createContext( + {} as FormItemContextValue +) + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId() + + return ( + +
+ + ) +}) +FormItem.displayName = "FormItem" + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField() + + return ( +