From fad6d9d5c2fcc7b8e6a1c874f0caf6038dfa3fa4 Mon Sep 17 00:00:00 2001
From: steel <mael.acier@ensiie.fr>
Date: Sun, 1 Sep 2024 02:36:07 +0200
Subject: [PATCH] feat: random color

---
 src/app.html                              |  4 +-
 src/lib/auth/index.ts                     |  2 +-
 src/lib/data.ts                           |  6 +--
 src/lib/graphql/queries.ts                |  8 +--
 src/routes/quiz/+layout.server.ts         | 42 ++++++++++++++++
 src/routes/quiz/+layout.svelte            | 18 ++++---
 src/routes/quiz/+page.svelte              | 60 +++++++++++------------
 src/routes/quiz/game-over/+page.server.ts |  2 +
 src/routes/quiz/game-over/+page.svelte    |  6 +--
 tailwind.config.ts                        |  8 +++
 10 files changed, 105 insertions(+), 51 deletions(-)
 create mode 100644 src/routes/quiz/+layout.server.ts

diff --git a/src/app.html b/src/app.html
index 0e11c0a..88d12e6 100644
--- a/src/app.html
+++ b/src/app.html
@@ -1,12 +1,12 @@
 <!doctype html>
-<html lang="en" class="h-full">
+<html lang="fr" class="h-full">
 	<head>
 		<meta charset="utf-8" />
 		<link rel="icon" href="%sveltekit.assets%/favicon.png" />
 		<meta name="viewport" content="width=device-width, initial-scale=1" />
 		%sveltekit.head%
 	</head>
-	<body data-sveltekit-preload-data="hover" class="h-full font-game text-zinc-800">
+	<body data-sveltekit-preload-data="hover">
 		<div style="display: contents">%sveltekit.body%</div>
 	</body>
 </html>
diff --git a/src/lib/auth/index.ts b/src/lib/auth/index.ts
index e1c36b3..3f4b947 100644
--- a/src/lib/auth/index.ts
+++ b/src/lib/auth/index.ts
@@ -5,6 +5,6 @@ import { defaultLucia } from '@arise/aidc-sveltekit/default';
 export const aidc = await AriseIdConnect.init({
 	client_id: env.AIDC_CLIENT_ID,
 	client_secret: env.AIDC_CLIENT_SECRET,
-	scope: 'openid offline_access profile',
+	scope: 'openid offline profile',
 	wrapper: defaultLucia
 });
diff --git a/src/lib/data.ts b/src/lib/data.ts
index 73d4339..cf26ee6 100644
--- a/src/lib/data.ts
+++ b/src/lib/data.ts
@@ -20,9 +20,9 @@ async function cacheImages(users: UserId[]): Promise<void> {
 			throw response.error;
 		}
 
-		const url = response.data?.page.nodes[0].photo;
-		if (!url) continue;
-		await fetch(url, { method: 'HEAD' });
+		const photo = response.data?.page.nodes[0].photo;
+		if (!photo?.url) continue;
+		await fetch(photo.url, { method: 'HEAD' });
 	}
 }
 
diff --git a/src/lib/graphql/queries.ts b/src/lib/graphql/queries.ts
index d568967..c9bb02d 100644
--- a/src/lib/graphql/queries.ts
+++ b/src/lib/graphql/queries.ts
@@ -5,7 +5,7 @@ export const PROMOTION_QUERY = graphql(`
 		page: users(
 			first: $first
 			after: $after
-			filter: { promotion: { eq: [$promotion] }, nickname: { null: false } }
+			filter: { promotion: { eq: [$promotion] }, nickname: { null: false }, photo: { null: false } }
 		) {
 			pageInfo {
 				endCursor
@@ -24,8 +24,10 @@ export const USER_DETAILS_QUERY = graphql(`
 			nodes {
 				id
 				nickname
-				photo
-				photoThumbnailHash
+				photo {
+					url
+					thumbnailHash
+				}
 			}
 		}
 	}
