All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m16s
435 lines
21 KiB
TypeScript
435 lines
21 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useState } from "react";
|
||
import { Info } from "lucide-react";
|
||
import { Button } from "~/components/ui/button";
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
DialogTrigger,
|
||
} from "~/components/ui/dialog";
|
||
import { Label } from "~/components/ui/label";
|
||
import { RadioGroup, RadioGroupItem } from "~/components/ui/radio-group";
|
||
import { TypingText, TypingTextCursor } from "~/components/ui/text-typing";
|
||
|
||
const ENCOURAGING_MESSAGES = [
|
||
// --- Les Classiques (Gardés) ---
|
||
"Tu es plus fort(e) que tu ne le penses. Continue comme ça ! 💪",
|
||
"Chaque jour est un pas de plus vers ton objectif. Bravo ! 🌟",
|
||
"Ta persévérance est admirable. Tu vas réussir ! 🎯",
|
||
"N'oublie pas de te reposer, le sommeil fixe la mémoire ! 😌",
|
||
"Les meilleurs résultats viennent avec le temps. Patience ! ⏰",
|
||
"Tu fais un travail incroyable. Continue ainsi ! 🚀",
|
||
"Crois en toi, tu as tout pour réussir ! ✨",
|
||
"Chaque exercice résolu te rapproche de ton rêve ! 📚",
|
||
"Ton travail acharné paiera, garde confiance ! 🌈",
|
||
"Tu es sur la bonne voie. Reste concentré(e) ! 🎓",
|
||
"Prends soin de toi, ta santé mentale est ta meilleure arme ! 💙",
|
||
"Ta détermination est inspirante ! 🔥",
|
||
"Les concours ne sont qu'une étape, tu es déjà quelqu'un de formidable ! 🌸",
|
||
"N'aie pas peur des erreurs, c'est là que tu apprends le plus ! 📝",
|
||
"Tu progresses chaque jour, même les jours où tu as l'impression de reculer ! 🌱",
|
||
"Ta famille et tes amis sont fiers de toi ! 💖",
|
||
"Le meilleur est à venir, l'école de tes rêves t'attend ! 🌅",
|
||
"Chaque difficulté surmontée te rend plus fort(e) ! 💎",
|
||
"Tu as choisi un chemin difficile, sois fier(e) de le parcourir ! 🏔️",
|
||
"N'oublie pas pourquoi tu as commencé. Tu vas y arriver ! 🎪",
|
||
|
||
// --- Les Nouveaux (Spécial Prépa) ---
|
||
"C'est un marathon, pas un sprint. Respire. 🏃",
|
||
"Même les major de promo doutent. Toi, tu avances. 🛡️",
|
||
"Une mauvaise note en khôlle ne définit pas ta valeur. Relève-toi. 🦋",
|
||
"Rappelle-toi la sensation de comprendre enfin une démo complexe. Cherche ça ! 💡",
|
||
"Tu es en train de te forger une capacité de travail pour la vie. 🧠",
|
||
"L'effort d'aujourd'hui est le sourire de toi-même en juillet. ☀️",
|
||
"Fais-le pour le 'toi' qui recevra son affectation SIGEM. 📩",
|
||
"La douleur de la discipline pèse moins lourd que celle du regret. ⚖️",
|
||
"Tu n'as pas besoin d'être un génie, juste d'être constant. 🐢",
|
||
"Visualise ton nom sur la liste des admis. Ça arrive. 👁️",
|
||
"Ce chapitre qui te résiste finira par céder. Insiste. 🔨",
|
||
"Tu n'es pas seul(e), des milliers d'autres galèrent aussi. Courage ! 🤝",
|
||
"Prends 5 minutes pour t'aérer, tu seras plus efficace après. 🌳",
|
||
"La prépa, c'est l'école de l'humilité et de la résilience. Tu gères. 🧘",
|
||
"Chaque théorème appris est une munition pour le jour J. 🔫",
|
||
"Ne te compare pas aux autres, compare-toi à toi hier. 📈",
|
||
"Tu construis ton avenir, brique par brique, DM par DM. 🏗️",
|
||
"C'est normal d'être fatigué(e), tu accomplis quelque chose de grand. 🛌",
|
||
"Garde la tête froide et le cœur chaud. ❤️",
|
||
"Il n'y a pas de question bête, il n'y a que des points à gagner. 🙋",
|
||
"Le déclic arrive souvent quand on s'y attend le moins. ⚡",
|
||
"Sois bienveillant(e) avec toi-même, tu es ton propre moteur. 🚗",
|
||
"Regarde tout le chemin parcouru depuis le début de l'année ! 🗺️",
|
||
"Tu es capable de comprendre des choses que 99% des gens ignorent. 🌌",
|
||
"L'intégration n'est pas une question de chance, c'est une question de ténacité. 🍀",
|
||
"Buvard ou Major, l'important c'est de tout donner. 🦁",
|
||
"Ton cerveau est un muscle, et là, tu fais de la muscu de haut niveau. 🏋️",
|
||
"Rien n'est joué jusqu'à la dernière épreuve. Fonce ! 🏁",
|
||
"La réussite, c'est tomber 7 fois et se relever 8. 🩹",
|
||
"Fais confiance à ta préparation. Tu as bossé pour ça. 🧱",
|
||
"Un jour, tu riras de cette période avec tes potes d'école. 🍻",
|
||
"Tu n'étudies pas pour le prof, tu étudies pour ta liberté future. 🕊️",
|
||
"Accroche-toi, la vue est superbe depuis le sommet. ⛰️",
|
||
"Ta capacité à encaisser la charge de travail est impressionnante. 🔋",
|
||
"Ne laisse pas un DS raté gâcher ta semaine. Reset. 🔄",
|
||
"Tu es l'architecte de ta propre réussite. 📐",
|
||
"Chaque minute investie maintenant te rapportera des années de confort. 🏦",
|
||
"Tu as le droit de craquer, mais tu as le devoir de revenir. 🥊",
|
||
"Pense à la fierté de porter le tricorne, le képi ou l'uniforme. 🧢",
|
||
"La prépa t'apprend à réfléchir, personne ne pourra t'enlever ça. 🗝️",
|
||
"C'est dur ? C'est que tu es en train de monter de niveau. 🆙",
|
||
"Garde le cap, la tempête finit toujours par passer. ⛵",
|
||
"Tu es bien plus intelligent(e) que tu ne le crois sous stress. 🧠",
|
||
"Fais-toi un bon thé/café et remets-toi en selle. ☕",
|
||
"Le succès est la somme de petits efforts répétés jour après jour. ➕",
|
||
"Ne lâche rien, l'admissibilité se joue parfois à des détails. 🔍",
|
||
"Tu as le potentiel pour intégrer l'école qui te correspond. 🧩",
|
||
"Respire par le ventre. Tout va bien se passer. 🌬️",
|
||
"Ta volonté est ton plus grand talent. ⭐",
|
||
"Allez, encore un petit effort. Tu es un(e) guerrier(e). ⚔️",
|
||
];
|
||
|
||
const STRESSFUL_MESSAGES = [
|
||
// --- Les Classiques (Gardés) ---
|
||
"Pendant que tu scroll, tes concurrents bossent les intégrales. 📉",
|
||
"Netflix ou les concours ? Choisis vite. ⏳",
|
||
"Les places à l'X ne se gagnent pas sur TikTok. 📱",
|
||
"Ton futur toi te regarde avec déception là. 👀",
|
||
"Les autres sont déjà au chapitre suivant... 📖",
|
||
"Ce DM ne va pas se faire tout seul. Allez hop ! 📝",
|
||
"Chaque minute perdue est une place de perdue au classement. ⚠️",
|
||
"Tu veux vraiment passer 5/2 ? Bouge-toi ! 🏃",
|
||
"Tes notes ne vont pas s'améliorer par magie. 📊",
|
||
"La médiocrité est confortable, mais l'X c'est mieux. 🤔",
|
||
"Tes concurrents ne prennent pas de pause, eux. ⚡",
|
||
"Le niveau monte, et toi tu stagnes. Réagis ! 📈",
|
||
"À ce rythme, tu vas finir à la fac (non je rigole... ou pas). 🔄",
|
||
"Les colles arrivent, es-tu prêt(e) ? Spoiler : non. 😬",
|
||
"Tu sais combien il reste de jours ? C'est terrifiant, non ? ⏰",
|
||
"Pendant que tu lis ce message, 3 exos auraient pu être pliés. 🤷",
|
||
"La motivation c'est pour les faibles, la discipline c'est pour les forts. 💼",
|
||
"Tu te rappelles pourquoi tu es en prépa ? Prouve-le ! 🎯",
|
||
"Les profs ont raison : tu gâches ton potentiel là. 📚",
|
||
"C'est pas avec des 'demain je m'y mets' que tu vas intégrer Centrale. 🚫",
|
||
|
||
// --- Les Nouveaux (Spécial "Violence") ---
|
||
"Tu vises l'ENS ou l'E3A là ? Ton attitude me met le doute. 🤨",
|
||
"Ton major de promo a déjà fini le sujet de 2018, lui. 🏎️",
|
||
"C'est pas en regardant le plafond que le théorème va rentrer. 🧱",
|
||
"Si tu ne bosses pas maintenant, prépare ton dossier Parcoursup. 📂",
|
||
"Dors ou travaille. Tout le reste est une perte de temps. 💤",
|
||
"Arrête de te mentir, tu n'es pas en 'pause', tu procrastines. 🤥",
|
||
"L'examinateur s'en fiche que tu sois fatigué. Il veut le résultat. 👹",
|
||
"Tu crois que Cauchy a procrastiné pour ses suites ? Non. 🔢",
|
||
"Ta mention au bac ne te sauvera pas aux concours. 🔥",
|
||
"La 5/2, c'est bien, mais intégrer en 3/2 c'est mieux. 🦄",
|
||
"Imagine ta tête devant le sujet si tu continues comme ça. 😱",
|
||
"Ton téléphone est ton pire ennemi. Éteins-le. 📵",
|
||
"Moins de story, plus de théorie. 📸",
|
||
"Tu veux finir ingénieur ou touriste ? 👷",
|
||
"Les Mines de Paris ne recrutent pas sur Candy Crush. 🍬",
|
||
"C'est le moment de souffrir pour ne pas pleurer en juillet. 😭",
|
||
"Tu connais tes formules de trigo ? J'en doute. Vérifie. 📐",
|
||
"Le jury ne fera pas de cadeau. Pourquoi tu t'en fais ? 🎁",
|
||
"Tu as vu le sujet de l'an dernier ? T'es pas prêt. 📉",
|
||
"Arrête de rêver ta vie, va étudier ta physique. ⚛️",
|
||
"La chimie orga ne s'apprend pas par osmose. 🧪",
|
||
"Chaque heure de perdue est une victoire pour ton concurrent direct. 🤺",
|
||
"C'est le moment de passer en mode machine. 🤖",
|
||
"Tu te reposeras après les écrits. Pour l'instant, au charbon. ⛏️",
|
||
"Si c'était facile, tout le monde serait à Polytechnique. 🏰",
|
||
"Ton excuse pour ne pas bosser est nulle. Retourne travailler. 🚮",
|
||
"L'avenir appartient à ceux qui se lèvent tôt (et qui font des maths). 🌅",
|
||
"Tu préfères la douleur de l'effort ou la douleur de l'échec ? 🎭",
|
||
"C'est pas le moment de flancher, c'est le money time ! 💰",
|
||
"Regarde tes notes de la dernière khôlle. Ça te suffit ? 📉",
|
||
"Tu n'es pas fatigué, tu es juste démotivé. Change ça. 🔋",
|
||
"La chance ne sourit qu'aux esprits bien préparés. 🍀",
|
||
"Tu veux voir tes amis intégrer pendant que tu redoubles ? 👯",
|
||
"Fais-le pour humilier ceux qui n'ont pas cru en toi. 😈",
|
||
"Pas de bras, pas de chocolat. Pas de travail, pas d'école. 🍫",
|
||
"Ton avenir se joue dans les 30 prochaines minutes. ⏳",
|
||
"L'excellence est une habitude, pas un acte isolé. 🏆",
|
||
"Arrête de chouiner et va faire un DL. 🔢",
|
||
"Tu as déjà oublié ton cours d'hier ? C'est grave. 🧠",
|
||
"Le concours blanc approche. La panique aussi. 🚨",
|
||
"Tu penses que tu as le niveau ? Prouve-le sur une feuille blanche. 📄",
|
||
"C'est pas le moment de faire du social. C'est la guerre. ⚔️",
|
||
"Tu veux une médaille ? Va la chercher avec tes dents. 🏅",
|
||
"La prépa c'est la jungle. Mange ou sois mangé. 🦁",
|
||
"Ton lit est confortable, mais le chômage l'est moins. 🛋️",
|
||
"Si tu lis ça, c'est que tu ne bosses pas. Allez, oust ! 👉",
|
||
"Tu as 5 minutes pour t'y mettre, sinon c'est mort pour aujourd'hui. ⏲️",
|
||
"Ne sois pas celui qui dit 'j'aurais dû'. Sois celui qui l'a fait. ✅",
|
||
"La physique quantique t'attend. Elle n'est pas patiente. 🌌",
|
||
"Arrête de scroller, ça ne va pas augmenter ton admissibilité. 🛑",
|
||
];
|
||
|
||
export default function StressPrepaPage() {
|
||
const [timeLeft, setTimeLeft] = useState({
|
||
days: 0,
|
||
hours: 0,
|
||
minutes: 0,
|
||
seconds: 0,
|
||
});
|
||
const [progress, setProgress] = useState(0);
|
||
const [messageMode, setMessageMode] = useState<
|
||
"encouraging" | "stressful" | "none"
|
||
>("none");
|
||
const [messages, setMessages] = useState<string[]>([]);
|
||
|
||
useEffect(() => {
|
||
const examDate = new Date("2026-04-13T07:00:00");
|
||
const schoolYearStart = new Date("2025-09-01T00:00:00");
|
||
const storedMode = localStorage.getItem("stress-prepa-message-mode");
|
||
if (
|
||
storedMode === "encouraging" ||
|
||
storedMode === "stressful" ||
|
||
storedMode === "none"
|
||
) {
|
||
setMessageMode(storedMode);
|
||
}
|
||
|
||
const updateCountdown = () => {
|
||
const now = new Date();
|
||
const difference = examDate.getTime() - now.getTime();
|
||
|
||
if (difference > 0) {
|
||
const days = Math.floor(difference / (1000 * 60 * 60 * 24));
|
||
const hours = Math.floor((difference / (1000 * 60 * 60)) % 24);
|
||
const minutes = Math.floor((difference / 1000 / 60) % 60);
|
||
const seconds = Math.floor((difference / 1000) % 60);
|
||
|
||
setTimeLeft({ days, hours, minutes, seconds });
|
||
|
||
// Calculate progress percentage
|
||
const totalDuration = examDate.getTime() - schoolYearStart.getTime();
|
||
const elapsed = now.getTime() - schoolYearStart.getTime();
|
||
const progressPercent = Math.min(
|
||
Math.max((elapsed / totalDuration) * 100, 0),
|
||
100
|
||
);
|
||
setProgress(progressPercent);
|
||
} else {
|
||
setTimeLeft({ days: 0, hours: 0, minutes: 0, seconds: 0 });
|
||
setProgress(100);
|
||
}
|
||
};
|
||
|
||
updateCountdown();
|
||
const interval = setInterval(updateCountdown, 1000);
|
||
|
||
return () => clearInterval(interval);
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
if (messageMode === "none") {
|
||
setMessages([]);
|
||
return;
|
||
}
|
||
const messages =
|
||
messageMode === "encouraging" ? ENCOURAGING_MESSAGES : STRESSFUL_MESSAGES;
|
||
setMessages(messages);
|
||
}, [messageMode]);
|
||
|
||
const formatNumber = (num: number) => num.toString().padStart(2, "0");
|
||
|
||
return (
|
||
<div className="relative min-h-full flex flex-col items-center justify-center bg-background px-4 overflow-hidden">
|
||
{/* Animated gradient background */}
|
||
<div className="absolute inset-0 bg-gradient-to-br from-background via-muted/20 to-background animate-gradient" />
|
||
|
||
{/* Enhanced grid pattern */}
|
||
<div className="absolute inset-0 opacity-[0.03]">
|
||
<div
|
||
className="absolute inset-0"
|
||
style={{
|
||
backgroundImage: `
|
||
linear-gradient(to right, currentColor 1px, transparent 1px),
|
||
linear-gradient(to bottom, currentColor 1px, transparent 1px)
|
||
`,
|
||
backgroundSize: "64px 64px",
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
<Dialog>
|
||
<DialogTrigger asChild>
|
||
<Button
|
||
variant="outline"
|
||
size="icon"
|
||
className="absolute z-100 top-4 right-4 rounded-full bg-card/80 backdrop-blur-sm hover:bg-card border-border/50 shadow-lg"
|
||
>
|
||
<Info className="h-4 w-4" />
|
||
<span className="sr-only">Informations</span>
|
||
</Button>
|
||
</DialogTrigger>
|
||
<DialogContent className="sm:max-w-md">
|
||
<DialogHeader>
|
||
<DialogTitle className="text-2xl font-bold">
|
||
Stress Prépa
|
||
</DialogTitle>
|
||
<DialogContent className="space-y-4 pt-4 text-base">
|
||
<div className="space-y-2">
|
||
<p className="text-foreground/90">
|
||
Compte à rebours jusqu'aux concours
|
||
</p>
|
||
<div className="h-px bg-border/50" />
|
||
</div>
|
||
|
||
<div className="space-y-3 text-sm">
|
||
<div className="flex justify-between items-center">
|
||
<span className="text-muted-foreground">
|
||
Début des concours
|
||
</span>
|
||
<span className="font-mono font-semibold text-foreground">
|
||
13 Avril 2026
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between items-center">
|
||
<span className="text-muted-foreground">
|
||
Début de l'année
|
||
</span>
|
||
<span className="font-mono font-semibold text-foreground">
|
||
1er Sept. 2025
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="pt-4 space-y-4">
|
||
<div className="h-px bg-border/50" />
|
||
<div className="space-y-3">
|
||
<Label className="text-sm font-semibold text-foreground">
|
||
Mode des messages
|
||
</Label>
|
||
<RadioGroup
|
||
value={messageMode}
|
||
onValueChange={(value) => {
|
||
localStorage.setItem("stress-prepa-message-mode", value);
|
||
setMessageMode(
|
||
value as "encouraging" | "stressful" | "none"
|
||
);
|
||
}}
|
||
className="space-y-0"
|
||
>
|
||
<div className="flex items-center space-x-3 px-3 pt-3 rounded-lg hover:bg-muted/50 transition-colors">
|
||
<RadioGroupItem value="none" id="none" />
|
||
<Label
|
||
htmlFor="none"
|
||
className="font-normal cursor-pointer flex-1"
|
||
>
|
||
Aucun message 🤐
|
||
</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-3 px-3 py-1 rounded-lg hover:bg-muted/50 transition-colors">
|
||
<RadioGroupItem value="encouraging" id="encouraging" />
|
||
<Label
|
||
htmlFor="encouraging"
|
||
className="font-normal cursor-pointer flex-1"
|
||
>
|
||
Encouragement 🙌
|
||
</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-3 px-3 rounded-lg hover:bg-muted/50 transition-colors">
|
||
<RadioGroupItem value="stressful" id="stressful" />
|
||
<Label
|
||
htmlFor="stressful"
|
||
className="font-normal cursor-pointer flex-1"
|
||
>
|
||
Trash talk 🤡
|
||
</Label>
|
||
</div>
|
||
</RadioGroup>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="pt-4">
|
||
<div className="h-px bg-border/50 mb-4" />
|
||
<p className="text-xs text-muted-foreground">
|
||
Tous droits réservés Khollisé © {new Date().getFullYear()} —
|
||
Messages générés avec l'intelligence artificielle.
|
||
</p>
|
||
</div>
|
||
</DialogContent>
|
||
</DialogHeader>
|
||
</DialogContent>
|
||
</Dialog>
|
||
|
||
<div className="relative w-full max-w-6xl mx-auto text-center space-y-16">
|
||
{/* Enhanced title section */}
|
||
<div className="space-y-3">
|
||
<h1 className="text-5xl md:text-7xl font-bold tracking-tight text-balance leading-tight">
|
||
Temps avant les concours
|
||
</h1>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 md:gap-4">
|
||
<div className="group bg-card border-2 border-border/50 rounded-2xl p-6 md:p-10 transition-all hover:border-border hover:shadow-xl hover:scale-[1.02]">
|
||
<div className="text-6xl md:text-8xl font-bold tabular-nums tracking-tight leading-none">
|
||
{timeLeft.days}
|
||
</div>
|
||
<div className="text-xs md:text-sm text-muted-foreground mt-3 font-medium uppercase tracking-wider">
|
||
Jour{timeLeft.days > 1 ? "s" : ""}
|
||
</div>
|
||
</div>
|
||
<div className="group bg-card border-2 border-border/50 rounded-2xl p-6 md:p-10 transition-all hover:border-border hover:shadow-xl hover:scale-[1.02]">
|
||
<div className="text-6xl md:text-8xl font-bold tabular-nums tracking-tight leading-none">
|
||
{formatNumber(timeLeft.hours)}
|
||
</div>
|
||
<div className="text-xs md:text-sm text-muted-foreground mt-3 font-medium uppercase tracking-wider">
|
||
Heure{timeLeft.hours > 1 ? "s" : ""}
|
||
</div>
|
||
</div>
|
||
<div className="group bg-card border-2 border-border/50 rounded-2xl p-6 md:p-10 transition-all hover:border-border hover:shadow-xl hover:scale-[1.02]">
|
||
<div className="text-6xl md:text-8xl font-bold tabular-nums tracking-tight leading-none">
|
||
{formatNumber(timeLeft.minutes)}
|
||
</div>
|
||
<div className="text-xs md:text-sm text-muted-foreground mt-3 font-medium uppercase tracking-wider">
|
||
Minute{timeLeft.minutes > 1 ? "s" : ""}
|
||
</div>
|
||
</div>
|
||
<div className="group bg-card border-2 border-border/50 rounded-2xl p-6 md:p-10 transition-all hover:border-border hover:shadow-xl hover:scale-[1.02]">
|
||
<div className="text-6xl md:text-8xl font-bold tabular-nums tracking-tight leading-none">
|
||
{formatNumber(timeLeft.seconds)}
|
||
</div>
|
||
<div className="text-xs md:text-sm text-muted-foreground mt-3 font-medium uppercase tracking-wider">
|
||
Seconde{timeLeft.seconds > 1 ? "s" : ""}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="min-h-10 flex items-center justify-center px-4">
|
||
{messages.length > 0 && (
|
||
<TypingText
|
||
text={messages}
|
||
duration={25}
|
||
holdDelay={5000}
|
||
className="text-lg md:text-xl text-muted-foreground/90 italic max-w-3xl leading-relaxed"
|
||
>
|
||
<TypingTextCursor className="!h-6 !w-1 rounded-full ml-1 -mb-1" />
|
||
</TypingText>
|
||
)}
|
||
</div>
|
||
|
||
<div className="space-y-4 max-w-3xl mx-auto">
|
||
<div className="relative w-full h-4 bg-muted/50 rounded-full overflow-hidden border border-border/30 shadow-inner">
|
||
<div
|
||
className="absolute inset-y-0 left-0 bg-primary rounded-full transition-all duration-1000 ease-out shadow-lg"
|
||
style={{ width: `${progress}%` }}
|
||
/>
|
||
</div>
|
||
<div className="flex items-center justify-between text-sm">
|
||
<span className="text-muted-foreground">
|
||
Progression de l'année
|
||
</span>
|
||
<span className="font-mono font-bold text-lg text-foreground tabular-nums">
|
||
{progress.toFixed(2)}%
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|