From 8c126676930355858a7ea1dc4b9f62e18c1862bd Mon Sep 17 00:00:00 2001 From: Ruben Date: Tue, 1 Apr 2025 19:26:46 +0100 Subject: [PATCH] style: login page Okay --- package.json | 5 +- pnpm-lock.yaml | 46 +++++++- src/app/(auth)/login/page.tsx | 134 ++++++++++----------- src/app/globals.css | 160 +++++++++++++++++++++----- src/app/layout.tsx | 2 + src/assets/icons/final-index.tsx | 16 +++ src/assets/icons/full-logo.svg | 9 ++ src/components/floatingLabelInput.tsx | 14 +-- src/components/form/form.tsx | 117 ++++++++++--------- src/components/header.tsx | 26 +++-- src/lib/bootstrapLoader.tsx | 9 ++ tsconfig.json | 2 +- 12 files changed, 367 insertions(+), 173 deletions(-) create mode 100644 src/assets/icons/final-index.tsx create mode 100644 src/assets/icons/full-logo.svg create mode 100644 src/lib/bootstrapLoader.tsx diff --git a/package.json b/package.json index 9d131ca..f90a0f5 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,11 @@ "@tanstack/react-query": "^5.69.0", "@tanstack/react-table": "^8.21.2", "axios": "^1.8.4", + "bootstrap": "^5.3.3", "clsx": "^2.1.1", + "declarations": "link:@/lib/declarations", "jwt-decode": "^4.0.0", + "leaflet": "^1.9.4", "next": "15.2.3", "next-auth": "^4.24.11", "nextjs-toploader": "^3.8.15", @@ -32,6 +35,7 @@ "@eslint/eslintrc": "^3", "@svgr/webpack": "^8.1.0", "@tailwindcss/postcss": "^4", + "@types/leaflet": "^1.9.17", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -39,7 +43,6 @@ "eslint-config-next": "15.2.3", "install": "^0.13.0", "npm": "^11.2.0", - "tailwindcss": "^4", "typescript": "^5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fab4d4..6bab45e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,12 +23,21 @@ importers: axios: specifier: ^1.8.4 version: 1.8.4 + bootstrap: + specifier: ^5.3.3 + version: 5.3.3(@popperjs/core@2.11.8) clsx: specifier: ^2.1.1 version: 2.1.1 + declarations: + specifier: link:@/lib/declarations + version: link:@/lib/declarations jwt-decode: specifier: ^4.0.0 version: 4.0.0 + leaflet: + specifier: ^1.9.4 + version: 1.9.4 next: specifier: 15.2.3 version: 15.2.3(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.86.0) @@ -72,6 +81,9 @@ importers: '@tailwindcss/postcss': specifier: ^4 version: 4.0.15 + '@types/leaflet': + specifier: ^1.9.17 + version: 1.9.17 '@types/node': specifier: ^20 version: 20.17.27 @@ -93,9 +105,6 @@ importers: npm: specifier: ^11.2.0 version: 11.2.0 - tailwindcss: - specifier: ^4 - version: 4.0.15 typescript: specifier: ^5 version: 5.8.2 @@ -1018,6 +1027,9 @@ packages: resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@radix-ui/colors@3.0.0': resolution: {integrity: sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==} @@ -1875,12 +1887,18 @@ packages: '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/leaflet@1.9.17': + resolution: {integrity: sha512-IJ4K6t7I3Fh5qXbQ1uwL3CFVbCi6haW9+53oLWgdKlLP7EaS21byWFJxxqOx9y8I0AP0actXSJLVMbyvxhkUTA==} + '@types/node@20.17.27': resolution: {integrity: sha512-U58sbKhDrthHlxHRJw7ZLiLDZGmAUOZUbpw0S6nL27sYUdhvgBLCRu/keSd6qcTsfArd1sRFCCBxzWATGr/0UA==} @@ -2100,6 +2118,11 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bootstrap@5.3.3: + resolution: {integrity: sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==} + peerDependencies: + '@popperjs/core': ^2.11.8 + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -2845,6 +2868,9 @@ packages: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} engines: {node: '>=0.10'} + leaflet@1.9.4: + resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -4716,6 +4742,8 @@ snapshots: '@parcel/watcher-win32-x64': 2.5.1 optional: true + '@popperjs/core@2.11.8': {} + '@radix-ui/colors@3.0.0': {} '@radix-ui/number@1.1.0': {} @@ -5614,10 +5642,16 @@ snapshots: '@types/estree@1.0.7': {} + '@types/geojson@7946.0.16': {} + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} + '@types/leaflet@1.9.17': + dependencies: + '@types/geojson': 7946.0.16 + '@types/node@20.17.27': dependencies: undici-types: 6.19.8 @@ -5882,6 +5916,10 @@ snapshots: boolbase@1.0.0: {} + bootstrap@5.3.3(@popperjs/core@2.11.8): + dependencies: + '@popperjs/core': 2.11.8 + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -6765,6 +6803,8 @@ snapshots: dependencies: language-subtag-registry: 0.3.23 + leaflet@1.9.4: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index 1bf1293..5246d7c 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -7,71 +7,77 @@ import { signIn } from "next-auth/react" import { useRouter, useSearchParams } from "next/navigation"; export default function LoginPage() { - const router = useRouter() - const params = useSearchParams().get("redirect_to"); + const router = useRouter() + const params = useSearchParams().get("redirect_to"); - const mutation = useMutation({ - mutationKey: ['login'], - mutationFn: async (data: { email: string; password: string }) => { - try { - const result = await signIn("credentials", { - email: data.email, - password: data.password, - redirect: false, - }) - - if (result?.error) { - const errorMessage = result.error.includes("CredentialsSignin") - ? "Email ou mot de passe incorrect" - : result.error; - console.error(errorMessage) - throw new Error(result.error) - } else { - if (params) { - router.push(params); - } else { - router.push('/admin/home') - } - } - return result - } catch (error: unknown) { - if (error instanceof Error && error.message.includes("Network Error")) { - console.error("Problème de connexion au serveur"); - } - console.error("Autre = ", error); - } - + const mutation = useMutation({ + mutationKey: ['login'], + mutationFn: async (data: { email: string; password: string }) => { + try { + const result = await signIn("credentials", { + email: data.email, + password: data.password, + redirect: false, + }) - }, - onError: (error: Error) => { - console.error(error.message) - }, - }) + if (result?.error) { + const errorMessage = result.error.includes("CredentialsSignin") + ? "Email ou mot de passe incorrect" + : result.error; + console.error(errorMessage) + throw new Error(result.error) + } else { + if (params) { + router.push(params); + } else { + router.push('/admin/home') + } + } + return result + } catch (error: unknown) { + if (error instanceof Error && error.message.includes("Network Error")) { + console.error("Problème de connexion au serveur"); + } + console.error("Autre = ", error); + } - return( -
-
{mutation.isPending ? "Chargement..." : "Connexion"}} - /> -
- ) + + }, + onError: (error: Error) => { + console.error(error.message) + }, + }) + + return ( +
+
+
} + /> +
+
+