diff --git a/src/routes/quiz/+layout.server.ts b/src/routes/quiz/+layout.server.ts
new file mode 100644
index 0000000..3293ca2
--- /dev/null
+++ b/src/routes/quiz/+layout.server.ts
@@ -0,0 +1,42 @@
+import colors from 'tailwindcss/colors';
+import { getRandomItems } from '$lib/utils';
+
+type Color = keyof typeof colors;
+
+function getColor(currentColor?: string): Color {
+	const palette: Color[] = [
+		'red',
+		'orange',
+		'amber',
+		'yellow',
+		'lime',
+		'green',
+		'emerald',
+		'teal',
+		'cyan',
+		'sky',
+		'blue',
+		'indigo',
+		'violet',
+		'purple',
+		'fuchsia',
+		'pink',
+		'rose'
+	];
+
+	if (palette.includes(currentColor as Color)) {
+		return currentColor as Color;
+	}
+
+	return getRandomItems(palette, 1)[0];
+}
+
+export function load({ cookies }) {
+	const colorName = getColor(cookies.get('color'));
+
+	cookies.set('color', colorName, { path: '/' });
+
+	return {
+		color: colors[colorName]
+	};
+}
diff --git a/src/routes/quiz/+layout.svelte b/src/routes/quiz/+layout.svelte
index 3616541..2e001b9 100644
--- a/src/routes/quiz/+layout.svelte
+++ b/src/routes/quiz/+layout.svelte
@@ -1,9 +1,11 @@
-<slot></slot>
+<script lang="ts">
+	export let data;
 
-<style>
-	:global(body) {
-		background-color: #f65a52;
-		font-size: 16px;
-		line-height: 1.875em;
-	}
-</style>
+	$: cssVarStyles = Object.entries(data.color)
+		.map(([key, value]) => `--tw-random-color-${key}:${value}`)
+		.join(';');
+</script>
+
+<div style={cssVarStyles} class="flex min-h-screen flex-col bg-random-500 font-game text-zinc-800">
+	<slot />
+</div>
diff --git a/src/routes/quiz/+page.svelte b/src/routes/quiz/+page.svelte
index 3e97318..5ef86b1 100644
--- a/src/routes/quiz/+page.svelte
+++ b/src/routes/quiz/+page.svelte
@@ -15,30 +15,28 @@
 	const questionAmount = 10;
 </script>
 
-<form method="post" use:enhance>
-	<div class="relative mx-auto my-12 w-full">
-		<section class="relative m-auto flex flex-col items-center">
-			<h1 class="absolute -top-8 text-xl">Qui est-ce ?</h1>
-			<div class="relative">
-				<span class="absolute -left-14 flex flex-col items-end">
-					<span class="text-9xl leading-[0.4] text-red-300"> {data.step} </span>
-					<span> / {questionAmount} </span>
-				</span>
-				<span
-					class="absolute right-[calc(100%_+_0.5rem)] top-24 whitespace-nowrap pt-4 text-xl text-zinc-800 before:absolute before:right-0 before:top-0 before:h-1.5 before:w-10 before:bg-zinc-800"
-				>
-					{data.score}
-					<small>pts</small>
-				</span>
-				<div
-					class="relative z-10 flex h-64 w-64 items-center justify-center overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-white before:absolute before:-z-10 before:h-32 before:w-32 before:rounded-full before:bg-slate-300 before:opacity-100 before:transition-[0.65s] before:duration-[ease-in-out] after:absolute after:-z-10 after:h-32 after:w-32 after:scale-0 after:rounded-full after:border-solid after:border-slate-300 after:transition-[0.4s] after:duration-[ease-in-out]"
-				>
-					<img src={data.photo} alt="Chargement..." class="w-auto" />
-				</div>
+<div class="relative mx-auto my-12 w-full grow">
+	<section class="relative m-auto flex flex-col items-center">
+		<h1 class="absolute -top-8 text-xl">Qui est-ce ?</h1>
+		<div class="relative">
+			<span class="absolute -left-14 flex flex-col items-end">
+				<span class="text-9xl leading-[0.4] text-random-300"> {data.step} </span>
+				<span> / {questionAmount} </span>
+			</span>
+			<span
+				class="absolute right-[calc(100%_+_0.5rem)] top-24 whitespace-nowrap pt-4 text-xl text-zinc-800 before:absolute before:right-0 before:top-0 before:h-1.5 before:w-10 before:bg-zinc-800"
+			>
+				{data.score}
+				<small>pts</small>
+			</span>
+			<div
+				class="relative z-10 flex h-64 w-64 items-center justify-center overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-white before:absolute before:-z-10 before:h-32 before:w-32 before:rounded-full before:bg-slate-300 before:opacity-100 before:transition-[0.65s] before:duration-[ease-in-out] after:absolute after:-z-10 after:h-32 after:w-32 after:scale-0 after:rounded-full after:border-solid after:border-slate-300 after:transition-[0.4s] after:duration-[ease-in-out]"
+			>
+				<img src={data.photo?.url} alt="Chargement..." class="w-auto" />
+			</div>
+			<form method="post" use:enhance>
 				<Fieldset form={form2} name="choice">
