style: login page Okay

This commit is contained in:
Ruben 2025-04-01 19:26:46 +01:00
parent 921007ae13
commit 8c12667693
12 changed files with 367 additions and 173 deletions

View File

@ -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"
}
}

46
pnpm-lock.yaml generated
View File

@ -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

View File

@ -49,7 +49,8 @@ export default function LoginPage() {
})
return (
<div>
<div className="d-flex flex-column bg-bluegray h-100 align-items-center">
<div className="login-main d-flex justify-content-center align-items-center position-relative">
<Form
title="Connexion"
formClassName="bg-white p-10 shadow-2xl w-3/4 lg:w-lg"
@ -70,8 +71,13 @@ export default function LoginPage() {
]}
submit={mutation.mutate}
schema={loginSchema}
child={<button disabled={mutation.isPending} type="submit" className={`${mutation.isPending ? "btn-auth-loading" : "btn-auth"} mt-4`}>{mutation.isPending ? "Chargement..." : "Connexion"}</button>}
child={<div className="d-flex justify-content-center w-100"> <button disabled={mutation.isPending} type="submit" className={`${mutation.isPending ? "btn-auth-loading" : "btn-auth"} cta modal-cta`}>{mutation.isPending ? "Chargement..." : "Connexion"}</button></div>}
/>
</div>
<div className="version">
<p className="fw-bold" >Version 0.0.1</p>
</div>
</div>
)
}

View File

@ -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;
}
@ -35,9 +33,12 @@
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,6 +111,11 @@ body {
transition: width 0.2s, height 0.2s;
}
button {
background-color: transparent;
border: none;
}
.cta {
padding: 10px 24px;
width: max-content;
@ -117,8 +131,9 @@ body {
}
.cta.modal-cta {
padding: 9px;
margin-top: 32px;
width: 240px;
height: 40px;
}
.cta.cancel {
@ -141,9 +156,11 @@ body {
.bg-bluegray {
background-color: var(--bluegray);
}
.bg-gray {
background-color: var(--gray);
}
hr {
color: var(--gray);
}
@ -189,7 +206,7 @@ input[type="checkbox"]:checked::before {
/* Scroll Bar */
::-webkit-scrollbar {
width: 4px;
width: 7px;
padding: 0;
margin: 0;
}
@ -225,3 +242,94 @@ input[type="checkbox"]:checked::before {
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;
}
}

View File

@ -21,6 +21,8 @@ export default function RootLayout({
<head>
<link rel="icon" href="/favicon.svg" />
<link rel="favicon.svg" href="/favicon.svg" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossOrigin="anonymous"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossOrigin="anonymous"></script>
</head>
<body>
<AuthProvider>

View File

@ -0,0 +1,16 @@
import React from "react";
//import { GeneralHtmlAttr } from "@/lib/declarations";
//export type GeneralHtmlAttr = React.HTMLAttributes<HTMLDivElement>;
import L from "leaflet";
export const HomeIcon = (props) => {
return (
<div {...props}>
<svg width="22" height="21" viewBox="0 0 22 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.25 11L10.205 2.045C10.3094 1.94056 10.4333 1.85772 10.5697 1.80119C10.7061 1.74467 10.8523 1.71558 11 1.71558C11.1477 1.71558 11.2939 1.74467 11.4303 1.80119C11.5667 1.85772 11.6906 1.94056 11.795 2.045L20.75 11M3.5 8.75V18.875C3.5 19.496 4.004 20 4.625 20H8.75V15.125C8.75 14.504 9.254 14 9.875 14H12.125C12.746 14 13.25 14.504 13.25 15.125V20H17.375C17.996 20 18.5 19.496 18.5 18.875V8.75M7.25 20H15.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
);
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 462 KiB

View File

@ -30,7 +30,7 @@ export default function FloatingLabelInput({
switch(type) {
case 'select':
return (
<div className="relative w-full">
<div className="position-relative w-full">
<select
className="input-form modal-input focus:ring-2 focus:ring-blue-500 outline-none"
name={name}
@ -46,7 +46,7 @@ export default function FloatingLabelInput({
case 'password':
return (
<div className="relative w-full">
<div className="position-relative w-full">
<input
name={name}
type={showPassword ? "text" : "password"}
@ -66,14 +66,14 @@ export default function FloatingLabelInput({
src={icons.eyeSlashIcon}
width={20}
height={20}
alt=''
alt='show password'
/>
) : (
<Image
src={icons.eyeIcon}
width={20}
height={20}
alt=''
alt='hide password'
/>
)}
</button>
@ -84,7 +84,7 @@ export default function FloatingLabelInput({
case 'search':
return (
<div className="relative w-full">
<div className="position-relative w-full">
<div className='btn-floating-left'>
<Image alt='' src={icons.searchIcon} />
</div>
@ -102,7 +102,7 @@ export default function FloatingLabelInput({
default:
return (
<div className="relative w-full">
<div className="position-relative w-full">
<input
type={type}
placeholder={placeholder}
@ -118,7 +118,7 @@ export default function FloatingLabelInput({
};
return (
<div className="relative">
<div className="position-relative">
<label
htmlFor={name}
className="input-label text-gray-400 text-sm"

View File

@ -43,12 +43,12 @@ export default function Form({
}
return (
<form onSubmit={handleSubmit} className={formClassName}>
<div className="flex justify-center text-black">
<p className="text-3xl font-bold">{title}</p>
<form onSubmit={handleSubmit} className={(formClassName) + " form-container"}>
<div className="form-title d-flex justify-content-center text-black mb-3 ">
<p className="fs-3 fw-bold">{title}</p>
</div>
<div className={`space-y-8 my-2 ${className}`}>
<div className={`d-flex flex-column form-fields ${className}`}>
{
fields.map((item, index) => (
@ -64,13 +64,12 @@ export default function Form({
showPasswordToggle={item.showPasswordToggle}
/>
<span className="text-red-500 text-xs mt-1">{errors[item.name]}</span>
<span className="form-error">{errors[item.name]}</span>
</div>
))
}
</div>
{child}
</form>
)
}

View File

@ -3,14 +3,16 @@ import Image from "next/image";
export default function Header() {
return (
<div className="w-full bg-white shadow-md py-4">
<div className="container mx-auto text-center flex items-center justify-center gap-2">
<div className="d-flex justify-content-center login-header ">
<div className="d-flex justify-content-center align-items-center gap-2">
<Image
src={icons.logo}
alt="Private Docs"
className="text-red-500 h-auto"
height={30}
/>
<p className="text-2xl font-bold text-black">Private Docs</p>
{/* <p className="text-2xl font-bold text-black">Private Docs</p> */}
<p className="r-p-m-0 word">Pr<span className="dot"></span>ıvate Docs</p>
</div>
</div>
)

View File

@ -0,0 +1,9 @@
"use client";
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
export default function Layout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}

View File

@ -23,6 +23,6 @@
"@/*": ["./src/*"]
}
},
"include": ["svgr.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": ["svgr.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/assets/icons/final-index.js"],
"exclude": ["node_modules"]
}