remove confetti

This commit is contained in:
gosangam
2026-10-16 20:04:25 +05:30
parent 0968b6046d
commit d64485daa4
+3 -30
View File
@@ -15,9 +15,7 @@
* *
* Signed in only: visitors get the sign-in modal over the page, and home if * Signed in only: visitors get the sign-in modal over the page, and home if
* they dismiss it. Nothing about the quiz loads until they're signed in. * they dismiss it. Nothing about the quiz loads until they're signed in.
*
* Finishing with every answer right sets off confetti — once, on finishing,
* not on revisiting the results later.
*/ */
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
@@ -43,13 +41,8 @@ import {
} from "@/lib/quiz"; } from "@/lib/quiz";
import { QuizResultView } from "@/components/quiz/quiz-result-view"; import { QuizResultView } from "@/components/quiz/quiz-result-view";
import { CopyPageLinkButton } from "@/components/layout/copy-page-link-button"; import { CopyPageLinkButton } from "@/components/layout/copy-page-link-button";
import { Confetti } from "@/components/sadhna/confetti";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
// The confetti's longest piece falls for 4.2s after a 0.5s delay; the layer
// is removed just after, so nothing lingers over the page once it's done.
const CONFETTI_MS = 5000;
type Stage = type Stage =
| { kind: "loading" } | { kind: "loading" }
| { kind: "intro"; card: QuizCard } | { kind: "intro"; card: QuizCard }
@@ -64,13 +57,6 @@ export function QuizPlayer({ id }: { id: string }) {
const [stage, setStage] = useState<Stage>({ kind: "loading" }); const [stage, setStage] = useState<Stage>({ kind: "loading" });
const [selected, setSelected] = useState<string[]>([]); const [selected, setSelected] = useState<string[]>([]);
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const [celebrate, setCelebrate] = useState(false);
useEffect(() => {
if (!celebrate) return;
const t = setTimeout(() => setCelebrate(false), CONFETTI_MS);
return () => clearTimeout(t);
}, [celebrate]);
// Every new question starts with nothing selected. // Every new question starts with nothing selected.
const goTo = (card: QuizCard, play: QuizPlay) => { const goTo = (card: QuizCard, play: QuizPlay) => {
@@ -93,7 +79,6 @@ export function QuizPlayer({ id }: { id: string }) {
async (card: QuizCard) => { async (card: QuizCard) => {
const result = await quizApi.result(id); const result = await quizApi.result(id);
setStage({ kind: "result", card, result }); setStage({ kind: "result", card, result });
return result;
}, },
[id], [id],
); );
@@ -133,12 +118,8 @@ export function QuizPlayer({ id }: { id: string }) {
setSubmitting(true); setSubmitting(true);
try { try {
const next = await quizApi.answer(id, play.question.id, selected); const next = await quizApi.answer(id, play.question.id, selected);
if (next.done) { if (next.done) await showResult(card);
const result = await showResult(card); else goTo(card, next);
if (result.total > 0 && result.score === result.total) {
setCelebrate(true);
}
} else goTo(card, next);
} catch (err) { } catch (err) {
// Most likely the question was already answered in another tab: pick up // Most likely the question was already answered in another tab: pick up
// wherever the attempt actually is rather than leaving this one stuck. // wherever the attempt actually is rather than leaving this one stuck.
@@ -329,14 +310,6 @@ export function QuizPlayer({ id }: { id: string }) {
)} )}
{stage.kind === "result" && <QuizResultView result={stage.result} />} {stage.kind === "result" && <QuizResultView result={stage.result} />}
{/* Full marks. Fixed over the viewport but pointer-events-none, so the
page stays usable while it falls, and unmounted once it's done. */}
{celebrate && (
<div className="pointer-events-none fixed inset-0 z-50" aria-hidden>
<Confetti />
</div>
)}
</main> </main>
); );
} }