-					<transition-group
-						tag="div"
-						name="animate-options"
+					<div
 						class="relative -top-6 z-20 mx-auto my-0 flex w-44 flex-col items-center space-y-0.5 rounded-2xl bg-zinc-800 px-5 py-0"
 					>
 						{#each data.options as option}
@@ -56,21 +54,21 @@
 									<Label
 										tabindex={0}
 										data-solution={form?.solution || null}
-										class="relative block cursor-pointer select-none overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-slate-300 p-2 text-center text-lg transition-[0.45s] before:absolute before:left-2/4 before:top-2/4 before:-z-10 before:h-[200px] before:w-[200px] before:-translate-x-2/4 before:-translate-y-2/4 before:scale-0 before:rounded-full before:bg-slate-400 before:transition-[0.2s] before:duration-[ease-in-out] focus:[outline:none] active:before:-translate-x-2/4 active:before:-translate-y-2/4 active:before:scale-100 peer-checked:bg-[#94acbd] peer-enabled:hover:translate-y-[-3px] peer-enabled:hover:bg-indigo-300 peer-enabled:focus:border-indigo-500 data-[solution]:cursor-default data-[solution]:text-[#94acbd] peer-checked:data-[solution]:bg-red-400 peer-checked:data-[solution]:text-inherit peer-data-[valid]:!bg-lime-400 peer-data-[valid]:text-inherit"
+										class="relative block cursor-pointer select-none overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-slate-300 p-2 text-center text-lg transition-[0.45s] before:absolute before:left-2/4 before:top-2/4 before:-z-10 before:h-[200px] before:w-[200px] before:-translate-x-2/4 before:-translate-y-2/4 before:scale-0 before:rounded-full before:bg-indigo-300 before:transition-[0.2s] before:duration-[ease-in-out] focus:[outline:none] active:before:-translate-x-2/4 active:before:-translate-y-2/4 active:before:scale-100 peer-enabled:hover:translate-y-[-3px] peer-enabled:hover:bg-slate-400 peer-enabled:focus:border-indigo-500 peer-checked:peer-enabled:bg-indigo-300 data-[solution]:cursor-default data-[solution]:text-[#94acbd] peer-checked:data-[solution]:bg-red-400 peer-checked:data-[solution]:text-inherit peer-data-[valid]:!bg-lime-400 peer-data-[valid]:text-inherit"
 									>
 										{option.label}
 									</Label>
 								</Control>
 							</div>
 						{/each}
-					</transition-group>
+					</div>
 				</Fieldset>
 				<footer class="space-y-1.5 text-center sm:absolute sm:left-full sm:top-5">
 					<button
 						type="submit"
 						formaction="?/results"
 						disabled={form?.solution !== undefined}
-						class="h-[100px] w-[110px] cursor-pointer rounded-2xl border-transparent bg-red-600 p-4 text-2xl text-white transition-[0.35s] duration-300 focus:border focus:border-dotted focus:border-[#f87f79] focus:[outline:none] enabled:hover:translate-x-0 enabled:hover:bg-[#333] enabled:hover:text-[#f65a52] disabled:cursor-default disabled:text-[#fa9f9b] disabled:opacity-70 sm:-translate-x-2.5 sm:rounded-bl-none sm:rounded-tl-none"
+						class="h-[100px] w-[110px] cursor-pointer rounded-2xl border-transparent bg-random-600 p-4 text-2xl text-white transition-[0.35s] duration-300 focus:border focus:border-dotted focus:border-random-400 focus:[outline:none] enabled:hover:translate-x-0 enabled:hover:bg-[#333] enabled:hover:text-random-500 disabled:cursor-default disabled:text-random-300 disabled:opacity-70 sm:-translate-x-2.5 sm:rounded-bl-none sm:rounded-tl-none"
 					>
 						OK
 					</button>
@@ -78,12 +76,12 @@
 						type="submit"
 						formaction="?/next"
 						disabled={form?.solution === undefined}
-						class="h-[100px] w-[110px] cursor-pointer rounded-2xl border-transparent bg-red-600 p-4 text-2xl text-white transition-[0.35s] duration-300 focus:border focus:border-dotted focus:border-[#f87f79] focus:[outline:none] enabled:hover:translate-x-0 enabled:hover:bg-[#333] enabled:hover:text-[#f65a52] disabled:cursor-default disabled:text-[#fa9f9b] disabled:opacity-70 sm:-translate-x-2.5 sm:rounded-bl-none sm:rounded-tl-none"
+						class="h-[100px] w-[110px] cursor-pointer rounded-2xl border-transparent bg-random-600 p-4 text-2xl text-white transition-[0.35s] duration-300 focus:border focus:border-dotted focus:border-random-400 focus:[outline:none] enabled:hover:translate-x-0 enabled:hover:bg-[#333] enabled:hover:text-random-500 disabled:cursor-default disabled:text-random-300 disabled:opacity-70 sm:-translate-x-2.5 sm:rounded-bl-none sm:rounded-tl-none"
 					>
 						Suivant
 					</button>
 				</footer>
-			</div>
-		</section>
-	</div>
-</form>
+			</form>
+		</div>
+	</section>
+</div>
diff --git a/src/routes/quiz/game-over/+page.server.ts b/src/routes/quiz/game-over/+page.server.ts
index 4c65ae4..c4d603a 100644
--- a/src/routes/quiz/game-over/+page.server.ts
+++ b/src/routes/quiz/game-over/+page.server.ts
@@ -14,5 +14,7 @@ export const actions = {
 		const game = new Game(event.cookies);
 
 		game.reset();
+
+		event.cookies.delete('color', { path: '/' });
 	}
 };
