Feature: Consequence rendszer implementálása minden kártya típushoz

- TaskCardEditor: Consequence és wrongConsequence kezelés hozzáadva
- JokerCardEditor: Teljesítés és nem teljesítés consequence-ek
- LuckCardEditor: Szerencse kártyák consequence kezelése
- CardEditor: Alapértelmezett consequence értékek az új kártyákhoz
- DeckCreator: Consequence mezők biztosítása mentéskor
- CardsList: Következmény típusok megjelenítése
- UI javítás: Mind a három editor külön szekciókba rendezve (info, szöveg, következmények)
- Egységes struktúra és design az összes kártya szerkesztőnél
This commit is contained in:
GitG0r0
2025-10-23 00:31:33 +02:00
parent f2a54154f5
commit 3bbd3f1e8a
6 changed files with 427 additions and 84 deletions
@@ -20,7 +20,8 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance
id: null, id: null,
type: type, type: type,
points: 10, points: 10,
timeLimit: 30 timeLimit: 30,
consequence: { type: 0, value: 1 }
} }
switch (type) { switch (type) {
@@ -31,7 +32,8 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance
question: '', question: '',
options: ['', '', '', ''], options: ['', '', '', ''],
correctAnswer: 0, correctAnswer: 0,
explanation: '' explanation: '',
wrongConsequence: { type: 1, value: 1 }
} }
case 'JOKER': case 'JOKER':
return { return {
@@ -40,7 +42,8 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance
description: '', description: '',
effect: '', effect: '',
actionType: 'skip', actionType: 'skip',
usage: 'once' usage: 'once',
wrongConsequence: { type: 1, value: 1 }
} }
case 'LUCK': case 'LUCK':
return { return {
@@ -263,14 +263,6 @@ export default function CardsList({
<div className="text-[color:var(--color-text)] font-semibold"> <div className="text-[color:var(--color-text)] font-semibold">
📊 Összesen: {cards.length} kártya 📊 Összesen: {cards.length} kártya
</div> </div>
{cards.length > 0 && (
<div className="flex justify-center gap-4 mt-2 text-xs text-[color:var(--color-text-muted)]">
<span>📋 {cards.filter(c => c.type === 'QUESTION').length}</span>
<span>🃏 {cards.filter(c => c.type === 'JOKER').length}</span>
<span>🎲 {cards.filter(c => c.type === 'LUCK').length}</span>
</div>
)}
</div> </div>
</div> </div>
</div> </div>
@@ -4,17 +4,29 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { FaTheaterMasks, FaInfoCircle, FaUsers } from 'react-icons/fa' import { FaTheaterMasks, FaInfoCircle, FaUsers } from 'react-icons/fa'
const consequenceTypes = [
{ value: 0, label: '⬆️ Előre lépés', description: 'A játékos előre lép X mezőt' },
{ value: 1, label: '⬇️ Hátra lépés', description: 'A játékos hátra lép X mezőt' },
{ value: 2, label: '⏸️ Kör kihagyás', description: 'A játékos kihagy egy kört' },
{ value: 3, label: '⏩ Extra kör', description: 'A játékos kap egy extra kört' },
{ value: 5, label: '🏁 Vissza a starthoz', description: 'A játékos visszakerül a starthoz' }
]
export default function JokerCardEditor({ card, onChange }) { export default function JokerCardEditor({ card, onChange }) {
const [cardData, setCardData] = useState({ const [cardData, setCardData] = useState({
type: 'JOKER', type: 'JOKER',
text: '' text: '',
consequence: { type: 0, value: 1 },
wrongConsequence: { type: 1, value: 1 }
}) })
useEffect(() => { useEffect(() => {
if (card) { if (card) {
setCardData({ setCardData({
type: 'JOKER', type: 'JOKER',
text: card.text || '' text: card.text || '',
consequence: card.consequence || { type: 0, value: 1 },
wrongConsequence: card.wrongConsequence || { type: 1, value: 1 }
}) })
} }
}, [card]) }, [card])
@@ -31,6 +43,36 @@ export default function JokerCardEditor({ card, onChange }) {
} }
} }
const updateConsequence = (field, value) => {
const newCardData = {
...cardData,
consequence: {
...cardData.consequence,
[field]: value
}
}
setCardData(newCardData)
if (onChange) {
onChange(newCardData)
}
}
const updateWrongConsequence = (field, value) => {
const newCardData = {
...cardData,
wrongConsequence: {
...cardData.wrongConsequence,
[field]: value
}
}
setCardData(newCardData)
if (onChange) {
onChange(newCardData)
}
}
// Példa joker kártyák // Példa joker kártyák
const exampleCards = [ const exampleCards = [
"Felelsz vagy mersz? (Az előző játékos kérdez)", "Felelsz vagy mersz? (Az előző játékos kérdez)",
@@ -57,18 +99,10 @@ export default function JokerCardEditor({ card, onChange }) {
} }
return ( return (
<div className="max-w-4xl mx-auto"> <div className="space-y-6">
{/* Info box */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6"> <div className="bg-[color:var(--color-surface)] rounded-xl p-6">
{/* Header */} <div className="bg-[color:var(--color-fun)]/10 border border-[color:var(--color-fun)]/30 rounded-lg p-4">
<div className="flex items-center gap-3 mb-6">
<FaTheaterMasks className="text-2xl text-[color:var(--color-fun)]" />
<h3 className="text-xl font-bold text-[color:var(--color-text)]">
Joker Kártya Szerkesztő
</h3>
</div>
{/* Info box */}
<div className="bg-[color:var(--color-fun)]/10 border border-[color:var(--color-fun)]/30 rounded-lg p-4 mb-6">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<FaInfoCircle className="text-[color:var(--color-fun)] mt-1 flex-shrink-0" /> <FaInfoCircle className="text-[color:var(--color-fun)] mt-1 flex-shrink-0" />
<div> <div>
@@ -86,28 +120,33 @@ export default function JokerCardEditor({ card, onChange }) {
</div> </div>
</div> </div>
</div> </div>
</div>
{/* Card text input */} {/* Kártya szövege */}
<div className="space-y-4"> <div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<div> <h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4 flex items-center gap-2">
<label className="block text-[color:var(--color-text)] font-medium mb-2"> <FaTheaterMasks className="text-[color:var(--color-fun)]" />
Joker kártya feladat * Kártya szövege
</label> </h3>
<textarea
value={cardData.text} <div>
onChange={handleTextChange} <label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
placeholder="Pl: Felelsz vagy mersz? (Az előző játékos kérdez)" Joker kártya feladat *
className="w-full h-32 p-4 bg-[color:var(--color-surface)] border border-[color:var(--color-border)] rounded-lg text-[color:var(--color-text)] placeholder-[color:var(--color-text-muted)] resize-none focus:outline-none focus:border-[color:var(--color-fun)] transition-colors" </label>
maxLength={150} <textarea
/> value={cardData.text}
<div className="flex justify-between items-center mt-2"> onChange={handleTextChange}
<span className="text-xs text-[color:var(--color-text-muted)]"> placeholder="Pl: Felelsz vagy mersz? (Az előző játékos kérdez)"
Maximális hossz: 150 karakter className="w-full h-32 px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] placeholder-[color:var(--color-text-muted)] resize-none focus:ring-2 focus:ring-[color:var(--color-fun)] focus:border-transparent outline-none transition-all duration-200"
</span> maxLength={150}
<span className="text-xs text-[color:var(--color-text-muted)]"> />
{cardData.text.length}/150 <div className="flex justify-between items-center mt-2">
</span> <span className="text-xs text-[color:var(--color-text-muted)]">
</div> Maximális hossz: 150 karakter
</span>
<span className="text-xs text-[color:var(--color-text-muted)]">
{cardData.text.length}/150
</span>
</div> </div>
</div> </div>
@@ -147,6 +186,100 @@ export default function JokerCardEditor({ card, onChange }) {
</div> </div>
)} )}
</div> </div>
{/* Következmények (teljesítés esetén) */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4">
🎯 Következmények (teljesítés esetén)
</h3>
<div className="space-y-4">
{/* Consequence Type */}
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Hatás típusa
</label>
<select
value={cardData.consequence?.type ?? 0}
onChange={(e) => updateConsequence('type', parseInt(e.target.value))}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-success)] focus:border-transparent outline-none transition-all duration-200"
>
{consequenceTypes.map(type => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
<div className="text-xs text-[color:var(--color-text-muted)] mt-1">
{consequenceTypes.find(t => t.value === (cardData.consequence?.type ?? 0))?.description}
</div>
</div>
{/* Consequence Value - csak ha előre/hátra lépés */}
{(cardData.consequence?.type === 0 || cardData.consequence?.type === 1) && (
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Mezők száma
</label>
<input
type="number"
value={cardData.consequence?.value ?? 1}
onChange={(e) => updateConsequence('value', parseInt(e.target.value) || 1)}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-success)] focus:border-transparent outline-none transition-all duration-200"
min="1"
max="10"
/>
</div>
)}
</div>
</div>
{/* Következmények (nem teljesítés esetén) */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4">
Következmények (nem teljesítés esetén)
</h3>
<div className="space-y-4">
{/* Wrong Consequence Type */}
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Hatás típusa
</label>
<select
value={cardData.wrongConsequence?.type ?? 1}
onChange={(e) => updateWrongConsequence('type', parseInt(e.target.value))}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-danger)] focus:border-transparent outline-none transition-all duration-200"
>
{consequenceTypes.map(type => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
<div className="text-xs text-[color:var(--color-text-muted)] mt-1">
{consequenceTypes.find(t => t.value === (cardData.wrongConsequence?.type ?? 1))?.description}
</div>
</div>
{/* Wrong Consequence Value - csak ha előre/hátra lépés */}
{(cardData.wrongConsequence?.type === 0 || cardData.wrongConsequence?.type === 1) && (
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Mezők száma
</label>
<input
type="number"
value={cardData.wrongConsequence?.value ?? 1}
onChange={(e) => updateWrongConsequence('value', parseInt(e.target.value) || 1)}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-danger)] focus:border-transparent outline-none transition-all duration-200"
min="1"
max="10"
/>
</div>
)}
</div>
</div>
</div> </div>
) )
} }
@@ -4,17 +4,27 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { FaDice, FaInfoCircle } from 'react-icons/fa' import { FaDice, FaInfoCircle } from 'react-icons/fa'
const consequenceTypes = [
{ value: 0, label: '⬆️ Előre lépés', description: 'A játékos előre lép X mezőt' },
{ value: 1, label: '⬇️ Hátra lépés', description: 'A játékos hátra lép X mezőt' },
{ value: 2, label: '⏸️ Kör kihagyás', description: 'A játékos kihagy egy kört' },
{ value: 3, label: '⏩ Extra kör', description: 'A játékos kap egy extra kört' },
{ value: 5, label: '🏁 Vissza a starthoz', description: 'A játékos visszakerül a starthoz' }
]
export default function LuckCardEditor({ card, onChange }) { export default function LuckCardEditor({ card, onChange }) {
const [cardData, setCardData] = useState({ const [cardData, setCardData] = useState({
type: 'LUCK', type: 'LUCK',
text: '' text: '',
consequence: { type: 0, value: 1 }
}) })
useEffect(() => { useEffect(() => {
if (card) { if (card) {
setCardData({ setCardData({
type: 'LUCK', type: 'LUCK',
text: card.text || '' text: card.text || '',
consequence: card.consequence || { type: 0, value: 1 }
}) })
} }
}, [card]) }, [card])
@@ -31,19 +41,26 @@ export default function LuckCardEditor({ card, onChange }) {
} }
} }
return ( const updateConsequence = (field, value) => {
<div className="max-w-4xl mx-auto"> const newCardData = {
<div className="bg-[color:var(--color-surface)] rounded-xl p-6"> ...cardData,
{/* Header */} consequence: {
<div className="flex items-center gap-3 mb-6"> ...cardData.consequence,
<FaDice className="text-2xl text-[color:var(--color-luck)]" /> [field]: value
<h3 className="text-xl font-bold text-[color:var(--color-text)]"> }
Szerencse Kártya Szerkesztő }
</h3> setCardData(newCardData)
</div>
if (onChange) {
onChange(newCardData)
}
}
{/* Info box */} return (
<div className="bg-[color:var(--color-luck)]/10 border border-[color:var(--color-luck)]/30 rounded-lg p-4 mb-6"> <div className="space-y-6">
{/* Info box */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<div className="bg-[color:var(--color-luck)]/10 border border-[color:var(--color-luck)]/30 rounded-lg p-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<FaInfoCircle className="text-[color:var(--color-luck)] mt-1 flex-shrink-0" /> <FaInfoCircle className="text-[color:var(--color-luck)] mt-1 flex-shrink-0" />
<div> <div>
@@ -60,28 +77,32 @@ export default function LuckCardEditor({ card, onChange }) {
</div> </div>
</div> </div>
</div> </div>
</div>
{/* Card text input */} {/* Kártya szövege */}
<div className="space-y-4"> <div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<div> <h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4 flex items-center gap-2">
<label className="block text-[color:var(--color-text)] font-medium mb-2"> <FaDice className="text-[color:var(--color-luck)]" />
Kártya szövege * Kártya szövege
</label> </h3>
<textarea <div>
value={cardData.text} <label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
onChange={handleTextChange} Szerencse esemény leírása *
placeholder="Pl: Órai projektekkel kiváltottál több vizsgát is! Lépj előre 4 mezőt" </label>
className="w-full h-32 p-4 bg-[color:var(--color-surface)] border border-[color:var(--color-border)] rounded-lg text-[color:var(--color-text)] placeholder-[color:var(--color-text-muted)] resize-none focus:outline-none focus:border-[color:var(--color-luck)] transition-colors" <textarea
maxLength={200} value={cardData.text}
/> onChange={handleTextChange}
<div className="flex justify-between items-center mt-2"> placeholder="Pl: Órai projektekkel kiváltottál több vizsgát is! Lépj előre 4 mezőt"
<span className="text-xs text-[color:var(--color-text-muted)]"> className="w-full h-32 px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] placeholder-[color:var(--color-text-muted)] resize-none focus:ring-2 focus:ring-[color:var(--color-luck)] focus:border-transparent outline-none transition-all duration-200"
Maximális hossz: 200 karakter maxLength={200}
</span> />
<span className="text-xs text-[color:var(--color-text-muted)]"> <div className="flex justify-between items-center mt-2">
{cardData.text.length}/200 <span className="text-xs text-[color:var(--color-text-muted)]">
</span> Maximális hossz: 200 karakter
</div> </span>
<span className="text-xs text-[color:var(--color-text-muted)]">
{cardData.text.length}/200
</span>
</div> </div>
</div> </div>
@@ -100,6 +121,53 @@ export default function LuckCardEditor({ card, onChange }) {
</div> </div>
)} )}
</div> </div>
{/* Következmények */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4">
🎯 Következmények
</h3>
<div className="space-y-4">
{/* Consequence Type */}
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Hatás típusa
</label>
<select
value={cardData.consequence?.type ?? 0}
onChange={(e) => updateConsequence('type', parseInt(e.target.value))}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-luck)] focus:border-transparent outline-none transition-all duration-200"
>
{consequenceTypes.map(type => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
<div className="text-xs text-[color:var(--color-text-muted)] mt-1">
{consequenceTypes.find(t => t.value === (cardData.consequence?.type ?? 0))?.description}
</div>
</div>
{/* Consequence Value - csak ha előre/hátra lépés */}
{(cardData.consequence?.type === 0 || cardData.consequence?.type === 1) && (
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Mezők száma
</label>
<input
type="number"
min="1"
max="10"
value={cardData.consequence?.value ?? 1}
onChange={(e) => updateConsequence('value', parseInt(e.target.value) || 1)}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-luck)] focus:border-transparent outline-none transition-all duration-200"
/>
</div>
)}
</div>
</div>
</div> </div>
) )
} }
@@ -20,6 +20,14 @@ const timeLimits = [
{ value: 120, label: '2 perc' } { value: 120, label: '2 perc' }
] ]
const consequenceTypes = [
{ value: 0, label: '⬆️ Előre lépés', description: 'A játékos előre lép X mezőt' },
{ value: 1, label: '⬇️ Hátra lépés', description: 'A játékos hátra lép X mezőt' },
{ value: 2, label: '⏸️ Kör kihagyás', description: 'A játékos kihagy egy kört' },
{ value: 3, label: '⏩ Extra kör', description: 'A játékos kap egy extra kört' },
{ value: 5, label: '🏁 Vissza a starthoz', description: 'A játékos visszakerül a starthoz' }
]
export default function TaskCardEditor({ card, onChange }) { export default function TaskCardEditor({ card, onChange }) {
const updateField = (field, value) => { const updateField = (field, value) => {
@@ -81,6 +89,26 @@ export default function TaskCardEditor({ card, onChange }) {
onChange({ acceptedAnswers: newAnswers }) onChange({ acceptedAnswers: newAnswers })
} }
const updateConsequence = (field, value) => {
const currentConsequence = card.consequence || { type: 0, value: 1 }
onChange({
consequence: {
...currentConsequence,
[field]: value
}
})
}
const updateWrongConsequence = (field, value) => {
const currentWrongConsequence = card.wrongConsequence || { type: 1, value: 1 }
onChange({
wrongConsequence: {
...currentWrongConsequence,
[field]: value
}
})
}
return ( return (
<div className="max-w-4xl mx-auto space-y-6"> <div className="max-w-4xl mx-auto space-y-6">
{/* Feladat típus választó */} {/* Feladat típus választó */}
@@ -513,6 +541,100 @@ export default function TaskCardEditor({ card, onChange }) {
</div> </div>
</div> </div>
</div> </div>
{/* Következmények (helyes válasz esetén) */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4">
🎯 Következmények (helyes válasz esetén)
</h3>
<div className="space-y-4">
{/* Consequence Type */}
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Hatás típusa
</label>
<select
value={card.consequence?.type ?? 0}
onChange={(e) => updateConsequence('type', parseInt(e.target.value))}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-success)] focus:border-transparent outline-none transition-all duration-200"
>
{consequenceTypes.map(type => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
<div className="text-xs text-[color:var(--color-text-muted)] mt-1">
{consequenceTypes.find(t => t.value === (card.consequence?.type ?? 0))?.description}
</div>
</div>
{/* Consequence Value - csak ha előre/hátra lépés */}
{(card.consequence?.type === 0 || card.consequence?.type === 1) && (
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Mezők száma
</label>
<input
type="number"
value={card.consequence?.value ?? 1}
onChange={(e) => updateConsequence('value', parseInt(e.target.value) || 1)}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-success)] focus:border-transparent outline-none transition-all duration-200"
min="1"
max="10"
/>
</div>
)}
</div>
</div>
{/* Következmények (rossz válasz esetén) */}
<div className="bg-[color:var(--color-surface)] rounded-xl p-6">
<h3 className="text-lg font-semibold text-[color:var(--color-text)] mb-4">
Következmények (rossz válasz esetén)
</h3>
<div className="space-y-4">
{/* Wrong Consequence Type */}
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Hatás típusa
</label>
<select
value={card.wrongConsequence?.type ?? 1}
onChange={(e) => updateWrongConsequence('type', parseInt(e.target.value))}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-danger)] focus:border-transparent outline-none transition-all duration-200"
>
{consequenceTypes.map(type => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</select>
<div className="text-xs text-[color:var(--color-text-muted)] mt-1">
{consequenceTypes.find(t => t.value === (card.wrongConsequence?.type ?? 1))?.description}
</div>
</div>
{/* Wrong Consequence Value - csak ha előre/hátra lépés */}
{(card.wrongConsequence?.type === 0 || card.wrongConsequence?.type === 1) && (
<div>
<label className="block text-[color:var(--color-text-muted)] text-sm font-medium mb-2">
Mezők száma
</label>
<input
type="number"
value={card.wrongConsequence?.value ?? 1}
onChange={(e) => updateWrongConsequence('value', parseInt(e.target.value) || 1)}
className="w-full px-4 py-2 rounded-xl bg-[color:var(--color-background)] border border-[color:var(--color-surface-selected)] text-[color:var(--color-text)] focus:ring-2 focus:ring-[color:var(--color-danger)] focus:border-transparent outline-none transition-all duration-200"
min="1"
max="10"
/>
</div>
)}
</div>
</div>
</div> </div>
) )
} }
@@ -51,9 +51,16 @@ export default function DeckCreator() {
const handleSaveDeck = async () => { const handleSaveDeck = async () => {
try { try {
// Konvertálás: Frontend string -> Backend enum number
const typeMapping = {
'LUCK': 0,
'JOKER': 1,
'QUESTION': 2
}
const payload = { const payload = {
name: deck.name, name: deck.name,
type: deck.type, type: typeMapping[deck.type] ?? 2, // Alapértelmezett: QUESTION
ctype: deck.privacy === 'public' ? 'PUBLIC' : 'PRIVATE', ctype: deck.privacy === 'public' ? 'PUBLIC' : 'PRIVATE',
description: deck.description || '', description: deck.description || '',
cards: deck.cards cards: deck.cards
@@ -95,18 +102,30 @@ export default function DeckCreator() {
const handleSaveCard = (cardData) => { const handleSaveCard = (cardData) => {
try { try {
// Biztosítjuk az alapértelmezett consequence értékeket
const defaultConsequence = { type: 0, value: 1 }
const defaultWrongConsequence = { type: 1, value: 1 }
const updatedCard = { const updatedCard = {
...cardData, ...cardData,
id: isCreatingCard ? Date.now() : cardData.id id: isCreatingCard ? Date.now() : cardData.id,
consequence: cardData.consequence || defaultConsequence,
// wrongConsequence csak QUESTION és JOKER típusoknál
...(cardData.type === 'QUESTION' || cardData.type === 'JOKER'
? { wrongConsequence: cardData.wrongConsequence || defaultWrongConsequence }
: {}
)
} }
let wasInvalidCardDeleted = false
setDeck(prev => { setDeck(prev => {
// Ellenőrizzük, vannak-e nem megfelelő típusú kártyák // Ellenőrizzük, vannak-e nem megfelelő típusú kártyák
const invalidCards = prev.cards.filter(card => card.type !== prev.type) const invalidCards = prev.cards.filter(card => card.type !== prev.type)
// Ha új kártyát mentünk megfelelő típussal és vannak nem megfelelők // Ha új kártyát mentünk megfelelő típussal és vannak nem megfelelők
if (isCreatingCard && cardData.type === prev.type && invalidCards.length > 0) { if (isCreatingCard && cardData.type === prev.type && invalidCards.length > 0) {
notifyWarning(`${invalidCards.length} db nem megfelelő típusú kártya törlésre került`) wasInvalidCardDeleted = true
return { return {
...prev, ...prev,
@@ -130,7 +149,13 @@ export default function DeckCreator() {
setIsCreatingCard(false) setIsCreatingCard(false)
setNewCardType(null) setNewCardType(null)
notifySuccess('Kártya sikeresen mentve!') // Csak egy értesítés
if (wasInvalidCardDeleted) {
const invalidCount = deck.cards.filter(card => card.type !== deck.type).length
notifyWarning(`Kártya mentve! ${invalidCount} db nem megfelelő típusú kártya törlésre került.`)
} else {
notifySuccess('Kártya sikeresen mentve!')
}
} catch (error) { } catch (error) {
console.error('Kártya mentési hiba:', error) console.error('Kártya mentési hiba:', error)
notifyError('Hiba történt a kártya mentése során') notifyError('Hiba történt a kártya mentése során')