Version 0.0.1

+
+ + + ) } \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 627de23..23a2526 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,8 +1,6 @@ -@import "tailwindcss"; - @font-face { - font-family: 'Urbanist'; /* Nom que vous donnerez à votre police */ - src: url('../assets/fonts/Urbanist.ttf') format('truetype'); /* Chemin vers votre fichier */ + font-family: 'Urbanist'; + src: url('../assets/fonts/Urbanist.ttf') format('truetype'); font-weight: normal; font-style: normal; } @@ -29,15 +27,18 @@ --background: #ffffff; --cinder: #999; --bluegray: --primary; -} + } } body { background: var(--background); color: var(--foreground); - font-family: Urbanist, sans-serif; + font-family: Urbanist, sans-serif !important; +} +*{ + margin: 0; + padding: 0; } - .input-form { width: 100%; padding: 12px; @@ -54,14 +55,22 @@ body { position: absolute; left: 12px; top: -0.45rem; - background-color: white; - padding-inline: 4px; + padding: 1px 5px; + line-height: normal; + color: var(--secondary); + background-color: var(--background); + border-radius: 400px; z-index: 1; } +.form-error { + font-size: 14px; + color: var(--danger); +} + .btn-floating-right { position: absolute; - right: 8px; + right: 12px; top: 50%; transform: translateY(-50%); } @@ -102,7 +111,12 @@ body { transition: width 0.2s, height 0.2s; } -.cta{ +button { + background-color: transparent; + border: none; +} + +.cta { padding: 10px 24px; width: max-content; height: max-content; @@ -116,35 +130,38 @@ body { text-wrap: nowrap; } -.cta.modal-cta{ +.cta.modal-cta { + padding: 9px; + margin-top: 32px; width: 240px; - height: 40px; } -.cta.cancel{ +.cta.cancel { color: var(--secondary); border: 1px solid var(--gray); background-color: var(--gray); } -.cta.info{ +.cta.info { color: var(--primary); background-color: var(--background); } -.cta.danger{ +.cta.danger { border: 1px solid var(--danger); background-color: var(--danger); } -.bg-bluegray{ +.bg-bluegray { background-color: var(--bluegray); } -.bg-gray{ + +.bg-gray { background-color: var(--gray); } -hr{ + +hr { color: var(--gray); } @@ -155,10 +172,10 @@ input[type="checkbox"] { width: 24px; height: 24px; - border: 1px solid var(--secondary) !important; - border-radius: 6px !important; - background-color: transparent; - cursor: pointer; + border: 1px solid var(--secondary) !important; + border-radius: 6px !important; + background-color: transparent; + cursor: pointer; position: relative; } @@ -170,7 +187,7 @@ input[type="checkbox"]:checked { input[type="checkbox"]:checked::before { - content: "✔"; + content: "✔"; font-size: 18px; color: white; position: absolute; @@ -179,7 +196,7 @@ input[type="checkbox"]:checked::before { transform: translate(-50%, -50%); } -.modal-input{ +.modal-input { width: 490px; margin-left: auto; margin-right: auto; @@ -189,7 +206,7 @@ input[type="checkbox"]:checked::before { /* Scroll Bar */ ::-webkit-scrollbar { - width: 4px; + width: 7px; padding: 0; margin: 0; } @@ -224,4 +241,95 @@ input[type="checkbox"]:checked::before { width: 16px; height: 16px; } +} + + + + +/* Login Header */ +.login-header { + padding: 20px 0; + box-shadow: 0 0 24px #0000001A; +} + +.word { + font-size: 24px; + font-weight: bold; + color: black; + position: relative; + line-height: normal; +} + +.dot { + /* font-size: 14px; */ + color: blue; + position: absolute; + top: -10px; + left: 22px; + animation: bounce 1s infinite ease-in-out; +} + +@keyframes bounce { + + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-3px); + } +} + +.login-main { + min-height: 100vh; +} + + +.form-container { + padding: 48px 64px; + margin: auto; + width: max-content; + max-width: 624px; + border-radius: 8px; + box-shadow: 0 0 24px #0000001A; +} + +.form-fields { + gap: 24px; +} + + + + +@media (max-width: 768px) { + + + .login-main{ + width: 100%; + } + .form-container { + padding: 24px 32px; + margin: 0 4%; + width: 80%; + } + + .form-fields { + gap: 12px; + } + + .modal-input { + width: 100%; + min-width: 100%; + } + .form-title{ + margin-bottom: 2px!important; + } + + .cta.modal-cta{ + margin: 0!important; + } + .input-form{ + margin: 0 auto; + } } \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ba57bb2..6f913f0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -21,6 +21,8 @@ export default function RootLayout({ + + diff --git a/src/assets/icons/final-index.tsx b/src/assets/icons/final-index.tsx new file mode 100644 index 0000000..c2f7c53 --- /dev/null +++ b/src/assets/icons/final-index.tsx @@ -0,0 +1,16 @@ +import React from "react"; + +//import { GeneralHtmlAttr } from "@/lib/declarations"; +//export type GeneralHtmlAttr = React.HTMLAttributes; + +import L from "leaflet"; + +export const HomeIcon = (props) => { + return ( +
+ + + +
+ ); +} \ No newline at end of file diff --git a/src/assets/icons/full-logo.svg b/src/assets/icons/full-logo.svg new file mode 100644 index 0000000..49ab970 --- /dev/null +++ b/src/assets/icons/full-logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/floatingLabelInput.tsx b/src/components/floatingLabelInput.tsx index 8e3b1e8..37499f8 100644 --- a/src/components/floatingLabelInput.tsx +++ b/src/components/floatingLabelInput.tsx @@ -30,7 +30,7 @@ export default function FloatingLabelInput({ switch(type) { case 'select': return ( -
+
) : ( )} @@ -84,7 +84,7 @@ export default function FloatingLabelInput({ case 'search': return ( -
+
@@ -102,7 +102,7 @@ export default function FloatingLabelInput({ default: return ( -
+
+