Skip to content

Commit 45b81d9

Browse files
committed
feat(quiz): replace emojis with lucide-react icons
1 parent 7d152a3 commit 45b81d9

6 files changed

Lines changed: 54 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: 29 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,49 @@ 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: 'Час вийшов',
42+
message: `Ви відповіли на ${answeredCount} з ${total} питань. Результат не зараховано.`,
43+
color: 'text-orange-600 dark:text-orange-400',
44+
};
45+
}
46+
4647
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-
}
48+
return {
49+
icon: <Clock className="w-14 h-14 text-gray-500" />,
50+
title: t('timeUp.title'),
51+
message: t('timeUp.message'),
52+
color: 'text-gray-600 dark:text-gray-400',
53+
};
54+
}
5455

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

6465
if (percentage < 50) {
6566
return {
66-
emoji: '📚',
67+
icon: <BookOpen className="w-14 h-14 text-red-500" />,
6768
title: t('needPractice.title'),
6869
message: t('needPractice.message'),
6970
color: 'text-red-600 dark:text-red-400',
7071
};
7172
} else if (percentage < 80) {
7273
return {
73-
emoji: '💪',
74+
icon: <TrendingUp className="w-14 h-14 text-orange-500" />,
7475
title: t('goodJob.title'),
7576
message: t('goodJob.message'),
7677
color: 'text-orange-600 dark:text-orange-400',
7778
};
7879
} else {
7980
return {
80-
emoji: '🎉',
81+
icon: <Trophy className="w-14 h-14 text-amber-500" />,
8182
title: t('excellent.title'),
8283
message: t('excellent.message'),
8384
color: 'text-green-600 dark:text-green-400',
@@ -89,7 +90,7 @@ export function QuizResult({
8990

9091
return (
9192
<div className="max-w-2xl mx-auto space-y-8">
92-
<div className="text-center text-6xl">{motivation.emoji}</div>
93+
<div className="flex justify-center">{motivation.icon}</div>
9394
{!isIncomplete && (
9495
<>
9596
<div className="text-center space-y-2">
@@ -124,7 +125,7 @@ export function QuizResult({
124125
{violationsCount >= 3 && (
125126
<div className="p-4 rounded-xl bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800">
126127
<p className="text-center text-orange-800 dark:text-orange-200 font-medium">
127-
<span aria-hidden="true">⚠️</span> {t('violations', { count: violationsCount })}
128+
<AlertTriangle className="w-4 h-4 inline" /> {t('violations', { count: violationsCount })}
128129
</p>
129130
</div>
130131
)}

0 commit comments

Comments
 (0)