import React, { useState, useEffect } from "react" import { useParams, useNavigate } from "react-router-dom" import { FaArrowLeft, FaFilter, FaArrowUp, FaArrowDown, FaSortAlphaDown, FaSortAlphaUp, FaQuestionCircle, FaChevronLeft, FaChevronRight, } from "react-icons/fa" import Navbar from "../../components/Navbar/Navbar" import SearchBox from "../../components/Search/SearchBox" import PopUp from "../../components/PopUp/PopUp" import { getDeckById } from "../../api/deckApi" const Card_display = () => { const { deckId } = useParams() const navigate = useNavigate() const [deck, setDeck] = useState(null) const [cards, setCards] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [search, setSearch] = useState("") const [sortBy, setSortBy] = useState("index") const [showSortHelp, setShowSortHelp] = useState(false) const [itemsPerPage, setItemsPerPage] = useState(20) const [currentPage, setCurrentPage] = useState(1) const [flippedCards, setFlippedCards] = useState(new Set()) // Track which cards are flipped // Load deck and parse cards useEffect(() => { let mounted = true const load = async () => { setLoading(true) setError(null) try { const result = await getDeckById(deckId) if (!mounted) return console.log('Loaded deck:', result) setDeck(result) // Parse cards from JSON if it's a string let parsedCards = [] if (result.cards) { if (typeof result.cards === 'string') { try { parsedCards = JSON.parse(result.cards) } catch (e) { console.error('Failed to parse cards JSON:', e) } } else if (Array.isArray(result.cards)) { parsedCards = result.cards } } console.log('Parsed cards:', parsedCards) console.log('First card structure:', parsedCards[0]) setCards(parsedCards) } catch (err) { console.error('Failed to load deck', err) if (!mounted) return setError(err.message || 'Hiba történt a pakli betöltése közben.') } finally { if (mounted) setLoading(false) } } load() return () => { mounted = false } }, [deckId]) // Filter logic let filteredCards = cards.filter((card) => { if (!search) return true const searchLower = search.toLowerCase() // Check question, statement, and options const questionText = card.question || card.statement || '' const questionMatch = questionText.toLowerCase().includes(searchLower) const answersMatch = Array.isArray(card.options) ? card.options.some(opt => opt && opt.toLowerCase().includes(searchLower)) : Array.isArray(card.answers) ? card.answers.some(a => a && a.toLowerCase().includes(searchLower)) : false return questionMatch || answersMatch }) // Sort logic filteredCards = [...filteredCards].sort((a, b) => { if (sortBy === "index") { // Keep original order return 0 } else if (sortBy === "question-asc") { const aText = a.question || a.statement || '' const bText = b.question || b.statement || '' return aText.localeCompare(bText) } else if (sortBy === "question-desc") { const aText = a.question || a.statement || '' const bText = b.question || b.statement || '' return bText.localeCompare(aText) } else if (sortBy === "answers-asc") { const aCount = Array.isArray(a.options) ? a.options.length : Array.isArray(a.answers) ? a.answers.length : 0 const bCount = Array.isArray(b.options) ? b.options.length : Array.isArray(b.answers) ? b.answers.length : 0 return aCount - bCount } else if (sortBy === "answers-desc") { const aCount = Array.isArray(a.options) ? a.options.length : Array.isArray(a.answers) ? a.answers.length : 0 const bCount = Array.isArray(b.options) ? b.options.length : Array.isArray(b.answers) ? b.answers.length : 0 return bCount - aCount } return 0 }) // Pagination logic const totalCards = filteredCards.length const totalPages = Math.ceil(totalCards / itemsPerPage) const startIndex = (currentPage - 1) * itemsPerPage const endIndex = startIndex + itemsPerPage const paginatedCards = filteredCards.slice(startIndex, endIndex) // Reset to page 1 when filters or items per page change useEffect(() => { setCurrentPage(1) }, [search, sortBy, itemsPerPage]) const deckTypes = { 0: { label: "Szerencse", color: "var(--color-luck)" }, 1: { label: "Joker", color: "var(--color-fun)" }, 2: { label: "Kérdés", color: "var(--color-question)" }, } // Card subtype Hungarian labels - UPDATED based on actual data const cardSubTypeLabels = { // String types (from DeckCreator) "truefalse": "Igaz/Hamis", "multiplechoice": "Feleletválasztós", "text": "Szöveges válasz", "number": "Számos válasz", "order": "Sorbarendezés", "matching": "Párosítás", "fill": "Kiegészítés", "QUESTION": "Kérdés", "LUCK": "Szerencse", "JOKER": "Joker", // If backend converts to different numbers, map them: "0": "Igaz/Hamis", // truefalse = 0 "1": "Feleletválasztós", // multiplechoice = 1 "2": "Szöveges válasz", // text = 2 "3": "Igaz/Hamis", // type 3 = truefalse (alternate encoding) "4": "Sorbarendezés", // order = 4 "5": "Párosítás", // matching = 5 "6": "Kiegészítés", // fill = 6 0: "Igaz/Hamis", 1: "Feleletválasztós", 2: "Szöveges válasz", 3: "Igaz/Hamis", // type 3 detected 4: "Sorbarendezés", 5: "Párosítás", 6: "Kiegészítés" } const currentDeckType = deck ? (deckTypes[deck.type] || { label: "Ismeretlen", color: "var(--color-success)" }) : null const toggleCardFlip = (cardId) => { setFlippedCards(prev => { const newSet = new Set(prev) if (newSet.has(cardId)) { newSet.delete(cardId) } else { newSet.add(cardId) } return newSet }) } return (
{/* Header with back button */}
{deck && (

{deck.name}

{currentDeckType && ( {currentDeckType.label} )}
)}
{/* Loading / Error states */} {loading && (
Betöltés...
)} {error && (
{error}
)} {/* Filters and controls */} {!loading && !error && ( <>
setSearch(e.target.value)} width={300} placeholder="Keresés kérdésben vagy válaszokban..." className="mr-4" /> Rendezés:
{showSortHelp && ( setShowSortHelp(false)}>

Rendezési lehetőségek magyarázata

  • Eredeti sorrend – A kártyák eredeti sorrendben jelennek meg
  • Kérdés A→Z – Kérdések ABC sorrendben (A-tól Z-ig)
  • Kérdés Z→A – Kérdések fordított ABC sorrendben (Z-től A-ig)
  • Válaszok száma ↑ – Kevesebb választól a több válasz felé
  • Válaszok száma ↓ – Több választól a kevesebb válasz felé
)} {/* Items per page selector and pagination info */}
Elemek oldalanként:
{totalCards > 0 ? ( <> {startIndex + 1}-{Math.min(endIndex, totalCards)} / {totalCards} kártya ) : ( <>0 kártya )}
{/* Cards Grid */}
{totalCards === 0 && (
Nincsenek kártyák ebben a pakliban.
)} {paginatedCards.map((card, idx) => { const cardIndex = startIndex + idx + 1 const questionText = card.question || card.statement || 'Kérdés hiányzik' // Get answers based on card type let answerOptions = [] let correctAnswerIndex = card.correctAnswer // Normalize subType (can be string or number or undefined) const subType = card.subType ? String(card.subType).toLowerCase() : 'undefined' // Detect card type by fields if subType is missing let detectedType = subType if (subType === 'undefined' || subType === 'null') { // Check by numeric type field first if (card.type === 3) { // type 3 = True/False detectedType = 'truefalse' } else if (card.type === 2) { // type 2 = Text answer detectedType = 'text' } else if (card.leftItems && card.rightItems && card.correctPairs) { // Has leftItems, rightItems AND correctPairs = matching detectedType = 'matching' } else if (card.acceptedAnswers && card.acceptedAnswers.length > 0 && card.acceptedAnswers[0] && card.acceptedAnswers[0].trim()) { // Only detect as text if acceptedAnswers has non-empty values detectedType = 'text' } else if (card.isTrue !== undefined) { detectedType = 'truefalse' } else if (card.options && Array.isArray(card.options) && card.options.some(opt => opt && opt.trim())) { // Has non-empty options - must be multiple choice detectedType = 'multiplechoice' } } if (detectedType === 'truefalse' || detectedType === '0') { // True/False cards answerOptions = ['Igaz', 'Hamis'] // correctAnswer: 0 = Igaz, 1 = Hamis (based on user feedback) correctAnswerIndex = card.correctAnswer !== undefined ? card.correctAnswer : (card.isTrue ? 0 : 1) } else if ((detectedType === 'text' || detectedType === '2') && card.acceptedAnswers && Array.isArray(card.acceptedAnswers)) { // Text-based cards with accepted answers answerOptions = card.acceptedAnswers correctAnswerIndex = -1 // All accepted answers are correct } else if (detectedType === 'matching' || detectedType === '5') { // Matching cards - pairs if (card.leftItems && card.rightItems && card.correctPairs) { // Build pairs from correctPairs object const pairs = [] for (const [leftIdx, rightIdx] of Object.entries(card.correctPairs)) { const left = card.leftItems[parseInt(leftIdx)] const right = card.rightItems[parseInt(rightIdx)] if (left && right) { pairs.push(`${left} → ${right}`) } } answerOptions = pairs correctAnswerIndex = -1 // All pairs are correct } } else if ((detectedType === 'multiplechoice' || detectedType === '1') && card.options && Array.isArray(card.options)) { // Multiple choice - filter out empty options answerOptions = card.options.filter(opt => opt && opt.trim()) correctAnswerIndex = card.correctAnswer } else if (card.options && Array.isArray(card.options)) { // Other types with options answerOptions = card.options.filter(opt => opt && opt.trim()) } else if (card.answers && Array.isArray(card.answers)) { // Other card types with answers array answerOptions = card.answers.filter(opt => opt && opt.trim()) } else if (card.acceptedAnswers && Array.isArray(card.acceptedAnswers)) { // Fallback for accepted answers answerOptions = card.acceptedAnswers correctAnswerIndex = -1 } const answerCount = answerOptions.length const cardId = card.id || idx const isFlipped = flippedCards.has(cardId) return (
toggleCardFlip(cardId)} >
{/* Front side - Question */}
Kártya #{cardIndex} {answerCount} válasz

{questionText}

{/* Type info only */}
Típus: {cardSubTypeLabels[detectedType] || cardSubTypeLabels[card.subType] || cardSubTypeLabels[card.type] || detectedType || 'Ismeretlen'}
Kattints a megoldáshoz →
{/* Back side - Answer */}
Megoldás {answerCount} válasz
{answerCount > 0 ? (
Helyes válasz:
{detectedType === 'truefalse' || detectedType === '0' ? ( // True/False - show only the correct answer
✓ {card.isTrue ? 'Igaz' : 'Hamis'}
) : detectedType === 'matching' || detectedType === '5' ? ( // Matching - show all correct pairs
    {answerOptions.map((pair, idx) => (
  • ✓ {pair}
  • ))}
) : (detectedType === 'text' || detectedType === '2') && card.acceptedAnswers && Array.isArray(card.acceptedAnswers) ? ( // Text answers - show all accepted answers
    {answerOptions.map((answer, ansIdx) => (
  • ✓ {answer}
  • ))}
) : ( // Multiple choice - show only the correct answer correctAnswerIndex !== undefined && correctAnswerIndex !== -1 && answerOptions[correctAnswerIndex] ? (
✓ {answerOptions[correctAnswerIndex]}
) : (
Nincs megadva helyes válasz
) )}
) : (
Nincs elérhető válasz
)}
Kattints a kérdéshez ←
) })}
{/* Pagination Controls */} {totalPages > 1 && (
{[...Array(totalPages)].map((_, index) => { const pageNum = index + 1 if ( pageNum === 1 || pageNum === totalPages || (pageNum >= currentPage - 1 && pageNum <= currentPage + 1) ) { return ( ) } else if ( pageNum === currentPage - 2 || pageNum === currentPage + 2 ) { return ( ... ) } return null })}
)} )}
) } export default Card_display