diff --git a/src/routes/quiz/game-over/+page.svelte b/src/routes/quiz/game-over/+page.svelte
index 46bcb47..6bbf498 100644
--- a/src/routes/quiz/game-over/+page.svelte
+++ b/src/routes/quiz/game-over/+page.svelte
@@ -8,15 +8,15 @@
 	<section class="text-center">
 		<h2>Score final</h2>
 		<span
-			class="relative mb-4 block before:absolute before:left-2/4 before:top-2/4 before:z-[-1] before:h-[100px] before:w-[100px] before:-translate-x-2/4 before:-translate-y-2/4 before:animate-[grow_2s_infinite_ease-in-out] before:rounded-[50%] before:border-6 before:border-solid before:border-[#f32c22] before:opacity-30 before:content-['']"
+			class="relative mb-4 block before:absolute before:left-2/4 before:top-2/4 before:z-[-1] before:h-[100px] before:w-[100px] before:-translate-x-2/4 before:-translate-y-2/4 before:animate-[grow_2s_infinite_ease-in-out] before:rounded-[50%] before:border-6 before:border-solid before:border-random-600 before:opacity-30"
 		>
-			<span class="translate-y-[-30px] text-9xl text-[#fa9f9b]">{data.score}</span>
+			<span class="translate-y-[-30px] text-9xl text-random-300">{data.score}</span>
 			pts
 		</span>
 		<form method="post" use:enhance>
 			<button
 				type="submit"
-				class="cursor-pointer rounded-2xl border-transparent bg-[#f32c22] px-[1.5em] py-[0.5em] text-2xl text-[#333] transition-[0.35s] hover:bg-[#333] hover:text-[#f65a52] focus:border focus:border-dotted focus:border-[#f87f79] focus:[outline:none]"
+				class="cursor-pointer rounded-2xl border-transparent bg-random-600 px-[1.5em] py-[0.5em] text-2xl text-white transition-[0.35s] hover:bg-zinc-800 hover:text-random-500 focus:border focus:border-dotted focus:border-random-400 focus:[outline:none]"
 			>
 				Rejouer
 			</button>
diff --git a/tailwind.config.ts b/tailwind.config.ts
index f12d001..c7309ef 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -10,6 +10,14 @@ export default {
 			},
 			borderWidth: {
 				6: '6px'
+			},
+			colors: {
+				random: Object.fromEntries(
+					[50, 100, 200, 300, 400, 500, 600, 700, 800, 900].map((shade) => [
+						shade,
+						`var(--tw-random-color-${shade})`
+					])
+				)
 			}
 		}
 	},
-- 
GitLab