Skip to content

Commit ad53461

Browse files
committed
feat: randomize textures
1 parent 7af2bbc commit ad53461

4 files changed

Lines changed: 49 additions & 8 deletions

File tree

client/src/components/QuizArea.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
1-
import { motion, AnimatePresence } from "motion/react";
1+
import { motion, AnimatePresence } from "framer-motion";
22
import { type QuizAreaProps } from "@/types/quiz";
3+
import { useIsMobile } from "@/hooks/useIsMobile";
4+
5+
export const QuizArea = ({ question, questionIndex, selectedAnswer, onSelectAnswer, textureUrl }: QuizAreaProps) => {
6+
const isMobile = useIsMobile();
37

4-
export const QuizArea = ({ question, questionIndex, selectedAnswer, onSelectAnswer }: QuizAreaProps) => {
58
return (
6-
<div className="md:bg-neutral-950 md:border-2 md:border-neutral-500 w-full h-full gap-6 md:p-10 md:shadow-2xl md:shadow-neutral-950/60 flex flex-col justify-center items-center md:bg-[url(/texture-two.png)]">
9+
<motion.div
10+
className={`md:bg-neutral-950 md:border-2 md:border-neutral-500 w-full h-full gap-6 md:p-10 md:shadow-2xl md:shadow-neutral-950/60 flex flex-col justify-center items-center relative`}
11+
initial={{ opacity: 0 }}
12+
animate={{ opacity: 1 }}
13+
transition={{ duration: 0.3 }}
14+
>
715
<AnimatePresence mode="wait">
16+
{!isMobile && textureUrl && (
17+
<motion.div
18+
key={`${question.id}-bg`}
19+
className="absolute inset-0 w-full h-full"
20+
style={{ backgroundImage: `url(${textureUrl})` }}
21+
initial={{ opacity: 0 }}
22+
animate={{ opacity: 1 }}
23+
exit={{ opacity: 0 }}
24+
transition={{ duration: 0.5 }}
25+
/>
26+
)}
827
<motion.div
928
key={question.id}
29+
className="relative w-full h-full flex flex-col justify-center items-center gap-6"
1030
initial={{ opacity: 0 }}
1131
animate={{ opacity: 1 }}
1232
exit={{ opacity: 0 }}
13-
transition={{ duration: 0.5 }}
14-
className="w-full h-full flex flex-col justify-center items-center gap-6"
33+
transition={{ duration: 0.3 }}
1534
>
1635
<div className="flex flex-col w-full max-w-3xl gap-4">
1736
<p className="font-heading text-4xl text-neutral-50">Question {questionIndex + 1}.</p>
@@ -40,6 +59,6 @@ export const QuizArea = ({ question, questionIndex, selectedAnswer, onSelectAnsw
4059
</div>
4160
</motion.div>
4261
</AnimatePresence>
43-
</div>
62+
</motion.div>
4463
);
4564
};

client/src/routes/Quiz/QuizOngoing.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useEffect, useState, useCallback } from "react";
22
import { useParams, useNavigate } from "react-router-dom";
33
import toast from "react-hot-toast";
44
import { ArrowLeft, ArrowRight, Clock } from "lucide-react";
5+
import { useTextureStore } from "@/stores/textureStore";
56
import { QuizArea } from "@/components/QuizArea";
67
import { QuizNav } from "@/components/QuizNav";
78
import { useIsMobile } from "@/hooks/useIsMobile";
@@ -21,6 +22,7 @@ export const QuizOngoingPage = () => {
2122
const [visited, setVisited] = useState<boolean[]>([]);
2223
const [elapsedTime, setElapsedTime] = useState(0);
2324
const [loading, setLoading] = useState(true);
25+
const { currentTexture, setRandomTexture } = useTextureStore();
2426

2527
useEffect(() => {
2628
if (!quizId) {
@@ -69,6 +71,10 @@ export const QuizOngoingPage = () => {
6971
return () => clearInterval(timer);
7072
}, []);
7173

74+
useEffect(() => {
75+
setRandomTexture();
76+
}, [currentQuestionIndex, setRandomTexture]);
77+
7278
const handleGoToQuestion = useCallback((index: number) => {
7379
setCurrentQuestionIndex(index);
7480
setVisited((prev) => {
@@ -193,11 +199,11 @@ export const QuizOngoingPage = () => {
193199
{headerContent}
194200
<div className="pb-28">
195201
<QuizArea
196-
key={currentQuestionIndex} // Ensures animation triggers
197202
question={quizData.questions[currentQuestionIndex]}
198203
questionIndex={currentQuestionIndex}
199204
selectedAnswer={answers[currentQuestionIndex]}
200205
onSelectAnswer={handleSelectAnswer}
206+
textureUrl={currentTexture}
201207
/>
202208
</div>
203209
</div>
@@ -211,11 +217,11 @@ export const QuizOngoingPage = () => {
211217
<div className="bg-neutral-900 md:h-screen min-h-screen flex">
212218
<div className="pl-6 py-6 w-full">
213219
<QuizArea
214-
key={currentQuestionIndex} // Ensures animation triggers
215220
question={quizData.questions[currentQuestionIndex]}
216221
questionIndex={currentQuestionIndex}
217222
selectedAnswer={answers[currentQuestionIndex]}
218223
onSelectAnswer={handleSelectAnswer}
224+
textureUrl={currentTexture}
219225
/>
220226
</div>
221227
<div className="flex flex-col lg:w-1/3 w-2/5 justify-between pb-6">

client/src/stores/textureStore.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { create } from 'zustand';
2+
3+
const textures = Array.from({ length: 12 }, (_, i) => `/textures/${i + 1}.png`);
4+
5+
interface TextureState {
6+
currentTexture: string;
7+
setRandomTexture: () => void;
8+
}
9+
10+
export const useTextureStore = create<TextureState>((set) => ({
11+
currentTexture: textures[Math.floor(Math.random() * textures.length)],
12+
setRandomTexture: () => {
13+
set({ currentTexture: textures[Math.floor(Math.random() * textures.length)] });
14+
},
15+
}));

client/src/types/quiz.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export interface QuizAreaProps {
9797
questionIndex: number;
9898
selectedAnswer: number | null;
9999
onSelectAnswer: (answerIndex: number) => void;
100+
textureUrl: string;
100101
}
101102

102103
/**

0 commit comments

Comments
 (0)