final POC

This commit is contained in:
magdo
2025-11-24 23:28:57 +01:00
parent ce02f55a99
commit 6b3446e9b6
49 changed files with 4634 additions and 4620 deletions
@@ -43,7 +43,6 @@ const Card_display = () => {
const result = await getDeckById(deckId)
if (!mounted) return
console.log('Loaded deck:', result)
setDeck(result)
// Parse cards from JSON if it's a string
@@ -60,8 +59,6 @@ const Card_display = () => {
}
}
console.log('Parsed cards:', parsedCards)
console.log('First card structure:', parsedCards[0])
setCards(parsedCards)
} catch (err) {
console.error('Failed to load deck', err)
@@ -79,8 +76,8 @@ const Card_display = () => {
let filteredCards = cards.filter((card) => {
if (!search) return true
const searchLower = search.toLowerCase()
// Check question, statement, and options
const questionText = card.question || card.statement || ''
// Check text field (or fallback to question/statement for old data)
const questionText = card.text || 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))
@@ -96,12 +93,12 @@ const Card_display = () => {
// Keep original order
return 0
} else if (sortBy === "question-asc") {
const aText = a.question || a.statement || ''
const bText = b.question || b.statement || ''
const aText = a.text || a.question || a.statement || ''
const bText = b.text || 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 || ''
const aText = a.text || a.question || a.statement || ''
const bText = b.text || 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
@@ -136,33 +133,26 @@ const Card_display = () => {
// Card subtype Hungarian labels - UPDATED based on actual data
const cardSubTypeLabels = {
// String types (from DeckCreator)
"quiz": "Quiz ",
"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",
"joker": "Joker",
"luck": "Szerencse",
// 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",
// Backend CardType enum (numeric):
"0": "Quiz", // CardType.QUIZ = 0
"1": "Párosítás", // CardType.SENTENCE_PAIRING = 1
"2": "Szöveges válasz", // CardType.OWN_ANSWER = 2
"3": "Igaz/Hamis", // CardType.TRUE_FALSE = 3
"4": "Közelítés", // CardType.CLOSER = 4
0: "Quiz",
1: "Párosítá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"
3: "Igaz/Hamis",
4: "Közelítés"
}
const currentDeckType = deck ? (deckTypes[deck.type] || { label: "Ismeretlen", color: "var(--color-success)" }) : null
@@ -361,48 +351,51 @@ const Card_display = () => {
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 - prioritize numeric card.type over subType
let detectedType = 'undefined'
// Detect card type by fields if subType is missing
let detectedType = subType
if (subType === 'undefined' || subType === 'null') {
// First check deck type - if deck is JOKER or LUCK type, cards inherit that
if (deck.type === 1) {
// Deck type 1 = Joker deck
// First check deck type - if deck is JOKER or LUCK type, cards inherit that
if (deck.type === 1) {
// Deck type 1 = Joker deck
detectedType = 'joker'
} else if (deck.type === 0) {
// Deck type 0 = Luck deck
detectedType = 'luck'
} else if (card.type !== undefined && card.type !== null) {
// Check by card.type field (numeric CardType enum)
const cardType = typeof card.type === 'string' ? card.type.toLowerCase() : card.type
if (cardType === 'joker' || card.type === 'JOKER') {
detectedType = 'joker'
} else if (deck.type === 0) {
// Deck type 0 = Luck deck
} else if (cardType === 'luck' || card.type === 'LUCK') {
detectedType = 'luck'
} else if (card.type !== undefined) {
// Check by card.type field (string or numeric)
const cardType = typeof card.type === 'string' ? card.type.toLowerCase() : card.type
if (cardType === 'joker' || card.type === 'JOKER') {
// Joker card
detectedType = 'joker'
} else if (cardType === 'luck' || card.type === 'LUCK') {
// Luck card
detectedType = 'luck'
} else 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
} else if (card.type === 0) {
// type 0 = Quiz (multiple choice)
detectedType = 'quiz'
} else if (card.type === 1) {
// type 1 = Matching/Pairing
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
} else if (card.type === 2) {
// type 2 = Text answer
detectedType = 'text'
} else if (card.isTrue !== undefined) {
} else if (card.type === 3) {
// type 3 = True/False
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'
}
} else if (card.subType) {
// Fallback to subType if card.type is missing
detectedType = String(card.subType).toLowerCase()
} 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'
}
// Extract consequence info for JOKER and LUCK cards
@@ -427,19 +420,40 @@ const Card_display = () => {
}
}
if (detectedType === 'truefalse' || detectedType === '0') {
if (detectedType === 'truefalse' || detectedType === '3') {
// 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
// Parse answer from various sources
let isCorrectTrue = false
if (card.isTrue !== undefined) {
isCorrectTrue = card.isTrue
} else if (card.answer !== undefined) {
const answerStr = String(card.answer).toLowerCase()
isCorrectTrue = answerStr === 'true' || answerStr === '1' || answerStr === 'igaz'
} else if (card.correctAnswer !== undefined) {
isCorrectTrue = card.correctAnswer === 0 || card.correctAnswer === true || card.correctAnswer === 'true'
}
correctAnswerIndex = isCorrectTrue ? 0 : 1
} else if (detectedType === 'quiz' || detectedType === 'multiplechoice' || detectedType === '0') {
// Quiz/Multiple choice - parse from backend answer array or frontend options
if (card.answer && Array.isArray(card.answer) && card.answer.length > 0 && typeof card.answer[0] === 'object') {
// Backend format: [{answer: "A", text: "...", correct: boolean}]
answerOptions = card.answer.map(opt => opt.text || opt.label || '')
const correctOption = card.answer.find(opt => opt.correct)
correctAnswerIndex = card.answer.indexOf(correctOption)
} else if (card.options && Array.isArray(card.options)) {
// Frontend format: ["option1", "option2"]
answerOptions = card.options.filter(opt => opt && opt.trim())
correctAnswerIndex = card.correctAnswer
}
} else if (detectedType === 'matching' || detectedType === '1') {
// Matching cards - parse from backend answer array or frontend fields
if (card.answer && Array.isArray(card.answer) && card.answer.length > 0 && typeof card.answer[0] === 'object') {
// Backend format: [{left: "...", right: "..."}]
answerOptions = card.answer.map(pair => `${pair.left}${pair.right}`)
correctAnswerIndex = -1 // All pairs are correct
} else if (card.leftItems && card.rightItems && card.correctPairs) {
// Frontend format with leftItems, rightItems, correctPairs
const pairs = []
for (const [leftIdx, rightIdx] of Object.entries(card.correctPairs)) {
const left = card.leftItems[parseInt(leftIdx)]
@@ -451,10 +465,17 @@ const Card_display = () => {
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 (detectedType === 'text' || detectedType === '2') {
// OWN_ANSWER - parse from backend answer array or frontend acceptedAnswers
if (card.answer) {
// Backend format: ["answer1", "answer2"] or single value
answerOptions = Array.isArray(card.answer) ? card.answer : [card.answer]
correctAnswerIndex = -1 // All answers are correct
} else if (card.acceptedAnswers && Array.isArray(card.acceptedAnswers)) {
// Frontend format
answerOptions = card.acceptedAnswers
correctAnswerIndex = -1 // All accepted answers are correct
}
} else if (card.options && Array.isArray(card.options)) {
// Other types with options
answerOptions = card.options.filter(opt => opt && opt.trim())
@@ -678,12 +699,26 @@ const Card_display = () => {
<div className="text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Helyes válasz:
</div>
{detectedType === 'truefalse' || detectedType === '0' ? (
{detectedType === 'truefalse' || detectedType === '3' ? (
// True/False - show only the correct answer
<div className="text-[color:var(--color-text)] text-lg font-bold bg-[color:var(--color-success)]/20 rounded-lg px-4 py-3 border-l-4 border-[color:var(--color-success)]">
{card.isTrue ? 'Igaz' : 'Hamis'}
</div>
) : detectedType === 'matching' || detectedType === '5' ? (
(() => {
// Determine if correct answer is true
let isCorrectTrue = false
if (card.isTrue !== undefined) {
isCorrectTrue = card.isTrue
} else if (card.answer !== undefined) {
const answerStr = String(card.answer).toLowerCase()
isCorrectTrue = answerStr === 'true' || answerStr === '1' || answerStr === 'igaz'
} else if (card.correctAnswer !== undefined) {
isCorrectTrue = card.correctAnswer === 0 || card.correctAnswer === true || card.correctAnswer === 'true'
}
return (
<div className="text-[color:var(--color-text)] text-lg font-bold bg-[color:var(--color-success)]/20 rounded-lg px-4 py-3 border-l-4 border-[color:var(--color-success)]">
{isCorrectTrue ? 'Igaz' : 'Hamis'}
</div>
)
})()
) : detectedType === 'matching' || detectedType === '1' ? (
// Matching - show all correct pairs
<ul className="space-y-2">
{answerOptions.map((pair, idx) => (
@@ -695,7 +730,7 @@ const Card_display = () => {
</li>
))}
</ul>
) : (detectedType === 'text' || detectedType === '2') && card.acceptedAnswers && Array.isArray(card.acceptedAnswers) ? (
) : (detectedType === 'text' || detectedType === '2') && answerOptions.length > 0 ? (
// Text answers - show all accepted answers
<ul className="space-y-1">
{answerOptions.map((answer, ansIdx) => (
@@ -707,8 +742,24 @@ const Card_display = () => {
</li>
))}
</ul>
) : (detectedType === 'quiz' || detectedType === 'multiplechoice' || detectedType === '0') && answerOptions.length > 0 ? (
// Quiz/Multiple choice - show all options with correct one highlighted
<ul className="space-y-2">
{answerOptions.map((option, ansIdx) => (
<li
key={ansIdx}
className={`text-[color:var(--color-text)] text-sm rounded-lg px-3 py-2 border-l-2 font-semibold ${
ansIdx === correctAnswerIndex
? 'bg-[color:var(--color-success)]/20 border-[color:var(--color-success)]'
: 'bg-[color:var(--color-surface)] border-[color:var(--color-surface-selected)]'
}`}
>
{ansIdx === correctAnswerIndex ? '✓ ' : ''}{String.fromCharCode(65 + ansIdx)}. {option}
</li>
))}
</ul>
) : (
// Multiple choice - show only the correct answer
// Other types - show only the correct answer
correctAnswerIndex !== undefined && correctAnswerIndex !== -1 && answerOptions[correctAnswerIndex] ? (
<div className="text-[color:var(--color-text)] text-lg font-bold bg-[color:var(--color-success)]/20 rounded-lg px-4 py-3 border-l-4 border-[color:var(--color-success)]">
{answerOptions[correctAnswerIndex]}