@jhbhan/kings-quiz
Version:
Old testament Kings trivia quiz game
1 lines • 36.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.tsx","#style-inject:#style-inject","../src/index.css","../src/KingsQuiz.tsx","../src/types.ts","../src/components/shared/slider.css","../src/components/shared/Slider.tsx","../src/components/Landing.tsx","../src/components/Results.tsx","../src/api.ts"],"sourcesContent":["import './index.css';\nimport KingsQuiz from './KingsQuiz';\n\nexport { KingsQuiz };\nexport default KingsQuiz;","\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\"* {\\n box-sizing: border-box;\\n}\\nbody {\\n margin: 0;\\n font-family:\\n \\\"Helvetica Neue\\\",\\n Arial,\\n sans-serif;\\n -webkit-font-smoothing: antialiased;\\n -moz-osx-font-smoothing: grayscale;\\n background-color: #f0f0f0;\\n min-height: 100vh;\\n color: #333;\\n}\\n.trivia-container {\\n max-width: 800px;\\n margin: 0 auto;\\n padding: 20px;\\n min-height: 100vh;\\n display: flex;\\n flex-direction: column;\\n}\\n.trivia-header {\\n background-color: #ffffff;\\n border-radius: 8px;\\n padding: 20px;\\n margin-bottom: 30px;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n border: 1px solid #ddd;\\n}\\n.progress-bar {\\n width: 100%;\\n height: 8px;\\n background-color: #e0e0e0;\\n border-radius: 4px;\\n overflow: hidden;\\n margin-bottom: 15px;\\n}\\n.progress-fill {\\n height: 100%;\\n background-color: #666666;\\n transition: width 0.3s ease;\\n}\\n.question-counter {\\n font-size: 14px;\\n color: #666;\\n margin-bottom: 5px;\\n}\\n.score {\\n font-size: 18px;\\n font-weight: bold;\\n color: #333;\\n}\\n.question-section {\\n background-color: #ffffff;\\n border-radius: 8px;\\n padding: 40px 30px;\\n margin-bottom: 30px;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n border: 1px solid #ddd;\\n text-align: center;\\n}\\n.question {\\n font-size: 28px;\\n font-weight: 600;\\n color: #333;\\n margin: 0;\\n line-height: 1.4;\\n}\\n.answers-section {\\n display: flex;\\n flex-direction: column;\\n gap: 15px;\\n margin-bottom: 30px;\\n}\\n.answer-option {\\n background-color: #ffffff;\\n border: 1px solid #ccc;\\n border-radius: 8px;\\n padding: 20px;\\n font-size: 18px;\\n cursor: pointer;\\n transition: all 0.2s ease;\\n display: flex;\\n align-items: center;\\n text-align: left;\\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\\n color: #333;\\n}\\n.answer-option:hover:not(:disabled) {\\n border-color: #666;\\n transform: translateY(-2px);\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n}\\n.answer-option.selected {\\n border-color: #333;\\n background-color: #e8e8e8;\\n}\\n.answer-option.correct {\\n border-color: #4a7c59;\\n background-color: #e6f4ea;\\n color: #333;\\n}\\n.answer-option.incorrect {\\n border-color: #b85c5c;\\n background-color: #fbeaea;\\n color: #333;\\n}\\n.answer-option:disabled {\\n cursor: not-allowed;\\n opacity: 0.7;\\n}\\n.option-letter {\\n background-color: #666;\\n color: #ffffff;\\n width: 32px;\\n height: 32px;\\n border-radius: 50%;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-weight: bold;\\n margin-right: 15px;\\n flex-shrink: 0;\\n}\\n.answer-option.correct .option-letter {\\n background-color: #4a7c59;\\n}\\n.answer-option.incorrect .option-letter {\\n background-color: #b85c5c;\\n}\\n.option-text {\\n flex: 1;\\n}\\n.submit-section {\\n text-align: center;\\n}\\n.submit-btn {\\n background-color: #333;\\n color: #ffffff;\\n border: none;\\n border-radius: 8px;\\n padding: 15px 40px;\\n font-size: 18px;\\n font-weight: 600;\\n cursor: pointer;\\n transition: all 0.2s ease;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n}\\n.submit-btn:hover:not(:disabled) {\\n background-color: #555;\\n transform: translateY(-2px);\\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\\n}\\n.submit-btn:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n transform: none;\\n}\\n.result-message {\\n font-size: 20px;\\n font-weight: 600;\\n padding: 15px;\\n}\\n.correct-message {\\n color: #333;\\n}\\n.incorrect-message {\\n color: #333;\\n}\\n.game-finished {\\n background-color: #ffffff;\\n border-radius: 8px;\\n padding: 60px 40px;\\n text-align: center;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n border: 1px solid #ddd;\\n margin-top: 50px;\\n}\\n.game-finished h1 {\\n color: #333;\\n margin-bottom: 30px;\\n font-size: 36px;\\n}\\n.final-score h2 {\\n color: #333;\\n margin-bottom: 15px;\\n font-size: 32px;\\n}\\n.score-percentage {\\n font-size: 24px;\\n color: #666;\\n margin-bottom: 40px;\\n}\\n.play-again-btn {\\n background-color: #333;\\n color: #ffffff;\\n border: none;\\n border-radius: 8px;\\n padding: 15px 40px;\\n font-size: 18px;\\n font-weight: 600;\\n cursor: pointer;\\n transition: all 0.2s ease;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n}\\n.play-again-btn:hover {\\n background-color: #555;\\n transform: translateY(-2px);\\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\\n}\\n.landing-screen {\\n background-color: #ffffff;\\n border-radius: 8px;\\n padding: 40px;\\n text-align: center;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n border: 1px solid #ddd;\\n margin-top: 20px;\\n max-width: 700px;\\n margin-left: auto;\\n margin-right: auto;\\n}\\n.app-title {\\n font-size: 48px;\\n font-weight: 700;\\n color: #333;\\n margin-bottom: 10px;\\n}\\n.app-description {\\n font-size: 20px;\\n color: #666;\\n margin-bottom: 40px;\\n line-height: 1.5;\\n}\\n.game-settings {\\n margin-bottom: 40px;\\n}\\n.setting-group {\\n margin-bottom: 30px;\\n}\\n.setting-group h3 {\\n font-size: 20px;\\n color: #333;\\n margin-bottom: 15px;\\n}\\n.category-options {\\n display: grid;\\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\\n gap: 15px;\\n}\\n.category-option {\\n background-color: #ffffff;\\n border: 1px solid #ccc;\\n border-radius: 8px;\\n padding: 15px;\\n cursor: pointer;\\n transition: all 0.2s ease;\\n text-align: left;\\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\\n}\\n.category-option:hover {\\n border-color: #666;\\n transform: translateY(-1px);\\n}\\n.category-option.selected {\\n border-color: #333;\\n background-color: #e8e8e8;\\n}\\n.category-name {\\n display: block;\\n font-size: 16px;\\n font-weight: 600;\\n color: #333;\\n margin-bottom: 5px;\\n}\\n.category-count {\\n font-size: 14px;\\n color: #666;\\n}\\n.game-info {\\n background-color: #f8f8f8;\\n border-radius: 8px;\\n padding: 20px;\\n margin-bottom: 30px;\\n border: 1px solid #ddd;\\n}\\n.info-summary p {\\n margin: 5px 0;\\n color: #333;\\n font-size: 16px;\\n}\\n.start-btn {\\n background-color: #333;\\n color: #ffffff;\\n border: none;\\n border-radius: 8px;\\n padding: 20px 50px;\\n font-size: 24px;\\n font-weight: 600;\\n cursor: pointer;\\n transition: all 0.2s ease;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n}\\n.start-btn:hover:not(:disabled) {\\n background-color: #555;\\n transform: translateY(-2px);\\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\\n}\\n.start-btn:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n transform: none;\\n}\\n.category-header {\\n display: flex;\\n justify-content: space-between;\\n align-items: center;\\n margin-bottom: 5px;\\n}\\n.checkmark {\\n color: #333;\\n font-size: 18px;\\n font-weight: bold;\\n}\\n.results-sections {\\n margin: 30px 0;\\n width: 100%;\\n}\\n.results-section {\\n margin-bottom: 20px;\\n border-radius: 8px;\\n overflow: hidden;\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\\n border: 1px solid #ddd;\\n}\\n.section-header {\\n width: 100%;\\n padding: 15px 20px;\\n border: none;\\n font-size: 18px;\\n font-weight: 600;\\n cursor: pointer;\\n display: flex;\\n justify-content: space-between;\\n align-items: center;\\n transition: all 0.2s ease;\\n background-color: #f8f8f8;\\n color: #333;\\n border-bottom: 1px solid #ddd;\\n}\\n.wrong-header {\\n background-color: #f8f8f8;\\n color: #333;\\n border-bottom: 1px solid #ddd;\\n}\\n.wrong-header:hover {\\n background-color: #e0e0e0;\\n}\\n.right-header {\\n background-color: #f8f8f8;\\n color: #333;\\n border-bottom: 1px solid #ddd;\\n}\\n.right-header:hover {\\n background-color: #e0e0e0;\\n}\\n.expand-icon {\\n transition: transform 0.2s ease;\\n font-size: 14px;\\n}\\n.expand-icon.expanded {\\n transform: rotate(180deg);\\n}\\n.questions-list {\\n background-color: #ffffff;\\n max-height: 400px;\\n overflow-y: auto;\\n}\\n.question-result {\\n padding: 20px;\\n border-bottom: 1px solid #e0e0e0;\\n}\\n.question-result:last-child {\\n border-bottom: none;\\n}\\n.wrong-result {\\n border-left: 4px solid #666;\\n}\\n.right-result {\\n border-left: 4px solid #666;\\n}\\n.result-question {\\n font-size: 16px;\\n font-weight: 600;\\n color: #333;\\n margin: 0 0 15px 0;\\n line-height: 1.4;\\n}\\n.result-options {\\n display: flex;\\n flex-direction: column;\\n gap: 8px;\\n}\\n.result-option {\\n display: flex;\\n align-items: center;\\n padding: 10px 12px;\\n border-radius: 6px;\\n font-size: 14px;\\n border: 1px solid #e0e0e0;\\n background-color: #f8f8f8;\\n}\\n.result-option .option-letter {\\n background-color: #666;\\n color: #ffffff;\\n width: 24px;\\n height: 24px;\\n border-radius: 50%;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-weight: bold;\\n margin-right: 12px;\\n flex-shrink: 0;\\n font-size: 12px;\\n}\\n.result-option .option-text {\\n flex: 1;\\n}\\n.result-option .option-indicator {\\n font-size: 12px;\\n font-weight: 600;\\n margin-left: 10px;\\n}\\n.correct-option {\\n background-color: #e6f4ea;\\n border-color: #4a7c59;\\n color: #333;\\n}\\n.correct-option .option-letter {\\n background-color: #4a7c59;\\n}\\n.correct-option .option-indicator {\\n color: #4a7c59;\\n}\\n.wrong-option {\\n background-color: #fbeaea;\\n border-color: #b85c5c;\\n color: #333;\\n}\\n.wrong-option .option-letter {\\n background-color: #b85c5c;\\n}\\n.wrong-option .option-indicator {\\n color: #b85c5c;\\n}\\n.no-questions {\\n padding: 40px 20px;\\n text-align: center;\\n font-size: 18px;\\n color: #666;\\n font-style: italic;\\n}\\n@media (max-width: 768px) {\\n .trivia-container {\\n padding: 15px;\\n }\\n .landing-screen {\\n padding: 30px 20px;\\n margin-top: 10px;\\n }\\n .app-title {\\n font-size: 36px;\\n }\\n .app-description {\\n font-size: 18px;\\n }\\n .category-options {\\n grid-template-columns: 1fr;\\n }\\n .start-btn {\\n padding: 15px 40px;\\n font-size: 20px;\\n }\\n .question {\\n font-size: 24px;\\n }\\n .answer-option {\\n padding: 15px;\\n font-size: 16px;\\n }\\n .option-letter {\\n width: 28px;\\n height: 28px;\\n margin-right: 12px;\\n }\\n .section-header {\\n padding: 12px 15px;\\n font-size: 16px;\\n }\\n .question-result {\\n padding: 15px;\\n }\\n .result-question {\\n font-size: 15px;\\n }\\n .result-option {\\n padding: 8px 10px;\\n font-size: 13px;\\n }\\n .result-option .option-letter {\\n width: 20px;\\n height: 20px;\\n margin-right: 10px;\\n font-size: 11px;\\n }\\n .questions-list {\\n max-height: 300px;\\n }\\n}\\n\")","import { useState } from \"react\"\nimport { type Category, type Question, type QuestionResult } from \"./types\"\nimport { LandingPage } from \"./components/Landing\"\nimport { Results } from \"./components/Results\"\nimport { fetchQuestions } from \"./api\"\n\nexport default function KingsQuiz() {\n const [showResult, setShowResult] = useState(false)\n const [gameFinished, setGameFinished] = useState(false)\n const [gameStarted, setGameStarted] = useState(false)\n const [loadingQuestions, setLoadingQuestions] = useState(false)\n\n const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0)\n const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null)\n const [score, setScore] = useState(0)\n const [selectedCategories, setSelectedCategories] = useState<Category[]>([\"successor\", \"kingdom\", \"approval\", \"prophetKing\"])\n const [selectedQuestionCount, setSelectedQuestionCount] = useState(10)\n const [gameQuestions, setGameQuestions] = useState<Question[]>([])\n const [questionResults, setQuestionResults] = useState<QuestionResult[]>([])\n\n const currentQuestion = gameQuestions[currentQuestionIndex]\n\n const handleAnswerSelect = (answer: string) => {\n if (showResult) return; // Prevent double click during result\n setSelectedAnswer(answer);\n // Immediately submit\n const isCorrect = answer === currentQuestion.correctAnswer;\n if (isCorrect) {\n setScore(score + 1);\n }\n // Store the result\n const result: QuestionResult = {\n question: currentQuestion,\n userAnswer: answer,\n isCorrect: isCorrect,\n };\n setQuestionResults((prev) => [...prev, result]);\n setShowResult(true);\n setTimeout(() => {\n if (currentQuestionIndex < gameQuestions.length - 1) {\n setCurrentQuestionIndex(currentQuestionIndex + 1);\n setSelectedAnswer(null);\n setShowResult(false);\n } else {\n setGameFinished(true);\n }\n }, 1000);\n };\n\n const handleCategoryToggle = (categoryId: Category) => {\n setSelectedCategories((prev) => {\n if (prev.includes(categoryId)) {\n return prev.filter((id) => id !== categoryId)\n } else {\n return [...prev, categoryId]\n }\n })\n }\n\n const startGame = async () => {\n setLoadingQuestions(true)\n const fetchedQuestions = await fetchQuestions(selectedQuestionCount, selectedCategories);\n const shuffled = [...fetchedQuestions].sort(() => Math.random() - 0.5)\n setGameQuestions(shuffled)\n setLoadingQuestions(false)\n setGameStarted(true)\n }\n\n const resetGame = () => {\n setCurrentQuestionIndex(0)\n setSelectedAnswer(null)\n setScore(0)\n setShowResult(false)\n setGameFinished(false)\n setGameStarted(false)\n setGameQuestions([])\n setQuestionResults([])\n }\n\n if (loadingQuestions) {\n return <div className=\"loading\">Loading questions...</div>\n }\n\n if (gameFinished) {\n return (\n <Results\n score={score}\n gameQuestions={gameQuestions}\n questionResults={questionResults}\n resetGame={resetGame}\n />\n )\n }\n\n if (!gameStarted) {\n return (\n <LandingPage\n selectedQuestionCount={selectedQuestionCount}\n setSelectedQuestionCount={setSelectedQuestionCount}\n selectedCategories={selectedCategories}\n handleCategoryChange={handleCategoryToggle}\n startGame={startGame}\n />\n )\n }\n\n return (\n <div className=\"trivia-container\">\n <div className=\"trivia-header\">\n <div className=\"progress-bar\">\n <div\n className=\"progress-fill\"\n style={{ width: `${((currentQuestionIndex + 1) / gameQuestions.length) * 100}%` }}\n ></div>\n </div>\n <div className=\"question-counter\">\n Question {currentQuestionIndex + 1} of {gameQuestions.length}\n </div>\n <div className=\"score\">Score: {score}</div>\n </div>\n\n <div className=\"question-section\">\n {showResult ? (\n <div className=\"result-message\">\n {selectedAnswer === currentQuestion.correctAnswer ? (\n <span className=\"correct-message\">✓ Correct!</span>\n ) : (\n <span className=\"incorrect-message\">\n ✗ Incorrect. The correct answer was {currentQuestion.correctAnswer}.\n </span>\n )}\n </div>\n ) : <h1 className=\"question\">{currentQuestion.question}</h1>}\n </div>\n\n <div className=\"answers-section\">\n {currentQuestion.options.map((option, index) => (\n <button\n key={index}\n className={`answer-option ${selectedAnswer === option ? \"selected\" : \"\"} ${\n showResult\n ? option === currentQuestion.correctAnswer\n ? \"correct\"\n : selectedAnswer === option\n ? \"incorrect\"\n : \"\"\n : \"\"\n }`}\n onClick={() => handleAnswerSelect(option)}\n disabled={showResult}\n >\n <span className=\"option-text\">{option}</span>\n </button>\n ))}\n </div>\n </div>\n )\n}\n","export interface Question {\n question: string;\n options: string[];\n correctAnswer: string;\n explanation?: string;\n}\n\nexport interface QuestionResult {\n question: Question\n userAnswer: string\n isCorrect: boolean\n}\nexport type Category = \"successor\" | \"kingdom\" | \"approval\" | \"prophetKing\"\n\nexport const categoryNamesMap: Record<Category, string> = {\n \"successor\": \"Succession\",\n \"kingdom\": \"Which Kingdom?\",\n \"approval\": \"Good or Bad\",\n \"prophetKing\": \"Who's your prophet?\"\n}","import styleInject from '#style-inject';styleInject(\".slider-container {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n gap: 10px;\\n}\\n.question-slider {\\n width: 100%;\\n max-width: 300px;\\n height: 8px;\\n border-radius: 4px;\\n background-color: #e0e0e0;\\n outline: none;\\n -webkit-appearance: none;\\n appearance: none;\\n}\\n.question-slider::-webkit-slider-thumb {\\n -webkit-appearance: none;\\n appearance: none;\\n width: 24px;\\n height: 24px;\\n border-radius: 50%;\\n background-color: #333;\\n cursor: pointer;\\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);\\n transition: all 0.2s ease;\\n}\\n.question-slider::-webkit-slider-thumb:hover {\\n transform: scale(1.1);\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\\n}\\n.question-slider::-moz-range-thumb {\\n width: 24px;\\n height: 24px;\\n border-radius: 50%;\\n background-color: #333;\\n cursor: pointer;\\n border: none;\\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);\\n transition: all 0.2s ease;\\n}\\n.question-slider::-moz-range-thumb:hover {\\n transform: scale(1.1);\\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\\n}\\n.question-slider:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n}\\n.question-slider:disabled::-webkit-slider-thumb {\\n cursor: not-allowed;\\n}\\n.question-slider:disabled::-moz-range-thumb {\\n cursor: not-allowed;\\n}\\n.slider-labels {\\n display: flex;\\n justify-content: space-between;\\n width: 100%;\\n max-width: 300px;\\n font-size: 14px;\\n color: #666;\\n padding: 0 12px;\\n}\\n\")","import './slider.css';\n\ntype SliderProps = {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n\n}\n\nexport const Slider = ({\n value,\n onChange,\n min = 5,\n max = 20,\n step = 1,\n disabled = false\n}: SliderProps) =>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={(e) => onChange(Number(e.target.value))}\n className=\"question-slider\"\n disabled={disabled}\n />\n <div className=\"slider-labels\">\n <span>{min}</span>\n <span>{max}</span>\n </div>\n </div>\n","import { categoryNamesMap, type Category } from \"../types\";\nimport { Slider } from \"./shared/Slider\";\n\ninterface GameSettings {\n selectedQuestionCount: number;\n setSelectedQuestionCount: (count: number) => void;\n selectedCategories: Category[];\n handleCategoryChange: (category: Category) => void;\n startGame: () => void;\n}\n\nexport function LandingPage(props: GameSettings) {\n const {\n selectedQuestionCount,\n setSelectedQuestionCount,\n selectedCategories,\n handleCategoryChange,\n startGame,\n } = props;\n \n return (\n <div className=\"trivia-container\">\n <div className=\"landing-screen\">\n <h1 className=\"app-title\">Trivia Challenge</h1>\n <p className=\"app-description\">Customize your trivia experience!</p>\n\n <div className=\"game-settings\">\n <div className=\"setting-group\">\n <h3>Number of Questions: {selectedQuestionCount}</h3>\n <Slider\n value={selectedQuestionCount}\n onChange={setSelectedQuestionCount}\n min={5}\n max={20}\n step={1}\n />\n </div>\n\n <div className=\"setting-group\">\n <h3>Select Categories</h3>\n <div className=\"category-options\">\n {Object.entries(categoryNamesMap).map(([key, name]) => {\n return (\n <button\n key={key}\n className={`category-option ${selectedCategories.includes(key as Category) ? \"selected\" : \"\"}`}\n onClick={() => handleCategoryChange(key as Category)}\n >\n <div className=\"category-header\">\n <span className=\"category-name\">{name}</span>\n {selectedCategories.includes(key as Category) && <span className=\"checkmark\">✓</span>}\n </div>\n </button>\n )\n })}\n </div>\n </div>\n\n <div className=\"game-info\">\n <div className=\"info-summary\">\n <p>\n <strong>{selectedCategories.length}</strong> selected categories\n </p>\n </div>\n </div>\n </div>\n\n <button\n className=\"start-btn\"\n onClick={startGame}\n disabled={selectedCategories.length === 0}\n >\n Start Game\n </button>\n </div>\n </div>\n )\n}\n","import { useState } from 'react'\nimport type { Question, QuestionResult } from '../types'\n\ninterface ResultsProps {\n score: number\n gameQuestions: Question[]\n questionResults: QuestionResult[]\n resetGame: () => void\n}\n\nexport const Results = (props: ResultsProps) => {\n const {\n score,\n gameQuestions,\n questionResults,\n resetGame,\n } = props;\n \n const [wrongAnswersExpanded, setWrongAnswersExpanded] = useState(true)\n const [rightAnswersExpanded, setRightAnswersExpanded] = useState(false)\n \n const wrongAnswers = questionResults.filter((result) => !result.isCorrect)\n const rightAnswers = questionResults.filter((result) => result.isCorrect)\n\n return (\n <div className=\"trivia-container\">\n <div className=\"game-finished\">\n <h1>Game Complete!</h1>\n <div className=\"final-score\">\n <h2>\n Your Score: {score} / {gameQuestions.length}\n </h2>\n <p className=\"score-percentage\">{Math.round((score / gameQuestions.length) * 100)}%</p>\n </div>\n\n <div className=\"results-sections\">\n {/* Wrong Answers Section */}\n <div className=\"results-section\">\n <button\n className=\"section-header wrong-header\"\n onClick={() => setWrongAnswersExpanded(!wrongAnswersExpanded)}\n >\n <span>❌ Questions You Got Wrong ({wrongAnswers.length})</span>\n <span className={`expand-icon ${wrongAnswersExpanded ? \"expanded\" : \"\"}`}>▼</span>\n </button>\n {wrongAnswersExpanded && (\n <div className=\"questions-list\">\n {wrongAnswers.map((result, index) => (\n <div key={`wrong-${index}`} className=\"question-result wrong-result\">\n <h4 className=\"result-question\">{result.question.question}</h4>\n <div className=\"result-options\">\n {/* Show user's wrong answer */}\n <div className=\"result-option wrong-option\">\n <span className=\"option-text\">{result.userAnswer}</span>\n <span className=\"option-indicator\">✗ Your Answer</span>\n </div>\n {/* Show correct answer */}\n <div className=\"result-option correct-option\">\n <span className=\"option-text\">{result.question.correctAnswer}</span>\n <span className=\"option-indicator\">✓ Correct</span>\n </div>\n </div>\n </div>\n ))}\n {wrongAnswers.length === 0 && (\n <div className=\"no-questions\">🎉 Perfect! You got all questions right!</div>\n )}\n </div>\n )}\n </div>\n\n {/* Right Answers Section */}\n <div className=\"results-section\">\n <button\n className=\"section-header right-header\"\n onClick={() => setRightAnswersExpanded(!rightAnswersExpanded)}\n >\n <span>✅ Questions You Got Right ({rightAnswers.length})</span>\n <span className={`expand-icon ${rightAnswersExpanded ? \"expanded\" : \"\"}`}>▼</span>\n </button>\n {rightAnswersExpanded && (\n <div className=\"questions-list\">\n {rightAnswers.map((result, index) => (\n <div key={`right-${index}`} className=\"question-result right-result\">\n <h4 className=\"result-question\">{result.question.question}</h4>\n <div className=\"result-options\">\n {/* Show user's correct answer */}\n <div className=\"result-option correct-option\">\n <span className=\"option-text\">{result.userAnswer}</span>\n <span className=\"option-indicator\">✓ Your Answer</span>\n </div>\n </div>\n </div>\n ))}\n {rightAnswers.length === 0 && (\n <div className=\"no-questions\">😔 No correct answers this time. Better luck next time!</div>\n )}\n </div>\n )}\n </div>\n </div>\n\n <button className=\"play-again-btn\" onClick={resetGame}>\n Play Again\n </button>\n </div>\n </div>\n )\n}\n","import type { Category, Question } from \"./types\"\n\nconst URL = \"https://8539852b27d737c54d69d5a15610e246.balena-devices.com/trivia\";\n\nexport const fetchQuestions = async (count: number, categories: Category[]): Promise<Question[]> => {\n const url = new URLSearchParams();\n url.append('type', 'kings');\n url.append('count', count.toString());\n url.append('categories', categories.join(','));\n const response = await fetch(`${URL}?${url.toString()}`);\n const data = await response.json();\n if (!response.ok) {\n throw new Error(data.message || 'Failed to fetch questions');\n }\n if (!Array.isArray(data)) {\n throw new Error('Invalid response format');\n }\n\n return data as Question[];\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCyB,SAAR,YAA6B,KAAK,EAAE,SAAS,IAAI,CAAC,GAAG;AAC1D,MAAI,CAAC,OAAO,OAAO,aAAa,YAAa;AAE7C,QAAM,OAAO,SAAS,QAAQ,SAAS,qBAAqB,MAAM,EAAE,CAAC;AACrE,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,OAAO;AAEb,MAAI,aAAa,OAAO;AACtB,QAAI,KAAK,YAAY;AACnB,WAAK,aAAa,OAAO,KAAK,UAAU;AAAA,IAC1C,OAAO;AACL,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF,OAAO;AACL,SAAK,YAAY,KAAK;AAAA,EACxB;AAEA,MAAI,MAAM,YAAY;AACpB,UAAM,WAAW,UAAU;AAAA,EAC7B,OAAO;AACL,UAAM,YAAY,SAAS,eAAe,GAAG,CAAC;AAAA,EAChD;AACF;;;ACvB8B,YAAY,y/TAA2/T;;;ACA/iU,IAAAA,gBAAyB;;;ACclB,IAAM,mBAA6C;AAAA,EACxD,aAAa;AAAA,EACb,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,eAAe;AACjB;;;ACnBwC,YAAY,u6CAAu6C;;;ACqBn9C;AATD,IAAM,SAAS,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AACf,MACI,6CAAC,SAAI,WAAU,oBACX;AAAA;AAAA,IAAC;AAAA;AAAA,MACG,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,CAAC,MAAM,SAAS,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,MAChD,WAAU;AAAA,MACV;AAAA;AAAA,EACJ;AAAA,EACA,6CAAC,SAAI,WAAU,iBACX;AAAA,gDAAC,UAAM,eAAI;AAAA,IACX,4CAAC,UAAM,eAAI;AAAA,KACf;AAAA,GACJ;;;ACZM,IAAAC,sBAAA;AAZH,SAAS,YAAY,OAAqB;AAC7C,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,IAAI;AAEJ,SACE,6CAAC,SAAI,WAAU,oBACb,wDAAC,SAAI,WAAU,kBACb;AAAA,iDAAC,QAAG,WAAU,aAAY,8BAAgB;AAAA,IAC1C,6CAAC,OAAE,WAAU,mBAAkB,+CAAiC;AAAA,IAEhE,8CAAC,SAAI,WAAU,iBACb;AAAA,oDAAC,SAAI,WAAU,iBACb;AAAA,sDAAC,QAAG;AAAA;AAAA,UAAsB;AAAA,WAAsB;AAAA,QAC9C;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,UAAU;AAAA,YACV,KAAK;AAAA,YACL,KAAK;AAAA,YACL,MAAM;AAAA;AAAA,QACR;AAAA,SACJ;AAAA,MAEA,8CAAC,SAAI,WAAU,iBACb;AAAA,qDAAC,QAAG,+BAAiB;AAAA,QACrB,6CAAC,SAAI,WAAU,oBACZ,iBAAO,QAAQ,gBAAgB,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM;AACrD,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,WAAW,mBAAmB,mBAAmB,SAAS,GAAe,IAAI,aAAa,EAAE;AAAA,cAC5F,SAAS,MAAM,qBAAqB,GAAe;AAAA,cAEnD,wDAAC,SAAI,WAAU,mBACb;AAAA,6DAAC,UAAK,WAAU,iBAAiB,gBAAK;AAAA,gBACrC,mBAAmB,SAAS,GAAe,KAAK,6CAAC,UAAK,WAAU,aAAY,oBAAC;AAAA,iBAChF;AAAA;AAAA,YAPK;AAAA,UAQP;AAAA,QAEJ,CAAC,GACH;AAAA,SACF;AAAA,MAEA,6CAAC,SAAI,WAAU,aACb,uDAAC,SAAI,WAAU,gBACb,wDAAC,OACC;AAAA,qDAAC,YAAQ,6BAAmB,QAAO;AAAA,QAAS;AAAA,SAC9C,GACF,GACF;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS;AAAA,QACT,UAAU,mBAAmB,WAAW;AAAA,QACzC;AAAA;AAAA,IAED;AAAA,KACF,GACF;AAEN;;;AC7EA,mBAAyB;AA2Bf,IAAAC,sBAAA;AAjBH,IAAM,UAAU,CAAC,UAAwB;AAC5C,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,IAAI;AAEJ,QAAM,CAAC,sBAAsB,uBAAuB,QAAI,uBAAS,IAAI;AACrE,QAAM,CAAC,sBAAsB,uBAAuB,QAAI,uBAAS,KAAK;AAEtE,QAAM,eAAe,gBAAgB,OAAO,CAAC,WAAW,CAAC,OAAO,SAAS;AACzE,QAAM,eAAe,gBAAgB,OAAO,CAAC,WAAW,OAAO,SAAS;AAExE,SACE,6CAAC,SAAI,WAAU,oBACb,wDAAC,SAAI,WAAU,iBACb;AAAA,iDAAC,QAAG,4BAAc;AAAA,IAClB,8CAAC,SAAI,WAAU,eACb;AAAA,oDAAC,QAAG;AAAA;AAAA,QACW;AAAA,QAAM;AAAA,QAAI,cAAc;AAAA,SACvC;AAAA,MACA,8CAAC,OAAE,WAAU,oBAAoB;AAAA,aAAK,MAAO,QAAQ,cAAc,SAAU,GAAG;AAAA,QAAE;AAAA,SAAC;AAAA,OACrF;AAAA,IAEA,8CAAC,SAAI,WAAU,oBAEb;AAAA,oDAAC,SAAI,WAAU,mBACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,MAAM,wBAAwB,CAAC,oBAAoB;AAAA,YAE5D;AAAA,4DAAC,UAAK;AAAA;AAAA,gBAA4B,aAAa;AAAA,gBAAO;AAAA,iBAAC;AAAA,cACvD,6CAAC,UAAK,WAAW,eAAe,uBAAuB,aAAa,EAAE,IAAI,oBAAC;AAAA;AAAA;AAAA,QAC7E;AAAA,QACC,wBACC,8CAAC,SAAI,WAAU,kBACZ;AAAA,uBAAa,IAAI,CAAC,QAAQ,UACzB,8CAAC,SAA2B,WAAU,gCACpC;AAAA,yDAAC,QAAG,WAAU,mBAAmB,iBAAO,SAAS,UAAS;AAAA,YAC1D,8CAAC,SAAI,WAAU,kBAEb;AAAA,4DAAC,SAAI,WAAU,8BACb;AAAA,6DAAC,UAAK,WAAU,eAAe,iBAAO,YAAW;AAAA,gBACjD,6CAAC,UAAK,WAAU,oBAAmB,gCAAa;AAAA,iBAClD;AAAA,cAEA,8CAAC,SAAI,WAAU,gCACb;AAAA,6DAAC,UAAK,WAAU,eAAe,iBAAO,SAAS,eAAc;AAAA,gBAC7D,6CAAC,UAAK,WAAU,oBAAmB,4BAAS;AAAA,iBAC9C;AAAA,eACF;AAAA,eAbQ,SAAS,KAAK,EAcxB,CACD;AAAA,UACA,aAAa,WAAW,KACvB,6CAAC,SAAI,WAAU,gBAAe,6DAAwC;AAAA,WAE1E;AAAA,SAEJ;AAAA,MAGA,8CAAC,SAAI,WAAU,mBACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,MAAM,wBAAwB,CAAC,oBAAoB;AAAA,YAE5D;AAAA,4DAAC,UAAK;AAAA;AAAA,gBAA4B,aAAa;AAAA,gBAAO;AAAA,iBAAC;AAAA,cACvD,6CAAC,UAAK,WAAW,eAAe,uBAAuB,aAAa,EAAE,IAAI,oBAAC;AAAA;AAAA;AAAA,QAC7E;AAAA,QACC,wBACC,8CAAC,SAAI,WAAU,kBACZ;AAAA,uBAAa,IAAI,CAAC,QAAQ,UACzB,8CAAC,SAA2B,WAAU,gCACpC;AAAA,yDAAC,QAAG,WAAU,mBAAmB,iBAAO,SAAS,UAAS;AAAA,YAC1D,6CAAC,SAAI,WAAU,kBAEb,wDAAC,SAAI,WAAU,gCACb;AAAA,2DAAC,UAAK,WAAU,eAAe,iBAAO,YAAW;AAAA,cACjD,6CAAC,UAAK,WAAU,oBAAmB,gCAAa;AAAA,eAClD,GACF;AAAA,eARQ,SAAS,KAAK,EASxB,CACD;AAAA,UACA,aAAa,WAAW,KACvB,6CAAC,SAAI,WAAU,gBAAe,4EAAuD;AAAA,WAEzF;AAAA,SAEJ;AAAA,OACF;AAAA,IAEA,6CAAC,YAAO,WAAU,kBAAiB,SAAS,WAAW,wBAEvD;AAAA,KACF,GACF;AAEN;;;AC1GA,IAAM,MAAM;AAEL,IAAM,iBAAiB,OAAO,OAAe,eAAgD;AAChG,QAAM,MAAM,IAAI,gBAAgB;AAChC,MAAI,OAAO,QAAQ,OAAO;AAC1B,MAAI,OAAO,SAAS,MAAM,SAAS,CAAC;AACpC,MAAI,OAAO,cAAc,WAAW,KAAK,GAAG,CAAC;AAC7C,QAAM,WAAW,MAAM,MAAM,GAAG,GAAG,IAAI,IAAI,SAAS,CAAC,EAAE;AACvD,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,CAAC,SAAS,IAAI;AACd,UAAM,IAAI,MAAM,KAAK,WAAW,2BAA2B;AAAA,EAC/D;AACA,MAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACtB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC7C;AAEA,SAAO;AACX;;;AN6DW,IAAAC,sBAAA;AA1EI,SAAR,YAA6B;AAClC,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAS,KAAK;AAClD,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAS,KAAK;AACtD,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AACpD,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,wBAAS,KAAK;AAE9D,QAAM,CAAC,sBAAsB,uBAAuB,QAAI,wBAAS,CAAC;AAClE,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,wBAAwB,IAAI;AACxE,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAS,CAAC;AACpC,QAAM,CAAC,oBAAoB,qBAAqB,QAAI,wBAAqB,CAAC,aAAa,WAAW,YAAY,aAAa,CAAC;AAC5H,QAAM,CAAC,uBAAuB,wBAAwB,QAAI,wBAAS,EAAE;AACrE,QAAM,CAAC,eAAe,gBAAgB,QAAI,wBAAqB,CAAC,CAAC;AACjE,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,wBAA2B,CAAC,CAAC;AAE3E,QAAM,kBAAkB,cAAc,oBAAoB;AAE1D,QAAM,qBAAqB,CAAC,WAAmB;AAC7C,QAAI,WAAY;AAChB,sBAAkB,MAAM;AAExB,UAAM,YAAY,WAAW,gBAAgB;AAC7C,QAAI,WAAW;AACb,eAAS,QAAQ,CAAC;AAAA,IACpB;AAEA,UAAM,SAAyB;AAAA,MAC7B,UAAU;AAAA,MACV,YAAY;AAAA,MACZ;AAAA,IACF;AACA,uBAAmB,CAAC,SAAS,CAAC,GAAG,MAAM,MAAM,CAAC;AAC9C,kBAAc,IAAI;AAClB,eAAW,MAAM;AACf,UAAI,uBAAuB,cAAc,SAAS,GAAG;AACnD,gCAAwB,uBAAuB,CAAC;AAChD,0BAAkB,IAAI;AACtB,sBAAc,KAAK;AAAA,MACrB,OAAO;AACL,wBAAgB,IAAI;AAAA,MACtB;AAAA,IACF,GAAG,GAAI;AAAA,EACT;AAEA,QAAM,uBAAuB,CAAC,eAAyB;AACrD,0BAAsB,CAAC,SAAS;AAC9B,UAAI,KAAK,SAAS,UAAU,GAAG;AAC7B,eAAO,KAAK,OAAO,CAAC,OAAO,OAAO,UAAU;AAAA,MAC9C,OAAO;AACL,eAAO,CAAC,GAAG,MAAM,UAAU;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,YAAY,YAAY;AAC5B,wBAAoB,IAAI;AACxB,UAAM,mBAAmB,MAAM,eAAe,uBAAuB,kBAAkB;AACvF,UAAM,WAAW,CAAC,GAAG,gBAAgB,EAAE,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AACrE,qBAAiB,QAAQ;AACzB,wBAAoB,KAAK;AACzB,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,YAAY,MAAM;AACtB,4BAAwB,CAAC;AACzB,sBAAkB,IAAI;AACtB,aAAS,CAAC;AACV,kBAAc,KAAK;AACnB,oBAAgB,KAAK;AACrB,mBAAe,KAAK;AACpB,qBAAiB,CAAC,CAAC;AACnB,uBAAmB,CAAC,CAAC;AAAA,EACvB;AAEA,MAAI,kBAAkB;AACpB,WAAO,6CAAC,SAAI,WAAU,WAAU,kCAAoB;AAAA,EACtD;AAEA,MAAI,cAAc;AAChB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,CAAC,aAAa;AAChB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB;AAAA,QACtB;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,SACE,8CAAC,SAAI,WAAU,oBACb;AAAA,kDAAC,SAAI,WAAU,iBACb;AAAA,mDAAC,SAAI,WAAU,gBACb;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,OAAO,IAAK,uBAAuB,KAAK,cAAc,SAAU,GAAG,IAAI;AAAA;AAAA,MACjF,GACH;AAAA,MACA,8CAAC,SAAI,WAAU,oBAAmB;AAAA;AAAA,QACtB,uBAAuB;AAAA,QAAE;AAAA,QAAK,cAAc;AAAA,SACxD;AAAA,MACA,8CAAC,SAAI,WAAU,SAAQ;AAAA;AAAA,QAAQ;AAAA,SAAM;AAAA,OACvC;AAAA,IAEA,6CAAC,SAAI,WAAU,oBACZ,uBACC,6CAAC,SAAI,WAAU,kBACZ,6BAAmB,gBAAgB,gBAClC,6CAAC,UAAK,WAAU,mBAAkB,6BAAU,IAE5C,8CAAC,UAAK,WAAU,qBAAoB;AAAA;AAAA,MACG,gBAAgB;AAAA,MAAc;AAAA,OACrE,GAEJ,IACE,6CAAC,QAAG,WAAU,YAAY,0BAAgB,UAAS,GACzD;AAAA,IAEA,6CAAC,SAAI,WAAU,mBACZ,0BAAgB,QAAQ,IAAI,CAAC,QAAQ,UACpC;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW,iBAAiB,mBAAmB,SAAS,aAAa,EAAE,IACrE,aACI,WAAW,gBAAgB,gBACzB,YACA,mBAAmB,SACjB,cACA,KACJ,EACN;AAAA,QACA,SAAS,MAAM,mBAAmB,MAAM;AAAA,QACxC,UAAU;AAAA,QAEV,uDAAC,UAAK,WAAU,eAAe,kBAAO;AAAA;AAAA,MAbjC;AAAA,IAcP,CACD,GACH;AAAA,KACF;AAEJ;;;AHzJA,IAAO,gBAAQ;","names":["import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}