Skip to content

Commit eb4dc6a

Browse files
Merge pull request #139 from DevLoversTeam/sl/feat/quiz
feat(quiz): replace emojis with lucide-react icons
2 parents af3ce94 + c18bbaa commit eb4dc6a

9 files changed

Lines changed: 65 additions & 45 deletions

File tree

frontend/components/quiz/CountdownTimer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useEffect, useState } from 'react';
44
import { useTranslations } from 'next-intl';
55
import { cn } from '@/lib/utils';
6+
import { AlertTriangle } from 'lucide-react';
67

78
interface CountdownTimerProps {
89
timeLimitSeconds: number;
@@ -105,7 +106,7 @@ export function CountdownTimer({
105106
<p className="text-xs mt-2 font-medium">
106107
{percentage <= 10 ? (
107108
<>
108-
<span aria-hidden="true">⚠️</span> {t('almostDone')}
109+
<AlertTriangle className="w-4 h-4 inline text-amber-500" /> {t('almostDone')}
109110
</>
110111
) : (
111112
<>

frontend/components/quiz/QuizCard.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useTranslations } from 'next-intl';
44
import { Link } from '@/i18n/routing';
55
import { Badge } from '@/components/ui/badge';
6+
import { FileText, Clock } from 'lucide-react';
67

78
interface QuizCardProps {
89
quiz: {
@@ -44,12 +45,16 @@ export function QuizCard({ quiz, userProgress }: QuizCardProps) {
4445
{quiz.description}
4546
</p>
4647
)}
47-
<div className="flex gap-3 text-xs text-gray-500 mb-3">
48-
<span>📝 {quiz.questionsCount} {t('questions')}</span>
49-
<span>
50-
⏱️ {Math.floor((quiz.timeLimitSeconds ?? quiz.questionsCount * 30) / 60)} {t('min')}
51-
</span>
52-
</div>
48+
<div className="flex gap-3 text-xs text-gray-500 mb-3">
49+
<span className="flex items-center gap-1">
50+
<FileText className="w-3.5 h-3.5 text-blue-500 dark:text-blue-400" />
51+
{quiz.questionsCount} {t('questions')}
52+
</span>
53+
<span className="flex items-center gap-1">
54+
<Clock className="w-3.5 h-3.5 text-blue-500 dark:text-blue-400" />
55+
{Math.floor((quiz.timeLimitSeconds ?? quiz.questionsCount * 30) / 60)} {t('min')}
56+
</span>
57+
</div>
5358
</div>
5459
{userProgress && (
5560
<div className="mb-6">

frontend/components/quiz/QuizContainer.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { savePendingQuizResult } from '@/lib/quiz/guest-quiz';
1717
import type { QuizQuestionClient } from '@/db/queries/quiz';
1818
import { ConfirmModal } from '@/components/ui/confirm-modal';
1919
import { Button } from '@/components/ui/button';
20+
import { FileText, Ban, AlertTriangle, Clock } from 'lucide-react';
2021

2122
interface Answer {
2223
questionId: string;
@@ -380,8 +381,8 @@ const confirmQuit = () => {
380381
</h2>
381382

382383
<div className="space-y-4 text-gray-700 dark:text-gray-300">
383-
<div className="flex gap-3">
384-
<span className="text-xl">📝</span>
384+
<div className="flex gap-3">
385+
<FileText className="w-5 h-5 text-blue-500 dark:text-blue-400 flex-shrink-0 mt-0.5" />
385386
<div>
386387
<p className="font-medium">{tRules('general.title')}</p>
387388
<p className="text-sm text-gray-600 dark:text-gray-400">
@@ -391,7 +392,7 @@ const confirmQuit = () => {
391392
</div>
392393

393394
<div className="flex gap-3">
394-
<span className="text-xl">🚫</span>
395+
<Ban className="w-5 h-5 text-red-500 dark:text-red-400 flex-shrink-0 mt-0.5" />
395396
<div>
396397
<p className="font-medium">{tRules('forbidden.title')}</p>
397398
<ul className="text-sm text-gray-600 dark:text-gray-400 list-disc list-inside space-y-1">
@@ -404,17 +405,16 @@ const confirmQuit = () => {
404405
</div>
405406

406407
<div className="flex gap-3">
407-
<span className="text-xl">⚠️</span>
408+
<AlertTriangle className="w-5 h-5 text-amber-500 dark:text-amber-400 flex-shrink-0 mt-0.5" />
408409
<div>
409410
<p className="font-medium">{tRules('control.title')}</p>
410411
<p className="text-sm text-gray-600 dark:text-gray-400">
411412
{tRules('control.description')}
412413
</p>
413414
</div>
414415
</div>
415-
416416
<div className="flex gap-3">
417-
<span className="text-xl">⏱️</span>
417+
<Clock className="w-5 h-5 text-blue-500 dark:text-blue-400 flex-shrink-0 mt-0.5" />
418418
<div>
419419
<p className="font-medium">{tRules('time.title')}</p>
420420
<p className="text-sm text-gray-600 dark:text-gray-400">

frontend/components/quiz/QuizProgress.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useTranslations } from 'next-intl';
44
import { cn } from '@/lib/utils';
5+
import { Check, X } from 'lucide-react';
56

67
interface Answer {
78
questionId: string;
@@ -90,7 +91,7 @@ export function QuizProgress({ current, total, answers }: QuizProgressProps) {
9091
>
9192
{isAnswered ? (
9293
<span className="text-white font-bold">
93-
{isCorrect ? '✓' : '✗'}
94+
{isCorrect ? <Check className="w-3 h-3" /> : <X className="w-3 h-3" />}
9495
</span>
9596
) : (
9697
<span

frontend/components/quiz/QuizQuestion.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
66
import { Button } from '@/components/ui/button';
77
import ExplanationRenderer from './ExplanationRenderer';
88
import { cn } from '@/lib/utils';
9+
import { Check, X, Lightbulb } from 'lucide-react';
910

1011
interface QuizQuestionProps {
1112
question: QuizQuestionClient;
@@ -66,12 +67,12 @@ export function QuizQuestion({
6667
<span className="flex-1 text-base">{answer.answerText}</span>
6768
{showCorrect && (
6869
<span className="text-green-600 dark:text-green-400 text-sm font-medium">
69-
{t('correct')}
70+
<Check className="w-4 h-4 inline" /> {t('correct')}
7071
</span>
7172
)}
7273
{showIncorrect && (
7374
<span className="text-red-600 dark:text-red-400 text-sm font-medium">
74-
{t('incorrect')}
75+
<X className="w-4 h-4 inline" /> {t('incorrect')}
7576
</span>
7677
)}
7778
</label>
@@ -99,7 +100,7 @@ export function QuizQuestion({
99100
)}
100101
>
101102
<div className="flex items-start gap-3">
102-
<div className="text-2xl">💡</div>
103+
<Lightbulb className="w-6 h-6 text-amber-500 flex-shrink-0" />
103104
<div className="flex-1">
104105
<h4 className="font-semibold text-gray-900 dark:text-gray-100 mb-1">
105106
{t('recommendation.title')}

frontend/components/quiz/QuizResult.tsx

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useLocale, useTranslations } from 'next-intl';
44
import { cn } from '@/lib/utils';
55
import { Button } from '@/components/ui/button';
6+
import { Clock, BookOpen, TrendingUp, Trophy, AlertTriangle } from 'lucide-react';
67

78
interface QuizResultProps {
89
score: number;
@@ -35,49 +36,48 @@ export function QuizResult({
3536
const t = useTranslations('quiz.result');
3637
const getMotivationalMessage = () => {
3738
if (isIncomplete && answeredCount > 0) {
38-
return {
39-
emoji: '⏱️',
40-
title: 'Час вийшов',
41-
message: `Ви відповіли на ${answeredCount} з ${total} питань. Результат не зараховано.`,
42-
color: 'text-orange-600 dark:text-orange-400',
43-
};
44-
}
45-
39+
return {
40+
icon: <Clock className="w-14 h-14 text-orange-500" />,
41+
title: t('incomplete.title'),
42+
message: t('incomplete.message', { answeredCount, total }),
43+
color: 'text-orange-600 dark:text-orange-400',
44+
};
45+
}
4646
if (score === 0 && answeredCount === 0) {
47-
return {
48-
emoji: '⏱️',
49-
title: t('timeUp.title'),
50-
message: t('timeUp.message'),
51-
color: 'text-gray-600 dark:text-gray-400',
52-
};
53-
}
47+
return {
48+
icon: <Clock className="w-14 h-14 text-gray-500" />,
49+
title: t('timeUp.title'),
50+
message: t('timeUp.message'),
51+
color: 'text-gray-600 dark:text-gray-400',
52+
};
53+
}
5454

55-
if (score === 0 && answeredCount > 0) {
56-
return {
57-
emoji: '📚',
58-
title: t('allWrong.title'),
59-
message: t('allWrong.message'),
60-
color: 'text-red-600 dark:text-red-400',
61-
};
62-
}
55+
if (score === 0 && answeredCount > 0) {
56+
return {
57+
icon: <BookOpen className="w-14 h-14 text-red-500" />,
58+
title: t('allWrong.title'),
59+
message: t('allWrong.message'),
60+
color: 'text-red-600 dark:text-red-400',
61+
};
62+
}
6363

6464
if (percentage < 50) {
6565
return {
66-
emoji: '📚',
66+
icon: <BookOpen className="w-14 h-14 text-red-500" />,
6767
title: t('needPractice.title'),
6868
message: t('needPractice.message'),
6969
color: 'text-red-600 dark:text-red-400',
7070
};
7171
} else if (percentage < 80) {
7272
return {
73-
emoji: '💪',
73+
icon: <TrendingUp className="w-14 h-14 text-orange-500" />,
7474
title: t('goodJob.title'),
7575
message: t('goodJob.message'),
7676
color: 'text-orange-600 dark:text-orange-400',
7777
};
7878
} else {
7979
return {
80-
emoji: '🎉',
80+
icon: <Trophy className="w-14 h-14 text-amber-500" />,
8181
title: t('excellent.title'),
8282
message: t('excellent.message'),
8383
color: 'text-green-600 dark:text-green-400',
@@ -89,7 +89,7 @@ export function QuizResult({
8989

9090
return (
9191
<div className="max-w-2xl mx-auto space-y-8">
92-
<div className="text-center text-6xl">{motivation.emoji}</div>
92+
<div className="flex justify-center">{motivation.icon}</div>
9393
{!isIncomplete && (
9494
<>
9595
<div className="text-center space-y-2">
@@ -124,7 +124,7 @@ export function QuizResult({
124124
{violationsCount >= 3 && (
125125
<div className="p-4 rounded-xl bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800">
126126
<p className="text-center text-orange-800 dark:text-orange-200 font-medium">
127-
<span aria-hidden="true">⚠️</span> {t('violations', { count: violationsCount })}
127+
<AlertTriangle className="w-4 h-4 inline" /> {t('violations', { count: violationsCount })}
128128
</p>
129129
</div>
130130
)}

frontend/messages/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@
130130
"title": "Excellent Work!",
131131
"message": "You have mastered the material well"
132132
},
133+
"incomplete": {
134+
"title": "Time's up",
135+
"message": "You answered {answeredCount} out of {total} questions. Result not counted."
136+
},
133137
"violations": "Quiz completed with rule violations ({count} violations). Result not counted towards leaderboard.",
134138
"pointsAwarded": "+{points} points added to rating",
135139
"noPointsAwarded": "No points awarded (result not improved)",

frontend/messages/pl.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@
130130
"title": "Doskonała Praca!",
131131
"message": "Dobrze opanowałeś materiał"
132132
},
133+
"incomplete": {
134+
"title": "Czas minął",
135+
"message": "Odpowiedzi udzielono na {answeredCount} z {total} pytań. Wynik nie został zaliczony."
136+
},
133137
"violations": "Quiz ukończony z naruszeniami zasad ({count} naruszeń). Wynik nie zaliczony do rankingu.",
134138
"pointsAwarded": "+{points} punktów dodanych do oceny",
135139
"noPointsAwarded": "Nie przyznano punktów (wynik nie poprawiony)",

frontend/messages/uk.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@
130130
"title": "Чудова робота!",
131131
"message": "Ви добре засвоїли матеріал"
132132
},
133+
"incomplete": {
134+
"title": "Час вийшов",
135+
"message": "Ви відповіли на {answeredCount} з {total} питань. Результат не зараховано."
136+
},
133137
"violations": "Квіз завершено з порушеннями правил ({count} порушень). Результат не зараховано до рейтингу.",
134138
"pointsAwarded": "+{points} балів додано до рейтингу",
135139
"noPointsAwarded": "Бали не нараховано (результат не покращено)",

0 commit comments

Comments
 (0)