From 4936b132ae1dac2bb1b6dc20a44000103b270f34 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 15:23:54 +0200 Subject: [PATCH 01/19] rollback css global.css --- frontend/src/styles/globals.css | 1671 ++----------------------------- 1 file changed, 58 insertions(+), 1613 deletions(-) diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index 70722ae8..a871195b 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -1,1405 +1,32 @@ -/* -! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com -*/ - -/* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { - box-sizing: border-box; - /* 1 */ - border-width: 0; - /* 2 */ - border-style: solid; - /* 2 */ - border-color: #e5e7eb; - /* 2 */ -} - -::before, -::after { - --tw-content: ''; -} - -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -6. Use the user's configured `sans` font-variation-settings by default. -7. Disable tap highlights on iOS -*/ - -html, -:host { - line-height: 1.5; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -moz-tab-size: 4; - /* 3 */ - -o-tab-size: 4; - tab-size: 4; - /* 3 */ - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - /* 4 */ - font-feature-settings: normal; - /* 5 */ - font-variation-settings: normal; - /* 6 */ - -webkit-tap-highlight-color: transparent; - /* 7 */ -} - -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - -body { - margin: 0; - /* 1 */ - line-height: inherit; - /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; - /* 1 */ - color: inherit; - /* 2 */ - border-top-width: 1px; - /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font-family by default. -2. Use the user's configured `mono` font-feature-settings by default. -3. Use the user's configured `mono` font-variation-settings by default. -4. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - /* 1 */ - font-feature-settings: normal; - /* 2 */ - font-variation-settings: normal; - /* 3 */ - font-size: 1em; - /* 4 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; - /* 1 */ - border-color: inherit; - /* 2 */ - border-collapse: collapse; - /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - /* 1 */ - font-feature-settings: inherit; - /* 1 */ - font-variation-settings: inherit; - /* 1 */ - font-size: 100%; - /* 1 */ - font-weight: inherit; - /* 1 */ - line-height: inherit; - /* 1 */ - letter-spacing: inherit; - /* 1 */ - color: inherit; - /* 1 */ - margin: 0; - /* 2 */ - padding: 0; - /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -input:where([type='button']), -input:where([type='reset']), -input:where([type='submit']) { - -webkit-appearance: button; - /* 1 */ - background-color: transparent; - /* 2 */ - background-image: none; - /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; - /* 1 */ - outline-offset: -2px; - /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; - /* 1 */ - font: inherit; - /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Reset default styling for dialogs. -*/ - -dialog { - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -input::placeholder, -textarea::placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ - -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; - /* 1 */ - vertical-align: middle; - /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ - -[hidden] { - display: none; -} - -*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -.container { - width: 100%; -} - -@media (min-width: 640px) { - .container { - max-width: 640px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 768px; - } -} - -@media (min-width: 1024px) { - .container { - max-width: 1024px; - } -} - -@media (min-width: 1280px) { - .container { - max-width: 1280px; - } -} - -@media (min-width: 1536px) { - .container { - max-width: 1536px; - } -} - -.fixed { - position: fixed; -} - -.absolute { - position: absolute; -} - -.relative { - position: relative; -} - -.inset-0 { - inset: 0px; -} - -.inset-y-0 { - top: 0px; - bottom: 0px; -} - -.left-0 { - left: 0px; -} - -.left-1\/2 { - left: 50%; -} - -.right-0 { - right: 0px; -} - -.top-0 { - top: 0px; -} - -.top-1\/2 { - top: 50%; -} - -.z-10 { - z-index: 10; -} - -.z-20 { - z-index: 20; -} - -.z-40 { - z-index: 40; -} - -.z-50 { - z-index: 50; -} - -.m-1 { - margin: 0.25rem; -} - -.m-2 { - margin: 0.5rem; -} - -.m-3 { - margin: 0.75rem; -} - -.m-4 { - margin: 1rem; -} - -.m-5 { - margin: 1.25rem; -} - -.m-\[3\%\] { - margin: 3%; -} - -.mx-4 { - margin-left: 1rem; - margin-right: 1rem; -} - -.mx-auto { - margin-left: auto; - margin-right: auto; -} - -.-ms-\[5px\] { - margin-inline-start: -5px; -} - -.mb-1 { - margin-bottom: 0.25rem; -} - -.mb-2 { - margin-bottom: 0.5rem; -} - -.mb-4 { - margin-bottom: 1rem; -} - -.mb-6 { - margin-bottom: 1.5rem; -} - -.mb-\[0\.25rem\] { - margin-bottom: 0.25rem; -} - -.mb-\[5\%\] { - margin-bottom: 5%; -} - -.me-3 { - margin-inline-end: 0.75rem; -} - -.ml-1 { - margin-left: 0.25rem; -} - -.ml-14 { - margin-left: 3.5rem; -} - -.ml-2 { - margin-left: 0.5rem; -} - -.ml-3 { - margin-left: 0.75rem; -} - -.ml-6 { - margin-left: 1.5rem; -} - -.mr-2 { - margin-right: 0.5rem; -} - -.mr-3 { - margin-right: 0.75rem; -} - -.mr-3\.5 { - margin-right: 0.875rem; -} - -.mr-4 { - margin-right: 1rem; -} - -.ms-4 { - margin-inline-start: 1rem; -} - -.mt-2 { - margin-top: 0.5rem; -} - -.mt-4 { - margin-top: 1rem; -} - -.mt-5 { - margin-top: 1.25rem; -} - -.mt-8 { - margin-top: 2rem; -} - -.mt-\[-2\%\] { - margin-top: -2%; -} - -.mt-\[1\%\] { - margin-top: 1%; -} - -.mt-\[4\%\] { - margin-top: 4%; -} - -.mt-\[5\%\] { - margin-top: 5%; -} - -.mt-\[10\%\] { - margin-top: 10%; -} - -.mt-\[50\%\] { - margin-top: 50%; -} - -.mt-3 { - margin-top: 0.75rem; -} - -.mt-10 { - margin-top: 2.5rem; -} - -.block { - display: block; -} - -.inline-block { - display: inline-block; -} - -.flex { - display: flex; -} - -.hidden { - display: none; -} - -.h-1\/2 { - height: 50%; -} - -.h-40 { - height: 10rem; -} - -.h-52 { - height: 13rem; -} - -.h-6 { - height: 1.5rem; -} - -.h-\[100\%\] { - height: 100%; -} - -.h-\[170px\] { - height: 170px; -} - -.h-\[460px\] { - height: 460px; -} - -.h-\[9px\] { - height: 9px; -} - -.h-\[calc\(100vh-xpx\)\] { - height: calc(100vh - xpx); -} - -.h-auto { - height: auto; -} - -.h-full { - height: 100%; -} - -.h-screen { - height: 100vh; -} - -.max-h-0 { - max-height: 0px; -} - -.w-12 { - width: 3rem; -} - -.w-40 { - width: 10rem; -} - -.w-6 { - width: 1.5rem; -} - -.w-64 { - width: 16rem; -} - -.w-\[100\%\] { - width: 100%; -} - -.w-\[100vh\] { - width: 100vh; -} - -.w-\[25px\] { - width: 25px; -} - -.w-\[350px\] { - width: 350px; -} - -.w-\[9px\] { - width: 9px; -} - -.w-full { - width: 100%; -} - -.max-w-7xl { - max-width: 80rem; -} - -.max-w-\[160px\] { - max-width: 160px; -} - -.max-w-\[210px\] { - max-width: 210px; -} - -.max-w-\[310px\] { - max-width: 310px; -} - -.max-w-md { - max-width: 28rem; -} - -.flex-1 { - flex: 1 1 0%; -} - -.flex-shrink-0 { - flex-shrink: 0; -} - -.flex-grow { - flex-grow: 1; -} - -.-translate-x-1\/2 { - --tw-translate-x: -50%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.-translate-y-1\/2 { - --tw-translate-y: -50%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.translate-x-full { - --tw-translate-x: 100%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.rotate-180 { - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.transform { - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.cursor-not-allowed { - cursor: not-allowed; -} - -.cursor-pointer { - cursor: pointer; -} - -.resize { - resize: both; -} - -.flex-row { - flex-direction: row; -} - -.flex-col { - flex-direction: column; -} - -.flex-col-reverse { - flex-direction: column-reverse; -} - -.flex-wrap { - flex-wrap: wrap; -} - -.flex-wrap-reverse { - flex-wrap: wrap-reverse; -} - -.items-center { - align-items: center; -} - -.justify-center { - justify-content: center; -} - -.justify-between { - justify-content: space-between; -} - -.justify-around { - justify-content: space-around; -} - -.space-x-3 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(0.75rem * var(--tw-space-x-reverse)); - margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1rem * var(--tw-space-x-reverse)); - margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-5 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1.25rem * var(--tw-space-x-reverse)); - margin-left: calc(1.25rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-y-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1rem * var(--tw-space-y-reverse)); -} - -.space-y-6 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); -} - -.overflow-hidden { - overflow: hidden; -} - -.overflow-x-auto { - overflow-x: auto; -} - -.overflow-y-auto { - overflow-y: auto; -} - -.overflow-y-hidden { - overflow-y: hidden; -} - -.whitespace-nowrap { - white-space: nowrap; -} - -.rounded-full { - border-radius: 9999px; -} - -.rounded-lg { - border-radius: 0.5rem; -} - -.rounded-md { - border-radius: 0.375rem; -} - -.border { - border-width: 1px; -} - -.border-4 { - border-width: 4px; -} - -.border-s { - border-inline-start-width: 1px; -} - -.border-none { - border-style: none; -} - -.border-gray-300 { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); -} - -.border-primary { - border-color: var(--primary-color); -} - -.border-secondary { - border-color: var(--secondary-color); -} - -.bg-black { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); -} - -.bg-body { - background-color: var(--body-color); -} - -.bg-footer { - background-color: var(--footer-color); -} - -.bg-gray-300 { - --tw-bg-opacity: 1; - background-color: rgb(209 213 219 / var(--tw-bg-opacity)); -} - -.bg-primary { - background-color: var(--primary-color); -} - -.bg-white { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); -} - -.object-cover { - -o-object-fit: cover; - object-fit: cover; -} - -.p-0 { - padding: 0px; -} - -.p-1 { - padding: 0.25rem; -} - -.p-4 { - padding: 1rem; -} - -.p-5 { - padding: 1.25rem; -} - -.p-6 { - padding: 1.5rem; -} - -.p-8 { - padding: 2rem; -} - -.px-4 { - padding-left: 1rem; - padding-right: 1rem; -} - -.px-5 { - padding-left: 1.25rem; - padding-right: 1.25rem; -} - -.py-1 { - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} - -.py-4 { - padding-top: 1rem; - padding-bottom: 1rem; -} - -.py-6 { - padding-top: 1.5rem; - padding-bottom: 1.5rem; -} - -.pb-2 { - padding-bottom: 0.5rem; -} - -.pb-5 { - padding-bottom: 1.25rem; -} - -.pb-\[0\.25rem\] { - padding-bottom: 0.25rem; -} - -.pt-0 { - padding-top: 0px; -} - -.pt-0\.5 { - padding-top: 0.125rem; -} - -.pt-2 { - padding-top: 0.5rem; -} - -.pt-3 { - padding-top: 0.75rem; -} - -.text-center { - text-align: center; -} - -.text-2xl { - font-size: 1.5rem; - line-height: 2rem; -} - -.text-4xl { - font-size: 2.25rem; - line-height: 2.5rem; -} - -.text-lg { - font-size: 1.125rem; - line-height: 1.75rem; -} - -.text-sm { - font-size: 0.875rem; - line-height: 1.25rem; -} - -.text-xl { - font-size: 1.25rem; - line-height: 1.75rem; -} - -.text-xs { - font-size: 0.75rem; - line-height: 1rem; -} - -.font-bold { - font-weight: 700; -} - -.font-semibold { - font-weight: 600; -} - -.leading-normal { - line-height: 1.5; -} - -.text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} - -.text-primary { - color: var(--primary-color); -} - -.text-secondary { - color: var(--secondary-color); -} - -.text-text { - color: var(--text-color); -} - -.text-text200 { - color: var(--text200-color); -} - -.text-text300 { - color: var(--text300-color); -} - -.text-textButton { - color: var(--textButton-color); -} - -.text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} - -.opacity-0 { - opacity: 0; -} - -.opacity-100 { - opacity: 1; -} - -.opacity-50 { - opacity: 0.5; -} - -.opacity-\[50\%\] { - opacity: 50%; -} - -.shadow { - --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-inner { - --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-lg { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-md { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.outline { - outline-style: solid; -} - -.blur { - --tw-blur: blur(8px); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.filter { - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.transition { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-opacity { - transition-property: opacity; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-transform { - transition-property: transform; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.duration-300 { - transition-duration: 300ms; -} - -.duration-500 { - transition-duration: 500ms; -} - -.ease-in-out { - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -} +@tailwind base; +@tailwind components; +@tailwind utilities; :root { - --primary-color: #B45852; - --secondary-color: #DFBB5F; - --scrollHandle-color: #19252E; - --scrollHandleHover-color: #162028; - --body-color: #01031B; - --grey-color: #7F7F7F; - --placeholder-color: #A0AEC0; - --text-color: #ffffff; - --text100-color: #030303; - --text200-color: #B2BDCC; - --text300-color: #64748b; - --textButton-color: white; - --success-color: #1C8036; - --error-color: #AA2020; - --warn-color: #EBCC2A; - --info-color: #3B89FF; - --footer-color: #050F1A; + --primary-color: #B45852; + --secondary-color: #DFBB5F; + --scrollHandle-color: #19252E; + --scrollHandleHover-color: #162028; + --body-color: #01031B; + --grey-color: #7F7F7F; + --placeholder-color: #A0AEC0; + --text-color: #ffffff; + --text100-color: #030303; + --text200-color: #B2BDCC; + --text300-color: #64748b; + --textButton-color: white; + --success-color: #1C8036; + --error-color: #AA2020; + --warn-color: #EBCC2A; + --info-color: #3B89FF; + --footer-color: #050F1A; } body { background-color: var(--body-color); } + /* .custom-scrollbar::-webkit-scrollbar { display: none; color: red; @@ -1411,63 +38,57 @@ body { } */ /* Cacher la barre de défilement par défaut */ - .custom-scrollbar { - overflow-y: hidden; - /* Désactiver le défilement vertical */ + overflow-y: hidden; /* Désactiver le défilement vertical */ } .custom-scrollbar:hover { - overflow-y: auto; - /* Activer le défilement vertical au survol */ + overflow-y: auto; /* Activer le défilement vertical au survol */ } .custom-scrollbar::-webkit-scrollbar { - width: 0; - /* Masquer la barre de défilement */ + width: 0; /* Masquer la barre de défilement */ height: 0; } .custom-scrollbar:hover::-webkit-scrollbar { - width: 2px; - /* Afficher la barre de défilement au survol */ + width: 2px; /* Afficher la barre de défilement au survol */ height: 2px; } -@keyframes expandOpen { - from { - opacity: 0; - max-height: 0; - } - - to { - opacity: 1; - max-height: 500px; - } -} - -@keyframes expandClose { - from { - opacity: 1; - max-height: 500px; - } - - to { - opacity: 0; - max-height: 0; - } -} - -.expanded-animation-open { - animation: expandOpen 1.0s ease-in-out forwards; -} - -.expanded-animation-close { - animation: expandClose 1.0s ease-in-out forwards; -} -.MuiCardContent-root { - padding: 0px; +@keyframes expandOpen { + from { + opacity: 0; + max-height: 0; + } + to { + opacity: 1; + max-height: 500px; + } + } + + @keyframes expandClose { + from { + opacity: 1; + max-height: 500px; + } + to { + opacity: 0; + max-height: 0; + } + } + + .expanded-animation-open { + animation: expandOpen 1.0s ease-in-out forwards; + } + + .expanded-animation-close { + animation: expandClose 1.0s ease-in-out forwards; + } + + .MuiCardContent-root { + padding: 0px; } ::-webkit-scrollbar { @@ -1519,8 +140,7 @@ body { .custom-video { width: 310px; height: 170px; - -o-object-fit: cover; - object-fit: cover; + object-fit: cover; } .Toastify__toast-container { @@ -1552,179 +172,4 @@ body { .Toastify__toast--info .Toastify__close-button, .Toastify__toast--warn .Toastify__close-button { color: var(--text-button-color); -} - -.hover\:bg-secondary:hover { - background-color: var(--secondary-color); -} - -.hover\:text-secondary:hover { - color: var(--secondary-color); -} - -.hover\:text-text100:hover { - color: var(--text100-color); -} - -.hover\:opacity-\[75\%\]:hover { - opacity: 75%; -} - -.focus\:outline-none:focus { - outline: 2px solid transparent; - outline-offset: 2px; -} - -@media (min-width: 640px) { - .sm\:ml-3 { - margin-left: 0.75rem; - } - - .sm\:max-w-\[80\%\] { - max-width: 80%; - } - - .sm\:max-w-\[90\%\] { - max-width: 90%; - } -} - -@media (min-width: 768px) { - .md\:-mt-\[5px\] { - margin-top: -5px; - } - - .md\:mb-0 { - margin-bottom: 0px; - } - - .md\:me-0 { - margin-inline-end: 0px; - } - - .md\:ml-4 { - margin-left: 1rem; - } - - .md\:ms-0 { - margin-inline-start: 0px; - } - - .md\:block { - display: block; - } - - .md\:inline-block { - display: inline-block; - } - - .md\:inline { - display: inline; - } - - .md\:flex { - display: flex; - } - - .md\:hidden { - display: none; - } - - .md\:w-1\/2 { - width: 50%; - } - - .md\:w-\[70\%\] { - width: 70%; - } - - .md\:max-w-\[60\%\] { - max-width: 60%; - } - - .md\:max-w-\[75\%\] { - max-width: 75%; - } - - .md\:justify-center { - justify-content: center; - } - - .md\:gap-6 { - gap: 1.5rem; - } - - .md\:border-s-0 { - border-inline-start-width: 0px; - } - - .md\:border-t { - border-top-width: 1px; - } - - .md\:pt-0 { - padding-top: 0px; - } - - .md\:text-base { - font-size: 1rem; - line-height: 1.5rem; - } -} - -@media (min-width: 1024px) { - .lg\:ml-6 { - margin-left: 1.5rem; - } - - .lg\:block { - display: block; - } - - .lg\:inline-block { - display: inline-block; - } - - .lg\:hidden { - display: none; - } - - .lg\:w-\[70\%\] { - width: 70%; - } - - .lg\:max-w-\[50\%\] { - max-width: 50%; - } - - .lg\:max-w-\[60\%\] { - max-width: 60%; - } - - .lg\:text-6xl { - font-size: 3.75rem; - line-height: 1; - } -} - -@media (min-width: 1280px) { - .xl\:block { - display: block; - } - - .xl\:hidden { - display: none; - } - - .xl\:max-w-\[35\%\] { - max-width: 35%; - } - - .xl\:max-w-\[40\%\] { - max-width: 40%; - } - - .xl\:max-w-\[50\%\] { - max-width: 50%; - } } \ No newline at end of file From b39fd4d1a6b043b6a565fa7da46ec5e58d673c17 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 17:50:32 +0200 Subject: [PATCH 02/19] fixed midleware redirect page, add test page auth/login add page test toto and fixed build css tailwind --- frontend/Dockerfile | 6 +- frontend/package-lock.json | 130 +- frontend/package.json | 3 + frontend/src/middleware.ts | 82 +- frontend/src/pages/404.tsx | 9 +- frontend/src/pages/admin/auth/login.tsx | 5 + frontend/src/pages/toto.tsx | 22 + frontend/src/styles/output.css | 1731 +---------------------- 8 files changed, 230 insertions(+), 1758 deletions(-) create mode 100644 frontend/src/pages/admin/auth/login.tsx create mode 100644 frontend/src/pages/toto.tsx diff --git a/frontend/Dockerfile b/frontend/Dockerfile index b6879ac4..72bb043f 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -17,10 +17,10 @@ ENV NEXT_PUBLIC_API_TOKEN=${NEXT_PUBLIC_API_TOKEN} ARG NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} -# CMD npm run dev +CMD npm run dev -RUN npm run build -CMD npm run start +# RUN npm run build +# CMD npm run start # RUN if [ "$NODE_ENV" = "production" ]; then npm run build; fi # CMD if [ "$NODE_ENV" = "production" ]; then npm run start; else npm run dev; fi \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 53638893..be444e55 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -29,6 +29,7 @@ "clsx": "^2.1.1", "framer-motion": "^11.2.5", "graphql": "^16.9.0", + "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", "next": "^14.2.14", "react": "^18.3.1", @@ -40,6 +41,7 @@ "tsparticles": "^3.4.0" }, "devDependencies": { + "@types/jsonwebtoken": "^9.0.10", "@types/lodash": "^4.17.4", "@types/node": "^20", "@types/react": "^18", @@ -3865,12 +3867,30 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, "node_modules/@types/lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.4.tgz", "integrity": "sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==", "dev": true }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.12.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", @@ -4737,6 +4757,12 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -4802,9 +4828,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001653", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", - "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "funding": [ { "type": "opencollective", @@ -4818,7 +4844,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capital-case": { "version": "1.0.4", @@ -5483,6 +5510,15 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.13", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", @@ -7631,6 +7667,28 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -7646,6 +7704,27 @@ "node": ">=4.0" } }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -7785,12 +7864,54 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -9325,7 +9446,6 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, "bin": { "semver": "bin/semver.js" }, diff --git a/frontend/package.json b/frontend/package.json index e724873f..e967c3dd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,7 @@ "start": "next start", "generate": "dotenv -e .env -- graphql-codegen --config codegen.yml --watch", "generatesave": "graphql-codegen --watch", + "build:css": "tailwindcss -i ./src/styles/globals.css -o ./src/styles/output.css --minify", "lint": "next lint" }, "dependencies": { @@ -32,6 +33,7 @@ "clsx": "^2.1.1", "framer-motion": "^11.2.5", "graphql": "^16.9.0", + "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", "next": "^14.2.14", "react": "^18.3.1", @@ -43,6 +45,7 @@ "tsparticles": "^3.4.0" }, "devDependencies": { + "@types/jsonwebtoken": "^9.0.10", "@types/lodash": "^4.17.4", "@types/node": "^20", "@types/react": "^18", diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index 0b484512..1953d09a 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -1,32 +1,80 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; +import jwt from "jsonwebtoken"; -function middleware (request: NextRequest): NextResponse { - return checkPath(request); +interface Payload { + email: string; + role: string; + pseudo: string; + id: string; } -const checkPath = (request: NextRequest) : NextResponse => { - // let response: NextResponse = NextResponse.next(); +const SECRET_KEY = process.env.SECRET_KEY || "dev-secret-key"; - // if (request.nextUrl.pathname.startsWith("/")) { - // response = NextResponse.next(); - // } +export const config = { + matcher: ["/admin/:path*"], +}; + +const middleware = async (request: NextRequest): Promise => { + const { pathname } = request.nextUrl; + const token = request.cookies.get("token")?.value; + const response = NextResponse.next(); - // if (!request.nextUrl.pathname.startsWith("/")) { - // response = NextResponse.redirect(new URL("/404", request.url)); - // } + // Autoriser accès libre à la page de login + if (pathname.startsWith("/admin/auth/login")) { + console.log("je suis là") + return response; + } - // return response; + // Gestion du logout : suppression des cookies + if (pathname.startsWith("/admin/auth/logout")) { + deleteAuthCookies(response); + return NextResponse.redirect(new URL("/", request.url)); + } - if (request.nextUrl.pathname.startsWith("/") || request.nextUrl.pathname.startsWith("/404")) { - return NextResponse.next(); + // Pas de token : redirection vers login + if (!token) { + deleteAuthCookies(response); + return NextResponse.redirect(new URL("/admin/auth/login", request.url)); + } + + // Vérification du token JWT + try { + const payload = verify(token); + + // Vérifier si le rôle autorise l’accès + if (pathname.startsWith("/admin") && payload.role !== "admin") { + return NextResponse.redirect(new URL("/400", request.url)); } - return NextResponse.redirect(new URL("/404", request.url)); -} + // Token valide : poser les cookies + setAuthCookies(response, payload); + return response; + } catch (err) { + console.error("JWT verification error:", err); + deleteAuthCookies(response); + return NextResponse.redirect(new URL("/admin/auth/login", request.url)); + } +}; -export const config = { - matcher: "/:path", +// Vérifie et décode le token +const verify = (token: string): Payload => { + return jwt.verify(token, SECRET_KEY) as Payload; +}; + +// Définit les cookies d'auth +const setAuthCookies = (res: NextResponse, payload: Payload): void => { + res.cookies.set("email", payload.email); + res.cookies.set("role", payload.role); + res.cookies.set("pseudo", payload.pseudo); + res.cookies.set("id", payload.id); +}; + +// Supprime les cookies d'auth +const deleteAuthCookies = (res: NextResponse): void => { + ["email", "role", "pseudo", "id", "token"].forEach((cookie) => + res.cookies.delete(cookie) + ); }; export default middleware; \ No newline at end of file diff --git a/frontend/src/pages/404.tsx b/frontend/src/pages/404.tsx index 35e58387..f87f41a6 100644 --- a/frontend/src/pages/404.tsx +++ b/frontend/src/pages/404.tsx @@ -1,14 +1,17 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; - const Custom404 = (): React.ReactElement => { const router = useRouter(); useEffect(() => { - router.push("/"); + // router.push("/"); }, []); - return <>; + return ( +
+ toto +
+ ); }; export default Custom404; diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx new file mode 100644 index 00000000..c23aca4c --- /dev/null +++ b/frontend/src/pages/admin/auth/login.tsx @@ -0,0 +1,5 @@ +const LoginPage = () => { + return
Page de connexion admin
; +}; + +export default LoginPage; \ No newline at end of file diff --git a/frontend/src/pages/toto.tsx b/frontend/src/pages/toto.tsx new file mode 100644 index 00000000..137167f7 --- /dev/null +++ b/frontend/src/pages/toto.tsx @@ -0,0 +1,22 @@ +import { useEffect } from "react"; + +const TotoPage = () => { + useEffect(() => { + console.log("je suis sur la page toto") + }, []); + + return ( +
+

Page de toto

+

Page de toto

+

Page de toto

+

Page de toto

+

Page de toto

+

Page de toto

+

Page de toto

+

Page de toto

+
+ ); +}; + +export default TotoPage; \ No newline at end of file diff --git a/frontend/src/styles/output.css b/frontend/src/styles/output.css index 70722ae8..96d80d03 100644 --- a/frontend/src/styles/output.css +++ b/frontend/src/styles/output.css @@ -1,1730 +1 @@ -/* -! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com -*/ - -/* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { - box-sizing: border-box; - /* 1 */ - border-width: 0; - /* 2 */ - border-style: solid; - /* 2 */ - border-color: #e5e7eb; - /* 2 */ -} - -::before, -::after { - --tw-content: ''; -} - -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -6. Use the user's configured `sans` font-variation-settings by default. -7. Disable tap highlights on iOS -*/ - -html, -:host { - line-height: 1.5; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -moz-tab-size: 4; - /* 3 */ - -o-tab-size: 4; - tab-size: 4; - /* 3 */ - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - /* 4 */ - font-feature-settings: normal; - /* 5 */ - font-variation-settings: normal; - /* 6 */ - -webkit-tap-highlight-color: transparent; - /* 7 */ -} - -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - -body { - margin: 0; - /* 1 */ - line-height: inherit; - /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; - /* 1 */ - color: inherit; - /* 2 */ - border-top-width: 1px; - /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font-family by default. -2. Use the user's configured `mono` font-feature-settings by default. -3. Use the user's configured `mono` font-variation-settings by default. -4. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - /* 1 */ - font-feature-settings: normal; - /* 2 */ - font-variation-settings: normal; - /* 3 */ - font-size: 1em; - /* 4 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; - /* 1 */ - border-color: inherit; - /* 2 */ - border-collapse: collapse; - /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - /* 1 */ - font-feature-settings: inherit; - /* 1 */ - font-variation-settings: inherit; - /* 1 */ - font-size: 100%; - /* 1 */ - font-weight: inherit; - /* 1 */ - line-height: inherit; - /* 1 */ - letter-spacing: inherit; - /* 1 */ - color: inherit; - /* 1 */ - margin: 0; - /* 2 */ - padding: 0; - /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -input:where([type='button']), -input:where([type='reset']), -input:where([type='submit']) { - -webkit-appearance: button; - /* 1 */ - background-color: transparent; - /* 2 */ - background-image: none; - /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; - /* 1 */ - outline-offset: -2px; - /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; - /* 1 */ - font: inherit; - /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Reset default styling for dialogs. -*/ - -dialog { - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -input::placeholder, -textarea::placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ - -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; - /* 1 */ - vertical-align: middle; - /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ - -[hidden] { - display: none; -} - -*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -.container { - width: 100%; -} - -@media (min-width: 640px) { - .container { - max-width: 640px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 768px; - } -} - -@media (min-width: 1024px) { - .container { - max-width: 1024px; - } -} - -@media (min-width: 1280px) { - .container { - max-width: 1280px; - } -} - -@media (min-width: 1536px) { - .container { - max-width: 1536px; - } -} - -.fixed { - position: fixed; -} - -.absolute { - position: absolute; -} - -.relative { - position: relative; -} - -.inset-0 { - inset: 0px; -} - -.inset-y-0 { - top: 0px; - bottom: 0px; -} - -.left-0 { - left: 0px; -} - -.left-1\/2 { - left: 50%; -} - -.right-0 { - right: 0px; -} - -.top-0 { - top: 0px; -} - -.top-1\/2 { - top: 50%; -} - -.z-10 { - z-index: 10; -} - -.z-20 { - z-index: 20; -} - -.z-40 { - z-index: 40; -} - -.z-50 { - z-index: 50; -} - -.m-1 { - margin: 0.25rem; -} - -.m-2 { - margin: 0.5rem; -} - -.m-3 { - margin: 0.75rem; -} - -.m-4 { - margin: 1rem; -} - -.m-5 { - margin: 1.25rem; -} - -.m-\[3\%\] { - margin: 3%; -} - -.mx-4 { - margin-left: 1rem; - margin-right: 1rem; -} - -.mx-auto { - margin-left: auto; - margin-right: auto; -} - -.-ms-\[5px\] { - margin-inline-start: -5px; -} - -.mb-1 { - margin-bottom: 0.25rem; -} - -.mb-2 { - margin-bottom: 0.5rem; -} - -.mb-4 { - margin-bottom: 1rem; -} - -.mb-6 { - margin-bottom: 1.5rem; -} - -.mb-\[0\.25rem\] { - margin-bottom: 0.25rem; -} - -.mb-\[5\%\] { - margin-bottom: 5%; -} - -.me-3 { - margin-inline-end: 0.75rem; -} - -.ml-1 { - margin-left: 0.25rem; -} - -.ml-14 { - margin-left: 3.5rem; -} - -.ml-2 { - margin-left: 0.5rem; -} - -.ml-3 { - margin-left: 0.75rem; -} - -.ml-6 { - margin-left: 1.5rem; -} - -.mr-2 { - margin-right: 0.5rem; -} - -.mr-3 { - margin-right: 0.75rem; -} - -.mr-3\.5 { - margin-right: 0.875rem; -} - -.mr-4 { - margin-right: 1rem; -} - -.ms-4 { - margin-inline-start: 1rem; -} - -.mt-2 { - margin-top: 0.5rem; -} - -.mt-4 { - margin-top: 1rem; -} - -.mt-5 { - margin-top: 1.25rem; -} - -.mt-8 { - margin-top: 2rem; -} - -.mt-\[-2\%\] { - margin-top: -2%; -} - -.mt-\[1\%\] { - margin-top: 1%; -} - -.mt-\[4\%\] { - margin-top: 4%; -} - -.mt-\[5\%\] { - margin-top: 5%; -} - -.mt-\[10\%\] { - margin-top: 10%; -} - -.mt-\[50\%\] { - margin-top: 50%; -} - -.mt-3 { - margin-top: 0.75rem; -} - -.mt-10 { - margin-top: 2.5rem; -} - -.block { - display: block; -} - -.inline-block { - display: inline-block; -} - -.flex { - display: flex; -} - -.hidden { - display: none; -} - -.h-1\/2 { - height: 50%; -} - -.h-40 { - height: 10rem; -} - -.h-52 { - height: 13rem; -} - -.h-6 { - height: 1.5rem; -} - -.h-\[100\%\] { - height: 100%; -} - -.h-\[170px\] { - height: 170px; -} - -.h-\[460px\] { - height: 460px; -} - -.h-\[9px\] { - height: 9px; -} - -.h-\[calc\(100vh-xpx\)\] { - height: calc(100vh - xpx); -} - -.h-auto { - height: auto; -} - -.h-full { - height: 100%; -} - -.h-screen { - height: 100vh; -} - -.max-h-0 { - max-height: 0px; -} - -.w-12 { - width: 3rem; -} - -.w-40 { - width: 10rem; -} - -.w-6 { - width: 1.5rem; -} - -.w-64 { - width: 16rem; -} - -.w-\[100\%\] { - width: 100%; -} - -.w-\[100vh\] { - width: 100vh; -} - -.w-\[25px\] { - width: 25px; -} - -.w-\[350px\] { - width: 350px; -} - -.w-\[9px\] { - width: 9px; -} - -.w-full { - width: 100%; -} - -.max-w-7xl { - max-width: 80rem; -} - -.max-w-\[160px\] { - max-width: 160px; -} - -.max-w-\[210px\] { - max-width: 210px; -} - -.max-w-\[310px\] { - max-width: 310px; -} - -.max-w-md { - max-width: 28rem; -} - -.flex-1 { - flex: 1 1 0%; -} - -.flex-shrink-0 { - flex-shrink: 0; -} - -.flex-grow { - flex-grow: 1; -} - -.-translate-x-1\/2 { - --tw-translate-x: -50%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.-translate-y-1\/2 { - --tw-translate-y: -50%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.translate-x-full { - --tw-translate-x: 100%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.rotate-180 { - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.transform { - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.cursor-not-allowed { - cursor: not-allowed; -} - -.cursor-pointer { - cursor: pointer; -} - -.resize { - resize: both; -} - -.flex-row { - flex-direction: row; -} - -.flex-col { - flex-direction: column; -} - -.flex-col-reverse { - flex-direction: column-reverse; -} - -.flex-wrap { - flex-wrap: wrap; -} - -.flex-wrap-reverse { - flex-wrap: wrap-reverse; -} - -.items-center { - align-items: center; -} - -.justify-center { - justify-content: center; -} - -.justify-between { - justify-content: space-between; -} - -.justify-around { - justify-content: space-around; -} - -.space-x-3 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(0.75rem * var(--tw-space-x-reverse)); - margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1rem * var(--tw-space-x-reverse)); - margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-5 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1.25rem * var(--tw-space-x-reverse)); - margin-left: calc(1.25rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-y-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1rem * var(--tw-space-y-reverse)); -} - -.space-y-6 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); -} - -.overflow-hidden { - overflow: hidden; -} - -.overflow-x-auto { - overflow-x: auto; -} - -.overflow-y-auto { - overflow-y: auto; -} - -.overflow-y-hidden { - overflow-y: hidden; -} - -.whitespace-nowrap { - white-space: nowrap; -} - -.rounded-full { - border-radius: 9999px; -} - -.rounded-lg { - border-radius: 0.5rem; -} - -.rounded-md { - border-radius: 0.375rem; -} - -.border { - border-width: 1px; -} - -.border-4 { - border-width: 4px; -} - -.border-s { - border-inline-start-width: 1px; -} - -.border-none { - border-style: none; -} - -.border-gray-300 { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); -} - -.border-primary { - border-color: var(--primary-color); -} - -.border-secondary { - border-color: var(--secondary-color); -} - -.bg-black { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); -} - -.bg-body { - background-color: var(--body-color); -} - -.bg-footer { - background-color: var(--footer-color); -} - -.bg-gray-300 { - --tw-bg-opacity: 1; - background-color: rgb(209 213 219 / var(--tw-bg-opacity)); -} - -.bg-primary { - background-color: var(--primary-color); -} - -.bg-white { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); -} - -.object-cover { - -o-object-fit: cover; - object-fit: cover; -} - -.p-0 { - padding: 0px; -} - -.p-1 { - padding: 0.25rem; -} - -.p-4 { - padding: 1rem; -} - -.p-5 { - padding: 1.25rem; -} - -.p-6 { - padding: 1.5rem; -} - -.p-8 { - padding: 2rem; -} - -.px-4 { - padding-left: 1rem; - padding-right: 1rem; -} - -.px-5 { - padding-left: 1.25rem; - padding-right: 1.25rem; -} - -.py-1 { - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} - -.py-4 { - padding-top: 1rem; - padding-bottom: 1rem; -} - -.py-6 { - padding-top: 1.5rem; - padding-bottom: 1.5rem; -} - -.pb-2 { - padding-bottom: 0.5rem; -} - -.pb-5 { - padding-bottom: 1.25rem; -} - -.pb-\[0\.25rem\] { - padding-bottom: 0.25rem; -} - -.pt-0 { - padding-top: 0px; -} - -.pt-0\.5 { - padding-top: 0.125rem; -} - -.pt-2 { - padding-top: 0.5rem; -} - -.pt-3 { - padding-top: 0.75rem; -} - -.text-center { - text-align: center; -} - -.text-2xl { - font-size: 1.5rem; - line-height: 2rem; -} - -.text-4xl { - font-size: 2.25rem; - line-height: 2.5rem; -} - -.text-lg { - font-size: 1.125rem; - line-height: 1.75rem; -} - -.text-sm { - font-size: 0.875rem; - line-height: 1.25rem; -} - -.text-xl { - font-size: 1.25rem; - line-height: 1.75rem; -} - -.text-xs { - font-size: 0.75rem; - line-height: 1rem; -} - -.font-bold { - font-weight: 700; -} - -.font-semibold { - font-weight: 600; -} - -.leading-normal { - line-height: 1.5; -} - -.text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} - -.text-primary { - color: var(--primary-color); -} - -.text-secondary { - color: var(--secondary-color); -} - -.text-text { - color: var(--text-color); -} - -.text-text200 { - color: var(--text200-color); -} - -.text-text300 { - color: var(--text300-color); -} - -.text-textButton { - color: var(--textButton-color); -} - -.text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} - -.opacity-0 { - opacity: 0; -} - -.opacity-100 { - opacity: 1; -} - -.opacity-50 { - opacity: 0.5; -} - -.opacity-\[50\%\] { - opacity: 50%; -} - -.shadow { - --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-inner { - --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-lg { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-md { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.outline { - outline-style: solid; -} - -.blur { - --tw-blur: blur(8px); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.filter { - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.transition { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-opacity { - transition-property: opacity; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-transform { - transition-property: transform; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.duration-300 { - transition-duration: 300ms; -} - -.duration-500 { - transition-duration: 500ms; -} - -.ease-in-out { - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -} - -:root { - --primary-color: #B45852; - --secondary-color: #DFBB5F; - --scrollHandle-color: #19252E; - --scrollHandleHover-color: #162028; - --body-color: #01031B; - --grey-color: #7F7F7F; - --placeholder-color: #A0AEC0; - --text-color: #ffffff; - --text100-color: #030303; - --text200-color: #B2BDCC; - --text300-color: #64748b; - --textButton-color: white; - --success-color: #1C8036; - --error-color: #AA2020; - --warn-color: #EBCC2A; - --info-color: #3B89FF; - --footer-color: #050F1A; -} - -body { - background-color: var(--body-color); -} - -/* .custom-scrollbar::-webkit-scrollbar { - display: none; - color: red; -} - -.custom-scrollbar::-webkit-scrollbar:hover { - display: block; - color: red; -} */ - -/* Cacher la barre de défilement par défaut */ - -.custom-scrollbar { - overflow-y: hidden; - /* Désactiver le défilement vertical */ -} - -.custom-scrollbar:hover { - overflow-y: auto; - /* Activer le défilement vertical au survol */ -} - -.custom-scrollbar::-webkit-scrollbar { - width: 0; - /* Masquer la barre de défilement */ - height: 0; -} - -.custom-scrollbar:hover::-webkit-scrollbar { - width: 2px; - /* Afficher la barre de défilement au survol */ - height: 2px; -} - -@keyframes expandOpen { - from { - opacity: 0; - max-height: 0; - } - - to { - opacity: 1; - max-height: 500px; - } -} - -@keyframes expandClose { - from { - opacity: 1; - max-height: 500px; - } - - to { - opacity: 0; - max-height: 0; - } -} - -.expanded-animation-open { - animation: expandOpen 1.0s ease-in-out forwards; -} - -.expanded-animation-close { - animation: expandClose 1.0s ease-in-out forwards; -} - -.MuiCardContent-root { - padding: 0px; -} - -::-webkit-scrollbar { - width: 10px; -} - -::-webkit-scrollbar-track { - background: var(--body-color); -} - -::-webkit-scrollbar-thumb { - background: var(--scrollHandle-color); -} - -::-webkit-scrollbar-thumb:hover { - background: var(--scrollHandleHover-color); -} - -.emulator { - align-items: center; - display: flex; - justify-content: center; - /* height: calc(100vh - 100px); */ - /* height: calc(100vh - 20px); */ - width: 100vh ; - overflow: auto; - /* padding: 10px; */ -} - -.inputTerminal { - background-color: var(--body-color); - color: var(--text-color); - caret-color: var(--primary-color); - margin-left: 5px; - width: 15vh; -} - -.inputTerminal:focus-visible { - outline: none; -} - -.video-container { - display: flex; - justify-content: center; - align-items: center; - overflow: hidden; -} - -.custom-video { - width: 310px; - height: 170px; - -o-object-fit: cover; - object-fit: cover; -} - -.Toastify__toast-container { - font-family: Arial, sans-serif; -} - -.Toastify__toast { - border-radius: 4px; -} - -.Toastify__toast--success .Toastify__icon { - color: var(--success-color); -} - -.Toastify__toast--error .Toastify__icon { - color: var(--error-color); -} - -.Toastify__toast--info .Toastify__icon { - color: var(--info-color); -} - -.Toastify__toast--warn .Toastify__icon { - color: var(--warn-color); -} - -.Toastify__toast--success .Toastify__close-button, -.Toastify__toast--error .Toastify__close-button, -.Toastify__toast--info .Toastify__close-button, -.Toastify__toast--warn .Toastify__close-button { - color: var(--text-button-color); -} - -.hover\:bg-secondary:hover { - background-color: var(--secondary-color); -} - -.hover\:text-secondary:hover { - color: var(--secondary-color); -} - -.hover\:text-text100:hover { - color: var(--text100-color); -} - -.hover\:opacity-\[75\%\]:hover { - opacity: 75%; -} - -.focus\:outline-none:focus { - outline: 2px solid transparent; - outline-offset: 2px; -} - -@media (min-width: 640px) { - .sm\:ml-3 { - margin-left: 0.75rem; - } - - .sm\:max-w-\[80\%\] { - max-width: 80%; - } - - .sm\:max-w-\[90\%\] { - max-width: 90%; - } -} - -@media (min-width: 768px) { - .md\:-mt-\[5px\] { - margin-top: -5px; - } - - .md\:mb-0 { - margin-bottom: 0px; - } - - .md\:me-0 { - margin-inline-end: 0px; - } - - .md\:ml-4 { - margin-left: 1rem; - } - - .md\:ms-0 { - margin-inline-start: 0px; - } - - .md\:block { - display: block; - } - - .md\:inline-block { - display: inline-block; - } - - .md\:inline { - display: inline; - } - - .md\:flex { - display: flex; - } - - .md\:hidden { - display: none; - } - - .md\:w-1\/2 { - width: 50%; - } - - .md\:w-\[70\%\] { - width: 70%; - } - - .md\:max-w-\[60\%\] { - max-width: 60%; - } - - .md\:max-w-\[75\%\] { - max-width: 75%; - } - - .md\:justify-center { - justify-content: center; - } - - .md\:gap-6 { - gap: 1.5rem; - } - - .md\:border-s-0 { - border-inline-start-width: 0px; - } - - .md\:border-t { - border-top-width: 1px; - } - - .md\:pt-0 { - padding-top: 0px; - } - - .md\:text-base { - font-size: 1rem; - line-height: 1.5rem; - } -} - -@media (min-width: 1024px) { - .lg\:ml-6 { - margin-left: 1.5rem; - } - - .lg\:block { - display: block; - } - - .lg\:inline-block { - display: inline-block; - } - - .lg\:hidden { - display: none; - } - - .lg\:w-\[70\%\] { - width: 70%; - } - - .lg\:max-w-\[50\%\] { - max-width: 50%; - } - - .lg\:max-w-\[60\%\] { - max-width: 60%; - } - - .lg\:text-6xl { - font-size: 3.75rem; - line-height: 1; - } -} - -@media (min-width: 1280px) { - .xl\:block { - display: block; - } - - .xl\:hidden { - display: none; - } - - .xl\:max-w-\[35\%\] { - max-width: 35%; - } - - .xl\:max-w-\[40\%\] { - max-width: 40%; - } - - .xl\:max-w-\[50\%\] { - max-width: 50%; - } -} \ No newline at end of file +/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.-ms-\[5px\]{margin-inline-start:-5px}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.me-3{margin-inline-end:.75rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.ms-4{margin-inline-start:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[100px\]{margin-top:100px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[9px\]{height:9px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.w-12{width:3rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-\[9px\]{width:9px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-s{border-inline-start-width:1px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-5{padding-bottom:1.25rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:-mt-\[5px\]{margin-top:-5px}.md\:mb-0{margin-bottom:0}.md\:me-0{margin-inline-end:0}.md\:ml-4{margin-left:1rem}.md\:ms-0{margin-inline-start:0}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.md\:border-s-0{border-inline-start-width:0}.md\:border-t{border-top-width:1px}.md\:pt-0{padding-top:0}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file From fb9fa00da4996825606e450408b82029ea19f37f Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 18:15:09 +0200 Subject: [PATCH 03/19] fixed timeline css careers --- frontend/src/components/Careers/Careers.tsx | 16 +++++++--------- frontend/src/pages/toto.tsx | 2 +- frontend/src/styles/output.css | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/Careers/Careers.tsx b/frontend/src/components/Careers/Careers.tsx index 2b425bed..a7e26f23 100644 --- a/frontend/src/components/Careers/Careers.tsx +++ b/frontend/src/components/Careers/Careers.tsx @@ -64,17 +64,15 @@ const Careers: React.FC = (): React.ReactElement => { }, [dataEducations, dataExperiences]); return ( -
-
    +
    +
      {combinedData?.map((item, index) => ( -
    1. -
      -
      -

      +

    2. + +
      +

      {item.startDate} - {item.endDate}

      -
      -

      {item.type}

      {(item as EducationType)?.title} {(item as ExperienceType)?.job} @@ -90,7 +88,7 @@ const Careers: React.FC = (): React.ReactElement => {

    3. ))}
    -
    +
); }; diff --git a/frontend/src/pages/toto.tsx b/frontend/src/pages/toto.tsx index 137167f7..203cb554 100644 --- a/frontend/src/pages/toto.tsx +++ b/frontend/src/pages/toto.tsx @@ -6,7 +6,7 @@ const TotoPage = () => { }, []); return ( -
+

Page de toto

Page de toto

Page de toto

diff --git a/frontend/src/styles/output.css b/frontend/src/styles/output.css index 96d80d03..6e86de14 100644 --- a/frontend/src/styles/output.css +++ b/frontend/src/styles/output.css @@ -1 +1 @@ -/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.-ms-\[5px\]{margin-inline-start:-5px}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.me-3{margin-inline-end:.75rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.ms-4{margin-inline-start:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[100px\]{margin-top:100px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[9px\]{height:9px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.w-12{width:3rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-\[9px\]{width:9px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-s{border-inline-start-width:1px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-5{padding-bottom:1.25rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:-mt-\[5px\]{margin-top:-5px}.md\:mb-0{margin-bottom:0}.md\:me-0{margin-inline-end:0}.md\:ml-4{margin-left:1rem}.md\:ms-0{margin-inline-start:0}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.md\:border-s-0{border-inline-start-width:0}.md\:border-t{border-top-width:1px}.md\:pt-0{padding-top:0}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file +/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file From 16ad3dfdff53e142ec191fca6ac242e10ae022a4 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 18:36:12 +0200 Subject: [PATCH 04/19] fixed navbar --- frontend/src/components/NavBar/NavBar.tsx | 40 +++++++++-------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index f2ace089..d20afb6c 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -24,27 +24,16 @@ const Navbar: React.FC = (): React.ReactElement => { const { toggleTheme } = useTheme(); const { selectedView } = useChoiceView(); - const [menuOpen, setMenuOpen]: [ - boolean, - React.Dispatch> - ] = useState(false); - const [open, setOpen]: [ - boolean, - React.Dispatch> - ] = React.useState(false); - const [isCheckedLang, setIsCheckedLang]: [ - boolean, - React.Dispatch> - ] = useState(false); + const [menuOpen, setMenuOpen] = useState(false); + const [open, setOpen] = useState(false); + const [isCheckedLang, setIsCheckedLang] = useState(false); - const handleOpen: () => void = (): void => setOpen(true); - const handleClose: () => void = (): void => setOpen(false); + const handleOpen = (): void => setOpen(true); + const handleClose = (): void => setOpen(false); - const toggleMenu: () => void = (): void => setMenuOpen(!menuOpen); + const toggleMenu = (): void => setMenuOpen(!menuOpen); - const handleChangeColorTheme: (newTheme: string) => void = ( - newTheme: string - ): void => { + const handleChangeColorTheme = (newTheme: string): void => { toggleTheme(newTheme); handleClose(); setMenuOpen(false); @@ -54,21 +43,24 @@ const Navbar: React.FC = (): React.ReactElement => { setIsCheckedLang(translations.file === "en"); }, [translations]); - const toggleCheckedLang: () => void = (): void => { + const toggleCheckedLang = (): void => { setIsCheckedLang(!isCheckedLang); setLang(lang === "fr" ? "en" : "fr"); }; - const handleScrollToSection: ( - event: React.MouseEvent, - sectionRef: React.RefObject - ) => void = ( + // --- CORRECTION : scroll fluide et animé --- + const handleScrollToSection = ( event: React.MouseEvent, sectionRef: React.RefObject ): void => { event.preventDefault(); if (sectionRef?.current) { - sectionRef.current.scrollIntoView({ behavior: "smooth" }); + const yOffset = -80; // Ajuste ici la hauteur de ta navbar + const y = + sectionRef.current.getBoundingClientRect().top + + window.pageYOffset + + yOffset; + window.scrollTo({ top: y, behavior: "smooth" }); // SCROLL ANIMÉ } setMenuOpen(false); }; From 8fa97f0b1d8d2422b83204acb9d1b1b1d7a2aa95 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 18:43:17 +0200 Subject: [PATCH 05/19] add css page 404 --- frontend/src/pages/404.tsx | 42 ++++++++++++++++++++++++--------- frontend/src/pages/toto.tsx | 7 ------ frontend/src/styles/globals.css | 4 ++++ frontend/src/styles/output.css | 2 +- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/frontend/src/pages/404.tsx b/frontend/src/pages/404.tsx index f87f41a6..ac20cd3f 100644 --- a/frontend/src/pages/404.tsx +++ b/frontend/src/pages/404.tsx @@ -1,16 +1,36 @@ -import { useEffect } from "react"; -import { useRouter } from "next/router"; -const Custom404 = (): React.ReactElement => { - const router = useRouter(); - - useEffect(() => { - // router.push("/"); - }, []); +import Link from "next/link"; +const Custom404 = (): React.ReactElement => { return ( -
- toto -
+
+
+ + + + 404 + + +

+ Oups, page introuvable ! +

+

+ La page que tu cherches n’existe pas ou a été déplacée. +

+ + + +
+
); }; diff --git a/frontend/src/pages/toto.tsx b/frontend/src/pages/toto.tsx index 203cb554..5fc68a1e 100644 --- a/frontend/src/pages/toto.tsx +++ b/frontend/src/pages/toto.tsx @@ -8,13 +8,6 @@ const TotoPage = () => { return (

Page de toto

-

Page de toto

-

Page de toto

-

Page de toto

-

Page de toto

-

Page de toto

-

Page de toto

-

Page de toto

); }; diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index a871195b..a024238d 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -172,4 +172,8 @@ body { .Toastify__toast--info .Toastify__close-button, .Toastify__toast--warn .Toastify__close-button { color: var(--text-button-color); +} + +html { + scroll-behavior: smooth; } \ No newline at end of file diff --git a/frontend/src/styles/output.css b/frontend/src/styles/output.css index 6e86de14..3a0c2287 100644 --- a/frontend/src/styles/output.css +++ b/frontend/src/styles/output.css @@ -1 +1 @@ -/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file +/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.min-h-\[calc\(100vh-64px\)\]{min-height:calc(100vh - 64px)}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}html{scroll-behavior:smooth}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file From b373f62b537c2ea925c8fb1d45929e3aa1fa1078 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 18:59:54 +0200 Subject: [PATCH 06/19] fixed page not found and text lang --- frontend/src/lang/en.tsx | 4 +++ frontend/src/lang/fr.tsx | 4 +++ frontend/src/lang/typeLang.tsx | 4 +++ frontend/src/pages/404.tsx | 65 +++++++++++++++++++--------------- 4 files changed, 49 insertions(+), 28 deletions(-) diff --git a/frontend/src/lang/en.tsx b/frontend/src/lang/en.tsx index 6bb8616e..aeba6fa0 100644 --- a/frontend/src/lang/en.tsx +++ b/frontend/src/lang/en.tsx @@ -3,6 +3,7 @@ import Lang from "./typeLang"; const en: Lang = { file: "en", titleHTML: "Alexandre Renard - Fullstack Developer | Portfolio", + titleHTMLNotFound: "Alexandre Renard - Fullstack Developer | 404", descHTML: "Junior developer with a lifelong passion for computer programming. Explore my portfolio to discover more about my skills!", welcome: "Welcome to my portfolio !", @@ -86,6 +87,9 @@ const en: Lang = { messageInfoCategoryCarCaptcha: "cats", messageInfoFirstCaptcha: "Select all the images containing", messageInfoLastCaptcha: "to prove you are not a robot.", + messagePageNotFoundH1: "Oops, page not found!", + messagePageNotFoundP: "The page you are looking for does not exist or has been moved.", + messagePageNotFoundButtom: "Return to home", }; export default en; diff --git a/frontend/src/lang/fr.tsx b/frontend/src/lang/fr.tsx index 02ade0da..1461f76c 100644 --- a/frontend/src/lang/fr.tsx +++ b/frontend/src/lang/fr.tsx @@ -3,6 +3,7 @@ import Lang from "./typeLang"; const fr: Lang = { file: "fr", titleHTML: "Alexandre Renard - Développeur Fullstack | Portfolio", + titleHTMLNotFound: "Alexandre Renard - Développeur Fullstack | 404", descHTML: "Développeur junior passionné par l'informatique depuis l'enfance. Explorez mon Portfolio pour découvrir mes compétences !", welcome: "Bienvenue sur mon portfolio !", @@ -86,6 +87,9 @@ const fr: Lang = { messageInfoCategoryCarCaptcha: "voitures", messageInfoFirstCaptcha: "Sélectionnez toutes les images contenant des", messageInfoLastCaptcha: "pour prouver que vous n'êtes pas un robot.", + messagePageNotFoundH1: "Oups, page introuvable !", + messagePageNotFoundP: "La page que tu cherches n’existe pas ou a été déplacée.", + messagePageNotFoundButtom: "Retour à l’accueil", }; export default fr; diff --git a/frontend/src/lang/typeLang.tsx b/frontend/src/lang/typeLang.tsx index 5ac87d80..1baf0f55 100644 --- a/frontend/src/lang/typeLang.tsx +++ b/frontend/src/lang/typeLang.tsx @@ -1,6 +1,7 @@ type Lang = { file: string; titleHTML: string; + titleHTMLNotFound : string; descHTML: string; welcome: string; theme1: string; @@ -69,6 +70,9 @@ type Lang = { messageInfoCategoryCarCaptcha: string; messageInfoFirstCaptcha: string; messageInfoLastCaptcha: string; + messagePageNotFoundH1 : string; + messagePageNotFoundP : string; + messagePageNotFoundButtom : string; }; export default Lang; diff --git a/frontend/src/pages/404.tsx b/frontend/src/pages/404.tsx index ac20cd3f..28d181db 100644 --- a/frontend/src/pages/404.tsx +++ b/frontend/src/pages/404.tsx @@ -1,36 +1,45 @@ import Link from "next/link"; +import { useLang } from "@/context/Lang/LangContext"; +import Head from "next/head"; const Custom404 = (): React.ReactElement => { + const { translations } = useLang(); + return ( -
-
- - - - 404 - - -

- Oups, page introuvable ! -

-

- La page que tu cherches n’existe pas ou a été déplacée. -

- - - + <> + + {translations.titleHTMLNotFound} + +
+
+ + + + 404 + + +

+ {translations.messagePageNotFoundH1} +

+

+ {translations.messagePageNotFoundP} +

+ + + +
-
+ ); }; From 57c0aabfc9421ebe96aff17ef1cce74fa7b1479c Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 19:24:01 +0200 Subject: [PATCH 07/19] delete css circle page not found --- frontend/src/pages/404.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/pages/404.tsx b/frontend/src/pages/404.tsx index 28d181db..ca1ce404 100644 --- a/frontend/src/pages/404.tsx +++ b/frontend/src/pages/404.tsx @@ -13,15 +13,14 @@ const Custom404 = (): React.ReactElement => {
- 404 From 3b367efba82c94c063d31d20067622da3215a4aa Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 21:36:11 +0200 Subject: [PATCH 08/19] fixed router redirect 404 --- frontend/src/pages/404.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontend/src/pages/404.tsx b/frontend/src/pages/404.tsx index ca1ce404..8ae3b5a1 100644 --- a/frontend/src/pages/404.tsx +++ b/frontend/src/pages/404.tsx @@ -1,10 +1,18 @@ import Link from "next/link"; import { useLang } from "@/context/Lang/LangContext"; import Head from "next/head"; +import { useEffect } from "react"; +import { Router, useRouter } from "next/router"; const Custom404 = (): React.ReactElement => { const { translations } = useLang(); + + const router = useRouter(); + useEffect(() => { + router.push("/404"); + }, []); + return ( <> From 220ea70f7aba69b32e18af094712f32c2cef1edd Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 23:02:27 +0200 Subject: [PATCH 09/19] add login page and components form login --- .../AuthFormLayout/AuthFormLayout.tsx | 24 +++++++++++ frontend/src/components/Button/Button.tsx | 2 +- .../TextFieldCustom/TextFieldCustom.tsx | 32 ++++++++++++++ frontend/src/pages/admin/auth/login.tsx | 43 ++++++++++++++++++- frontend/src/styles/output.css | 2 +- 5 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/AuthFormLayout/AuthFormLayout.tsx create mode 100644 frontend/src/components/TextFieldCustom/TextFieldCustom.tsx diff --git a/frontend/src/components/AuthFormLayout/AuthFormLayout.tsx b/frontend/src/components/AuthFormLayout/AuthFormLayout.tsx new file mode 100644 index 00000000..0f98af76 --- /dev/null +++ b/frontend/src/components/AuthFormLayout/AuthFormLayout.tsx @@ -0,0 +1,24 @@ +import { ReactNode } from "react"; +import { Box } from "@mui/material"; + +interface AuthFormLayoutProps { + title: string; + children: ReactNode; +} + +const AuthFormLayout = ({ title, children } : AuthFormLayoutProps) : React.ReactElement => { + return ( +
+ +

+ {title} +

+
+ {children} +
+
+
+ ); +} + +export default AuthFormLayout; \ No newline at end of file diff --git a/frontend/src/components/Button/Button.tsx b/frontend/src/components/Button/Button.tsx index 923b0b27..733aede2 100644 --- a/frontend/src/components/Button/Button.tsx +++ b/frontend/src/components/Button/Button.tsx @@ -1,7 +1,7 @@ import { Button } from "@mui/material"; type Props = { - onClick?: () => void; + onClick?: (e: React.MouseEvent) => void; text: string; disable?: boolean; disableHover?: boolean; diff --git a/frontend/src/components/TextFieldCustom/TextFieldCustom.tsx b/frontend/src/components/TextFieldCustom/TextFieldCustom.tsx new file mode 100644 index 00000000..066229a6 --- /dev/null +++ b/frontend/src/components/TextFieldCustom/TextFieldCustom.tsx @@ -0,0 +1,32 @@ +import { TextField, TextFieldProps } from "@mui/material"; + +const TextFieldCustom = (props : TextFieldProps) : React.ReactElement => { + return ( + + ); +} + +export default TextFieldCustom; \ No newline at end of file diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx index c23aca4c..0a74742d 100644 --- a/frontend/src/pages/admin/auth/login.tsx +++ b/frontend/src/pages/admin/auth/login.tsx @@ -1,5 +1,44 @@ -const LoginPage = () => { - return
Page de connexion admin
; +import { useState } from "react"; +import { TextField, Button, Box } from "@mui/material"; +import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; +import CustomTextField from "@/components/TextFieldCustom/TextFieldCustom"; +import ButtonCustom from "@/components/Button/Button"; + +const LoginPage = (): React.ReactElement => { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + + const handleLogin = (e: React.FormEvent) => { + e.preventDefault(); + console.log("Login cliqué !"); + console.log("Email:", email); + console.log("Password:", password); + }; + + return ( + +
+ setEmail(e.target.value)} + /> + setPassword(e.target.value)} + /> +
+ +
+ +
+ ); }; export default LoginPage; \ No newline at end of file diff --git a/frontend/src/styles/output.css b/frontend/src/styles/output.css index 3a0c2287..83b2ba8f 100644 --- a/frontend/src/styles/output.css +++ b/frontend/src/styles/output.css @@ -1 +1 @@ -/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.min-h-\[calc\(100vh-64px\)\]{min-height:calc(100vh - 64px)}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}html{scroll-behavior:smooth}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file +/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.min-h-\[calc\(100vh-64px\)\]{min-height:calc(100vh - 64px)}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}html{scroll-behavior:smooth}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file From cb1d66e2bd0183bc4cce73a931b2eb11f91bf576 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Mon, 16 Jun 2025 23:55:29 +0200 Subject: [PATCH 10/19] fixed page login and Factorization Navbar split composent --- .../src/components/Button/BurgerButton.tsx | 28 +++ .../components/Button/ButtonLinkNavBar.tsx | 35 ++++ .../components/ModalCustom/ModalCustom.tsx | 43 ++++ frontend/src/components/NavBar/NavBar.tsx | 188 ++++++++---------- frontend/src/lang/en.tsx | 4 + frontend/src/lang/fr.tsx | 4 + frontend/src/lang/typeLang.tsx | 4 + frontend/src/pages/admin/auth/login.tsx | 58 ++++-- frontend/src/styles/output.css | 2 +- 9 files changed, 242 insertions(+), 124 deletions(-) create mode 100644 frontend/src/components/Button/BurgerButton.tsx create mode 100644 frontend/src/components/Button/ButtonLinkNavBar.tsx create mode 100644 frontend/src/components/ModalCustom/ModalCustom.tsx diff --git a/frontend/src/components/Button/BurgerButton.tsx b/frontend/src/components/Button/BurgerButton.tsx new file mode 100644 index 00000000..b4c550e5 --- /dev/null +++ b/frontend/src/components/Button/BurgerButton.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +type BurgerButtonProps = { + open: boolean; + toggleMenu: () => void; + className?: string; +}; + +const BurgerButton: React.FC = ({ open, toggleMenu, className }) => ( + +); + +export default BurgerButton; \ No newline at end of file diff --git a/frontend/src/components/Button/ButtonLinkNavBar.tsx b/frontend/src/components/Button/ButtonLinkNavBar.tsx new file mode 100644 index 00000000..815afecf --- /dev/null +++ b/frontend/src/components/Button/ButtonLinkNavBar.tsx @@ -0,0 +1,35 @@ +import React from "react"; +import { usePathname } from "next/navigation"; + +type ButtonLinkNavBarProps = { + children: React.ReactNode; + sectionRef: React.RefObject; + handleScrollToSection: ( + event: React.MouseEvent, + sectionRef: React.RefObject + ) => void; + className?: string; +}; + +const ButtonLinkNavBar: React.FC = ({ + children, + sectionRef, + handleScrollToSection, + className = "", +}) => { + const pathname = usePathname(); + + if (pathname !== "/") return null; + + return ( + + ); +}; + +export default ButtonLinkNavBar; \ No newline at end of file diff --git a/frontend/src/components/ModalCustom/ModalCustom.tsx b/frontend/src/components/ModalCustom/ModalCustom.tsx new file mode 100644 index 00000000..c7bfa0af --- /dev/null +++ b/frontend/src/components/ModalCustom/ModalCustom.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import Modal from "@mui/material/Modal"; +import Box from "@mui/material/Box"; +import { useTheme } from "@mui/material/styles"; + +interface ModalCustomProps { + open: boolean; + onClose: () => void; + children: React.ReactNode; + width?: number | string; + className?: string; +} + +const ModalCustom: React.FC = ({ + open, + onClose, + children, + width = 400, + className = "", +}) => { + const theme = useTheme(); + + return ( + + + {children} + + + ); +}; + +export default ModalCustom; \ No newline at end of file diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index d20afb6c..3ccae14c 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -3,14 +3,22 @@ import { useTheme } from "@/context/Theme/ThemeContext"; import { useLang } from "@/context/Lang/LangContext"; import { useSectionRefs } from "@/context/SectionRefs/SectionRefsContext"; import ColorLensIcon from "@mui/icons-material/ColorLens"; -import Box from "@mui/material/Box"; import Button from "@/components/Button/Button"; -import Modal from "@mui/material/Modal"; import { useChoiceView } from "@/context/ChoiceView/ChoiceViewContext"; import ToggleButton from "../Button/ToggleButton"; import ChoiceViewButton from "../Button/ChoiceViewButton"; +import ButtonLinkNavBar from "../Button/ButtonLinkNavBar"; +import BurgerButton from "../Button/BurgerButton"; +import { usePathname } from "next/navigation"; +import Link from "next/link"; +import ModalCustom from "../ModalCustom/ModalCustom"; const Navbar: React.FC = (): React.ReactElement => { + + const pathname = usePathname(); + + console.log("pathname", pathname); + const { lang, setLang, translations } = useLang(); const { aboutMeRef, @@ -48,19 +56,18 @@ const Navbar: React.FC = (): React.ReactElement => { setLang(lang === "fr" ? "en" : "fr"); }; - // --- CORRECTION : scroll fluide et animé --- const handleScrollToSection = ( event: React.MouseEvent, sectionRef: React.RefObject ): void => { event.preventDefault(); if (sectionRef?.current) { - const yOffset = -80; // Ajuste ici la hauteur de ta navbar + const yOffset = -80; const y = sectionRef.current.getBoundingClientRect().top + window.pageYOffset + yOffset; - window.scrollTo({ top: y, behavior: "smooth" }); // SCROLL ANIMÉ + window.scrollTo({ top: y, behavior: "smooth" }); } setMenuOpen(false); }; @@ -69,71 +76,82 @@ const Navbar: React.FC = (): React.ReactElement => { ); }; -export default Navbar; +export default Navbar; \ No newline at end of file diff --git a/frontend/src/lang/en.tsx b/frontend/src/lang/en.tsx index aeba6fa0..3d2ed398 100644 --- a/frontend/src/lang/en.tsx +++ b/frontend/src/lang/en.tsx @@ -90,6 +90,10 @@ const en: Lang = { messagePageNotFoundH1: "Oops, page not found!", messagePageNotFoundP: "The page you are looking for does not exist or has been moved.", messagePageNotFoundButtom: "Return to home", + messagePageLoginTitle: "Login", + messagePageLoginInputEmail: "E-mail", + messagePageLoginInputPassword: "Password", + messagePageLoginInputButtom: "Log in", }; export default en; diff --git a/frontend/src/lang/fr.tsx b/frontend/src/lang/fr.tsx index 1461f76c..5827d989 100644 --- a/frontend/src/lang/fr.tsx +++ b/frontend/src/lang/fr.tsx @@ -90,6 +90,10 @@ const fr: Lang = { messagePageNotFoundH1: "Oups, page introuvable !", messagePageNotFoundP: "La page que tu cherches n’existe pas ou a été déplacée.", messagePageNotFoundButtom: "Retour à l’accueil", + messagePageLoginTitle : "Connexion", + messagePageLoginInputEmail : "Email", + messagePageLoginInputPassword : "Mot de passe", + messagePageLoginInputButtom : "Se connecter", }; export default fr; diff --git a/frontend/src/lang/typeLang.tsx b/frontend/src/lang/typeLang.tsx index 1baf0f55..6fc710ef 100644 --- a/frontend/src/lang/typeLang.tsx +++ b/frontend/src/lang/typeLang.tsx @@ -73,6 +73,10 @@ type Lang = { messagePageNotFoundH1 : string; messagePageNotFoundP : string; messagePageNotFoundButtom : string; + messagePageLoginTitle : string; + messagePageLoginInputEmail : string; + messagePageLoginInputPassword : string; + messagePageLoginInputButtom : string; }; export default Lang; diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx index 0a74742d..fced603a 100644 --- a/frontend/src/pages/admin/auth/login.tsx +++ b/frontend/src/pages/admin/auth/login.tsx @@ -1,38 +1,58 @@ -import { useState } from "react"; -import { TextField, Button, Box } from "@mui/material"; +import { useState, ChangeEvent, FormEvent } from "react"; import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; -import CustomTextField from "@/components/TextFieldCustom/TextFieldCustom"; +import TextFieldCustom from "@/components/TextFieldCustom/TextFieldCustom"; import ButtonCustom from "@/components/Button/Button"; +import { useLang } from "@/context/Lang/LangContext"; + +type LoginFormState = { + email: string; + password: string; +}; const LoginPage = (): React.ReactElement => { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const handleLogin = (e: React.FormEvent) => { + const { translations } = useLang(); + + const [form, setForm] = useState({ + email: "", + password: "", + }); + + const handleChange = (e: ChangeEvent) => { + const { name, value } = e.target; + setForm(prev => ({ + ...prev, + [name]: value, + })); + }; + + const handleLogin = (e: FormEvent) => { e.preventDefault(); console.log("Login cliqué !"); - console.log("Email:", email); - console.log("Password:", password); + console.log("Email:", form.email); + console.log("Password:", form.password); }; return ( - -
- + + setEmail(e.target.value)} + name="email" + value={form.email} + onChange={handleChange} /> - setPassword(e.target.value)} + name="password" + value={form.password} + onChange={handleChange} />
diff --git a/frontend/src/styles/output.css b/frontend/src/styles/output.css index 83b2ba8f..9326ed84 100644 --- a/frontend/src/styles/output.css +++ b/frontend/src/styles/output.css @@ -1 +1 @@ -/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.min-h-\[calc\(100vh-64px\)\]{min-height:calc(100vh - 64px)}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}html{scroll-behavior:smooth}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file +/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-3{margin:.75rem}.m-5{margin:1.25rem}.m-\[3\%\]{margin:3%}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-\[0\.25rem\]{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-3\.5{margin-right:.875rem}.mr-4{margin-right:1rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.mt-\[-2\%\]{margin-top:-2%}.mt-\[1\%\]{margin-top:1%}.mt-\[64px\]{margin-top:64px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.hidden{display:none}.h-1\/2{height:50%}.h-4{height:1rem}.h-40{height:10rem}.h-52{height:13rem}.h-6{height:1.5rem}.h-\[100\%\]{height:100%}.h-\[170px\]{height:170px}.h-\[460px\]{height:460px}.h-\[calc\(100vh-xpx\)\]{height:calc(100vh - xpx)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-0{max-height:0}.min-h-\[calc\(100vh-64px\)\]{min-height:calc(100vh - 64px)}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-4{width:1rem}.w-40{width:10rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-\[100\%\]{width:100%}.w-\[100vh\]{width:100vh}.w-\[25px\]{width:25px}.w-\[350px\]{width:350px}.w-full{width:100%}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[210px\]{max-width:210px}.max-w-\[310px\]{max-width:310px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.rotate-180,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1.25rem*var(--tw-space-x-reverse));margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-4{border-width:4px}.border-l-2{border-left-width:2px}.border-none{border-style:none}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary{border-color:var(--primary-color)}.border-secondary{border-color:var(--secondary-color)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-body{background-color:var(--body-color)}.bg-footer{background-color:var(--footer-color)}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-primary{background-color:var(--primary-color)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-\[0\.25rem\]{padding-bottom:.25rem}.pl-8{padding-left:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-normal{line-height:1.5}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-primary{color:var(--primary-color)}.text-secondary{color:var(--secondary-color)}.text-text{color:var(--text-color)}.text-text200{color:var(--text200-color)}.text-text300{color:var(--text300-color)}.text-textButton{color:var(--textButton-color)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-\[50\%\]{opacity:50%}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--primary-color:#b45852;--secondary-color:#dfbb5f;--scrollHandle-color:#19252e;--scrollHandleHover-color:#162028;--body-color:#01031b;--grey-color:#7f7f7f;--placeholder-color:#a0aec0;--text-color:#fff;--text100-color:#030303;--text200-color:#b2bdcc;--text300-color:#64748b;--textButton-color:#fff;--success-color:#1c8036;--error-color:#aa2020;--warn-color:#ebcc2a;--info-color:#3b89ff;--footer-color:#050f1a}body{background-color:var(--body-color)}.custom-scrollbar{overflow-y:hidden}.custom-scrollbar:hover{overflow-y:auto}.custom-scrollbar::-webkit-scrollbar{width:0;height:0}.custom-scrollbar:hover::-webkit-scrollbar{width:2px;height:2px}@keyframes expandOpen{0%{opacity:0;max-height:0}to{opacity:1;max-height:500px}}@keyframes expandClose{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}.expanded-animation-open{animation:expandOpen 1s ease-in-out forwards}.expanded-animation-close{animation:expandClose 1s ease-in-out forwards}.MuiCardContent-root{padding:0}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:var(--body-color)}::-webkit-scrollbar-thumb{background:var(--scrollHandle-color)}::-webkit-scrollbar-thumb:hover{background:var(--scrollHandleHover-color)}.emulator{align-items:center;display:flex;justify-content:center;width:100vh;overflow:auto}.inputTerminal{background-color:var(--body-color);color:var(--text-color);caret-color:var(--primary-color);margin-left:5px;width:15vh}.inputTerminal:focus-visible{outline:none}.video-container{display:flex;justify-content:center;align-items:center;overflow:hidden}.custom-video{width:310px;height:170px;-o-object-fit:cover;object-fit:cover}.Toastify__toast-container{font-family:Arial,sans-serif}.Toastify__toast{border-radius:4px}.Toastify__toast--success .Toastify__icon{color:var(--success-color)}.Toastify__toast--error .Toastify__icon{color:var(--error-color)}.Toastify__toast--info .Toastify__icon{color:var(--info-color)}.Toastify__toast--warn .Toastify__icon{color:var(--warn-color)}.Toastify__toast--error .Toastify__close-button,.Toastify__toast--info .Toastify__close-button,.Toastify__toast--success .Toastify__close-button,.Toastify__toast--warn .Toastify__close-button{color:var(--text-button-color)}html{scroll-behavior:smooth}.hover\:bg-secondary:hover{background-color:var(--secondary-color)}.hover\:text-secondary:hover{color:var(--secondary-color)}.hover\:text-text100:hover{color:var(--text100-color)}.hover\:opacity-\[75\%\]:hover{opacity:75%}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}@media (min-width:640px){.sm\:ml-3{margin-left:.75rem}.sm\:max-w-\[80\%\]{max-width:80%}.sm\:max-w-\[90\%\]{max-width:90%}}@media (min-width:768px){.md\:left-auto{left:auto}.md\:top-0{top:0}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mb-0{margin-bottom:0}.md\:ml-4{margin-left:1rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-1\/2{width:50%}.md\:w-\[70\%\]{width:70%}.md\:max-w-\[60\%\]{max-width:60%}.md\:max-w-\[75\%\]{max-width:75%}.md\:-translate-y-1\/2{--tw-translate-y:-50%}.md\:-translate-y-1\/2,.md\:translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.md\:translate-x-0{--tw-translate-x:0px}.md\:justify-center{justify-content:center}.md\:gap-6{gap:1.5rem}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:border-l-0{border-left-width:0}.md\:border-t{border-top-width:1px}.md\:pl-0{padding-left:0}.md\:pt-8{padding-top:2rem}}@media (min-width:1024px){.lg\:ml-6{margin-left:1.5rem}.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:hidden{display:none}.lg\:w-\[70\%\]{width:70%}.lg\:max-w-\[50\%\]{max-width:50%}.lg\:max-w-\[60\%\]{max-width:60%}.lg\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1280px){.xl\:block{display:block}.xl\:hidden{display:none}.xl\:max-w-\[35\%\]{max-width:35%}.xl\:max-w-\[40\%\]{max-width:40%}.xl\:max-w-\[50\%\]{max-width:50%}} \ No newline at end of file From b045f4cc383e2da14ad9ba7461ca4995254cf7fb Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 00:23:24 +0200 Subject: [PATCH 11/19] update login composent input --- .../TextFieldCustom/TextFieldCustom.tsx | 32 ------------------- frontend/src/pages/admin/auth/login.tsx | 14 ++++---- 2 files changed, 8 insertions(+), 38 deletions(-) delete mode 100644 frontend/src/components/TextFieldCustom/TextFieldCustom.tsx diff --git a/frontend/src/components/TextFieldCustom/TextFieldCustom.tsx b/frontend/src/components/TextFieldCustom/TextFieldCustom.tsx deleted file mode 100644 index 066229a6..00000000 --- a/frontend/src/components/TextFieldCustom/TextFieldCustom.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { TextField, TextFieldProps } from "@mui/material"; - -const TextFieldCustom = (props : TextFieldProps) : React.ReactElement => { - return ( - - ); -} - -export default TextFieldCustom; \ No newline at end of file diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx index fced603a..48704fe6 100644 --- a/frontend/src/pages/admin/auth/login.tsx +++ b/frontend/src/pages/admin/auth/login.tsx @@ -1,8 +1,8 @@ import { useState, ChangeEvent, FormEvent } from "react"; import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; -import TextFieldCustom from "@/components/TextFieldCustom/TextFieldCustom"; import ButtonCustom from "@/components/Button/Button"; import { useLang } from "@/context/Lang/LangContext"; +import InputField from "@/components/InputField/InputField"; type LoginFormState = { email: string; @@ -18,7 +18,9 @@ const LoginPage = (): React.ReactElement => { password: "", }); - const handleChange = (e: ChangeEvent) => { + const handleChange = ( + e: ChangeEvent + ) => { const { name, value } = e.target; setForm(prev => ({ ...prev, @@ -36,17 +38,17 @@ const LoginPage = (): React.ReactElement => { return ( - - From b6fb48735ae0f92ee0e0467b870712cab8308515 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 00:27:28 +0200 Subject: [PATCH 12/19] fixed input login --- frontend/src/components/InputField/InputField.tsx | 3 +++ frontend/src/pages/admin/auth/login.tsx | 2 ++ 2 files changed, 5 insertions(+) diff --git a/frontend/src/components/InputField/InputField.tsx b/frontend/src/components/InputField/InputField.tsx index f4eeb5e1..4a84ce46 100644 --- a/frontend/src/components/InputField/InputField.tsx +++ b/frontend/src/components/InputField/InputField.tsx @@ -9,6 +9,7 @@ interface InputFieldProps { onChange: (e: ChangeEvent) => void; multiline?: boolean; rows?: number; + name?: string; } const InputField: React.FC = ({ @@ -19,6 +20,7 @@ const InputField: React.FC = ({ onChange, multiline = false, rows, + name }) => { return ( = ({ onChange={onChange} multiline={multiline} rows={rows} + name={name} className="bg-white border border-gray-300 rounded-md text-text" sx={{ "& .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline": diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx index 48704fe6..3efd01a1 100644 --- a/frontend/src/pages/admin/auth/login.tsx +++ b/frontend/src/pages/admin/auth/login.tsx @@ -44,6 +44,7 @@ const LoginPage = (): React.ReactElement => { type="email" value={form.email} onChange={handleChange} + name="email" /> { type="password" value={form.password} onChange={handleChange} + name="password" />
Date: Tue, 17 Jun 2025 00:38:44 +0200 Subject: [PATCH 13/19] add page choicePassword --- frontend/src/lang/en.tsx | 4 ++ frontend/src/lang/fr.tsx | 4 ++ frontend/src/lang/typeLang.tsx | 4 ++ frontend/src/middleware.ts | 19 ++++-- .../src/pages/admin/auth/ChoicePassword.tsx | 65 +++++++++++++++++++ 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 frontend/src/pages/admin/auth/ChoicePassword.tsx diff --git a/frontend/src/lang/en.tsx b/frontend/src/lang/en.tsx index 3d2ed398..acc4eac9 100644 --- a/frontend/src/lang/en.tsx +++ b/frontend/src/lang/en.tsx @@ -94,6 +94,10 @@ const en: Lang = { messagePageLoginInputEmail: "E-mail", messagePageLoginInputPassword: "Password", messagePageLoginInputButtom: "Log in", + messagePagChoicePasswordTitle: "Choose a password", + messagePagChoicePasswordOld: "Current password", + messagePagChoicePasswordNew: "New password", + messagePagChoicePasswordButton: "Validate", }; export default en; diff --git a/frontend/src/lang/fr.tsx b/frontend/src/lang/fr.tsx index 5827d989..063917b0 100644 --- a/frontend/src/lang/fr.tsx +++ b/frontend/src/lang/fr.tsx @@ -94,6 +94,10 @@ const fr: Lang = { messagePageLoginInputEmail : "Email", messagePageLoginInputPassword : "Mot de passe", messagePageLoginInputButtom : "Se connecter", + messagePagChoicePasswordTitle : "Choisir un mot de passe", + messagePagChoicePasswordOld : "Mot de passe actuel", + messagePagChoicePasswordNew : "Nouveau mot de passe", + messagePagChoicePasswordButton : "Valider", }; export default fr; diff --git a/frontend/src/lang/typeLang.tsx b/frontend/src/lang/typeLang.tsx index 6fc710ef..faaf0f3f 100644 --- a/frontend/src/lang/typeLang.tsx +++ b/frontend/src/lang/typeLang.tsx @@ -77,6 +77,10 @@ type Lang = { messagePageLoginInputEmail : string; messagePageLoginInputPassword : string; messagePageLoginInputButtom : string; + messagePagChoicePasswordTitle : string; + messagePagChoicePasswordOld : string; + messagePagChoicePasswordNew : string; + messagePagChoicePasswordButton : string; }; export default Lang; diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index 1953d09a..de8dfc58 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -20,17 +20,22 @@ const middleware = async (request: NextRequest): Promise => { const token = request.cookies.get("token")?.value; const response = NextResponse.next(); - // Autoriser accès libre à la page de login - if (pathname.startsWith("/admin/auth/login")) { + // Autoriser accès libre aux pages non connecté + if ( + pathname.startsWith("/admin/auth/login") || + pathname.startsWith("/admin/auth/ForgotPassword") || + pathname.startsWith("/admin/auth/register") || + pathname.startsWith("/admin/auth/ChoicePassword") + ) { console.log("je suis là") return response; } - // Gestion du logout : suppression des cookies - if (pathname.startsWith("/admin/auth/logout")) { - deleteAuthCookies(response); - return NextResponse.redirect(new URL("/", request.url)); - } + // // Gestion du logout : suppression des cookies + // if (pathname.startsWith("/admin/auth/logout")) { + // deleteAuthCookies(response); + // return NextResponse.redirect(new URL("/", request.url)); + // } // Pas de token : redirection vers login if (!token) { diff --git a/frontend/src/pages/admin/auth/ChoicePassword.tsx b/frontend/src/pages/admin/auth/ChoicePassword.tsx new file mode 100644 index 00000000..1ae5ca08 --- /dev/null +++ b/frontend/src/pages/admin/auth/ChoicePassword.tsx @@ -0,0 +1,65 @@ +import { useState, ChangeEvent, FormEvent } from "react"; +import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; +import ButtonCustom from "@/components/Button/Button"; +import InputField from "@/components/InputField/InputField"; +import { useLang } from "@/context/Lang/LangContext"; + +type ChoicePasswordFormState = { + password: string; + newPassword: string; +}; + +const ChoicePasswordPage = (): React.ReactElement => { + const { translations } = useLang(); + + const [form, setForm] = useState({ + password: "", + newPassword: "", + }); + + const handleChange = ( + e: ChangeEvent + ) => { + const { name, value } = e.target; + setForm((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + console.log("Changement de mot de passe !", form); + }; + + return ( + + + + +
+ +
+ +
+ ); +}; + +export default ChoicePasswordPage; \ No newline at end of file From 6627d3bb23f7e7207069ccc0680e34901ccf6e34 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 00:55:25 +0200 Subject: [PATCH 14/19] add page forgotPassword --- frontend/src/lang/en.tsx | 13 +++-- frontend/src/lang/fr.tsx | 13 +++-- frontend/src/lang/typeLang.tsx | 13 +++-- frontend/src/middleware.ts | 4 +- .../src/pages/admin/auth/ChoicePassword.tsx | 8 +-- .../src/pages/admin/auth/forgotpassword.tsx | 55 +++++++++++++++++++ 6 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 frontend/src/pages/admin/auth/forgotpassword.tsx diff --git a/frontend/src/lang/en.tsx b/frontend/src/lang/en.tsx index acc4eac9..821c0518 100644 --- a/frontend/src/lang/en.tsx +++ b/frontend/src/lang/en.tsx @@ -94,10 +94,13 @@ const en: Lang = { messagePageLoginInputEmail: "E-mail", messagePageLoginInputPassword: "Password", messagePageLoginInputButtom: "Log in", - messagePagChoicePasswordTitle: "Choose a password", - messagePagChoicePasswordOld: "Current password", - messagePagChoicePasswordNew: "New password", - messagePagChoicePasswordButton: "Validate", + messagePageChoicePasswordTitle: "Choose a password", + messagePageChoicePasswordOld: "Current password", + messagePageChoicePasswordNew: "New password", + messagePageChoicePasswordButton: "Validate", + messagePageForgotPasswordTitle: "Forgot Password", + messagePageForgotPasswordEmail: "E-mail", + messagePageForgotPasswordButton: "Send", }; -export default en; +export default en; \ No newline at end of file diff --git a/frontend/src/lang/fr.tsx b/frontend/src/lang/fr.tsx index 063917b0..2526ea30 100644 --- a/frontend/src/lang/fr.tsx +++ b/frontend/src/lang/fr.tsx @@ -94,10 +94,13 @@ const fr: Lang = { messagePageLoginInputEmail : "Email", messagePageLoginInputPassword : "Mot de passe", messagePageLoginInputButtom : "Se connecter", - messagePagChoicePasswordTitle : "Choisir un mot de passe", - messagePagChoicePasswordOld : "Mot de passe actuel", - messagePagChoicePasswordNew : "Nouveau mot de passe", - messagePagChoicePasswordButton : "Valider", + messagePageChoicePasswordTitle : "Choisir un mot de passe", + messagePageChoicePasswordOld : "Mot de passe actuel", + messagePageChoicePasswordNew : "Nouveau mot de passe", + messagePageChoicePasswordButton : "Valider", + messagePageForgotPasswordTitle : "Mot de passe oublié", + messagePageForgotPasswordEmail : "Email", + messagePageForgotPasswordButton : "Envoyer", }; -export default fr; +export default fr; \ No newline at end of file diff --git a/frontend/src/lang/typeLang.tsx b/frontend/src/lang/typeLang.tsx index faaf0f3f..6139cf4a 100644 --- a/frontend/src/lang/typeLang.tsx +++ b/frontend/src/lang/typeLang.tsx @@ -77,10 +77,13 @@ type Lang = { messagePageLoginInputEmail : string; messagePageLoginInputPassword : string; messagePageLoginInputButtom : string; - messagePagChoicePasswordTitle : string; - messagePagChoicePasswordOld : string; - messagePagChoicePasswordNew : string; - messagePagChoicePasswordButton : string; + messagePageChoicePasswordTitle : string; + messagePageChoicePasswordOld : string; + messagePageChoicePasswordNew : string; + messagePageChoicePasswordButton : string; + messagePageForgotPasswordTitle : string; + messagePageForgotPasswordEmail : string; + messagePageForgotPasswordButton : string; }; -export default Lang; +export default Lang; \ No newline at end of file diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index de8dfc58..4d7dbd77 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -23,9 +23,9 @@ const middleware = async (request: NextRequest): Promise => { // Autoriser accès libre aux pages non connecté if ( pathname.startsWith("/admin/auth/login") || - pathname.startsWith("/admin/auth/ForgotPassword") || + pathname.startsWith("/admin/auth/forgotpassword") || pathname.startsWith("/admin/auth/register") || - pathname.startsWith("/admin/auth/ChoicePassword") + pathname.startsWith("/admin/auth/choicepassword") ) { console.log("je suis là") return response; diff --git a/frontend/src/pages/admin/auth/ChoicePassword.tsx b/frontend/src/pages/admin/auth/ChoicePassword.tsx index 1ae5ca08..c02d9fba 100644 --- a/frontend/src/pages/admin/auth/ChoicePassword.tsx +++ b/frontend/src/pages/admin/auth/ChoicePassword.tsx @@ -33,12 +33,12 @@ const ChoicePasswordPage = (): React.ReactElement => { }; return ( - +
{
diff --git a/frontend/src/pages/admin/auth/forgotpassword.tsx b/frontend/src/pages/admin/auth/forgotpassword.tsx new file mode 100644 index 00000000..de6ac4f9 --- /dev/null +++ b/frontend/src/pages/admin/auth/forgotpassword.tsx @@ -0,0 +1,55 @@ +import { useState, ChangeEvent, FormEvent } from "react"; +import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; +import ButtonCustom from "@/components/Button/Button"; +import InputField from "@/components/InputField/InputField"; +import { useLang } from "@/context/Lang/LangContext"; + +type ForgotPasswordFormState = { + email: string; +}; + +const ForgotPasswordPage = (): React.ReactElement => { + const { translations } = useLang(); + + const [form, setForm] = useState({ + email: "", + }); + + const handleChange = ( + e: ChangeEvent + ) => { + const { name, value } = e.target; + setForm((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + console.log("Demande de réinitialisation envoyée !", form); + }; + + return ( + + + +
+ +
+ +
+ ); +}; + +export default ForgotPasswordPage; \ No newline at end of file From db3d79a37efe09e251423297cf812f1fdec28512 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 02:20:03 +0200 Subject: [PATCH 15/19] add page register and component customSelect --- .../components/CustomSelect/CustomSelect.tsx | 99 +++++++++++++++++++ frontend/src/lang/en.tsx | 6 ++ frontend/src/lang/fr.tsx | 6 ++ frontend/src/lang/typeLang.tsx | 6 ++ frontend/src/pages/admin/auth/register.tsx | 95 ++++++++++++++++++ 5 files changed, 212 insertions(+) create mode 100644 frontend/src/components/CustomSelect/CustomSelect.tsx create mode 100644 frontend/src/pages/admin/auth/register.tsx diff --git a/frontend/src/components/CustomSelect/CustomSelect.tsx b/frontend/src/components/CustomSelect/CustomSelect.tsx new file mode 100644 index 00000000..efe67f4d --- /dev/null +++ b/frontend/src/components/CustomSelect/CustomSelect.tsx @@ -0,0 +1,99 @@ +import React from "react"; +import { FormControl, InputLabel, Select, MenuItem, SelectChangeEvent } from "@mui/material"; + +interface CustomSelectProps { + id: string; + label: string; + name: string; + value: string; + onChange: (event: SelectChangeEvent) => void; + options: { value: string; label: string }[]; +} + +const CustomSelect: React.FC = ({ + id, + label, + name, + value, + onChange, + options, +}) => { + return ( + + + {label} + + + + ); +}; + +export default CustomSelect; \ No newline at end of file diff --git a/frontend/src/lang/en.tsx b/frontend/src/lang/en.tsx index 821c0518..efac12ee 100644 --- a/frontend/src/lang/en.tsx +++ b/frontend/src/lang/en.tsx @@ -101,6 +101,12 @@ const en: Lang = { messagePageForgotPasswordTitle: "Forgot Password", messagePageForgotPasswordEmail: "E-mail", messagePageForgotPasswordButton: "Send", + messagePageRegisterTitle: "Register", + messagePageRegisterEmail: "Email", + messagePageRegisterFirstName: "First Name", + messagePageRegisterLastName: "Last Name", + messagePageRegisterRole: "Role", + messagePageRegisterButtom: "Register", }; export default en; \ No newline at end of file diff --git a/frontend/src/lang/fr.tsx b/frontend/src/lang/fr.tsx index 2526ea30..68950870 100644 --- a/frontend/src/lang/fr.tsx +++ b/frontend/src/lang/fr.tsx @@ -101,6 +101,12 @@ const fr: Lang = { messagePageForgotPasswordTitle : "Mot de passe oublié", messagePageForgotPasswordEmail : "Email", messagePageForgotPasswordButton : "Envoyer", + messagePageRegisterTitle : "Inscription", + messagePageRegisterEmail : "Email", + messagePageRegisterFirstName : "Prénom", + messagePageRegisterLastName : "Nom", + messagePageRegisterRole : "Rôle", + messagePageRegisterButtom : "S'inscrire", }; export default fr; \ No newline at end of file diff --git a/frontend/src/lang/typeLang.tsx b/frontend/src/lang/typeLang.tsx index 6139cf4a..063e935f 100644 --- a/frontend/src/lang/typeLang.tsx +++ b/frontend/src/lang/typeLang.tsx @@ -84,6 +84,12 @@ type Lang = { messagePageForgotPasswordTitle : string; messagePageForgotPasswordEmail : string; messagePageForgotPasswordButton : string; + messagePageRegisterTitle : string; + messagePageRegisterEmail : string; + messagePageRegisterFirstName : string; + messagePageRegisterLastName : string; + messagePageRegisterRole : string; + messagePageRegisterButtom : string; }; export default Lang; \ No newline at end of file diff --git a/frontend/src/pages/admin/auth/register.tsx b/frontend/src/pages/admin/auth/register.tsx new file mode 100644 index 00000000..b952f64c --- /dev/null +++ b/frontend/src/pages/admin/auth/register.tsx @@ -0,0 +1,95 @@ +import { useState, ChangeEvent, FormEvent } from "react"; +import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; +import ButtonCustom from "@/components/Button/Button"; +import InputField from "@/components/InputField/InputField"; +import { useLang } from "@/context/Lang/LangContext"; +import CustomSelect from "@/components/CustomSelect/CustomSelect"; + +type RegisterFormState = { + email: string; + prenom: string; + nom: string; + role: "admin" | "editor" | "view"; +}; + +const RegisterPage = (): React.ReactElement => { + const { translations } = useLang(); + + const [form, setForm] = useState({ + email: "", + prenom: "", + nom: "", + role: "view", + }); + + const handleChange = ( + e: ChangeEvent + ) => { + const { name, value } = e.target; + setForm((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const handleRoleChange = (event: any) => { + setForm((prev) => ({ + ...prev, + role: event.target.value as RegisterFormState["role"], + })); + }; + + const handleRegister = (e: FormEvent) => { + e.preventDefault(); + console.log("Register cliqué !", form); + }; + + return ( + +
+ + + + +
+ +
+ +
+ ); +}; + +export default RegisterPage; From 0683984b522c35c779874ac7fa96f2eac7866a7c Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 09:52:44 +0200 Subject: [PATCH 16/19] delete file test toto.tsx --- frontend/src/middleware.ts | 6 +++--- frontend/src/pages/toto.tsx | 15 --------------- 2 files changed, 3 insertions(+), 18 deletions(-) delete mode 100644 frontend/src/pages/toto.tsx diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index 4d7dbd77..9af3d1ec 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -23,9 +23,9 @@ const middleware = async (request: NextRequest): Promise => { // Autoriser accès libre aux pages non connecté if ( pathname.startsWith("/admin/auth/login") || - pathname.startsWith("/admin/auth/forgotpassword") || - pathname.startsWith("/admin/auth/register") || - pathname.startsWith("/admin/auth/choicepassword") + pathname.startsWith("/admin/auth/forgotpassword") + // pathname.startsWith("/admin/auth/register") || + // pathname.startsWith("/admin/auth/choicepassword") ) { console.log("je suis là") return response; diff --git a/frontend/src/pages/toto.tsx b/frontend/src/pages/toto.tsx deleted file mode 100644 index 5fc68a1e..00000000 --- a/frontend/src/pages/toto.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { useEffect } from "react"; - -const TotoPage = () => { - useEffect(() => { - console.log("je suis sur la page toto") - }, []); - - return ( -
-

Page de toto

-
- ); -}; - -export default TotoPage; \ No newline at end of file From d770697504770a8efe111ed06e1ba6b9b323711e Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 10:33:46 +0200 Subject: [PATCH 17/19] add login form backend --- frontend/src/middleware.ts | 5 +- frontend/src/pages/admin/auth/login.tsx | 59 +++++++++++++++---- .../src/requetes/mutations/login.mutations.ts | 11 ++++ frontend/src/types/graphql.ts | 42 +++++++++++++ 4 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 frontend/src/requetes/mutations/login.mutations.ts diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index 9af3d1ec..519db4f1 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -5,7 +5,6 @@ import jwt from "jsonwebtoken"; interface Payload { email: string; role: string; - pseudo: string; id: string; } @@ -18,6 +17,7 @@ export const config = { const middleware = async (request: NextRequest): Promise => { const { pathname } = request.nextUrl; const token = request.cookies.get("token")?.value; + console.log("token", token); const response = NextResponse.next(); // Autoriser accès libre aux pages non connecté @@ -71,13 +71,12 @@ const verify = (token: string): Payload => { const setAuthCookies = (res: NextResponse, payload: Payload): void => { res.cookies.set("email", payload.email); res.cookies.set("role", payload.role); - res.cookies.set("pseudo", payload.pseudo); res.cookies.set("id", payload.id); }; // Supprime les cookies d'auth const deleteAuthCookies = (res: NextResponse): void => { - ["email", "role", "pseudo", "id", "token"].forEach((cookie) => + ["email", "role", "id", "token"].forEach((cookie) => res.cookies.delete(cookie) ); }; diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx index 3efd01a1..7f3567dd 100644 --- a/frontend/src/pages/admin/auth/login.tsx +++ b/frontend/src/pages/admin/auth/login.tsx @@ -3,6 +3,12 @@ import AuthFormLayout from "@/components/AuthFormLayout/AuthFormLayout"; import ButtonCustom from "@/components/Button/Button"; import { useLang } from "@/context/Lang/LangContext"; import InputField from "@/components/InputField/InputField"; +import { useMutation } from "@apollo/client"; +import { + MutationDocument, + MutationMutation, + MutationMutationVariables, +} from "@/types/graphql"; type LoginFormState = { email: string; @@ -10,29 +16,52 @@ type LoginFormState = { }; const LoginPage = (): React.ReactElement => { - const { translations } = useLang(); - + const [form, setForm] = useState({ email: "", password: "", }); + const [login, { data, loading, error }] = useMutation< + MutationMutation, + MutationMutationVariables + >(MutationDocument); + const handleChange = ( e: ChangeEvent ) => { const { name, value } = e.target; - setForm(prev => ({ + setForm((prev) => ({ ...prev, [name]: value, })); }; - const handleLogin = (e: FormEvent) => { + const handleLogin = async (e: FormEvent) => { e.preventDefault(); - console.log("Login cliqué !"); - console.log("Email:", form.email); - console.log("Password:", form.password); + + try { + const res = await login({ + variables: { + data: { + email: form.email, + password: form.password, + }, + }, + }); + + const response = res.data?.login; + + if (response?.code === 200) { + console.log("✅ Connexion réussie :", response.message); + // TODO : set auth context / redirect + } else { + console.warn("❌ Erreur :", response?.message); + } + } catch (err) { + console.error("Erreur Apollo :", err); + } }; return ( @@ -44,7 +73,7 @@ const LoginPage = (): React.ReactElement => { type="email" value={form.email} onChange={handleChange} - name="email" + name="email" /> { type="password" value={form.password} onChange={handleChange} - name="password" + name="password" /> + + {error &&

{error.message}

} + {data?.login?.code !== 200 && ( +

{data?.login?.message}

+ )} +
diff --git a/frontend/src/requetes/mutations/login.mutations.ts b/frontend/src/requetes/mutations/login.mutations.ts new file mode 100644 index 00000000..f8de76e3 --- /dev/null +++ b/frontend/src/requetes/mutations/login.mutations.ts @@ -0,0 +1,11 @@ +import { gql } from "@apollo/client"; + +export const LOGIN = gql` +mutation Mutation($data: LoginInput!) { + login(data: $data) { + token + message + code + } +} +`; \ No newline at end of file diff --git a/frontend/src/types/graphql.ts b/frontend/src/types/graphql.ts index f5d2ac70..127eefee 100644 --- a/frontend/src/types/graphql.ts +++ b/frontend/src/types/graphql.ts @@ -581,6 +581,13 @@ export type SendContactMutationVariables = Exact<{ export type SendContactMutation = { __typename?: 'Mutation', sendContact: { __typename?: 'MessageType', label: string, message: string, status: boolean } }; +export type MutationMutationVariables = Exact<{ + data: LoginInput; +}>; + + +export type MutationMutation = { __typename?: 'Mutation', login: { __typename?: 'LoginResponse', token?: string | null, message: string, code: number } }; + export type GenerateCaptchaQueryVariables = Exact<{ [key: string]: never; }>; @@ -712,6 +719,41 @@ export function useSendContactMutation(baseOptions?: Apollo.MutationHookOptions< export type SendContactMutationHookResult = ReturnType; export type SendContactMutationResult = Apollo.MutationResult; export type SendContactMutationOptions = Apollo.BaseMutationOptions; +export const MutationDocument = gql` + mutation Mutation($data: LoginInput!) { + login(data: $data) { + token + message + code + } +} + `; +export type MutationMutationFn = Apollo.MutationFunction; + +/** + * __useMutationMutation__ + * + * To run a mutation, you first call `useMutationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useMutationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [mutationMutation, { data, loading, error }] = useMutationMutation({ + * variables: { + * data: // value for 'data' + * }, + * }); + */ +export function useMutationMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(MutationDocument, options); + } +export type MutationMutationHookResult = ReturnType; +export type MutationMutationResult = Apollo.MutationResult; +export type MutationMutationOptions = Apollo.BaseMutationOptions; export const GenerateCaptchaDocument = gql` query generateCaptcha { generateCaptcha { From cfcec6eafc2349150fce5961455349d3282819f1 Mon Sep 17 00:00:00 2001 From: Alexandre78R Date: Tue, 17 Jun 2025 19:04:34 +0200 Subject: [PATCH 18/19] add page 400, modify midleware v1 and login page v1 --- .env.sample | 3 +- backend/src/lib/generateSecurePassword.ts | 3 +- backend/src/resolvers/user.resolver.ts | 20 ++++++--- docker-compose.yml | 4 ++ frontend/.env.sample | 4 +- frontend/Dockerfile | 6 +++ frontend/src/lang/en.tsx | 8 ++++ frontend/src/lang/fr.tsx | 8 ++++ frontend/src/lang/typeLang.tsx | 8 ++++ frontend/src/middleware.ts | 41 +++++++++++++----- frontend/src/pages/400.tsx | 53 +++++++++++++++++++++++ frontend/src/pages/_app.tsx | 2 +- frontend/src/pages/admin/auth/login.tsx | 22 ++++++---- 13 files changed, 153 insertions(+), 29 deletions(-) create mode 100644 frontend/src/pages/400.tsx diff --git a/.env.sample b/.env.sample index be13e163..a01289e7 100644 --- a/.env.sample +++ b/.env.sample @@ -1,4 +1,5 @@ NEXT_PUBLIC_API_TOKEN="" JWT_SECRET="" NODE_ENV="" -NEXT_PUBLIC_API_URL="" \ No newline at end of file +NEXT_PUBLIC_API_URL="" +NEXT_PUBLIC_JWT_SECRET="" \ No newline at end of file diff --git a/backend/src/lib/generateSecurePassword.ts b/backend/src/lib/generateSecurePassword.ts index 20e48af5..ce82ee36 100644 --- a/backend/src/lib/generateSecurePassword.ts +++ b/backend/src/lib/generateSecurePassword.ts @@ -2,7 +2,8 @@ export function generateSecurePassword(): string { const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const lowercase = "abcdefghijklmnopqrstuvwxyz"; const numbers = "0123456789"; - const symbols = "!@#$%^&*()_+[]{}|;:,.<>?"; + // const symbols = "!@#$%^&*()_+[]{}|;:,.<>?"; + const symbols = "!@#$%^*-_=+"; const all = uppercase + lowercase + numbers + symbols; diff --git a/backend/src/resolvers/user.resolver.ts b/backend/src/resolvers/user.resolver.ts index 66805839..137c7ed8 100644 --- a/backend/src/resolvers/user.resolver.ts +++ b/backend/src/resolvers/user.resolver.ts @@ -10,10 +10,12 @@ import argon2 from "argon2"; import { structureMessageCreatedAccountHTML, structureMessageCreatedAccountTEXT } from "../mail/structureMail.service"; import { Response } from "../entities/response.types"; import { emailRegex, passwordRegex, checkRegex } from "../regex"; -import jwt from "jsonwebtoken"; +import { SignJWT } from "jose"; +import { TextEncoder } from "util"; import { MyContext } from ".."; // const prisma = new PrismaClient(); +const secret = new TextEncoder().encode(process.env.JWT_SECRET); @Resolver(() => User) export class UserResolver { @@ -164,15 +166,21 @@ export class UserResolver { } const tokenPayload = { - userId: user.id, + id: user.id, + email: user.email, + role: user.role, }; if (!process.env.JWT_SECRET) { return { code: 500, message: "Please check your JWT configuration !" }; } - const token = jwt.sign(tokenPayload, process.env.JWT_SECRET , { expiresIn: "7d" }); - + const token = await new SignJWT(tokenPayload) + .setProtectedHeader({ alg: "HS256" }) + .setIssuedAt() + .setExpirationTime("7d") + .sign(secret); + const cookieOptions = { httpOnly: true, secure: process.env.NODE_ENV === 'production', @@ -181,7 +189,7 @@ export class UserResolver { path: '/', }; - ctx.cookies.set("jwt", token, cookieOptions); + ctx.cookies.set("token", token, cookieOptions); return { code: 200, @@ -208,7 +216,7 @@ export class UserResolver { return { code: 401, message: "Authentication required." }; } - ctx.cookies.set("jwt", "", { + ctx.cookies.set("token", "", { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax' as const, diff --git a/docker-compose.yml b/docker-compose.yml index 8c5868fe..593248ce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,8 @@ services: args: NEXT_PUBLIC_API_TOKEN: ${NEXT_PUBLIC_API_TOKEN} NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL} + NEXT_PUBLIC_JWT_SECRET: ${NEXT_PUBLIC_JWT_SECRET} + JWT_SECRET: ${JWT_SECRET} ports: - 3000:3000 volumes: @@ -32,6 +34,8 @@ services: - NEXT_PUBLIC_IMAGE_URL=http://localhost:8000 - NEXT_PUBLIC_API_TOKEN=${NEXT_PUBLIC_API_TOKEN} - NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} + - NEXT_PUBLIC_JWT_SECRET=${NEXT_PUBLIC_JWT_SECRET} + - JWT_SECRET=${JWT_SECRET} - API_URL=${API_URL} - NODE_ENV=development env_file: diff --git a/frontend/.env.sample b/frontend/.env.sample index f139ba9e..a1028186 100644 --- a/frontend/.env.sample +++ b/frontend/.env.sample @@ -1,4 +1,6 @@ isProduction="true and false" NEXT_DISABLE_HMR="true and false" NEXT_PUBLIC_API_TOKEN="" -NEXT_PUBLIC_API_URL="" \ No newline at end of file +NEXT_PUBLIC_API_URL="" +NEXT_PUBLIC_JWT_SECRET="" +JWT_SECRET="" \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 72bb043f..66e4a195 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -17,6 +17,12 @@ ENV NEXT_PUBLIC_API_TOKEN=${NEXT_PUBLIC_API_TOKEN} ARG NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} +ARG NEXT_PUBLIC_JWT_SECRET +ENV NEXT_PUBLIC_JWT_SECRET=${NEXT_PUBLIC_JWT_SECRET} + +ARG JWT_SECRET +ENV JWT_SECRET=${JWT_SECRET} + CMD npm run dev # RUN npm run build diff --git a/frontend/src/lang/en.tsx b/frontend/src/lang/en.tsx index efac12ee..ad46ee98 100644 --- a/frontend/src/lang/en.tsx +++ b/frontend/src/lang/en.tsx @@ -4,6 +4,7 @@ const en: Lang = { file: "en", titleHTML: "Alexandre Renard - Fullstack Developer | Portfolio", titleHTMLNotFound: "Alexandre Renard - Fullstack Developer | 404", + titleHTMLUnauthorizedAccess : "Unauthorized Access", descHTML: "Junior developer with a lifelong passion for computer programming. Explore my portfolio to discover more about my skills!", welcome: "Welcome to my portfolio !", @@ -90,10 +91,17 @@ const en: Lang = { messagePageNotFoundH1: "Oops, page not found!", messagePageNotFoundP: "The page you are looking for does not exist or has been moved.", messagePageNotFoundButtom: "Return to home", + messagePageUnauthorizedH1 : "Oops, you're not authorized!", + messagePageUnauthorizedP : "It looks like you're trying to access a page or feature you dont have permission for.", + messagePageUnauthorizedButtom : "Return to home", messagePageLoginTitle: "Login", messagePageLoginInputEmail: "E-mail", messagePageLoginInputPassword: "Password", messagePageLoginInputButtom: "Log in", + messagePageLoginMessageSuccess : "Authentication successful. You are now logged in.", + messagePageLoginMessageErrorEmailOrPasswordIncorrect : "Incorrect email or password.", + messagePageLoginMessageErrorServer : "Server error: Please try again later.", + messagePageLoginMessageErrorUnexpected : "An unexpected error has occurred.", messagePageChoicePasswordTitle: "Choose a password", messagePageChoicePasswordOld: "Current password", messagePageChoicePasswordNew: "New password", diff --git a/frontend/src/lang/fr.tsx b/frontend/src/lang/fr.tsx index 68950870..ae6b151c 100644 --- a/frontend/src/lang/fr.tsx +++ b/frontend/src/lang/fr.tsx @@ -4,6 +4,7 @@ const fr: Lang = { file: "fr", titleHTML: "Alexandre Renard - Développeur Fullstack | Portfolio", titleHTMLNotFound: "Alexandre Renard - Développeur Fullstack | 404", + titleHTMLUnauthorizedAccess : "Accès non autorisé", descHTML: "Développeur junior passionné par l'informatique depuis l'enfance. Explorez mon Portfolio pour découvrir mes compétences !", welcome: "Bienvenue sur mon portfolio !", @@ -90,10 +91,17 @@ const fr: Lang = { messagePageNotFoundH1: "Oups, page introuvable !", messagePageNotFoundP: "La page que tu cherches n’existe pas ou a été déplacée.", messagePageNotFoundButtom: "Retour à l’accueil", + messagePageUnauthorizedH1 : "Oups, vous n'avez pas l'autorisation !", + messagePageUnauthorizedP : "Il semble que vous essayez d'accéder à une page ou une fonctionnalité pour laquelle vous n'avez pas les droits nécessaires.", + messagePageUnauthorizedButtom : "Retour à l’accueil", messagePageLoginTitle : "Connexion", messagePageLoginInputEmail : "Email", messagePageLoginInputPassword : "Mot de passe", messagePageLoginInputButtom : "Se connecter", + messagePageLoginMessageSuccess : "Authentification réussie. Vous êtes maintenant connecté.", + messagePageLoginMessageErrorEmailOrPasswordIncorrect : "Email ou mot de passe incorrect.", + messagePageLoginMessageErrorServer : "Erreur serveur : veuillez réessayer plus tard.", + messagePageLoginMessageErrorUnexpected : "Une erreur inattendue est survenue.", messagePageChoicePasswordTitle : "Choisir un mot de passe", messagePageChoicePasswordOld : "Mot de passe actuel", messagePageChoicePasswordNew : "Nouveau mot de passe", diff --git a/frontend/src/lang/typeLang.tsx b/frontend/src/lang/typeLang.tsx index 063e935f..5d75230e 100644 --- a/frontend/src/lang/typeLang.tsx +++ b/frontend/src/lang/typeLang.tsx @@ -2,6 +2,7 @@ type Lang = { file: string; titleHTML: string; titleHTMLNotFound : string; + titleHTMLUnauthorizedAccess : string; descHTML: string; welcome: string; theme1: string; @@ -73,10 +74,17 @@ type Lang = { messagePageNotFoundH1 : string; messagePageNotFoundP : string; messagePageNotFoundButtom : string; + messagePageUnauthorizedH1 : string; + messagePageUnauthorizedP : string; + messagePageUnauthorizedButtom : string; messagePageLoginTitle : string; messagePageLoginInputEmail : string; messagePageLoginInputPassword : string; messagePageLoginInputButtom : string; + messagePageLoginMessageSuccess : string; + messagePageLoginMessageErrorEmailOrPasswordIncorrect : string; + messagePageLoginMessageErrorServer : string; + messagePageLoginMessageErrorUnexpected : string; messagePageChoicePasswordTitle : string; messagePageChoicePasswordOld : string; messagePageChoicePasswordNew : string; diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index 519db4f1..b6481ddc 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -1,14 +1,18 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; -import jwt from "jsonwebtoken"; +import { jwtVerify } from "jose"; interface Payload { email: string; role: string; - id: string; + id: number; + iat?: number; + exp?: number; } -const SECRET_KEY = process.env.SECRET_KEY || "dev-secret-key"; +// const SECRET_KEY = process.env.NEXT_PUBLIC_JWT_SECRET || ""; +const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET); +// console.log("SECRET_KEY -->", SECRET_KEY); export const config = { matcher: ["/admin/:path*"], @@ -17,7 +21,7 @@ export const config = { const middleware = async (request: NextRequest): Promise => { const { pathname } = request.nextUrl; const token = request.cookies.get("token")?.value; - console.log("token", token); + // console.log("token", token); const response = NextResponse.next(); // Autoriser accès libre aux pages non connecté @@ -27,7 +31,7 @@ const middleware = async (request: NextRequest): Promise => { // pathname.startsWith("/admin/auth/register") || // pathname.startsWith("/admin/auth/choicepassword") ) { - console.log("je suis là") + // console.log("je suis là"); return response; } @@ -39,15 +43,17 @@ const middleware = async (request: NextRequest): Promise => { // Pas de token : redirection vers login if (!token) { + console.log("!token"); deleteAuthCookies(response); return NextResponse.redirect(new URL("/admin/auth/login", request.url)); } // Vérification du token JWT try { - const payload = verify(token); - - // Vérifier si le rôle autorise l’accès + const payload = await verify(token); + + console.log("payload", payload) + if (pathname.startsWith("/admin") && payload.role !== "admin") { return NextResponse.redirect(new URL("/400", request.url)); } @@ -62,9 +68,22 @@ const middleware = async (request: NextRequest): Promise => { } }; -// Vérifie et décode le token -const verify = (token: string): Payload => { - return jwt.verify(token, SECRET_KEY) as Payload; +const verify = async (token: string): Promise => { + const { payload } = await jwtVerify(token, SECRET_KEY); + + if ( + typeof payload.id === "number" && + typeof payload.email === "string" && + typeof payload.role === "string" + ) { + return { + id: payload.id, + email: payload.email, + role: payload.role, + }; + } + + throw new Error("Invalid JWT payload structure"); }; // Définit les cookies d'auth diff --git a/frontend/src/pages/400.tsx b/frontend/src/pages/400.tsx new file mode 100644 index 00000000..ffe6c2fe --- /dev/null +++ b/frontend/src/pages/400.tsx @@ -0,0 +1,53 @@ +import Link from "next/link"; +import { useLang } from "@/context/Lang/LangContext"; +import Head from "next/head"; +import { useEffect } from "react"; +import { Router, useRouter } from "next/router"; + +const Custom404 = (): React.ReactElement => { + const { translations } = useLang(); + + const router = useRouter(); + + useEffect(() => { + router.push("/400"); + }, []); + + return ( + <> + + {translations.titleHTMLUnauthorizedAccess} + +
+
+ + + 400 + + +

+ {translations.messagePageUnauthorizedH1} +

+

+ {translations.messagePageUnauthorizedP} +

+ + + +
+
+ + ); +}; + +export default Custom404; diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx index 808e7a74..4d44819f 100644 --- a/frontend/src/pages/_app.tsx +++ b/frontend/src/pages/_app.tsx @@ -33,6 +33,7 @@ const App = ({ Component, pageProps }: AppProps): React.ReactElement => { const httpLink = new HttpLink({ uri: `${API_URL}`, + credentials: "include", }); const authLink = setContext((_, { headers }) => { @@ -47,7 +48,6 @@ const App = ({ Component, pageProps }: AppProps): React.ReactElement => { const apolloClient = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), - credentials: "include", }); setClient(apolloClient); diff --git a/frontend/src/pages/admin/auth/login.tsx b/frontend/src/pages/admin/auth/login.tsx index 7f3567dd..d9964962 100644 --- a/frontend/src/pages/admin/auth/login.tsx +++ b/frontend/src/pages/admin/auth/login.tsx @@ -9,6 +9,7 @@ import { MutationMutation, MutationMutationVariables, } from "@/types/graphql"; +import CustomToast from "@/components/ToastCustom/CustomToast"; type LoginFormState = { email: string; @@ -16,6 +17,8 @@ type LoginFormState = { }; const LoginPage = (): React.ReactElement => { + + const { showAlert } = CustomToast(); const { translations } = useLang(); const [form, setForm] = useState({ @@ -54,13 +57,21 @@ const LoginPage = (): React.ReactElement => { const response = res.data?.login; if (response?.code === 200) { - console.log("✅ Connexion réussie :", response.message); - // TODO : set auth context / redirect + // console.log("✅ Connexion réussie :", response.message); + showAlert("success", translations.messagePageLoginMessageSuccess); + } else if (response?.code === 401) { + // console.warn("❌ Identifiants invalides :", response.message); + showAlert("error", translations.messagePageLoginMessageErrorServer); + } else if (response?.code === 500) { + // console.error("❌ Erreur serveur :", response.message); + showAlert("error", translations.messagePageLoginMessageErrorUnexpected); } else { - console.warn("❌ Erreur :", response?.message); + // console.warn("⚠️ Autre erreur :", response?.message); + showAlert("error", translations.messagePageLoginMessageErrorServer); } } catch (err) { console.error("Erreur Apollo :", err); + showAlert("error", "Erreur serveur : veuillez réessayer plus tard."); } }; @@ -84,11 +95,6 @@ const LoginPage = (): React.ReactElement => { name="password" /> - {error &&

{error.message}

} - {data?.login?.code !== 200 && ( -

{data?.login?.message}

- )} -
Date: Tue, 17 Jun 2025 20:36:46 +0200 Subject: [PATCH 19/19] add context and page admin test protection and upgrade backend secury and frontend --- backend/src/entities/user.entity.ts | 2 +- backend/src/index.ts | 23 +++-- backend/src/resolvers/user.resolver.ts | 24 +++++- backend/src/types/graphql.ts | 1 + .../src/context/UserContext/UserContext.tsx | 48 +++++++++++ frontend/src/middleware.ts | 85 +++---------------- frontend/src/pages/_app.tsx | 26 +++--- frontend/src/pages/admin/index.tsx | 48 +++++++++++ .../src/requetes/queries/users.queries.ts | 14 +++ frontend/src/types/graphql.ts | 52 +++++++++++- 10 files changed, 228 insertions(+), 95 deletions(-) create mode 100644 frontend/src/context/UserContext/UserContext.tsx create mode 100644 frontend/src/pages/admin/index.tsx create mode 100644 frontend/src/requetes/queries/users.queries.ts diff --git a/backend/src/entities/user.entity.ts b/backend/src/entities/user.entity.ts index 011acf60..03e85cea 100644 --- a/backend/src/entities/user.entity.ts +++ b/backend/src/entities/user.entity.ts @@ -30,4 +30,4 @@ export class User { @Field() isPasswordChange: boolean; -} \ No newline at end of file +} diff --git a/backend/src/index.ts b/backend/src/index.ts index 88831c21..b5585b88 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -29,7 +29,7 @@ import { loadedLogos, loadLogos } from './lib/logoLoader'; const prisma = new PrismaClient(); export interface JwtPayload { - userId: number; + id: number; } export interface MyContext { @@ -37,9 +37,18 @@ export interface MyContext { res: express.Response; apiKey: string | undefined; cookies: Cookies; + token : string | undefined | null; user: User | null; } +// export interface JwtPayload { +// userId: number; +// email?: string; +// role?: string; +// iat?: number; +// exp?: number; +// } + const app = express(); const httpServer = http.createServer(app); @@ -170,13 +179,13 @@ async function main() { expressMiddleware(server, { context: async ({ req, res }) => { const cookies = new Cookies(req, res); - // console.log("cookies:", cookies.get("jwt")); + let user: User | null = null; - const token = cookies.get("jwt"); - // console.log("Token du cookie:", token ? "Présent" : "Absent"); + const token = cookies.get("token"); if (token && process.env.JWT_SECRET) { + // console.log("token ---->", token) try { const { payload } = await jwtVerify( token, @@ -186,7 +195,7 @@ async function main() { // console.log("Payload du token décodé:", payload); const prismaUser = await prisma.user.findUnique({ - where: { id: payload.userId } + where: { id: payload.id } }); if (prismaUser) { @@ -202,7 +211,7 @@ async function main() { } catch (err) { console.error("Erreur de vérification JWT:", err); // Log l'erreur complète - cookies.set("jwt", "", { expires: new Date(0), httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax' as const }); + cookies.set("token", "", { expires: new Date(0), httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax' as const }); } } @@ -219,7 +228,7 @@ async function main() { await checkApiKey(apiKey); } - return { req, res, apiKey, cookies, user }; + return { req, res, apiKey, cookies, token, user }; }, }) ); diff --git a/backend/src/resolvers/user.resolver.ts b/backend/src/resolvers/user.resolver.ts index 137c7ed8..34e5a754 100644 --- a/backend/src/resolvers/user.resolver.ts +++ b/backend/src/resolvers/user.resolver.ts @@ -10,7 +10,7 @@ import argon2 from "argon2"; import { structureMessageCreatedAccountHTML, structureMessageCreatedAccountTEXT } from "../mail/structureMail.service"; import { Response } from "../entities/response.types"; import { emailRegex, passwordRegex, checkRegex } from "../regex"; -import { SignJWT } from "jose"; +import { jwtVerify, SignJWT } from "jose"; import { TextEncoder } from "util"; import { MyContext } from ".."; @@ -205,6 +205,28 @@ export class UserResolver { } } + @Query(() => User, { nullable: true }) + async me(@Ctx() { req, token }: MyContext): Promise { + // console.log("refresh FRONTcdodddof") + // console.log("req.cookies", req.cookies) + // console.log(cookies) + // const token = req.cookies.token; + console.log("token", token) + if (!token) return null; + + try { + const payload = await jwtVerify(token, new TextEncoder().encode(process.env.JWT_SECRET)); + const user = await this.db.user.findUnique({ where: { id: payload.payload.id as number } }); + if (!user) return null; + return { + ...user, + role: user.role as UserRole, + }; + } catch { + return null; + } + } + @Mutation(() => Response) async logout( @Ctx() ctx: MyContext diff --git a/backend/src/types/graphql.ts b/backend/src/types/graphql.ts index d9e2e384..b3611283 100644 --- a/backend/src/types/graphql.ts +++ b/backend/src/types/graphql.ts @@ -413,6 +413,7 @@ export type Query = { generateCaptcha: CaptchaResponse; getGlobalStats: GlobalStatsResponse; listBackupFiles: BackupFilesResponse; + me?: Maybe; projectById: ProjectResponse; projectList: ProjectsResponse; skillList: CategoryResponse; diff --git a/frontend/src/context/UserContext/UserContext.tsx b/frontend/src/context/UserContext/UserContext.tsx new file mode 100644 index 00000000..2ccebd51 --- /dev/null +++ b/frontend/src/context/UserContext/UserContext.tsx @@ -0,0 +1,48 @@ +import { + createContext, + useContext, + useEffect, + useState, + ReactNode, +} from "react"; +import { + GetMeQuery, + useGetMeQuery, +} from "@/types/graphql"; + +interface UserContextType { + user: GetMeQuery["me"] | null; + loading: boolean; + error: Error | null; + refetch: () => void; +} + +const UserContext = createContext(undefined); + +export const UserProvider = ({ children }: { children: ReactNode }) => { + const { data, loading, error, refetch } = useGetMeQuery(); + const [user, setUser] = useState(null); + + useEffect(() => { + console.log("data", data) + if (data?.me) { + setUser(data.me); + } else { + setUser(null); + } + }, [data]); + + return ( + + {children} + + ); +}; + +export const useUser = (): UserContextType => { + const context = useContext(UserContext); + if (!context) { + throw new Error("useUser must be used within a UserProvider"); + } + return context; +}; \ No newline at end of file diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index b6481ddc..94190315 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -2,102 +2,39 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { jwtVerify } from "jose"; -interface Payload { - email: string; - role: string; - id: number; - iat?: number; - exp?: number; -} - -// const SECRET_KEY = process.env.NEXT_PUBLIC_JWT_SECRET || ""; const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET); -// console.log("SECRET_KEY -->", SECRET_KEY); export const config = { matcher: ["/admin/:path*"], }; -const middleware = async (request: NextRequest): Promise => { - const { pathname } = request.nextUrl; - const token = request.cookies.get("token")?.value; - // console.log("token", token); +export default async function middleware(request: NextRequest) { const response = NextResponse.next(); + const token = request.cookies.get("token")?.value; - // Autoriser accès libre aux pages non connecté if ( - pathname.startsWith("/admin/auth/login") || - pathname.startsWith("/admin/auth/forgotpassword") - // pathname.startsWith("/admin/auth/register") || - // pathname.startsWith("/admin/auth/choicepassword") + request.nextUrl.pathname.startsWith("/admin/auth/login") || + request.nextUrl.pathname.startsWith("/admin/auth/forgotpassword") ) { - // console.log("je suis là"); return response; } - // // Gestion du logout : suppression des cookies - // if (pathname.startsWith("/admin/auth/logout")) { - // deleteAuthCookies(response); - // return NextResponse.redirect(new URL("/", request.url)); - // } - - // Pas de token : redirection vers login if (!token) { - console.log("!token"); - deleteAuthCookies(response); + response.cookies.delete("token"); return NextResponse.redirect(new URL("/admin/auth/login", request.url)); } - // Vérification du token JWT try { - const payload = await verify(token); - - console.log("payload", payload) - - if (pathname.startsWith("/admin") && payload.role !== "admin") { + const { payload } = await jwtVerify(token, SECRET_KEY); + + if (typeof payload.role !== "string" || payload.role !== "admin") { return NextResponse.redirect(new URL("/400", request.url)); } - // Token valide : poser les cookies - setAuthCookies(response, payload); return response; } catch (err) { - console.error("JWT verification error:", err); - deleteAuthCookies(response); + console.error("JWT error:", err); + response.cookies.delete("token"); return NextResponse.redirect(new URL("/admin/auth/login", request.url)); } -}; - -const verify = async (token: string): Promise => { - const { payload } = await jwtVerify(token, SECRET_KEY); - - if ( - typeof payload.id === "number" && - typeof payload.email === "string" && - typeof payload.role === "string" - ) { - return { - id: payload.id, - email: payload.email, - role: payload.role, - }; - } - - throw new Error("Invalid JWT payload structure"); -}; - -// Définit les cookies d'auth -const setAuthCookies = (res: NextResponse, payload: Payload): void => { - res.cookies.set("email", payload.email); - res.cookies.set("role", payload.role); - res.cookies.set("id", payload.id); -}; - -// Supprime les cookies d'auth -const deleteAuthCookies = (res: NextResponse): void => { - ["email", "role", "id", "token"].forEach((cookie) => - res.cookies.delete(cookie) - ); -}; - -export default middleware; \ No newline at end of file +} \ No newline at end of file diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx index 4d44819f..f2b9e213 100644 --- a/frontend/src/pages/_app.tsx +++ b/frontend/src/pages/_app.tsx @@ -18,6 +18,7 @@ import { import { API_URL } from "@/config"; import { setContext } from "@apollo/client/link/context"; import LoadingCustom from "@/components/Loading/LoadingCustom"; +import { UserProvider } from "@/context/UserContext/UserContext"; const App = ({ Component, pageProps }: AppProps): React.ReactElement => { const [client, setClient] = useState | null>(null); @@ -48,6 +49,7 @@ const App = ({ Component, pageProps }: AppProps): React.ReactElement => { const apolloClient = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), + credentials: "include", }); setClient(apolloClient); @@ -60,17 +62,19 @@ const App = ({ Component, pageProps }: AppProps): React.ReactElement => { return ( - - - - - - - - - - - + + + + + + + + + + + + + ); diff --git a/frontend/src/pages/admin/index.tsx b/frontend/src/pages/admin/index.tsx new file mode 100644 index 00000000..f244bf0f --- /dev/null +++ b/frontend/src/pages/admin/index.tsx @@ -0,0 +1,48 @@ +import { useUser } from "@/context/UserContext/UserContext"; +import { useEffect } from "react"; +import { useRouter } from "next/router"; + +const AdminDashboard = () => { + const { user, loading, error } = useUser(); + const router = useRouter(); + + useEffect(() => { + console.log("user avant if", user); + if (!loading) { + if (!user) { + console.log("user !user", user); + // router.push("/admin/auth/login"); + } else if (user.role !== "admin") { + console.log("user !== role", user); + // router.push("/400"); + } + } + }, [user, loading, router]); + +// if (loading) { +// return

Chargement...

; +// } + +// if (error) { +// return

Erreur : {error.message}

; +// } + +// if (!user || user.role !== "admin") { +// return null; +// } + + return ( +
+

Tableau de bord Admin

+

Bienvenue, {user?.firstname} {user?.lastname} !

+

Email : {user?.email}

+

Rôle : {user?.role}

+

Rôle : {user?.role}

+

Rôle : {user?.role}

+

Rôle : {user?.role}

+

Rôle : {user?.role}

+
+ ); +}; + +export default AdminDashboard; \ No newline at end of file diff --git a/frontend/src/requetes/queries/users.queries.ts b/frontend/src/requetes/queries/users.queries.ts new file mode 100644 index 00000000..d3853105 --- /dev/null +++ b/frontend/src/requetes/queries/users.queries.ts @@ -0,0 +1,14 @@ +import { gql } from "@apollo/client"; + +export const GET_ME = gql` + query GetMe { + me { + role + lastname + isPasswordChange + id + firstname + email + } + } +`; \ No newline at end of file diff --git a/frontend/src/types/graphql.ts b/frontend/src/types/graphql.ts index 127eefee..8d903b89 100644 --- a/frontend/src/types/graphql.ts +++ b/frontend/src/types/graphql.ts @@ -416,6 +416,7 @@ export type Query = { generateCaptcha: CaptchaResponse; getGlobalStats: GlobalStatsResponse; listBackupFiles: BackupFilesResponse; + me?: Maybe; projectById: ProjectResponse; projectList: ProjectsResponse; skillList: CategoryResponse; @@ -613,6 +614,11 @@ export type GetSkillsListQueryVariables = Exact<{ [key: string]: never; }>; export type GetSkillsListQuery = { __typename?: 'Query', skillList: { __typename?: 'CategoryResponse', code: number, message: string, categories?: Array<{ __typename?: 'Skill', categoryFR: string, id: string, categoryEN: string, skills: Array<{ __typename?: 'SkillSubItem', categoryId: number, id: string, image: string, name: string }> }> | null } }; +export type GetMeQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', role: Role, lastname: string, isPasswordChange: boolean, id: string, firstname: string, email: string } | null }; + export const ValidateCaptchaDocument = gql` mutation ValidateCaptcha($challengeType: String!, $selectedIndices: [Float!]!, $idCaptcha: String!) { @@ -1021,4 +1027,48 @@ export function useGetSkillsListSuspenseQuery(baseOptions?: Apollo.SuspenseQuery export type GetSkillsListQueryHookResult = ReturnType; export type GetSkillsListLazyQueryHookResult = ReturnType; export type GetSkillsListSuspenseQueryHookResult = ReturnType; -export type GetSkillsListQueryResult = Apollo.QueryResult; \ No newline at end of file +export type GetSkillsListQueryResult = Apollo.QueryResult; +export const GetMeDocument = gql` + query GetMe { + me { + role + lastname + isPasswordChange + id + firstname + email + } +} + `; + +/** + * __useGetMeQuery__ + * + * To run a query within a React component, call `useGetMeQuery` and pass it any options that fit your needs. + * When your component renders, `useGetMeQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetMeQuery({ + * variables: { + * }, + * }); + */ +export function useGetMeQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetMeDocument, options); + } +export function useGetMeLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetMeDocument, options); + } +export function useGetMeSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(GetMeDocument, options); + } +export type GetMeQueryHookResult = ReturnType; +export type GetMeLazyQueryHookResult = ReturnType; +export type GetMeSuspenseQueryHookResult = ReturnType; +export type GetMeQueryResult = Apollo.QueryResult; \ No newline at end of file