import { useMemo, useState } from 'react'; import { motion } from 'motion/react'; import { Badge } from '@/components/ui/badge'; import { CodingQuestion, codingQuestions } from '@/data/codingQuestions'; import { DIFFICULTY_TOTALS, TOTAL_CODING_QUESTIONS, getQuestionCaseCount, getQuestionReward, getSolvedDifficultyCounts, } from '@/lib/codingProgress'; import { cn } from '@/lib/utils'; import { BookOpen, CheckCircle2, Code2, Coins, Search, Target, Trophy, } from 'lucide-react'; interface CodingSheetProps { onSelectQuestion: (question: CodingQuestion, mode: 'code' | 'solution') => void; solvedQuestionIds: string[]; } const categories = Array.from(new Set(codingQuestions.map((question) => question.category))); export default function CodingSheet({ onSelectQuestion, solvedQuestionIds, }: CodingSheetProps) { const [searchQuery, setSearchQuery] = useState(''); const [selectedCategory, setSelectedCategory] = useState(null); const solvedSet = useMemo(() => new Set(solvedQuestionIds), [solvedQuestionIds]); const difficultySolved = useMemo( () => getSolvedDifficultyCounts(solvedQuestionIds), [solvedQuestionIds], ); const filteredQuestions = useMemo(() => { return codingQuestions.filter((question) => { const matchesSearch = question.title.toLowerCase().includes(searchQuery.toLowerCase()) || question.category.toLowerCase().includes(searchQuery.toLowerCase()); const matchesCategory = selectedCategory ? question.category === selectedCategory : true; return matchesSearch && matchesCategory; }); }, [searchQuery, selectedCategory]); const solvedCount = solvedSet.size; const progressPercent = Math.min( 100, Math.round((solvedCount / TOTAL_CODING_QUESTIONS) * 100), ); return (
Problem Set

Coding Question Bank

Track real progress across all {TOTAL_CODING_QUESTIONS} coding questions with shared solved state, live rewards, and category-by-category completion.

Your Progress
{solvedCount} / {TOTAL_CODING_QUESTIONS}
{progressPercent}% Complete
{[ { label: 'Easy', solved: difficultySolved.Easy, total: DIFFICULTY_TOTALS.Easy, color: 'text-emerald-400', glow: 'bg-emerald-500/5', }, { label: 'Medium', solved: difficultySolved.Medium, total: DIFFICULTY_TOTALS.Medium, color: 'text-amber-400', glow: 'bg-amber-500/5', }, { label: 'Hard', solved: difficultySolved.Hard, total: DIFFICULTY_TOTALS.Hard, color: 'text-rose-400', glow: 'bg-rose-500/5', }, ].map((card) => (
{card.label}
{card.solved}
{card.solved} / {card.total} solved
))}
setSearchQuery(event.target.value)} className="w-full rounded-2xl border border-zinc-800 bg-zinc-950/60 py-3.5 pl-12 pr-4 text-sm text-white outline-none transition-all placeholder:text-zinc-600 focus:border-emerald-500/50 focus:ring-1 focus:ring-emerald-500/30" />
{categories.map((category) => ( ))}
{categories.map((category) => { const categoryQuestions = filteredQuestions.filter((question) => question.category === category); if (categoryQuestions.length === 0) { return null; } const categorySolved = categoryQuestions.filter((question) => solvedSet.has(question.id)).length; const categoryPercent = categoryQuestions.length > 0 ? Math.round((categorySolved / categoryQuestions.length) * 100) : 0; return (

{category}

{categoryQuestions.length} problems
{categorySolved}/{categoryQuestions.length} solved
{categoryPercent}%
{categoryQuestions.map((question, index) => { const isSolved = solvedSet.has(question.id); const reward = getQuestionReward(question.difficulty); const testCaseCount = getQuestionCaseCount(question); return ( ); })}
Status Title Test Cases Difficulty Reward Actions
{isSolved ? (
) : (
{index + 1}
)}
{question.title} {testCaseCount} checks {question.difficulty}
{reward}
); })} {filteredQuestions.length === 0 && (

No problems match your search

)}
); }