From 9d74bb0ea0a0d314ac958c55d9bc6a0d7304c0ae Mon Sep 17 00:00:00 2001 From: Mylow Date: Tue, 3 Feb 2026 21:56:59 +0100 Subject: [PATCH] Preprod (#38) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Grades subject - Added a badge on the grade cards to display the subject * More subjects - Added more subjects * Data sync race fix - Fix initial data sync race causing missing session on startup * Cache persistence - Set React Query persist maxAge to 30 days * Offline fallback - Allow webapp to run under /webapp by setting base path and router basename * Cherry theme - Added a cherry theme * Pride theme * Ocean and forest themes - Added ocean and forest themes - Fixed dark and oled hover color * Storage logs - Add logs page - Add loaclStorage logging * Change 'Fierté' to 'Rainbow' in en-US.json * Update 'pride' translation to 'Arc-en-ciel' * Update translation for 'pride' in Spanish locale * Update French translation for 'pride' key --------- Co-authored-by: Dark-Louis Co-authored-by: Dark-Louis <116973803+Dark-Louis@users.noreply.github.com> --- src/App.tsx | 8 +- src/components/bottom-navigation.tsx | 22 +- src/components/drawer-event-task.tsx | 2 +- src/components/sidebar.tsx | 51 +- src/components/theme-provider.tsx | 12 +- src/components/theme-toggle.tsx | 24 +- .../ui/shadcn-io/grid-pattern/index.tsx | 5 +- src/components/ui/sonner.tsx | 6 +- src/contexts/initialGetter.tsx | 63 +- src/contexts/reactQueryContext.tsx | 7 +- src/lib/utils/grades.ts | 43 ++ src/lib/utils/storage.ts | 96 +++ src/locales/en-US.json | 6 +- src/locales/es-ES.json | 6 +- src/locales/fr-FR.json | 6 +- src/main.tsx | 3 + src/pages/grades/grade-card.tsx | 28 +- src/pages/grades/page.tsx | 2 +- src/pages/home/sections.tsx | 8 +- src/pages/secondary/login.tsx | 6 +- src/pages/secondary/logs.tsx | 97 +++ src/styles/globals.css | 555 +++++++++++++++++- vite.config.ts | 17 +- 23 files changed, 1011 insertions(+), 62 deletions(-) create mode 100644 src/pages/secondary/logs.tsx diff --git a/src/App.tsx b/src/App.tsx index 872bfe5..052a27d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -24,6 +24,7 @@ import { PlanningPage } from "./pages/planning/page"; import { LoginPage } from "./pages/secondary/login"; import { AgendaPage } from "./pages/secondary/agenda"; import { WelcomePage } from "./pages/secondary/welcome"; +import { LogsPage } from "./pages/secondary/logs"; import * as Sentry from "@sentry/react"; import { InitialGetter } from "./contexts/initialGetter"; @@ -84,6 +85,7 @@ function AppRoutes() { path="/associations" element={} /> + } /> } /> @@ -92,6 +94,10 @@ function AppRoutes() { } function App() { + const baseUrl = import.meta.env.BASE_URL ?? "/"; + const routerBaseName = + baseUrl === "/" ? undefined : baseUrl.replace(/\/$/, ""); + return ( @@ -99,7 +105,7 @@ function App() { - + diff --git a/src/components/bottom-navigation.tsx b/src/components/bottom-navigation.tsx index 4ddc7e6..9d6423a 100644 --- a/src/components/bottom-navigation.tsx +++ b/src/components/bottom-navigation.tsx @@ -11,12 +11,18 @@ import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils/cn"; import { useNavigate, useLocation } from "react-router"; import { useTranslation } from "react-i18next"; +import { useTheme } from "@/components/theme-provider"; export default function BottomNavigation() { const navigate = useNavigate(); const { t } = useTranslation(); const location = useLocation(); const pathname = location.pathname; + const { theme } = useTheme(); + const hoverWhite = theme === "dark" || theme === "oled"; + const hoverTextClass = hoverWhite + ? "group-hover:text-white" + : "group-hover:text-mauria-purple"; const items = [ { @@ -70,7 +76,7 @@ export default function BottomNavigation() { "group flex h-auto flex-1 flex-col items-center gap-1 rounded-full px-4 pb-2 pt-2 text-[0.7rem] font-medium transition-colors hover:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 [&_svg]:size-7 min-w-0", isActive ? "text-mauria-purple dark:text-white oled:text-gray-100" - : "text-gray-400 dark:text-gray-500 oled:text-gray-500 group-hover:text-mauria-purple dark:group-hover:text-white oled:group-hover:text-gray-200" + : "text-gray-400 dark:text-gray-500 oled:text-gray-500" )} onClick={() => navigate(item.path)} aria-current={isActive ? "page" : undefined} @@ -84,9 +90,19 @@ export default function BottomNavigation() { : "bg-transparent group-hover:bg-mauria-purple/10 dark:group-hover:bg-white/10 oled:group-hover:bg-white/10" )} /> - + - + {item.label} diff --git a/src/components/drawer-event-task.tsx b/src/components/drawer-event-task.tsx index 7b55f86..d5e088d 100644 --- a/src/components/drawer-event-task.tsx +++ b/src/components/drawer-event-task.tsx @@ -259,7 +259,7 @@ export function DrawerEventTask({ )} - + {drawerTitle} diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx index 842fbcb..8e7eac0 100644 --- a/src/components/sidebar.tsx +++ b/src/components/sidebar.tsx @@ -3,9 +3,13 @@ import { useEffect, useState, type CSSProperties } from "react"; import { + Rainbow, + Cherry, Moon, Sun, MoonStar, + TreePine, + Waves, Menu, HeartHandshake, BadgeX, @@ -83,6 +87,10 @@ export default function Sidebar() { light: { Icon: Sun, label: t("sidebar.themeParameter.light") }, dark: { Icon: Moon, label: t("sidebar.themeParameter.dark") }, oled: { Icon: MoonStar, label: t("sidebar.themeParameter.oled") }, + cherry: { Icon: Cherry, label: t("sidebar.themeParameter.cherry") }, + ocean: { Icon: Waves, label: t("sidebar.themeParameter.ocean") }, + forest: { Icon: TreePine, label: t("sidebar.themeParameter.forest") }, + pride: { Icon: Rainbow, label: t("sidebar.themeParameter.pride") }, } as const; const { Icon: ThemeIcon, label: themeLabel } = @@ -120,6 +128,22 @@ export default function Sidebar() { value: "oled", label: t("sidebar.themeParameter.oled"), }, + { + value: "cherry", + label: t("sidebar.themeParameter.cherry"), + }, + { + value: "ocean", + label: t("sidebar.themeParameter.ocean"), + }, + { + value: "forest", + label: t("sidebar.themeParameter.forest"), + }, + { + value: "pride", + label: t("sidebar.themeParameter.pride"), + }, ], }, { @@ -210,7 +234,7 @@ export default function Sidebar() { + + diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx index 8ed65f2..a0696af 100644 --- a/src/components/theme-provider.tsx +++ b/src/components/theme-provider.tsx @@ -5,7 +5,7 @@ import type React from "react"; import { createContext, useContext, useEffect, useState } from "react"; -type Theme = "dark" | "light" | "oled"; +type Theme = "dark" | "light" | "oled" | "cherry" | "pride" | "ocean" | "forest"; type ThemeProviderProps = { children: React.ReactNode; @@ -30,7 +30,15 @@ export function ThemeProvider({ useEffect(() => { const root = window.document.documentElement; - root.classList.remove("light", "dark", "oled"); + root.classList.remove( + "light", + "dark", + "oled", + "cherry", + "pride", + "ocean", + "forest" + ); root.classList.add(theme); saveToStorage("theme", theme); }, [theme]); diff --git a/src/components/theme-toggle.tsx b/src/components/theme-toggle.tsx index f52108d..b86bbb6 100644 --- a/src/components/theme-toggle.tsx +++ b/src/components/theme-toggle.tsx @@ -1,13 +1,21 @@ "use client"; -import { Moon, MoonStar, Sun } from "lucide-react"; +import { Cherry, Moon, MoonStar, Rainbow, Sun, TreePine, Waves } from "lucide-react"; import { useTheme } from "@/components/theme-provider"; import { Button } from "@/components/ui/button"; export function ThemeToggle() { const { theme, setTheme } = useTheme(); - const themeCycle: typeof theme[] = ["light", "dark", "oled"]; + const themeCycle: typeof theme[] = [ + "light", + "cherry", + "ocean", + "forest", + "pride", + "dark", + "oled", + ]; const nextTheme = () => { const currentIndex = themeCycle.indexOf(theme); const nextIndex = (currentIndex + 1) % themeCycle.length; @@ -31,6 +39,18 @@ export function ThemeToggle() { {theme === "oled" && ( )} + {theme === "cherry" && ( + + )} + {theme === "ocean" && ( + + )} + {theme === "forest" && ( + + )} + {theme === "pride" && ( + + )} ); } diff --git a/src/components/ui/shadcn-io/grid-pattern/index.tsx b/src/components/ui/shadcn-io/grid-pattern/index.tsx index 94c61e2..ed0a664 100644 --- a/src/components/ui/shadcn-io/grid-pattern/index.tsx +++ b/src/components/ui/shadcn-io/grid-pattern/index.tsx @@ -11,6 +11,7 @@ interface GridPatternProps { squares?: Array<[number, number]>; strokeDasharray?: string; className?: string; + style?: React.CSSProperties; [key: string]: unknown; } @@ -22,6 +23,7 @@ export function GridPattern({ strokeDasharray = "0", squares, className, + style, ...props }: GridPatternProps) { const id = React.useId(); @@ -30,9 +32,10 @@ export function GridPattern({
@@ -52,7 +55,7 @@ export function GradeCardAnimate({
-
+
{grade.name}
@@ -91,9 +94,10 @@ export function GradeCard({ return ( +
@@ -104,7 +108,7 @@ export function GradeCard({
-
+
{grade.name}
@@ -131,3 +135,19 @@ export function GradeCard({ ); } + +const GradeTypeBadge = ({ code }: { code?: string | null }) => { + if (!code?.trim()) return null; + + const badgeInfo = getGradeBadgeInfoFromCode(code); + if (!badgeInfo?.label) return null; + + return ( + + {badgeInfo.label} + + ); +}; diff --git a/src/pages/grades/page.tsx b/src/pages/grades/page.tsx index 334cda8..0ea594c 100644 --- a/src/pages/grades/page.tsx +++ b/src/pages/grades/page.tsx @@ -147,7 +147,7 @@ export function GradesPage() { {selectedGrade && (
-

+

{selectedGrade.name}

diff --git a/src/pages/home/sections.tsx b/src/pages/home/sections.tsx index 42cb9f5..8cc61d0 100644 --- a/src/pages/home/sections.tsx +++ b/src/pages/home/sections.tsx @@ -64,9 +64,7 @@ export const LessonCard = ({

{lesson.courseTitle}

- + {formatLessonType(lesson.type)}
@@ -167,10 +165,10 @@ export const ImportantMessage = ({ message }: { message?: MessageEntry }) => ( className="rounded-lg bg-white dark:bg-mauria-alert oled:bg-black" > - + {message?.title ?? "Aucun message important"} - + {message?.message ?? "Bonne journée !"} diff --git a/src/pages/secondary/login.tsx b/src/pages/secondary/login.tsx index 55610ed..2c7eaf6 100644 --- a/src/pages/secondary/login.tsx +++ b/src/pages/secondary/login.tsx @@ -23,6 +23,7 @@ import { readInitialLocale, type LocaleOption, } from "@/lib/utils/translations"; +import { useNavigate } from "react-router"; const FIRST_LAUNCH_KEY = "firstLaunch"; @@ -33,6 +34,7 @@ export function LoginPage() { const [showPassword, setShowPassword] = useState(false); const [locale, setLocale] = useState(readInitialLocale); const { t } = useTranslation(); + const navigate = useNavigate(); useEffect(() => { applyLocale(locale); @@ -59,7 +61,9 @@ export function LoginPage() { ); } - window.location.href = shouldShowWelcome ? "/welcome" : "/"; + navigate(shouldShowWelcome ? "/welcome" : "/", { + replace: true, + }); } else { toast.error("Identifiants invalides", { description: diff --git a/src/pages/secondary/logs.tsx b/src/pages/secondary/logs.tsx new file mode 100644 index 0000000..4f782ae --- /dev/null +++ b/src/pages/secondary/logs.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { clearStorageLogs, getStorageLogs, logAppLaunch } from "@/lib/utils/storage"; + +type StorageLogEntry = { + ts: string; + action: "set" | "override" | "remove" | "clear" | "launch"; + key?: string; + size?: number; + details?: string; +}; + +function formatLogLine(entry: StorageLogEntry) { + if (entry.action === "launch") { + return `[${formatTimestamp(entry.ts)}] ${ + entry.details ?? "----- LANCEMENT DE L'APP -----" + }`; + } + const parts = [`[${formatTimestamp(entry.ts)}]`, entry.action.toUpperCase()]; + if (entry.key) parts.push(entry.key); + if (entry.size !== undefined) parts.push(`size=${entry.size}`); + if (entry.details) parts.push(entry.details); + return parts.join(" "); +} + +function formatTimestamp(ts: string) { + const date = new Date(ts); + if (Number.isNaN(date.getTime())) return ts; + const pad = (value: number) => String(value).padStart(2, "0"); + const year = date.getFullYear(); + const month = pad(date.getMonth() + 1); + const day = pad(date.getDate()); + const hours = pad(date.getHours()); + const minutes = pad(date.getMinutes()); + const seconds = pad(date.getSeconds()); + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} + +export function LogsPage() { + const [logs, setLogs] = useState([]); + + useEffect(() => { + const refresh = () => { + const nextLogs = getStorageLogs(); + setLogs(nextLogs); + }; + refresh(); + const interval = window.setInterval(refresh, 1000); + return () => { + window.clearInterval(interval); + }; + }, []); + + return ( +
+
+ + +
+ + Logs + + +
+
+ + + {logs.length === 0 ? ( +
+ Aucun log localStorage pour le moment. +
+ ) : ( +
+                                    {logs.map(formatLogLine).join("\n")}
+                                
+ )} +
+
+
+
+
+ ); +} diff --git a/src/styles/globals.css b/src/styles/globals.css index 4bce13c..db1e042 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -5,6 +5,8 @@ @custom-variant dark (&:is(.dark *, .oled *)); @custom-variant oled (&:is(.oled *)); +@custom-variant ocean (&:is(.ocean *)); +@custom-variant forest (&:is(.forest *)); @utility container { margin-inline: auto; @@ -30,10 +32,10 @@ --mauria-scale: 1; --background: 40 33% 98%; - --foreground: 222 47% 11%; + --foreground: 0 0% 0%; --card: 0 0% 100%; - --card-foreground: 222 47% 11%; + --card-foreground: 0 0% 0%; --popover: 0 0% 100%; --popover-foreground: 222 47% 11%; @@ -101,23 +103,21 @@ --planning-event-default-gradient: linear-gradient( 45deg, - hsl(var(--mauria-purple)), - hsl(var(--mauria-purple-soft)) - ); - --planning-event-default-shadow: 0 16px 32px hsl( - var(--mauria-purple) / 0.24 + hsl(352 90% 65%), + hsl(50 95% 58%), + hsl(200 85% 60%) ); + --planning-event-default-shadow: 0 16px 32px hsl(200 85% 60% / 0.28); --planning-event-default-text: hsl(var(--mauria-white)); - --planning-event-default-solid: hsl(var(--mauria-purple-soft)); + --planning-event-default-solid: hsl(352 90% 65%); --planning-event-epreuve-gradient: linear-gradient( 45deg, - hsl(var(--mauria-accent)), - hsl(var(--mauria-accent-dark)) - ); - --planning-event-epreuve-shadow: 0 16px 32px hsl( - var(--mauria-accent) / 0.24 + hsl(25 95% 60%), + hsl(50 95% 58%), + hsl(135 65% 50%) ); + --planning-event-epreuve-shadow: 0 16px 32px hsl(50 95% 58% / 0.28); --planning-event-epreuve-text: hsl(var(--mauria-white)); --planning-event-personal-gradient: linear-gradient( @@ -225,6 +225,504 @@ hsl(var(--mauria-green)) ); } + .ocean { + color-scheme: light; + + --background: 202 60% 96%; + --foreground: 210 30% 16%; + + --card: 200 60% 98%; + --card-foreground: 210 30% 16%; + + --popover: 200 60% 98%; + --popover-foreground: 210 30% 16%; + + --primary: 204 88% 40%; + --primary-foreground: 210 40% 98%; + + --secondary: 198 45% 90%; + --secondary-foreground: 210 30% 20%; + + --muted: 198 45% 92%; + --muted-foreground: 210 16% 38%; + + --accent: 190 75% 45%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 84% 60%; + --destructive-foreground: 210 40% 98%; + + --border: 200 40% 88%; + --input: 200 40% 88%; + --ring: 204 70% 60%; + + --mauria-bg: 202 60% 96%; + --mauria-card: 200 60% 98%; + --mauria-accent: 190 75% 45%; + --mauria-alert: 195 60% 92%; + --mauria-border: 200 40% 88%; + --mauria-purple: 210 45% 22%; + --mauria-text: 210 30% 16%; + + --mauria-white: 0 0% 100%; + --mauria-black: 0 0% 0%; + --mauria-accent-dark: 190 70% 38%; + --mauria-purple-soft: 210 35% 34%; + --mauria-purple-bright: 204 70% 48%; + --mauria-purple-light: 204 70% 60%; + --mauria-green: 170 45% 45%; + --mauria-green-dark: 170 50% 34%; + --mauria-green-soft: 170 40% 58%; + --mauria-planning-slot-border: 200 35% 82% / 0.25; + --mauria-planning-today: 190 80% 85% / 0.35; + --mauria-particles: 195 70% 55%; + --mauria-meteor-glow: 200 80% 98% / 0.35; + --mauria-chart-line: 204 30% 85%; + + --planning-button-text: hsl(var(--mauria-purple)); + --planning-button-background: hsl(var(--mauria-card)); + --planning-button-shadow: 0 12px 32px hsl(var(--mauria-purple) / 0.18); + --planning-button-active-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-button-active-shadow: 0 12px 24px hsl( + var(--mauria-accent) / 0.22 + ); + --planning-button-active-text: hsl(var(--mauria-white)); + + --planning-grid-background: hsl(var(--mauria-card)); + --planning-slot-border-color: hsl(var(--mauria-planning-slot-border)); + --planning-today-background: hsl(var(--mauria-planning-today)); + + --planning-event-default-gradient: linear-gradient( + 45deg, + hsl(204 88% 55%), + hsl(190 75% 50%) + ); + --planning-event-default-shadow: 0 16px 30px hsl(204 88% 55% / 0.22); + --planning-event-default-text: hsl(var(--mauria-white)); + --planning-event-default-solid: hsl(204 88% 55%); + + --planning-event-epreuve-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-event-epreuve-shadow: 0 16px 30px hsl( + var(--mauria-accent) / 0.24 + ); + --planning-event-epreuve-text: hsl(var(--mauria-white)); + + --planning-event-personal-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-green)), + hsl(var(--mauria-green-dark)) + ); + --planning-event-personal-shadow: 0 16px 30px hsl( + var(--mauria-green) / 0.22 + ); + --planning-event-personal-text: hsl(var(--mauria-white)); + + --planning-event-autogere-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-green)), + hsl(var(--mauria-green-dark)) + ); + --planning-event-autogere-shadow: 0 16px 30px hsl( + var(--mauria-green) / 0.22 + ); + --planning-event-autogere-text: hsl(var(--mauria-white)); + + --particles-color: hsl(var(--mauria-particles)); + --meteors-trail-glow: hsl(var(--mauria-meteor-glow)); + --chart-grid-stroke: hsl(var(--mauria-chart-line)); + --chart-dot-stroke: transparent; + --bubble-color-first: 120, 196, 235; + --bubble-color-second: 96, 182, 226; + --bubble-color-third: 58, 136, 194; + --bubble-color-fourth: 72, 200, 210; + --bubble-color-fifth: 156, 220, 230; + --bubble-color-sixth: 84, 164, 214; + } + .forest { + color-scheme: light; + + --background: 120 25% 96%; + --foreground: 140 18% 18%; + + --card: 120 25% 98%; + --card-foreground: 140 18% 18%; + + --popover: 120 25% 98%; + --popover-foreground: 140 18% 18%; + + --primary: 142 45% 32%; + --primary-foreground: 120 20% 96%; + + --secondary: 110 20% 90%; + --secondary-foreground: 140 18% 20%; + + --muted: 110 20% 92%; + --muted-foreground: 140 12% 42%; + + --accent: 168 45% 38%; + --accent-foreground: 120 20% 96%; + + --destructive: 0 84% 60%; + --destructive-foreground: 210 40% 98%; + + --border: 120 20% 88%; + --input: 120 20% 88%; + --ring: 142 40% 45%; + + --mauria-bg: 120 25% 96%; + --mauria-card: 120 25% 98%; + --mauria-accent: 168 45% 38%; + --mauria-alert: 120 30% 92%; + --mauria-border: 120 20% 88%; + --mauria-purple: 142 40% 28%; + --mauria-text: 140 18% 18%; + + --mauria-white: 0 0% 100%; + --mauria-black: 0 0% 0%; + --mauria-accent-dark: 168 50% 30%; + --mauria-purple-soft: 142 35% 40%; + --mauria-purple-bright: 142 45% 36%; + --mauria-purple-light: 142 35% 52%; + --mauria-green: 142 40% 40%; + --mauria-green-dark: 142 45% 30%; + --mauria-green-soft: 142 35% 56%; + --mauria-planning-slot-border: 120 20% 85% / 0.25; + --mauria-planning-today: 90 50% 85% / 0.35; + --mauria-particles: 142 35% 45%; + --mauria-meteor-glow: 120 30% 96% / 0.35; + --mauria-chart-line: 120 20% 84%; + + --planning-button-text: hsl(var(--mauria-purple)); + --planning-button-background: hsl(var(--mauria-card)); + --planning-button-shadow: 0 12px 32px hsl(var(--mauria-purple) / 0.18); + --planning-button-active-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-button-active-shadow: 0 12px 24px hsl( + var(--mauria-accent) / 0.22 + ); + --planning-button-active-text: hsl(var(--mauria-white)); + + --planning-grid-background: hsl(var(--mauria-card)); + --planning-slot-border-color: hsl(var(--mauria-planning-slot-border)); + --planning-today-background: hsl(var(--mauria-planning-today)); + + --planning-event-default-gradient: linear-gradient( + 45deg, + hsl(142 45% 38%), + hsl(110 45% 50%) + ); + --planning-event-default-shadow: 0 16px 30px hsl(142 45% 38% / 0.22); + --planning-event-default-text: hsl(var(--mauria-white)); + --planning-event-default-solid: hsl(142 45% 40%); + + --planning-event-epreuve-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-event-epreuve-shadow: 0 16px 30px hsl( + var(--mauria-accent) / 0.24 + ); + --planning-event-epreuve-text: hsl(var(--mauria-white)); + + --planning-event-personal-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-green)), + hsl(var(--mauria-green-dark)) + ); + --planning-event-personal-shadow: 0 16px 30px hsl( + var(--mauria-green) / 0.22 + ); + --planning-event-personal-text: hsl(var(--mauria-white)); + + --planning-event-autogere-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-green)), + hsl(var(--mauria-green-dark)) + ); + --planning-event-autogere-shadow: 0 16px 30px hsl( + var(--mauria-green) / 0.22 + ); + --planning-event-autogere-text: hsl(var(--mauria-white)); + + --particles-color: hsl(var(--mauria-particles)); + --meteors-trail-glow: hsl(var(--mauria-meteor-glow)); + --chart-grid-stroke: hsl(var(--mauria-chart-line)); + --chart-dot-stroke: transparent; + --bubble-color-first: 86, 140, 96; + --bubble-color-second: 120, 176, 124; + --bubble-color-third: 64, 112, 76; + --bubble-color-fourth: 180, 156, 98; + --bubble-color-fifth: 148, 196, 140; + --bubble-color-sixth: 98, 150, 108; + } + .cherry { + color-scheme: light; + + --background: 338 100% 94%; + --foreground: 340 16% 20%; + + --card: 344 100% 92%; + --card-foreground: 340 16% 20%; + + --popover: 344 100% 92%; + --popover-foreground: 340 16% 20%; + + --primary: 351 100% 86%; + --primary-foreground: 340 16% 20%; + + --secondary: 344 100% 92%; + --secondary-foreground: 340 18% 26%; + + --muted: 338 100% 94%; + --muted-foreground: 340 12% 48%; + + --accent: 342 50% 54%; + --accent-foreground: 0 0% 0%; + + --destructive: 0 84% 60%; + --destructive-foreground: 210 40% 98%; + + --border: 347 100% 90%; + --input: 347 100% 90%; + --ring: 349 100% 88%; + + --mauria-bg: 338 100% 94%; + --mauria-card: 344 100% 92%; + --mauria-accent: 342 50% 54%; + --mauria-alert: 340 100% 96%; + --mauria-border: 347 100% 90%; + --mauria-purple: 342 50% 54%; + --mauria-text: 340 16% 20%; + + --mauria-white: 0 0% 100%; + --mauria-black: 0 0% 0%; + --mauria-accent-dark: 342 55% 48%; + --mauria-purple-soft: 342 40% 66%; + --mauria-purple-bright: 342 55% 48%; + --mauria-purple-light: 342 35% 78%; + --mauria-green: 148 34% 52%; + --mauria-green-dark: 148 34% 40%; + --mauria-green-soft: 148 34% 64%; + --mauria-planning-slot-border: 347 100% 90% / 0.25; + --mauria-planning-today: 338 100% 94% / 0.35; + --mauria-particles: 349 100% 88%; + --mauria-meteor-glow: 338 100% 94% / 0.25; + --mauria-chart-line: 344 100% 92%; + + --planning-button-text: hsl(var(--mauria-purple)); + --planning-button-background: hsl(var(--mauria-card)); + --planning-button-shadow: 0 12px 32px hsl(var(--mauria-purple) / 0.18); + --planning-button-active-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-button-active-shadow: 0 12px 24px hsl( + var(--mauria-accent) / 0.22 + ); + --planning-button-active-text: hsl(var(--mauria-white)); + + --planning-grid-background: hsl(var(--mauria-card)); + --planning-slot-border-color: hsl(var(--mauria-planning-slot-border)); + --planning-today-background: hsl(var(--mauria-planning-today)); + + --planning-event-default-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-purple)), + hsl(var(--mauria-purple-soft)) + ); + --planning-event-default-shadow: 0 16px 30px hsl( + var(--mauria-purple) / 0.18 + ); + --planning-event-default-text: hsl(var(--mauria-white)); + --planning-event-default-solid: hsl(var(--mauria-purple-soft)); + + --planning-event-epreuve-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-event-epreuve-shadow: 0 16px 30px hsl( + var(--mauria-accent) / 0.2 + ); + --planning-event-epreuve-text: hsl(var(--mauria-white)); + + --planning-event-personal-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-green)), + hsl(var(--mauria-green-soft)) + ); + --planning-event-personal-shadow: 0 16px 30px hsl( + var(--mauria-green) / 0.2 + ); + --planning-event-personal-text: hsl(var(--mauria-white)); + + --planning-event-autogere-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-green)), + hsl(var(--mauria-green-soft)) + ); + --planning-event-autogere-shadow: 0 16px 30px hsl( + var(--mauria-green) / 0.2 + ); + --planning-event-autogere-text: hsl(var(--mauria-white)); + + --particles-color: hsl(var(--mauria-particles)); + --meteors-trail-glow: hsl(var(--mauria-meteor-glow)); + --chart-grid-stroke: hsl(var(--mauria-chart-line)); + --chart-dot-stroke: transparent; + --bubble-color-first: 255, 225, 236; + --bubble-color-second: 255, 215, 226; + --bubble-color-third: 255, 205, 216; + --bubble-color-fourth: 255, 195, 206; + --bubble-color-fifth: 255, 185, 196; + --bubble-color-sixth: 255, 205, 216; + } + .pride { + color-scheme: light; + + --background: 0 0% 98%; + --foreground: 222 47% 11%; + + --card: 0 0% 100%; + --card-foreground: 222 47% 11%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 0%; + + --primary: 200 85% 55%; + --primary-foreground: 0 0% 100%; + + --secondary: 210 40% 96%; + --secondary-foreground: 0 0% 0%; + + --muted: 210 40% 96%; + --muted-foreground: 0 0% 25%; + + --accent: 352 90% 60%; + --accent-foreground: 0 0% 0%; + + --destructive: 0 84% 60%; + --destructive-foreground: 210 40% 98%; + + --border: 214 32% 91%; + --input: 214 32% 91%; + --ring: 200 85% 70%; + + --mauria-bg: 0 0% 98%; + --mauria-card: 0 0% 100%; + --mauria-accent: 25 95% 60%; + --mauria-alert: 0 100% 95%; + --mauria-border: 214 32% 91%; + --mauria-purple: 0 0% 0%; + --mauria-text: 0 0% 0%; + + --mauria-white: 0 0% 100%; + --mauria-black: 0 0% 0%; + --mauria-accent-dark: 50 95% 58%; + --mauria-purple-soft: 0 0% 0%; + --mauria-purple-bright: 0 0% 0%; + --mauria-purple-light: 0 0% 0%; + --mauria-green: 135 65% 45%; + --mauria-green-dark: 135 65% 35%; + --mauria-green-soft: 135 65% 55%; + --mauria-planning-slot-border: 214 32% 91% / 0.4; + --mauria-planning-today: 50 95% 80% / 0.25; + --mauria-particles: 200 85% 60%; + --mauria-meteor-glow: 352 90% 70% / 0.25; + --mauria-chart-line: 270 50% 70%; + + --planning-button-text: hsl(var(--mauria-purple)); + --planning-button-background: hsl(var(--mauria-card)); + --planning-button-shadow: 0 12px 32px hsl(var(--mauria-purple) / 0.2); + --planning-button-active-gradient: linear-gradient( + 45deg, + hsl(var(--mauria-accent)), + hsl(var(--mauria-accent-dark)) + ); + --planning-button-active-shadow: 0 12px 24px hsl( + var(--mauria-accent) / 0.24 + ); + --planning-button-active-text: hsl(var(--mauria-white)); + + --planning-grid-background: hsl(var(--mauria-card)); + --planning-slot-border-color: hsl(var(--mauria-planning-slot-border)); + --planning-today-background: hsl(var(--mauria-planning-today)); + + --planning-event-default-gradient: linear-gradient( + 45deg, + hsl(25 95% 60%), + hsl(50 95% 58%) + ); + --planning-event-default-shadow: 0 16px 32px hsl(25 95% 60% / 0.28); + --planning-event-default-text: hsl(var(--mauria-black)); + --planning-event-default-solid: hsl(352 90% 65%); + + --planning-event-epreuve-gradient: linear-gradient( + 45deg, + hsl(330 85% 60%), + hsl(352 90% 65%) + ); + --planning-event-epreuve-shadow: 0 16px 32px hsl(330 85% 60% / 0.28); + --planning-event-epreuve-text: hsl(var(--mauria-black)); + + --planning-event-personal-gradient: linear-gradient( + 45deg, + hsl(135 65% 50%), + hsl(170 65% 45%) + ); + --planning-event-personal-shadow: 0 16px 32px hsl(135 65% 50% / 0.28); + --planning-event-personal-text: hsl(var(--mauria-black)); + + --planning-event-autogere-gradient: linear-gradient( + 45deg, + hsl(200 85% 60%), + hsl(240 70% 60%) + ); + --planning-event-autogere-shadow: 0 16px 32px hsl(200 85% 60% / 0.28); + --planning-event-autogere-text: hsl(var(--mauria-black)); + + --particles-color: hsl(var(--mauria-particles)); + --meteors-trail-glow: hsl(var(--mauria-meteor-glow)); + --chart-grid-stroke: hsl(var(--mauria-chart-line)); + --chart-dot-stroke: transparent; + --bubble-color-first: 255, 99, 132; + --bubble-color-second: 255, 159, 64; + --bubble-color-third: 255, 205, 86; + --bubble-color-fourth: 75, 192, 192; + --bubble-color-fifth: 54, 162, 235; + --bubble-color-sixth: 153, 102, 255; + --mauria-pride-gradient: linear-gradient( + 135deg, + hsl(352 90% 65%), + hsl(25 95% 60%), + hsl(50 95% 58%), + hsl(135 65% 50%), + hsl(200 85% 60%), + hsl(270 80% 65%) + ); + --mauria-pride-gradient-soft: linear-gradient( + 135deg, + hsl(352 90% 65% / 0.25), + hsl(25 95% 60% / 0.25), + hsl(50 95% 58% / 0.25), + hsl(135 65% 50% / 0.25), + hsl(200 85% 60% / 0.25), + hsl(270 80% 65% / 0.25) + ); + } .oled { color-scheme: dark; @@ -358,6 +856,37 @@ .oled .bg-mauria-accent\/20 { background-color: hsl(0 0% 16% / 0.65) !important; } + .pride header .text-white { + color: hsl(var(--mauria-black)); + } + .pride header .text-white:hover { + color: hsl(var(--mauria-black)); + } + .pride .bg-mauria-purple { + background-image: var(--mauria-pride-gradient); + background-color: transparent; + } + .pride .bg-mauria-purple\/10 { + background-image: var(--mauria-pride-gradient-soft); + background-color: transparent; + } + .pride .bg-mauria-accent { + background-image: var(--mauria-pride-gradient); + background-color: transparent; + } + .pride .bg-mauria-accent\/20 { + background-image: var(--mauria-pride-gradient-soft); + background-color: transparent; + } + .pride .bg-accent { + background-image: var(--mauria-pride-gradient-soft); + background-color: transparent; + } + .toaster [data-sonner-toast] { + background-color: hsl(var(--background)); + color: hsl(var(--foreground)); + border: 1px solid hsl(var(--border)); + } } /* diff --git a/vite.config.ts b/vite.config.ts index 77db572..aa2248f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,11 +3,16 @@ import react from "@vitejs/plugin-react"; import { resolve } from "path"; // https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - resolve: { - alias: { - "@": resolve(__dirname, "./src"), +export default defineConfig(() => { + const basePath = process.env.VITE_BASE_PATH ?? "/"; + + return { + base: basePath, + plugins: [react()], + resolve: { + alias: { + "@": resolve(__dirname, "./src"), + }, }, - }, + }; });