feat: Update consent cookie setting function

This commit is contained in:
Gauthier Daniels 2025-04-18 17:04:35 +02:00
parent ca55b7a282
commit 4901eb8477
7 changed files with 71 additions and 43 deletions

View File

@ -14,12 +14,12 @@ export async function onUpdateConsentCookie(cookieName: ConsentCookies, cookieVa
return { ok: true, message: "Updated consent cookie", cookieName, cookieValue }; return { ok: true, message: "Updated consent cookie", cookieName, cookieValue };
} }
export async function onAcceptAllConsentCookie() { export async function onSetAllConsentCookie(cookieValue: boolean) {
const context = getTelefuncContext(); const context = getTelefuncContext();
const { reply } = context; const { reply } = context;
CookieParser.set(reply, "analytics", "true", 365); CookieParser.set(reply, "analytics", cookieValue.toString(), 365);
CookieParser.set(reply, "customization", "true", 365); CookieParser.set(reply, "customization", cookieValue.toString(), 365);
return { ok: true, message: "Updated consents cookies" }; return { ok: true, message: "Updated consents cookies" };
} }

View File

@ -1,5 +1,5 @@
import { onUpdateConsentCookie, onAcceptAllConsentCookie, type ConsentCookies } from "./Cookies.telefunc"; import { onUpdateConsentCookie, onSetAllConsentCookie, type ConsentCookies } from "./Cookies.telefunc";
import React, { useState, useContext, createContext } from "react"; import React, { useState, useContext, createContext, useMemo } from "react";
import { usePageContext } from "vike-react/usePageContext"; import { usePageContext } from "vike-react/usePageContext";
import { reload } from "vike/client/router"; import { reload } from "vike/client/router";
import { Button } from "@syntax/Button"; import { Button } from "@syntax/Button";
@ -13,7 +13,7 @@ export const CookiesContext = createContext<{
customization: boolean; customization: boolean;
}; };
setCookie: (cookieName: ConsentCookies, cookieValue: boolean) => void; setCookie: (cookieName: ConsentCookies, cookieValue: boolean) => void;
acceptAll: () => void; setAllCookies: (cookieValue: boolean) => void;
isOpen: boolean; isOpen: boolean;
setIsOpen: (isOpen: boolean) => void; setIsOpen: (isOpen: boolean) => void;
isSelectionOpen: boolean; isSelectionOpen: boolean;
@ -24,7 +24,7 @@ export const CookiesContext = createContext<{
customization: false, customization: false,
}, },
setCookie: (_cookieName: ConsentCookies, _cookieValue: boolean) => {}, setCookie: (_cookieName: ConsentCookies, _cookieValue: boolean) => {},
acceptAll: () => {}, setAllCookies: () => {},
isOpen: false, isOpen: false,
setIsOpen: () => {}, setIsOpen: () => {},
isSelectionOpen: false, isSelectionOpen: false,
@ -44,34 +44,31 @@ export function CookiesContainer(props: CookiesContainerProps) {
return !Object.keys(cookies.consent).every((value) => value); return !Object.keys(cookies.consent).every((value) => value);
}); });
const toastPromiseMessages = useMemo(
() => ({
pending: "Mise à jour des cookies...",
success: "Cookies mis à jour !",
error: "Erreur lors de la mise à jour des cookies",
}),
[],
);
const handleUpdateCookie = (cookieName: ConsentCookies, cookieValue: boolean) => { const handleUpdateCookie = (cookieName: ConsentCookies, cookieValue: boolean) => {
setConsentCookies((prev) => ({ setConsentCookies((prev) => ({
...prev, ...prev,
[cookieName]: cookieValue, [cookieName]: cookieValue,
})); }));
toast toast.promise(onUpdateConsentCookie(cookieName, cookieValue), toastPromiseMessages).then(() => {
.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); setIsOpen(false);
reload(); reload();
}); });
}; };
const handleAcceptAll = () => { const handleSetAll = (value: boolean) => {
setConsentCookies({ analytics: true, customization: true }); setConsentCookies({ analytics: true, customization: true });
toast toast.promise(onSetAllConsentCookie(value), toastPromiseMessages).then(() => {
.promise(onAcceptAllConsentCookie(), {
pending: "Acceptation des cookies...",
success: "Cookies acceptés !",
error: "Erreur lors de l'acceptation des cookies",
})
.then(() => {
setIsOpen(false); setIsOpen(false);
setIsSelectionOpen(false); setIsSelectionOpen(false);
reload(); reload();
@ -83,7 +80,7 @@ export function CookiesContainer(props: CookiesContainerProps) {
value={{ value={{
cookies: consentCookies, cookies: consentCookies,
setCookie: handleUpdateCookie, setCookie: handleUpdateCookie,
acceptAll: handleAcceptAll, setAllCookies: handleSetAll,
isOpen, isOpen,
setIsOpen, setIsOpen,
isSelectionOpen, isSelectionOpen,
@ -171,7 +168,7 @@ function CookieModal() {
<div className="grid items-center grid-cols-3 justify-between bg-slate-100 dark:bg-slate-700"> <div className="grid items-center grid-cols-3 justify-between bg-slate-100 dark:bg-slate-700">
<button <button
className="cursor-pointer px-2 py-1 text-slate-600 dark:text-slate-300" className="cursor-pointer px-2 py-1 text-slate-600 dark:text-slate-300"
onClick={() => cookiesContext.setIsOpen(false)} onClick={() => cookiesContext.setAllCookies(false)}
> >
Non merci Non merci
</button> </button>
@ -185,7 +182,7 @@ function CookieModal() {
<button <button
className="cursor-pointer px-2 py-1 font-bold text-white dark:text-black bg-violet-600 dark:bg-violet-300" className="cursor-pointer px-2 py-1 font-bold text-white dark:text-black bg-violet-600 dark:bg-violet-300"
onClick={cookiesContext.acceptAll} onClick={() => cookiesContext.setAllCookies(true)}
> >
Oui, j&lsquo;ai faim ! Oui, j&lsquo;ai faim !
</button> </button>

View File

@ -2,7 +2,7 @@ import React from "react";
export function Page() { export function Page() {
return ( return (
<div className="flex flex-col gap-4 p-4 text-slate-700 dark:text-slate-300"> <div className="px-4 py-16 lg:max-w-none lg:pr-0 lg:pl-8 xl:px-16 flex flex-col gap-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> <h1 className="font-display text-3xl tracking-tight text-slate-900 dark:text-white">Mentions légales</h1>
<section> <section>

View File

@ -7,7 +7,7 @@ export function Page() {
const { setIsOpen } = useContext(CookiesContext); const { setIsOpen } = useContext(CookiesContext);
return ( return (
<div className="flex flex-col gap-4 p-4 text-slate-700 dark:text-slate-300"> <div className="px-4 py-16 lg:max-w-none lg:pr-0 lg:pl-8 xl:px-16 flex flex-col gap-4 text-slate-700 dark:text-slate-300">
<h1 className="font-display text-3xl tracking-tight text-slate-900 dark:text-white"> <h1 className="font-display text-3xl tracking-tight text-slate-900 dark:text-white">
Politique de confidentialité Politique de confidentialité
</h1> </h1>

View File

@ -11,3 +11,12 @@ export async function onUpdateThemeCookie(value: Theme) {
return { ok: true, message: "Updated theme cookie", value }; return { ok: true, message: "Updated theme cookie", value };
} }
export async function onDeleteThemeCookie() {
const context = getTelefuncContext();
const { reply } = context;
CookieParser.delete(reply, "theme");
return { ok: true, message: "Deleted theme cookie" };
}

View File

@ -1,4 +1,4 @@
import { onUpdateThemeCookie } from "@/providers/ThemeProvider.telefunc"; import { onUpdateThemeCookie, onDeleteThemeCookie } from "@/providers/ThemeProvider.telefunc";
import { ThemeContext, type Theme } from "@/contexts/ThemeContext"; import { ThemeContext, type Theme } from "@/contexts/ThemeContext";
import { usePageContext } from "vike-react/usePageContext"; import { usePageContext } from "vike-react/usePageContext";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
@ -23,8 +23,12 @@ export function ThemeProvider(props: ThemeProviderProps) {
onUpdateThemeCookie(theme).catch(() => { onUpdateThemeCookie(theme).catch(() => {
toast.error("Erreur lors de la mise à jour du cookie de thème"); toast.error("Erreur lors de la mise à jour du cookie de thème");
}); });
} else {
onDeleteThemeCookie().catch(() => {
toast.error("Erreur lors de la suppression du cookie de thème");
});
} }
}, [theme]); }, [theme, cookies.consent.customization]);
return <ThemeContext.Provider value={{ theme, setTheme }}>{props.children}</ThemeContext.Provider>; return <ThemeContext.Provider value={{ theme, setTheme }}>{props.children}</ThemeContext.Provider>;
} }

View File

@ -17,6 +17,23 @@ export class CookieParser {
this.parse(); this.parse();
} }
public static buildOptions(daysDuration: number | Date) {
let expires: Date;
if (daysDuration instanceof Date) {
expires = daysDuration;
} else {
expires = new Date(Date.now() + 60 * 60 * 24 * daysDuration * 1000);
}
return {
path: "/",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
expires,
};
}
parse() { parse() {
this.cookies = this.rawCookies.split("; ").reduce( this.cookies = this.rawCookies.split("; ").reduce(
(acc, cookie) => { (acc, cookie) => {
@ -38,15 +55,16 @@ export class CookieParser {
} }
static set(reply: FastifyReply, key: CookieKeys, value: string, daysDuration = 30): FastifyReply { static set(reply: FastifyReply, key: CookieKeys, value: string, daysDuration = 30): FastifyReply {
const options = { const options = CookieParser.buildOptions(daysDuration);
path: "/",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
expires: new Date(Date.now() + 60 * 60 * 24 * daysDuration * 1000),
};
reply.setCookie(key, value, options); reply.setCookie(key, value, options);
return reply; return reply;
} }
static delete(reply: FastifyReply, key: CookieKeys): FastifyReply {
const options = CookieParser.buildOptions(new Date("1900-01-01"));
reply.setCookie(key, "", options);
return reply;
}
} }