Compare commits
No commits in common. "a36aca1ad3eaf9f42973c66061f39f6769dba122" and "bbdbb1aec1e1a2d3cca65e32b5263a111cc16a36" have entirely different histories.
a36aca1ad3
...
bbdbb1aec1
@ -1,195 +0,0 @@
|
||||
import { onUpdateConsentCookie, onAcceptAllConsentCookie, type ConsentCookies } from "./Cookies.telefunc";
|
||||
import React, { useState, useContext, createContext } from "react";
|
||||
import { usePageContext } from "vike-react/usePageContext";
|
||||
import { reload } from "vike/client/router";
|
||||
import { Button } from "@syntax/Button";
|
||||
import { toast } from "react-toastify";
|
||||
import { Toggle } from "./Toggle";
|
||||
import { Link } from "./Link";
|
||||
|
||||
export const CookiesContext = createContext<{
|
||||
cookies: {
|
||||
analytics: boolean;
|
||||
customization: boolean;
|
||||
};
|
||||
setCookie: (cookieName: ConsentCookies, cookieValue: boolean) => void;
|
||||
acceptAll: () => void;
|
||||
isOpen: boolean;
|
||||
setIsOpen: (isOpen: boolean) => void;
|
||||
isSelectionOpen: boolean;
|
||||
setIsSelectionOpen: (isSelectionOpen: boolean) => void;
|
||||
}>({
|
||||
cookies: {
|
||||
analytics: false,
|
||||
customization: false,
|
||||
},
|
||||
setCookie: (_cookieName: ConsentCookies, _cookieValue: boolean) => {},
|
||||
acceptAll: () => {},
|
||||
isOpen: false,
|
||||
setIsOpen: () => {},
|
||||
isSelectionOpen: false,
|
||||
setIsSelectionOpen: () => {},
|
||||
});
|
||||
|
||||
type CookiesContainerProps = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export function CookiesContainer(props: CookiesContainerProps) {
|
||||
const { cookies } = usePageContext();
|
||||
|
||||
const [consentCookies, setConsentCookies] = useState(cookies.consent);
|
||||
const [isSelectionOpen, setIsSelectionOpen] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(() => {
|
||||
return !Object.keys(cookies.consent).every((value) => value);
|
||||
});
|
||||
|
||||
const handleUpdateCookie = (cookieName: ConsentCookies, cookieValue: boolean) => {
|
||||
setConsentCookies((prev) => ({
|
||||
...prev,
|
||||
[cookieName]: cookieValue,
|
||||
}));
|
||||
|
||||
toast
|
||||
.promise(onUpdateConsentCookie(cookieName, cookieValue), {
|
||||
pending: "Mise à jour des cookies...",
|
||||
success: "Cookies mis à jour !",
|
||||
error: "Erreur lors de la mise à jour des cookies",
|
||||
})
|
||||
.then(() => {
|
||||
setIsOpen(false);
|
||||
reload();
|
||||
});
|
||||
};
|
||||
|
||||
const handleAcceptAll = () => {
|
||||
setConsentCookies({ analytics: true, customization: true });
|
||||
|
||||
toast
|
||||
.promise(onAcceptAllConsentCookie(), {
|
||||
pending: "Acceptation des cookies...",
|
||||
success: "Cookies acceptés !",
|
||||
error: "Erreur lors de l'acceptation des cookies",
|
||||
})
|
||||
.then(() => {
|
||||
setIsOpen(false);
|
||||
setIsSelectionOpen(false);
|
||||
reload();
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<CookiesContext.Provider
|
||||
value={{
|
||||
cookies: consentCookies,
|
||||
setCookie: handleUpdateCookie,
|
||||
acceptAll: handleAcceptAll,
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
isSelectionOpen,
|
||||
setIsSelectionOpen,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
{isSelectionOpen && <CookieChoices />}
|
||||
{isOpen && <CookieModal />}
|
||||
</CookiesContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function CookieChoices() {
|
||||
const cookiesContext = useContext(CookiesContext);
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-900/50 backdrop-blur-sm">
|
||||
<div className="relative flex flex-col gap-2 bg-slate-50 dark:bg-slate-800 rounded-md shadow-xl w-full max-w-sm p-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="absolute top-0 right-0"
|
||||
onClick={() => cookiesContext.setIsSelectionOpen(false)}
|
||||
>
|
||||
Fermer
|
||||
</Button>
|
||||
|
||||
<p className="font-display dark:text-slate-300 font-bold text-lg">Personnalisation des cookies 🍪</p>
|
||||
|
||||
<div className="flex flex-col gap-2 w-full items-start">
|
||||
<Toggle
|
||||
id="cookies-analytics"
|
||||
label="Cookies d‘analyse (Umami et Google Analytics)"
|
||||
checked={cookiesContext.cookies.analytics}
|
||||
onChange={(checked) => cookiesContext.setCookie("analytics", checked)}
|
||||
/>
|
||||
|
||||
<Toggle
|
||||
id="cookies-customization"
|
||||
label="Cookie de personnalisation (thème)"
|
||||
checked={cookiesContext.cookies.customization}
|
||||
onChange={(checked) => cookiesContext.setCookie("customization", checked)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CookieModal() {
|
||||
const cookiesContext = useContext(CookiesContext);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col fixed bottom-4 left-4 bg-slate-50 dark:bg-slate-800 z-50 rounded-md shadow-xl w-full max-w-sm overflow-hidden">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="absolute top-0 right-0"
|
||||
onClick={() => cookiesContext.setIsOpen(false)}
|
||||
>
|
||||
Fermer
|
||||
</Button>
|
||||
|
||||
<div className="flex flex-col gap-2 p-4">
|
||||
<p className="font-display dark:text-slate-300">
|
||||
<span className="text-sm">Coucou c'est nous...</span>
|
||||
<br />
|
||||
<span className="font-bold text-lg">les cookies ! 🍪</span>
|
||||
</p>
|
||||
|
||||
<p className="text-slate-700 dark:text-slate-300">
|
||||
On ne t‘embête pas longtemps, on te laisse même le choix <em>(si ça c‘est pas la classe 😎)</em>.
|
||||
</p>
|
||||
|
||||
<p className="text-slate-700 dark:text-slate-300">
|
||||
Si tu veux en savoir plus, tu peux consulter la page{" "}
|
||||
<Link href="/politique-de-confidentialite" className="font-bold">
|
||||
Politique de confidentialité
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid items-center grid-cols-3 justify-between bg-slate-100 dark:bg-slate-700">
|
||||
<button
|
||||
className="cursor-pointer px-2 py-1 text-slate-600 dark:text-slate-300"
|
||||
onClick={() => cookiesContext.setIsOpen(false)}
|
||||
>
|
||||
Non merci
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="cursor-pointer px-2 py-1 text-slate-600 dark:text-slate-300"
|
||||
onClick={() => cookiesContext.setIsSelectionOpen(true)}
|
||||
>
|
||||
Je choisis
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="cursor-pointer px-2 py-1 font-bold text-white dark:text-black bg-violet-600 dark:bg-violet-300"
|
||||
onClick={cookiesContext.acceptAll}
|
||||
>
|
||||
Oui, j‘ai faim !
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
type ToggleProps = {
|
||||
|
||||
@ -161,7 +161,6 @@ export function Navigation({
|
||||
onLinkClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
}) {
|
||||
const firstSections = navigation.filter((section) => section.position === "start");
|
||||
const lastSections = navigation.filter((section) => section.position === "end");
|
||||
|
||||
const filteredSections = navigation
|
||||
.filter((section) => section.position === "auto" || section.position === undefined)
|
||||
@ -193,12 +192,6 @@ export function Navigation({
|
||||
))}
|
||||
</li>
|
||||
))}
|
||||
<li>
|
||||
<h2 className="font-display font-bold text-base text-slate-900 dark:text-white">{lastSections[0]?.type}</h2>
|
||||
{lastSections.map((section) => (
|
||||
<NavigationItem key={section.title} section={section} onLinkClick={onLinkClick} />
|
||||
))}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
|
||||
@ -36,7 +36,6 @@ export default tseslint.config(
|
||||
"@typescript-eslint/no-unused-vars": [1, { argsIgnorePattern: "^_" }],
|
||||
"@typescript-eslint/no-namespace": 0,
|
||||
"react/react-in-jsx-scope": "warn",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/jsx-filename-extension": [1, { extensions: [".tsx"] }],
|
||||
},
|
||||
},
|
||||
|
||||
@ -3,7 +3,7 @@ import type { PageContext } from "vike/types";
|
||||
import { getTelefuncContext } from "@/lib/getTelefuncContext";
|
||||
import { CookieParser } from "@/services/CookieParser";
|
||||
|
||||
export type ConsentCookies = keyof PageContext["cookies"]["consent"];
|
||||
type ConsentCookies = keyof PageContext["cookies"]["consent"];
|
||||
|
||||
export async function onUpdateConsentCookie(cookieName: ConsentCookies, cookieValue: boolean) {
|
||||
const context = getTelefuncContext();
|
||||
@ -1,13 +1,17 @@
|
||||
import { CookiesContainer } from "@/components/common/Cookies";
|
||||
import { onUpdateConsentCookie, onAcceptAllConsentCookie } from "./LayoutDefault.telefunc";
|
||||
import { MobileNavigation } from "@syntax/MobileNavigation";
|
||||
import { usePageContext } from "vike-react/usePageContext";
|
||||
import { ThemeProvider } from "@/providers/ThemeProvider";
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
import { ThemeSelector } from "@syntax/ThemeSelector";
|
||||
import { Button } from "@/components/syntax/Button";
|
||||
import { Toggle } from "@/components/common/Toggle";
|
||||
import { clientOnly } from "vike-react/clientOnly";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import { Navigation } from "@syntax/Navigation";
|
||||
import { Link } from "@/components/common/Link";
|
||||
import { navigation } from "@/lib/navigation";
|
||||
import { reload } from "vike/client/router";
|
||||
import { Hero } from "@syntax/Hero";
|
||||
import { Logo } from "@syntax/Logo";
|
||||
import clsx from "clsx";
|
||||
@ -77,6 +81,141 @@ function Header() {
|
||||
);
|
||||
}
|
||||
|
||||
function CookieModal() {
|
||||
const { cookies } = usePageContext();
|
||||
|
||||
const [consentCookies, setConsentCookies] = useState(cookies.consent);
|
||||
const [isSelectionOpen, setIsSelectionOpen] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(() => {
|
||||
return Object.keys(cookies.consent).every((value) => value);
|
||||
});
|
||||
|
||||
if (isSelectionOpen) {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-900/50 backdrop-blur-sm">
|
||||
<div className="relative flex flex-col gap-2 bg-slate-50 dark:bg-slate-800 rounded-md shadow-xl w-full max-w-sm p-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="absolute top-0 right-0"
|
||||
onClick={() => setIsSelectionOpen(false)}
|
||||
>
|
||||
Fermer
|
||||
</Button>
|
||||
|
||||
<p className="font-display dark:text-slate-300 font-bold text-lg">Personnalisation des cookies 🍪</p>
|
||||
|
||||
<div className="flex flex-col gap-2 w-full items-start">
|
||||
<Toggle
|
||||
id="cookies-analytics"
|
||||
label="Cookies d'analyse (Umami et Google Analytics)"
|
||||
checked={consentCookies.analytics}
|
||||
onChange={(checked) => {
|
||||
setConsentCookies({ ...consentCookies, analytics: checked });
|
||||
|
||||
toast
|
||||
.promise(onUpdateConsentCookie("analytics", checked), {
|
||||
pending: "Mise à jour des cookies...",
|
||||
success: "Cookies mis à jour !",
|
||||
error: "Erreur lors de la mise à jour des cookies.",
|
||||
})
|
||||
.finally(reload);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Toggle
|
||||
id="cookies-customization"
|
||||
label="Cookie de personnalisation (thème)"
|
||||
checked={consentCookies.customization}
|
||||
onChange={(checked) => {
|
||||
setConsentCookies({ ...consentCookies, analytics: checked });
|
||||
|
||||
toast
|
||||
.promise(onUpdateConsentCookie("customization", checked), {
|
||||
pending: "Mise à jour des cookies...",
|
||||
success: "Cookies mis à jour !",
|
||||
error: "Erreur lors de la mise à jour des cookies.",
|
||||
})
|
||||
.then((data) => {
|
||||
setConsentCookies({ ...consentCookies, [data.cookieName]: data.cookieValue });
|
||||
reload();
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col fixed bottom-4 left-4 bg-slate-50 dark:bg-slate-800 z-50 rounded-md shadow-xl w-full max-w-sm overflow-hidden">
|
||||
<Button variant="ghost" size="sm" className="absolute top-0 right-0" onClick={() => setIsOpen(false)}>
|
||||
Fermer
|
||||
</Button>
|
||||
|
||||
<div className="flex flex-col gap-2 p-4">
|
||||
<p className="font-display dark:text-slate-300">
|
||||
<span className="text-sm">Coucou c'est nous...</span>
|
||||
<br />
|
||||
<span className="font-bold text-lg">les cookies ! 🍪</span>
|
||||
</p>
|
||||
|
||||
<p className="text-slate-700 dark:text-slate-300">
|
||||
On ne t'embête pas longtemps, on te laisse même le choix <em>(si ça c'est pas la classe 😎)</em>.
|
||||
</p>
|
||||
|
||||
<p className="text-slate-700 dark:text-slate-300">
|
||||
Si tu veux en savoir plus, tu peux consulter la page{" "}
|
||||
<Link href="/politique-de-confidentialite" className="font-bold">
|
||||
Politique de confidentialité
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid items-center grid-cols-3 justify-between bg-slate-100 dark:bg-slate-700">
|
||||
<button
|
||||
className="cursor-pointer px-2 py-1 text-slate-600 dark:text-slate-300"
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
Non merci
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="cursor-pointer px-2 py-1 text-slate-600 dark:text-slate-300"
|
||||
onClick={() => setIsSelectionOpen(true)}
|
||||
>
|
||||
Je choisis
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="cursor-pointer px-2 py-1 font-bold text-white dark:text-black bg-violet-600 dark:bg-violet-300"
|
||||
onClick={() => {
|
||||
setConsentCookies({ analytics: true, customization: true });
|
||||
|
||||
toast
|
||||
.promise(onAcceptAllConsentCookie(), {
|
||||
pending: "Mise à jour des cookies...",
|
||||
success: "Cookies mis à jour !",
|
||||
error: "Erreur lors de la mise à jour des cookies.",
|
||||
})
|
||||
.then(() => {
|
||||
setIsOpen(false);
|
||||
setIsOpen(false);
|
||||
reload();
|
||||
});
|
||||
}}
|
||||
>
|
||||
Oui, j'ai faim !
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Footer() {
|
||||
return (
|
||||
<footer className="bg-slate-50 dark:bg-slate-950 text-slate-700 dark:text-slate-200">
|
||||
@ -89,7 +228,7 @@ function Footer() {
|
||||
|
||||
<p>
|
||||
Plateforme de ressources et documentations synthétiques et concises, conçue pour les développeurs ou
|
||||
passionnés de l‘informatique en quête de savoir.
|
||||
passionnés de l'informatique en quête de savoir.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@ -118,29 +257,29 @@ export default function DefaultLayout({ children }: { children: React.ReactNode
|
||||
const isHomePage = urlPathname === "/";
|
||||
|
||||
return (
|
||||
<CookiesContainer>
|
||||
<ThemeProvider defaultTheme={cookies.settings.theme}>
|
||||
<div className="flex w-full flex-col font-sans">
|
||||
<Header />
|
||||
<ThemeProvider defaultTheme={cookies.settings.theme}>
|
||||
<CookieModal />
|
||||
|
||||
{isHomePage && <Hero />}
|
||||
<div className="flex w-full flex-col font-sans">
|
||||
<Header />
|
||||
|
||||
<div className="relative mx-auto w-full flex max-w-8xl flex-auto justify-center sm:px-2 lg:px-8 xl:px-12">
|
||||
<div className="hidden lg:relative lg:block lg:flex-none">
|
||||
<div className="absolute inset-y-0 right-0 w-[50vw] bg-slate-50 dark:hidden" />
|
||||
<div className="absolute top-16 right-0 bottom-0 hidden h-12 w-px bg-linear-to-t from-slate-800 dark:block" />
|
||||
<div className="absolute top-28 right-0 bottom-0 hidden w-px bg-slate-800 dark:block" />
|
||||
<div className="sticky top-[4.75rem] -ml-0.5 h-[calc(100vh-4.75rem)] w-64 overflow-x-hidden overflow-y-auto py-16 pr-8 pl-0.5 xl:w-72 xl:pr-16">
|
||||
<Navigation />
|
||||
</div>
|
||||
{isHomePage && <Hero />}
|
||||
|
||||
<div className="relative mx-auto w-full flex max-w-8xl flex-auto justify-center sm:px-2 lg:px-8 xl:px-12">
|
||||
<div className="hidden lg:relative lg:block lg:flex-none">
|
||||
<div className="absolute inset-y-0 right-0 w-[50vw] bg-slate-50 dark:hidden" />
|
||||
<div className="absolute top-16 right-0 bottom-0 hidden h-12 w-px bg-linear-to-t from-slate-800 dark:block" />
|
||||
<div className="absolute top-28 right-0 bottom-0 hidden w-px bg-slate-800 dark:block" />
|
||||
<div className="sticky top-[4.75rem] -ml-0.5 h-[calc(100vh-4.75rem)] w-64 overflow-x-hidden overflow-y-auto py-16 pr-8 pl-0.5 xl:w-72 xl:pr-16">
|
||||
<Navigation />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
{children}
|
||||
</div>
|
||||
<ToastContainer />
|
||||
</ThemeProvider>
|
||||
</CookiesContainer>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
<ToastContainer />
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,13 +2,12 @@ const navigationsTypes = {
|
||||
GLOBAL: "👋 Général",
|
||||
CERTIFICATIONS: "🎓 Certifications",
|
||||
DOCUMENTATIONS: "📚 Documentations",
|
||||
OTHER: "🔗 Autres",
|
||||
};
|
||||
|
||||
export type NavigationSection = {
|
||||
title: string;
|
||||
type: (typeof navigationsTypes)[keyof typeof navigationsTypes];
|
||||
position: "start" | "end" | "auto";
|
||||
position: "start" | "auto";
|
||||
links: NavigationLink[];
|
||||
};
|
||||
|
||||
@ -48,15 +47,6 @@ export const navigation: NavigationSection[] = [
|
||||
{ title: "Partages et réutilisations", href: "/docs/communaute/partages", subitems: [] },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Légal",
|
||||
type: navigationsTypes.OTHER,
|
||||
position: "end",
|
||||
links: [
|
||||
{ title: "Mentions légales", href: "/mentions-legales", subitems: [] },
|
||||
{ title: "Politique de confidentialité", href: "/politique-de-confidentialite", subitems: [] },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Développeur Web et Web Mobile",
|
||||
type: navigationsTypes.CERTIFICATIONS,
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
export function Page() {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 p-4 text-slate-700 dark:text-slate-300">
|
||||
<h1 className="font-display text-3xl tracking-tight text-slate-900 dark:text-white">Mentions légales</h1>
|
||||
|
||||
<section>
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">Éditeur du site</h2>
|
||||
<p>
|
||||
<span className="font-bold">Nom :</span> <strong className="font-normal">Gauthier Daniels</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Adresse physique :</span>{" "}
|
||||
<strong className="font-normal">689 Chemin Latéral, 45240 La Ferté Saint-Aubin</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Adresse email :</span>{" "}
|
||||
<strong className="font-normal">gauthier@gauthierdaniels.fr</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Téléphone :</span> <strong className="font-normal">+33 6 52 84 92 41</strong>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">Directeur de la publication</h2>
|
||||
<p>
|
||||
<span className="font-bold">Nom :</span> <strong className="font-normal">Gauthier Daniels</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Adresse email :</span>{" "}
|
||||
<strong className="font-normal">gauthier@gauthierdaniels.fr</strong>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">Hébergement du site</h2>
|
||||
<p>
|
||||
<span className="font-bold">Nom :</span> <strong className="font-normal">Infomaniak Network SA</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Site internet :</span> <strong className="font-normal">www.infomaniak.com</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Adresse physique :</span>{" "}
|
||||
<strong className="font-normal">Rue Eugène Marziano 25, 1227 Les Acacias (GE), Suisse</strong>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,189 +1,3 @@
|
||||
import { CookiesContext } from "@/components/common/Cookies";
|
||||
import { Button } from "@/components/syntax/Button";
|
||||
import { Link } from "@/components/common/Link";
|
||||
import React, { useContext } from "react";
|
||||
|
||||
export function Page() {
|
||||
const { setIsOpen } = useContext(CookiesContext);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 p-4 text-slate-700 dark:text-slate-300">
|
||||
<h1 className="font-display text-3xl tracking-tight text-slate-900 dark:text-white">
|
||||
Politique de confidentialité
|
||||
</h1>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">1. Introduction</h2>
|
||||
|
||||
<p>
|
||||
Sur <strong>Memento Dev</strong>, qui est un site à but de documentation, je prends très au sérieux la
|
||||
protection de votre vie privée et de vos données personnelles.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Cette politique de confidentialité explique comment je collecte, utilise et protège les informations des
|
||||
utilisateurs de ce site.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">2. Outils externes</h2>
|
||||
|
||||
<p>
|
||||
Mon site ne collecte aucune donnée personnelle de manière directe. Cependant, j'utilise des outils externes
|
||||
pour améliorer votre expérience utilisateur et analyser l'utilisation du site.
|
||||
</p>
|
||||
|
||||
<section className="ml-4">
|
||||
<h3 className="font-display text-lg text-slate-900 dark:text-slate-100">a. Google Analytics</h3>
|
||||
<p>
|
||||
J'utilise <strong>Google Analytics</strong> pour analyser le trafic et l'utilisation de mon site. Les
|
||||
données collectées par Google Analytics sont anonymisées et ne sont pas partagées avec des tiers.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="ml-4">
|
||||
<h3 className="font-display text-lg text-slate-900 dark:text-slate-100">b. Umami</h3>
|
||||
<p>
|
||||
<strong>Umami</strong> est un autre outil d'analyse que j'utilise pour comprendre comment les visiteurs
|
||||
interagissent avec mon site. Comme <strong>Google Analytics</strong>, les données collectées sont
|
||||
anonymisées et ne sont pas tranmises à des tiers.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="ml-4">
|
||||
<h3 className="font-display text-lg text-slate-900 dark:text-slate-100">c. Cookie "theme"</h3>
|
||||
<p>
|
||||
J'utilise et dépose un cookie nommé "theme" pour mémoriser votre préférence de thème (clair ou sombre). Ce
|
||||
cookie est utilisé uniquement pour personnaliser votre expérience utilisateur et n'est pas utilisé à des
|
||||
fins de suivi ou de marketing.
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">3. Cookies</h2>
|
||||
|
||||
<p>
|
||||
Ce site utilise des cookies pour améliorer votre expérience utilisateur et analyser l'utilisation du site. Les
|
||||
cookies sont de petits fichiers texte stockés sur votre appareil lorsque vous visitez un site web. Ils
|
||||
permettent de mémoriser vos préférences et d'analyser le trafic du site.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Vous pouvez gérer vos préférences de cookies directement via les paramètres de votre navigateur. La plupart
|
||||
des navigateurs vous permettent de refuser ou de supprimer les cookies. Cependant, cela peut affecter votre
|
||||
expérience sur le site et certaines fonctionnalités peuvent ne pas fonctionner correctement (comme la
|
||||
personnalisation du thème par exemple).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pour reconfigurer les cookies, vous pouvez appuyer sur le bouton "Paramétrer les cookies" à la suite de ce
|
||||
paragraphe.
|
||||
</p>
|
||||
|
||||
<Button variant="secondary" className="w-max max-w-full" onClick={() => setIsOpen(true)}>
|
||||
Paramétrer les cookies
|
||||
</Button>
|
||||
|
||||
<p>
|
||||
Pour plus d'informations sur la gestion des cookies, vous pouvez consulter la documentation de votre
|
||||
navigateur. Voici quelques liens utiles :
|
||||
</p>
|
||||
|
||||
<ul className="list-disc pl-4">
|
||||
<li>
|
||||
<Link
|
||||
href="https://support.google.com/chrome/answer/95647?hl=fr"
|
||||
className="text-violet-500 dark:text-violet-400"
|
||||
>
|
||||
Google Chrome
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
href="https://support.mozilla.org/fr/kb/activer-desactiver-cookies"
|
||||
className="text-violet-500 dark:text-violet-400"
|
||||
>
|
||||
Mozilla Firefox
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
href="https://support.microsoft.com/fr-fr/help/278835/how-to-delete-cookie-files-in-internet-explorer"
|
||||
className="text-violet-500 dark:text-violet-400"
|
||||
>
|
||||
Internet Explorer
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="https://support.apple.com/fr-fr/HT201265" className="text-violet-500 dark:text-violet-400">
|
||||
Safari
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
href="https://support.microsoft.com/fr-fr/help/278835/how-to-delete-cookie-files-in-internet-explorer"
|
||||
className="text-violet-500 dark:text-violet-400"
|
||||
>
|
||||
Microsoft Edge
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">4. Utilisation des données</h2>
|
||||
|
||||
<p>
|
||||
Les données collectées par les outils d'analyse sont utilisées uniquement pour améliorer le site Memento Dev
|
||||
et comprendre comment les visiteurs l'utilisent. Je n'utilise pas ces données à des fins commerciales ou pour
|
||||
cibler des publicités.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">5. Protection des données</h2>
|
||||
|
||||
<p>
|
||||
Les données collectées par <strong>Google Analytics</strong> et <strong>Umami</strong> sont anonymisées et
|
||||
stockées de manière sécurisée par ces services. Je ne stocke aucune donnée personnelle sur mes propres
|
||||
serveurs. Pour plus d'informations sur la manière dont ces services protègent vos données, veuillez consulter
|
||||
leurs politiques de confidentialité respectives.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">6. Vos droits</h2>
|
||||
|
||||
<p>
|
||||
Étant donné que je ne stocke aucune donnée personnelle, je ne suis pas en mesure de répondre aux demandes
|
||||
d'accès, de rectification ou de suppression de données personnelles. Cependant, vous pouvez gérer vos
|
||||
préférences de cookies directement via les paramètres de votre navigateur. Pour toute question concernant vos
|
||||
droits, veuillez me contacter à <strong>gauthier@gauthierdaniels.fr</strong>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">
|
||||
7. Modifications de la Politique de Confidentialité
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Je me réserve le droit de modifier cette politique de confidentialité à tout moment. Les modifications seront
|
||||
publiées sur cette page et entreront en vigueur immédiatement. Je vous encourage à consulter régulièrement
|
||||
cette page pour rester informé de mes pratiques en matière de confidentialité.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="font-display text-xl text-slate-900 dark:text-slate-100">8. Contact</h2>
|
||||
|
||||
<p>
|
||||
Si vous avez des questions ou des préoccupations concernant ma politique de confidentialité, veuillez me
|
||||
contacter à l'adresse suivante : <strong>gauthier@gauthierdaniels.fr</strong>.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
return <div>Rédaction en cours</div>;
|
||||
}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
import type { Theme } from "@/contexts/ThemeContext";
|
||||
|
||||
import { getTelefuncContext } from "@/lib/getTelefuncContext";
|
||||
import { CookieParser } from "@/services/CookieParser";
|
||||
|
||||
export async function onUpdateThemeCookie(value: Theme) {
|
||||
const context = getTelefuncContext();
|
||||
const { reply } = context;
|
||||
|
||||
CookieParser.set(reply, "theme", value, 365);
|
||||
|
||||
return { ok: true, message: "Updated theme cookie", value };
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
import { onUpdateThemeCookie } from "@/providers/ThemeProvider.telefunc";
|
||||
import { ThemeContext, type Theme } from "@/contexts/ThemeContext";
|
||||
import { usePageContext } from "vike-react/usePageContext";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
type ThemeProviderProps = {
|
||||
children: React.ReactNode;
|
||||
@ -20,9 +18,7 @@ export function ThemeProvider(props: ThemeProviderProps) {
|
||||
rootElement.classList.toggle("light", theme === "light");
|
||||
|
||||
if (cookies.consent.customization) {
|
||||
onUpdateThemeCookie(theme).catch(() => {
|
||||
toast.error("Erreur lors de la mise à jour du cookie de thème");
|
||||
});
|
||||
// TODO: update the theme in the cookies
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user