From d0bafacaba9bead3005ce26b3c10ebe76a5e90a8 Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:27:20 +0200 Subject: [PATCH 1/9] feat: conventions git --- CONVENTIONS.md | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 CONVENTIONS.md diff --git a/CONVENTIONS.md b/CONVENTIONS.md new file mode 100644 index 0000000..1758476 --- /dev/null +++ b/CONVENTIONS.md @@ -0,0 +1,106 @@ +# Git Convention Guide + +## Commits (Conventional Commits) + +### Format + +``` +type(scope?): description +``` + +### Types principaux + +* `feat`: nouvelle fonctionnalité +* `fix`: correction de bug +* `refactor`: modification interne sans changement fonctionnel +* `style`: formatage / UI mineur (pas de logique) +* `docs`: documentation +* `test`: ajout/modification de tests +* `chore`: maintenance (deps, config…) +* `perf`: amélioration de performance +* `build`: build / dépendances +* `ci`: intégration continue + +### Exemples + +``` +feat(auth): add login with CAS +fix(navbar): fix mobile display issue +refactor(api): simplify error handling +style(ui): adjust spacing in header +``` + +### Bonnes pratiques + +* écrire à l’impératif → `add`, `fix`, `update` +* description courte (-50 caractères) et explicite +* un commit = une seule intention + +### Breaking changes + +L'ajour d'un point d'exclamation est possible pour signifier un breaking change. +``` +feat!: remove old API +``` + +--- + +## Branches + +### Format + +``` +type/short-description +``` + +### Types + +* `feat/` +* `fix/` +* `refactor/` +* `chore/` +* `docs/` +* `perf/` +* `test/` + +### Exemples + +``` +feat/login-page +fix/navbar-mobile +refactor/auth-hooks +``` + +### Bonnes pratiques + +* utiliser kebab-case +* rester court et clair +* une branche = un objectif + +--- + +## Choisir le bon type (exemple avec le frontend) + +| Situation | Type | +| ------------------------ | -------- | +| Nouvelle feature visible | feat | +| Bug | fix | +| Refacto interne | refactor | +| Amélioration performance | perf | +| Ajustement visuel mineur | style | + +--- + +## Exemple workflow + +``` +prod + └── feat/login-page + |── fix(auth): login-error + └── style(auth): color for 2026 edition +``` + +1. créer une branche depuis prod +2. faire des commits propres +3. ouvrir une pull request +4. merge après review From f3331a5029f47f15dd9989a7c4f8e45dd0c6c7fb Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:32:06 +0200 Subject: [PATCH 2/9] update: footer & navbar standardization --- frontend/src/components/footer.tsx | 19 ++ frontend/src/components/navbar.tsx | 234 ++++++++++-------- frontend/src/pages/challenge.tsx | 19 +- frontend/src/pages/food.tsx | 23 +- frontend/src/pages/games.tsx | 19 +- frontend/src/pages/home.tsx | 7 +- frontend/src/pages/news.tsx | 19 +- frontend/src/pages/parrainage.tsx | 27 +- frontend/src/pages/perm.tsx | 21 +- frontend/src/pages/plannings.tsx | 7 +- frontend/src/pages/profil.tsx | 19 +- frontend/src/pages/sdi.tsx | 24 +- frontend/src/pages/shotgun.tsx | 5 +- frontend/src/pages/wei.tsx | 19 +- .../src/services/requests/user.service.ts | 79 +++--- 15 files changed, 290 insertions(+), 251 deletions(-) create mode 100644 frontend/src/components/footer.tsx diff --git a/frontend/src/components/footer.tsx b/frontend/src/components/footer.tsx new file mode 100644 index 0000000..9ef9bfd --- /dev/null +++ b/frontend/src/components/footer.tsx @@ -0,0 +1,19 @@ +export const Footer = () => { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/src/components/navbar.tsx b/frontend/src/components/navbar.tsx index 0b4d9c3..2693945 100644 --- a/frontend/src/components/navbar.tsx +++ b/frontend/src/components/navbar.tsx @@ -12,6 +12,10 @@ interface NavItem { to: string; icon?: React.ComponentType>; rolesAllowed?: string[]; // ["Admin", "Respo CE", ...] + public?: boolean; + showWhen?: "always" | "auth" | "guest"; + kind?: "link" | "action"; + onClick?: () => void; children?: NavItem[]; // pour dropdown } @@ -19,85 +23,106 @@ export const Navbar = () => { const { pathname } = useLocation(); const token = getToken(); const [menuOpen, setMenuOpen] = useState(false); + const isAuthenticated = Boolean(token); + const { userPermission, userRoles = [] } = token ? decodeToken(token) : { userPermission: undefined, userRoles: [] }; + const roles = [userPermission, ...userRoles.map(r => r.roleName)].filter(Boolean) as string[]; + + const handleLogout = () => { + localStorage.removeItem("authToken"); + window.location.href = "/"; + }; useEffect(() => { setMenuOpen(false); }, [pathname]); - if (!token) return null; - const { userPermission, userRoles = [] } = decodeToken(token); - const roles = [userPermission, ...userRoles.map(r => r.roleName)]; - const navItems: NavItem[] = [ - { label: "Home", to: "/Home", icon: HomeIcon }, - { label: "Plannings", to: "/Plannings" }, - { label: "Parrainage", to: "/Parrainage" }, - { label: "Challenges", to: "/Challenges" }, - { label: "Mes Actus", to: "/News" }, - { - label: "Permanences", - to: "#", - children: [ - { label: "Listes des permanences", to: "/PermanencesList", rolesAllowed: ["Admin", "Student"] }, - { label: "Mes permanences", to: "/MyPermanences", rolesAllowed: ["Admin", "Student"] }, - { label: "Faire l'appel", to: "/PermanencesAppeal", rolesAllowed: ["Admin", "Student"] }, - ], - }, - { - label: "Events", - to: "#", - children: [ - { label: "Shotgun", to: "/Shotgun", rolesAllowed: ["Admin", "Student"] }, - { label: "WEI", to: "/Wei" }, - { label: "SDI", to: "/SDI" }, - { label: "Repas", to: "/Food" }, - { label: "Defis Commissions", to: "/Games", rolesAllowed: ["Admin", "Student"] }, - ], - }, - { label: "Mon compte", to: "/Profil", icon: UsersIcon }, - { - label: "Admin", - to: "#", - icon: CogIcon, - children: [ - { label: "Users", to: "/admin/users", rolesAllowed: ["Admin"] }, - { label: "Roles", to: "/admin/roles", rolesAllowed: ["Admin"] }, - { label: "Teams", to: "/admin/teams", rolesAllowed: ["Admin", "Respo CE"] }, - { label: "Factions", to: "/admin/factions", rolesAllowed: ["Admin", "Respo CE"] }, - { label: "Events", to: "/admin/events", rolesAllowed: ["Admin"] }, - { label: "Permanences", to: "/admin/permanences", rolesAllowed: ["Admin", "Respo CE"] }, - { label: "Challenge", to: "/admin/challenge", rolesAllowed: ["Admin", "Arbitre"] }, - { label: "Export / Import", to: "/admin/export-import", rolesAllowed: ["Admin"] }, - { label: "Email", to: "/admin/email", rolesAllowed: ["Admin"] }, - { label: "News", to: "/admin/news", rolesAllowed: ["Admin", "Communication"] }, - { label: "Tentes", to: "/admin/tent", rolesAllowed: ["Admin"] }, - { label: "Bus", to: "/admin/bus", rolesAllowed: ["Admin"] }, - { label: "Games", to: "/admin/games", rolesAllowed: ["Admin"] }, - ], - }, - -]; + { label: "Home", to: "/Home", icon: HomeIcon }, + { label: "Plannings", to: "/Plannings" }, + { label: "Parrainage", to: "/Parrainage" }, + { label: "Challenges", to: "/Challenges" }, + { label: "Mes Actus", to: "/News" }, + { + label: "Permanences", + to: "#", + children: [ + { label: "Listes des permanences", to: "/PermanencesList", rolesAllowed: ["Admin", "Student"] }, + { label: "Mes permanences", to: "/MyPermanences", rolesAllowed: ["Admin", "Student"] }, + { label: "Faire l'appel", to: "/PermanencesAppeal", rolesAllowed: ["Admin", "Student"] }, + ], + }, + { + label: "Events", + to: "#", + children: [ + { label: "Shotgun", to: "/Shotgun", rolesAllowed: ["Admin", "Student"] }, + { label: "WEI", to: "/Wei" }, + { label: "SDI", to: "/SDI" }, + { label: "Repas", to: "/Food" }, + { label: "Defis Commissions", to: "/Games", rolesAllowed: ["Admin", "Student"] }, + ], + }, + { label: "Mon compte", to: "/Profil", icon: UsersIcon }, + { + label: "Admin", + to: "#", + icon: CogIcon, + children: [ + { label: "Users", to: "/admin/users", rolesAllowed: ["Admin"] }, + { label: "Roles", to: "/admin/roles", rolesAllowed: ["Admin"] }, + { label: "Teams", to: "/admin/teams", rolesAllowed: ["Admin", "Respo CE"] }, + { label: "Factions", to: "/admin/factions", rolesAllowed: ["Admin", "Respo CE"] }, + { label: "Events", to: "/admin/events", rolesAllowed: ["Admin"] }, + { label: "Permanences", to: "/admin/permanences", rolesAllowed: ["Admin", "Respo CE"] }, + { label: "Challenge", to: "/admin/challenge", rolesAllowed: ["Admin", "Arbitre"] }, + { label: "Export / Import", to: "/admin/export-import", rolesAllowed: ["Admin"] }, + { label: "Email", to: "/admin/email", rolesAllowed: ["Admin"] }, + { label: "News", to: "/admin/news", rolesAllowed: ["Admin", "Communication"] }, + { label: "Tentes", to: "/admin/tent", rolesAllowed: ["Admin"] }, + { label: "Bus", to: "/admin/bus", rolesAllowed: ["Admin"] }, + { label: "Games", to: "/admin/games", rolesAllowed: ["Admin"] }, + ], + }, + { + label: "Déconnexion", + to: "/", + kind: "action", + showWhen: "auth", + onClick: handleLogout, + }, + { + label: "Se connecter", + to: "/", + public: true, + showWhen: "guest", + }, + ]; - // helper d’autorisation - const isAllowed = (item: NavItem): boolean => { - // Si l'item a une restriction directe - if (item.rolesAllowed) { - return item.rolesAllowed.some(r => roles.includes(r)); - } - // Si l'item a des enfants, on vérifie au moins un enfant - if (item.children && item.children.length > 0) { - return item.children.some(child => isAllowed(child)); - } + const canShowItem = (item: NavItem): boolean => { + if (item.showWhen === "auth") return isAuthenticated; + if (item.showWhen === "guest") return !isAuthenticated; - // Sinon accessible par défaut - return true; -}; + if (!isAuthenticated) { + if (item.public) return true; - const handleLogout = () => { - localStorage.removeItem("authToken"); - window.location.href = "/"; + if (item.children && item.children.length > 0) { + return item.children.some(child => canShowItem(child)); + } + + return false; + } + + if (item.rolesAllowed) { + return item.rolesAllowed.some(r => roles.includes(r)); + } + + if (item.children && item.children.length > 0) { + return item.children.some(child => canShowItem(child)); + } + + return true; }; return ( @@ -124,24 +149,18 @@ export const Navbar = () => { {/* Menu desktop */}
    {navItems.map(item => - isAllowed(item) ? ( + canShowItem(item) ? (
  • {item.children ? ( - + + ) : item.kind === "action" ? ( + ) : ( )}
  • ) : null )} -
  • - -
@@ -155,24 +174,20 @@ export const Navbar = () => { className="lg:hidden bg-blue-700 overflow-hidden" > {navItems.map(item => - isAllowed(item) ? ( + canShowItem(item) ? ( {!item.children ? ( - + item.kind === "action" ? ( + + ) : ( + + ) ) : ( - + )} ) : null )} -
  • - -
  • )} @@ -180,6 +195,29 @@ export const Navbar = () => { ); }; +const NavActionItem = ({ + item, + mobile = false, +}: { + item: NavItem; + mobile?: boolean; +}) => { + const base = mobile ? "block py-2 px-4 text-left w-full" : "inline-flex items-center py-2"; + + return ( + + ); +}; + // Composant MenuItem const MenuItem = ({ item, @@ -207,26 +245,19 @@ const MenuItem = ({ ); }; -// Composant Dropdown (desktop & mobile) // Composant Dropdown (desktop & mobile) const Dropdown = ({ item, mobile = false, + canShowItem, }: { item: NavItem; mobile?: boolean; + canShowItem: (item: NavItem) => boolean; }) => { const [open, setOpen] = useState(false); const trigger = mobile ? "p-4" : "py-2 cursor-pointer"; - // helper pour roles - const token = getToken(); - const { userPermission, userRoles = [] } = token ? decodeToken(token) : {}; - const roles = [userPermission, ...(userRoles?.map((r: any) => r.roleName) || [])]; - - const isAllowed = (child: NavItem) => - !child.rolesAllowed || child.rolesAllowed.some(r => roles.includes(r)); - return (
    {item.children! - .filter(child => isAllowed(child)) // ✅ filtre selon les rôles + .filter(child => canShowItem(child)) .map(child => (
  • ( - -
    - -
    -
    - + +
    + +
    +
    + +
    +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    -
    ); diff --git a/frontend/src/pages/food.tsx b/frontend/src/pages/food.tsx index 5fc9180..e5aaae3 100644 --- a/frontend/src/pages/food.tsx +++ b/frontend/src/pages/food.tsx @@ -1,20 +1,19 @@ import { Navbar } from "../components/navbar"; -import { FoodSection } from "../components/WEI_SDI_Food/foodSection"; +import { FoodSection } from "../components/WEI_SDI_Food/foodSection" +import { Footer } from "../components/footer"; export const FoodPage = () => { - - return( + + return (
    - -
    -
    - -
    + +
    +
    +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    +
    - ); + ); } \ No newline at end of file diff --git a/frontend/src/pages/games.tsx b/frontend/src/pages/games.tsx index 36e46b7..08aa247 100644 --- a/frontend/src/pages/games.tsx +++ b/frontend/src/pages/games.tsx @@ -1,18 +1,17 @@ import { RoleLeaderboard } from "../components/Games/roleLeaderboard"; import { Navbar } from "../components/navbar"; +import { Footer } from "../components/footer"; export const GamesPage = () => ( - -
    - -
    -
    - + +
    + +
    +
    + +
    +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    -
    ); diff --git a/frontend/src/pages/home.tsx b/frontend/src/pages/home.tsx index 9508ce1..d0d9b19 100644 --- a/frontend/src/pages/home.tsx +++ b/frontend/src/pages/home.tsx @@ -1,7 +1,8 @@ // src/pages/index.tsx import { Navbar } from "../components/navbar"; import { Infos } from "../components/home/infosSection"; -import {SocialLinks} from "../components/home/socialSection"; +import { SocialLinks } from "../components/home/socialSection"; +import { Footer } from "../components/footer"; export const HomePage = () => { @@ -11,9 +12,7 @@ export const HomePage = () => { -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    ); } diff --git a/frontend/src/pages/news.tsx b/frontend/src/pages/news.tsx index 73bee95..32b03bf 100644 --- a/frontend/src/pages/news.tsx +++ b/frontend/src/pages/news.tsx @@ -1,17 +1,16 @@ import { Navbar } from "../components/navbar"; import { MyNews } from "../components/news/newsSection"; +import { Footer } from "../components/footer"; export const NewsPage = () => ( - -
    - -
    -
    - + +
    + +
    +
    + +
    +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    -
    ); diff --git a/frontend/src/pages/parrainage.tsx b/frontend/src/pages/parrainage.tsx index 38191aa..82bf5d1 100644 --- a/frontend/src/pages/parrainage.tsx +++ b/frontend/src/pages/parrainage.tsx @@ -2,6 +2,7 @@ import { Navbar } from "../components/navbar"; import { useNavigate } from "react-router-dom"; import { ParrainageNewStudent, ParrainageStudent } from "../components/Parrainnage/parrainageForm"; import { getPermission } from "../services/requests/user.service"; +import { Footer } from "../components/footer"; export const ParrainagePage = () => { @@ -12,23 +13,21 @@ export const ParrainagePage = () => { if (!permission) { navigate("/"); return null; -} - return( -
    - -
    -
    + } + return ( +
    + +
    +
    - {(permission === "Nouveau" || permission === "Admin") && ( - )} + {(permission === "Nouveau" || permission === "Admin") && ( + )} - {(permission === "Student" || permission === "Admin") && ( - )} + {(permission === "Student" || permission === "Admin") && ( + )} +
    +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    -
    ); } \ No newline at end of file diff --git a/frontend/src/pages/perm.tsx b/frontend/src/pages/perm.tsx index 9e35979..991cf3f 100644 --- a/frontend/src/pages/perm.tsx +++ b/frontend/src/pages/perm.tsx @@ -16,6 +16,7 @@ import { DecodedToken } from "../interfaces/token.interfaces"; import { Navbar } from "../components/navbar"; import { RespoPresenceManagement } from "../components/permanence/appealPerm"; import { MyPermanencesList } from "../components/permanence/permUser"; +import { Footer } from "../components/footer"; export const AvailablePermanencesPage: React.FC = () => { const [permanences, setPermanences] = useState([]); @@ -59,16 +60,16 @@ export const AvailablePermanencesPage: React.FC = () => { return (
    -
    +
    - -
    + />
    +
    ); }; @@ -133,14 +134,14 @@ export const MyPermanencesPage: React.FC = () => { return (
    -
    +
    - -
    + />
    +
    ); }; @@ -192,9 +193,7 @@ export const RespoCallPage = () => { )}
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    ); }; diff --git a/frontend/src/pages/plannings.tsx b/frontend/src/pages/plannings.tsx index ca8f0bb..2a5c2d5 100644 --- a/frontend/src/pages/plannings.tsx +++ b/frontend/src/pages/plannings.tsx @@ -1,5 +1,6 @@ import { Navbar } from "../components/navbar"; import { PlanningSection } from "../components/Plannings/planningSection"; +import { Footer } from "../components/footer"; export const PlanningsPage = () => ( @@ -7,11 +8,9 @@ export const PlanningsPage = () => (
    - +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    ); \ No newline at end of file diff --git a/frontend/src/pages/profil.tsx b/frontend/src/pages/profil.tsx index 43afa08..da84fca 100644 --- a/frontend/src/pages/profil.tsx +++ b/frontend/src/pages/profil.tsx @@ -3,26 +3,25 @@ import { Navbar } from "../components/navbar"; import { UserPreferences } from "../components/profil/roleForm"; import { getPermission } from "../services/requests/user.service"; import { ProfilForm } from "../components/profil/profilForm"; +import { Footer } from "../components/footer"; export const ProfilPage = () => { - const navigate = useNavigate(); - const permission = getPermission(); + const navigate = useNavigate(); + const permission = getPermission(); - if (!permission) { - navigate("/"); - return null; - } + if (!permission) { + navigate("/"); + return null; + } return (
    - < ProfilForm/> + {(permission === "Student" || permission === "Admin") && ()} -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    ); } \ No newline at end of file diff --git a/frontend/src/pages/sdi.tsx b/frontend/src/pages/sdi.tsx index 016af1b..9e80517 100644 --- a/frontend/src/pages/sdi.tsx +++ b/frontend/src/pages/sdi.tsx @@ -1,20 +1,18 @@ import { Navbar } from "../components/navbar"; -import { SdiSection } from "../components/WEI_SDI_Food/sdiSection"; - +import { SdiSection } from "../components/WEI_SDI_Food/sdiSection"; +import { Footer } from "../components/footer"; export const SdiPage = () => { - - return( + + return (
    - -
    -
    - -
    + +
    +
    +
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    +
    - ); + ); } \ No newline at end of file diff --git a/frontend/src/pages/shotgun.tsx b/frontend/src/pages/shotgun.tsx index a8ef5e6..0a8bb3b 100644 --- a/frontend/src/pages/shotgun.tsx +++ b/frontend/src/pages/shotgun.tsx @@ -2,6 +2,7 @@ import { Navbar } from "../components/navbar"; import { PreregisterCESection } from "../components/shotgun/preregisterCESection"; import { PreregisterTeamSection } from "../components/shotgun/preregisterTeamSection"; import { Shotgun } from "../components/shotgun/shotgunSection"; +import { Footer } from "../components/footer"; export const ShotgunPage = () => ( @@ -15,8 +16,6 @@ export const ShotgunPage = () => (
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    ); diff --git a/frontend/src/pages/wei.tsx b/frontend/src/pages/wei.tsx index 88377e5..e7fdf5e 100644 --- a/frontend/src/pages/wei.tsx +++ b/frontend/src/pages/wei.tsx @@ -3,17 +3,18 @@ import { WeiSection } from "../components/WEI_SDI_Food/weiSection"; import { TentPublic } from "../components/tent/tentSection"; import { useNavigate } from "react-router-dom"; import { getPermission } from "../services/requests/user.service"; +import { Footer } from "../components/footer"; export const WeiPage = () => { - const navigate = useNavigate(); - const permission = getPermission(); + const navigate = useNavigate(); + const permission = getPermission(); + + if (!permission) { + navigate("/"); + return null; + } - if (!permission) { - navigate("/"); - return null; - } - return (
    @@ -23,9 +24,7 @@ export const WeiPage = () => { {(permission === "Nouveau" || permission === "Admin") && }
    -
    -

    © 2025 Semaine d'Intégration UTT

    -
    +
    ); }; \ No newline at end of file diff --git a/frontend/src/services/requests/user.service.ts b/frontend/src/services/requests/user.service.ts index 9f5d316..f7e5cf1 100644 --- a/frontend/src/services/requests/user.service.ts +++ b/frontend/src/services/requests/user.service.ts @@ -3,90 +3,93 @@ import { User } from '../../interfaces/user.interface'; import api from '../api'; export const getPermission = (): string | null => { - const token = localStorage.getItem('authToken'); - if (token) { - try { - // Suppose que le token est un JWT et qu'il contient un payload avec un rôle - const decodedToken = JSON.parse(atob(token.split('.')[1])); // Décodage du token JWT - return decodedToken?.userPermission || null; // Retourne le rôle ou null - } catch (error) { - console.error('Erreur lors du décodage du token:', error); - return null; - } + const token = localStorage.getItem('authToken'); + if (token) { + try { + // Suppose que le token est un JWT et qu'il contient un payload avec un rôle + const decodedToken = JSON.parse(atob(token.split('.')[1])); // Décodage du token JWT + return decodedToken?.userPermission || null; // Retourne le rôle ou null + } catch (error) { + console.error('Erreur lors du décodage du token:', error); + return null; } - return null; - }; + } + return null; +}; export const isAdmin = (): boolean => { return getPermission() === 'Admin'; }; +export const isConnected = (): boolean => { + return getPermission() !== null; +}; export const getUsers = async () => { - const response = await api.get("/user/user/getusers"); - const users = response.data.data; - - return users; + const response = await api.get("/user/user/getusers"); + const users = response.data.data; + + return users; } export const getUsersAdmin = async () => { - const response = await api.get("/user/admin/getusers"); - const users = response.data.data; - - return users; - + const response = await api.get("/user/admin/getusers"); + const users = response.data.data; + + return users; + } export const getUsersByPermission = async () => { - const response = await api.get("/user/admin/getusersbypermission"); - const users = response.data.data; - - return users; + const response = await api.get("/user/admin/getusersbypermission"); + const users = response.data.data; + + return users; } export const getCurrentUser = async () => { - const res = await api.get("/user/user/me"); + const res = await api.get("/user/user/me"); return res.data.data; }; export const updateCurrentUser = async (data: Partial) => { - const response = await api.patch("/user/user/me", data); - return response.data + const response = await api.patch("/user/user/me", data); + return response.data }; export const updateUserByAdmin = async (id: number, data: Partial) => { - - const response = await api.patch(`/user/admin/user/${id}`, data); - return response.data + + const response = await api.patch(`/user/admin/user/${id}`, data); + return response.data }; export const deleteUserByAdmin = async (id: number) => { - const response = await api.delete(`/user/admin/user/${id}`); - return response.data + const response = await api.delete(`/user/admin/user/${id}`); + return response.data }; export const syncnewStudent = async (date: string) => { - const response = await api.post(`/user/admin/syncnewstudent/`,{date}); - return response.data + const response = await api.post(`/user/admin/syncnewstudent/`, { date }); + return response.data }; -export const syncDiscordUser = async(code : string) =>{ +export const syncDiscordUser = async (code: string) => { - const response = await api.post(`/discord/user/callback/`,{code}); - return response.data + const response = await api.post(`/discord/user/callback/`, { code }); + return response.data } From 5e94362b778fa40206f540fa1d46953439378f2c Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:34:54 +0200 Subject: [PATCH 3/9] update: "close" message standardization --- .../components/Parrainnage/parrainageForm.tsx | 4 +- .../components/Plannings/planningSection.tsx | 2 +- .../components/WEI_SDI_Food/sdiSection.tsx | 4 +- .../components/challenge/challengeList.tsx | 42 +++++++++---------- .../shotgun/preregisterCESection.tsx | 2 +- .../shotgun/preregisterTeamSection.tsx | 2 +- .../src/components/shotgun/shotgunSection.tsx | 11 +++-- 7 files changed, 33 insertions(+), 34 deletions(-) diff --git a/frontend/src/components/Parrainnage/parrainageForm.tsx b/frontend/src/components/Parrainnage/parrainageForm.tsx index 78eecf5..39e1837 100644 --- a/frontend/src/components/Parrainnage/parrainageForm.tsx +++ b/frontend/src/components/Parrainnage/parrainageForm.tsx @@ -20,7 +20,7 @@ export const ParrainageNewStudent = () => {
  • */}

    - 🚫 Ce formulaire n’est pas encore disponible. + 🚫 Ce formulaire n'est pas encore disponible.

    @@ -49,7 +49,7 @@ export const ParrainageStudent = () => { */}

    - 🚫 Ce formulaire n’est pas encore disponible. + 🚫 Ce formulaire n'est pas encore disponible.

    diff --git a/frontend/src/components/Plannings/planningSection.tsx b/frontend/src/components/Plannings/planningSection.tsx index 87dab9c..9c9f725 100644 --- a/frontend/src/components/Plannings/planningSection.tsx +++ b/frontend/src/components/Plannings/planningSection.tsx @@ -99,7 +99,7 @@ export const PlanningSection = () => { ) : (

    - 🚫 Ce planning n’est pas encore disponible. + 🚫 Ce planning n'est pas encore disponible.

    )} diff --git a/frontend/src/components/WEI_SDI_Food/sdiSection.tsx b/frontend/src/components/WEI_SDI_Food/sdiSection.tsx index 977e4b9..6d1d0df 100644 --- a/frontend/src/components/WEI_SDI_Food/sdiSection.tsx +++ b/frontend/src/components/WEI_SDI_Food/sdiSection.tsx @@ -30,14 +30,14 @@ export const SdiSection = () => { 🎉 Participe à la Soirée d'Intégration (SDI) !

    - Un événement incroyable t’attend… Inscris-toi dès maintenant pour ne rien rater de cette Soirée d’Intégration 2025 ! + Un événement incroyable t'attend… Inscris-toi dès maintenant pour ne rien rater de cette Soirée d'Intégration 2025 !

    {!isSDIOpen ? (

    - 🚫 La billetterie de la Soirée d'intégration(SDI) n’est pas encore disponible. + 🚫 La billetterie de la Soirée d'intégration(SDI) n'est pas encore disponible.

    Reste connecté, elle ouvrira bientôt ! diff --git a/frontend/src/components/challenge/challengeList.tsx b/frontend/src/components/challenge/challengeList.tsx index 9c5a35d..1f99736 100644 --- a/frontend/src/components/challenge/challengeList.tsx +++ b/frontend/src/components/challenge/challengeList.tsx @@ -16,25 +16,25 @@ export const UserChallengeList = () => { const [isChallOpen, setIsChallOpen] = useState(false); const [loading, setLoading] = useState(true); - useEffect(() => { - const init = async () => { - try { - await fetchInitialData(); - const status = await checkChallengeStatus(); - setIsChallOpen(status); - } catch (error) { - console.error("Erreur lors de la récupération des données :", error); - await Swal.fire({ - icon: "error", - title: "Oups...", - text: "Une erreur est survenue lors de la récupération des données.", - }); - } finally { - setLoading(false); - } - }; - init(); -}, []); + useEffect(() => { + const init = async () => { + try { + await fetchInitialData(); + const status = await checkChallengeStatus(); + setIsChallOpen(status); + } catch (error) { + console.error("Erreur lors de la récupération des données :", error); + await Swal.fire({ + icon: "error", + title: "Oups...", + text: "Une erreur est survenue lors de la récupération des données.", + }); + } finally { + setLoading(false); + } + }; + init(); + }, []); const fetchInitialData = async () => { await Promise.all([fetchChallenges(), fetchFactions()]); @@ -44,7 +44,7 @@ export const UserChallengeList = () => { const fetchChallenges = async () => { try { const challenges = await getAllChallenges(); - const challengesFiltered = challenges.filter((c : Challenge) => c.category != "Free") + const challengesFiltered = challenges.filter((c: Challenge) => c.category != "Free") setAvailableChallenges(challengesFiltered); } catch (err) { console.error("Erreur lors du chargement des challenges", err); @@ -122,7 +122,7 @@ export const UserChallengeList = () => { {loading ? (

    Chargement en cours...

    ) : !isChallOpen ? ( -

    +

    🚫 Les challenges ne sont pas encore ouverts.

    ) : availableChallenges.length === 0 ? ( diff --git a/frontend/src/components/shotgun/preregisterCESection.tsx b/frontend/src/components/shotgun/preregisterCESection.tsx index 9f29082..edc6de7 100644 --- a/frontend/src/components/shotgun/preregisterCESection.tsx +++ b/frontend/src/components/shotgun/preregisterCESection.tsx @@ -40,7 +40,7 @@ export const PreregisterCESection = () => { ) : (

    - La pré-inscription est actuellement fermée. + 🚫 La pré-inscription est actuellement fermée.

    )}
    diff --git a/frontend/src/components/shotgun/preregisterTeamSection.tsx b/frontend/src/components/shotgun/preregisterTeamSection.tsx index 84c057d..e4b665d 100644 --- a/frontend/src/components/shotgun/preregisterTeamSection.tsx +++ b/frontend/src/components/shotgun/preregisterTeamSection.tsx @@ -152,7 +152,7 @@ export const PreregisterTeamSection = () => { ) : (

    - La pré-inscription est actuellement fermée. + 🚫 La pré-inscription est actuellement fermée.

    )} diff --git a/frontend/src/components/shotgun/shotgunSection.tsx b/frontend/src/components/shotgun/shotgunSection.tsx index 0da54c8..5d84bcf 100644 --- a/frontend/src/components/shotgun/shotgunSection.tsx +++ b/frontend/src/components/shotgun/shotgunSection.tsx @@ -75,11 +75,10 @@ export const Shotgun = () => { {message && (

    {message}

    @@ -87,7 +86,7 @@ export const Shotgun = () => { ) : (

    - Le shotgun n'est pas encore ouvert. + 🚫 Le shotgun n'est pas encore ouvert.

    )} From bb3ed5517b8edc950dafb6159d302a7e608a266b Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:35:25 +0200 Subject: [PATCH 4/9] feat: legals & privacy pages --- frontend/src/App.tsx | 4 + .../src/components/legals/legalsSection.tsx | 98 +++++++++++++ frontend/src/pages/legals.tsx | 15 ++ frontend/src/pages/privacy.tsx | 15 ++ frontend/src/privacy/privacySection.tsx | 130 ++++++++++++++++++ 5 files changed, 262 insertions(+) create mode 100644 frontend/src/components/legals/legalsSection.tsx create mode 100644 frontend/src/pages/legals.tsx create mode 100644 frontend/src/pages/privacy.tsx create mode 100644 frontend/src/privacy/privacySection.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 07d0cab..d462ac1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -38,6 +38,8 @@ import { GamesPage } from './pages/games'; import { FoodPage } from './pages/food'; import { PlanningsPage } from './pages/plannings'; import { Roadbook } from './pages/roadbook'; +import { PrivacyPage } from './pages/privacy'; +import { LegalsPage } from './pages/legals'; const App: React.FC = () => { @@ -64,6 +66,8 @@ const App: React.FC = () => { } /> } /> } /> + } /> + } /> {/* Utilisateurs connectés */} } /> diff --git a/frontend/src/components/legals/legalsSection.tsx b/frontend/src/components/legals/legalsSection.tsx new file mode 100644 index 0000000..c8c03df --- /dev/null +++ b/frontend/src/components/legals/legalsSection.tsx @@ -0,0 +1,98 @@ +import { Link } from "react-router-dom"; + +export const LegalsSection = () => { + return ( +
    +
    +
    +

    Mentions Légales

    +

    Informations légales et conformité RGPD

    +
    + +
    +
    +

    Editeur du Site

    +
    +
    +

    BDE UTT

    +

    Association loi 1901

    +

    N° RNA : W103000735

    +

    N° SIRET : 44838667200019

    +

    N° SIREN : 448386672

    +
    +
    +

    + 12 rue Marie Curie +
    + 10000 TROYES +

    +

    + 03 25 71 76 00 +

    +

    + bde@utt.fr +

    +
    +
    +

    + Le projet Intégration UTT est porté par l'association BDE UTT. +

    +
    + +
    +

    Propriétaire et Hébergeur

    +
    +
    +

    UTT Net Group

    +

    Association loi 1901

    +

    N° RNA : W103000699

    +

    N° RCS : 500164249

    +
    +
    +

    + 12 rue Marie Curie +
    + 10000 TROYES +

    +

    + 03 25 71 85 50 +

    +

    + ung@utt.fr +

    +
    +
    +
    + +
    +

    Protection des Données Personnelles

    +

    + Le site collecte et traite des données personnelles conformément a la loi Informatique et Libertés du 6 janvier 1978 modifiée et au RGPD EU-2016/679. +

    +

    + Pour plus d'informations, consultez notre{" "} + + Politique de confidentialite + + . +

    +
    + +
    +

    Droits d'Auteur

    +

    + L'ensemble du contenu de ce site est protegé par le droit d'auteur. Sauf mention contraire, les contenus relatifs au projet Integration UTT sont diffusés sous la responsabilité du BDE UTT. Toute reproduction, distribution ou modification est interdite sans autorisation écrite préalable. +

    +
    + +
    +

    Credits

    +

    + Ce site est developpé pour le projet Integration UTT du BDE UTT, avec le support technique de l'association UTT Net Group. +

    +
    +
    +
    +
    + ); +}; \ No newline at end of file diff --git a/frontend/src/pages/legals.tsx b/frontend/src/pages/legals.tsx new file mode 100644 index 0000000..697bb32 --- /dev/null +++ b/frontend/src/pages/legals.tsx @@ -0,0 +1,15 @@ +// src/pages/legals.tsx +import { Navbar } from "../components/navbar"; +import { Footer } from "../components/footer"; +import { LegalsSection } from "../components/legals/legalsSection"; + +export const LegalsPage = () => { + + return ( +
    + + +
    +
    + ); +} diff --git a/frontend/src/pages/privacy.tsx b/frontend/src/pages/privacy.tsx new file mode 100644 index 0000000..21789a9 --- /dev/null +++ b/frontend/src/pages/privacy.tsx @@ -0,0 +1,15 @@ +// src/pages/privacy.tsx +import { Navbar } from "../components/navbar"; +import { Footer } from "../components/footer"; +import { PrivacySection } from "../privacy/privacySection"; + +export const PrivacyPage = () => { + + return ( +
    + + +
    +
    + ); +} diff --git a/frontend/src/privacy/privacySection.tsx b/frontend/src/privacy/privacySection.tsx new file mode 100644 index 0000000..dd21fdd --- /dev/null +++ b/frontend/src/privacy/privacySection.tsx @@ -0,0 +1,130 @@ +import { Link } from "react-router-dom"; + +export const PrivacySection = () => { + return ( +
    +
    +
    +

    Politique de Confidentialité

    +

    Vos données personnelles et votre vie privée

    +
    + +
    +
    +

    Vie Privée et Données à Caractère Personnel

    +

    + A l'Université de Technologie de Troyes et au sein des associations BDE UTT et UTT Net Group, nous respectons votre vie privée. Les données collectées et utilisées par la plateforme Integration UTT sont nécessaires pour la gestion des membres, des inscriptions aux évènements et des services propoés pendant l'intégration. +

    +
    + +
    +

    Données Personnelles Collectées

    +

    + Les données suivantes sont effectivement stockées et traitées par la plateforme Intégration UTT. +

    +
      +
    • Identité: nom, prenom
    • +
    • Coordonnées: adresse email UTT, contact saisi dans le profil (optionnel)
    • +
    • Données de compte: mot de passe de connexion chiffré, date de création
    • +
    • Informations profil: branche/niveau suivie à l'UTT, majorité
    • +
    • Liaison externe optionnelle: identifiant Discord en cas de connexion Discord (optionnel)
    • +
    • Organisation intégration: éuipe, faction, rôles et préférences de rôles/commissions (optionnel, pour les organisateurs uniquement)
    • +
    • Participation aux services: inscriptions permanences, attribution bus, binôme tente, validations de challenges
    • +
    +
    + +
    +

    Comment Ces Informations Sont-Elles Utilisées ?

    +

    + Les données à caractère personnel sont des informations qui permettent sous quelque forme que ce soit, directement ou indirectement, l'identification des personnes physiques auxquelles elles s'appliquent. +

    +

    Ces informations sont utilisées pour :

    +
      +
    • Permettre l'authentification (mot de passe ou CAS), la gestion de session et la sécurisation des accès
    • +
    • Gérer les comptes utilisateurs, les droits d'accès et les rôles d'organisation
    • +
    • Permettre les fonctionnalités du site: profil, affectations d'equipes/factions, permanences, bus, tentes, challenges et évènements
    • +
    • Afficher certaines informations aux organisateurs pour la coordination opérationnelle (ex: contact, équipe, rôle)
    • +
    • Lier un compte Discord lorsque l'utilisateur active cette option
    • +
    • Executer des opérations d'administration (support, import/export, modération et gestion interne)
    • +
    +
    + +
    +

    Durée de Conservation des Données

    +

    + Les données personnelles sont conservées pendant un (1) an maximum, puis supprimées. +
    + Des données anonymisées peuvent être conservées à des fins statistiques et d'amélioration du service, mais ne permettent pas l'identification des individus. +

    +

    Les cookies de session sont détruits à la déconnexion ou à leur expiration.

    +
    + +
    +

    Vos Droits sur Vos Données

    +

    Conformément à la réglementation sur les données à caractère personnel, vous disposez des droits suivants :

    +
      +
    • Droit d'accès : obtenir une copie de vos données
    • +
    • Droit de rectification : corriger des données inexactes vous concernant
    • +
    • Droit à l'effacement : demander la suppression de vos données
    • +
    • Droit d'opposition : vous opposer au traitement de vos données
    • +
    • Droit à la portabilité : récupérer vos données dans un format structuré
    • +
    +
    + +
    +

    Comment Exercer Vos Droits ?

    +

    Si vous avez des questions ou que vous souhaitez exercer vos droits (accès, rectification, suppression), vous pouvez :

    +
      +
    • + Envoyer un courriel à {" "} + + integration@utt.fr + +
    • +
    • + Contacter le délégué à la protection des données :{" "} + + ung+dpo@utt.fr + +
    • +
    • + Par courrier : UTT Net Group, 12 rue Marie Curie, CS 42060, 10004 TROYES CEDEX +
    • +
    +

    + Si vous estimez, après nous avoir contacté, que vos droits ne sont pas respectés, vous pouvez adresser une réclamation en ligne à la CNIL ou par voie postale. +

    +
    + +
    +

    Responsable du Traitement

    +

    + Le responsable du traitement des données pour la plateforme Intégration UTT est Arthur Dodin, Président de l'association UTT Net Group. +

    +

    + L'équipe technique et les administrateurs du site pourront accéder aux données dans le cadre de la gestion de la plateforme et du support technique. +

    +
    + +
    +

    Sécurité des Données

    +

    + Nous mettons en œuvre toutes les mesures techniques et organisationnelles appropriées afin de garantir un niveau de sécurité adapté au risque, conformément aux exigences du RGPD. +

    +

    Ces données ne seront en aucun cas échangées, distribuées ou vendues à un tiers.

    +
    + +
    +

    Cookies

    +

    + Nous utilisons des cookies afin d'obtenir des statistiques sur notre site web. Ces informations ne seront en aucun cas vendues, échangées ou données. Ces cookies sont anonymisés. +

    +

    + Afin d'assurer le fonctionnement du service à l'utilisateur authentifié, des cookies de session sont inscrits sur le navigateur lors de l'authentification sur le site. Ceux-ci ont pour seule fonction d'assurer la persistance de la session authentifiée de l'utilisateur. Ils sont détruits lors de la déconnexion ou à leur expiration. +

    +
    +
    +
    +
    + ); +}; \ No newline at end of file From fd503934215a8afdf5fb0d59bad9e3a682676faa Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:40:37 +0200 Subject: [PATCH 5/9] update(home): vertical centered image --- frontend/src/components/home/infosSection.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/home/infosSection.tsx b/frontend/src/components/home/infosSection.tsx index 1688e5c..1d34cdc 100644 --- a/frontend/src/components/home/infosSection.tsx +++ b/frontend/src/components/home/infosSection.tsx @@ -8,23 +8,22 @@ export const Infos = () => { return (
    {/* Hero Carousel */} -
    +
    {["Home1", "Home2", "Home3", "Home4"].map((img, i) => ( - + {`Photo {/* Overlay sombre */}
    From 3935d6982bf256155b77319172191bdcd6f6bf6c Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:41:01 +0200 Subject: [PATCH 6/9] update(home): 2026 factions --- frontend/src/components/home/infosSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/home/infosSection.tsx b/frontend/src/components/home/infosSection.tsx index 1d34cdc..4e23515 100644 --- a/frontend/src/components/home/infosSection.tsx +++ b/frontend/src/components/home/infosSection.tsx @@ -68,7 +68,7 @@ export const Infos = () => { La petite histoire

    - Chaque année, deux factions composées d'une multitude d'équipes s'affrontent. Le thème de cette année : Vilains vs Justiciers. + Chaque année, deux factions composées d'une multitude d'équipes s'affrontent. Le thème de cette année : Divinités vs Monstres.

    From 2b8493e8ff7ebc23d2412dffce4d281449bbb499 Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 18:41:47 +0200 Subject: [PATCH 7/9] feat(profil): highlight contact input when empty --- frontend/src/components/profil/profilForm.tsx | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/profil/profilForm.tsx b/frontend/src/components/profil/profilForm.tsx index 55eb0ef..b22662a 100644 --- a/frontend/src/components/profil/profilForm.tsx +++ b/frontend/src/components/profil/profilForm.tsx @@ -20,7 +20,7 @@ const branchOptions = [ { value: "SN_APPR", label: "Systeme Numérique en Apprentissage" }, { value: "Branch", label: "Branche" }, { value: "MM", label: "Mécanique et Matériaux" }, - { value : "Master", label: "Master"}, + { value: "Master", label: "Master" }, { value: "RI", label: "Ressources International" }, ]; @@ -46,7 +46,7 @@ export const ProfilForm = () => { const handleSubmit = async () => { setLoading(true); - const response = await updateCurrentUser({ branch : branch, contact : contact }); + const response = await updateCurrentUser({ branch: branch, contact: contact }); alert(response.message); setLoading(false); }; @@ -92,33 +92,37 @@ export const ProfilForm = () => { isClearable />
    -
    - - setContact(e.target.value)} /> +
    + {user.permission === "Student" || user.permission === "Admin" ? ( + + ) : ( + + )} + setContact(e.target.value)} className={user.contact === null || user.contact === "" ? "bg-white" : ""} />
    - <> - {user.discord_id ? ( -
    - ✅ Ton compte Discord est bien lié ! -
    - ) : ( - - )} - + <> + {user.discord_id ? ( +
    + ✅ Ton compte Discord est bien lié ! +
    + ) : ( + + )} + -
    +
    ); }; From b3dc0ea9c222a579a55162974d3e0023ba454e61 Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 19:53:10 +0200 Subject: [PATCH 8/9] lint: fix --- .../{ => components}/privacy/privacySection.tsx | 2 -- frontend/src/pages/privacy.tsx | 2 +- frontend/tsconfig.json | 14 ++++++++++---- 3 files changed, 11 insertions(+), 7 deletions(-) rename frontend/src/{ => components}/privacy/privacySection.tsx (99%) diff --git a/frontend/src/privacy/privacySection.tsx b/frontend/src/components/privacy/privacySection.tsx similarity index 99% rename from frontend/src/privacy/privacySection.tsx rename to frontend/src/components/privacy/privacySection.tsx index dd21fdd..b82a8b8 100644 --- a/frontend/src/privacy/privacySection.tsx +++ b/frontend/src/components/privacy/privacySection.tsx @@ -1,5 +1,3 @@ -import { Link } from "react-router-dom"; - export const PrivacySection = () => { return (
    diff --git a/frontend/src/pages/privacy.tsx b/frontend/src/pages/privacy.tsx index 21789a9..77b9090 100644 --- a/frontend/src/pages/privacy.tsx +++ b/frontend/src/pages/privacy.tsx @@ -1,7 +1,7 @@ // src/pages/privacy.tsx import { Navbar } from "../components/navbar"; import { Footer } from "../components/footer"; -import { PrivacySection } from "../privacy/privacySection"; +import { PrivacySection } from "../components/privacy/privacySection"; export const PrivacyPage = () => { diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index fec8c8e..20ff94b 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,13 +1,19 @@ { "files": [], "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } ], "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] } } -} +} \ No newline at end of file From 72cef2705b669b5ccff3f3825b9ea2caa7536718 Mon Sep 17 00:00:00 2001 From: Arthur Dodin Date: Sun, 12 Apr 2026 20:06:48 +0200 Subject: [PATCH 9/9] ci: fix with npm 10 --- backend/package-lock.json | 389 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) diff --git a/backend/package-lock.json b/backend/package-lock.json index 42f6889..f252eba 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -219,6 +219,395 @@ "source-map-support": "^0.5.21" } }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, "node_modules/@esbuild-kit/esm-loader": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",