diff --git a/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx b/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx
index 2fc5cbe3..9ca7797e 100644
--- a/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx
+++ b/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx
@@ -33,6 +33,19 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance
options: ['', '', '', ''],
correctAnswer: 0,
explanation: '',
+ acceptedAnswers: [''],
+ wrongConsequence: { type: 1, value: 1 }
+ }
+ case 'PAIRING':
+ case 'MATCHING':
+ return {
+ ...baseData,
+ type: 'QUESTION',
+ subType: 'matching',
+ taskDescription: '',
+ leftItems: ['', ''],
+ rightItems: ['', ''],
+ correctPairs: { 0: 0, 1: 1 },
wrongConsequence: { type: 1, value: 1 }
}
case 'JOKER':
@@ -84,13 +97,60 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance
}
if (data.type === 'QUESTION') {
- if (!data.question && !data.statement) {
- notifyError("Kérdés vagy állítás megadása kötelező!")
- return false
+ // Quiz típus validálás
+ if (data.subType === 'quiz') {
+ if (!data.question || !data.question.trim()) {
+ notifyError("Kérdés megadása kötelező!")
+ return false
+ }
+ if (data.options && data.options.some(opt => !opt.trim())) {
+ notifyError("Minden válaszlehetőséget ki kell tölteni!")
+ return false
+ }
}
- if (data.subType === 'quiz' && data.options && data.options.some(opt => !opt.trim())) {
- notifyError("Minden válaszlehetőséget ki kell tölteni!")
- return false
+ // Igaz/Hamis típus validálás
+ else if (data.subType === 'truefalse') {
+ if (!data.statement || !data.statement.trim()) {
+ notifyError("Állítás megadása kötelező!")
+ return false
+ }
+ if (data.isTrue === undefined || data.isTrue === null) {
+ notifyError("Válaszd ki, hogy az állítás igaz vagy hamis!")
+ return false
+ }
+ }
+ // Párosítás típus validálás
+ else if (data.subType === 'matching') {
+ if (!data.taskDescription || !data.taskDescription.trim()) {
+ notifyError("Feladat leírása kötelező!")
+ return false
+ }
+ if (!data.leftItems || data.leftItems.length === 0) {
+ notifyError("Legalább egy párosítást meg kell adni!")
+ return false
+ }
+ if (data.leftItems.some(item => !item.trim()) || data.rightItems.some(item => !item.trim())) {
+ notifyError("Minden párosítási elemet ki kell tölteni!")
+ return false
+ }
+ }
+ // Szöveges válasz típus validálás
+ else if (data.subType === 'text') {
+ if (!data.question || !data.question.trim()) {
+ notifyError("Kérdés megadása kötelező!")
+ return false
+ }
+ if (!data.acceptedAnswers || data.acceptedAnswers.length === 0 || data.acceptedAnswers.every(ans => !ans.trim())) {
+ notifyError("Legalább egy elfogadott választ meg kell adni!")
+ return false
+ }
+ }
+ // Általános validálás (ha nincs subType megadva)
+ else {
+ if (!data.question && !data.statement) {
+ notifyError("Kérdés vagy állítás megadása kötelező!")
+ return false
+ }
}
} else if (data.type === 'JOKER') {
if (!data.text || !data.text.trim()) {
diff --git a/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx b/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx
index 6aa60f09..301839db 100644
--- a/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx
+++ b/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx
@@ -9,6 +9,8 @@ import {
FaSortAlphaDown,
FaSortAlphaUp,
FaQuestionCircle,
+ FaChevronLeft,
+ FaChevronRight,
} from "react-icons/fa"
import SearchBox from "../Search/SearchBox"
import PopUp from "../PopUp/PopUp"
@@ -70,18 +72,25 @@ const DeckManager = () => {
const [search, setSearch] = useState("")
const [showSortHelp, setShowSortHelp] = useState(false)
const [selectedDeck, setSelectedDeck] = useState(null)
- const [decks, setDecks] = useState([])
+ const [allDecks, setAllDecks] = useState([]) // Összes pakli
const [loading, setLoading] = useState(false)
+ const [itemsPerPage, setItemsPerPage] = useState(20)
+ const [currentPage, setCurrentPage] = useState(1)
+ // Load all decks once
useEffect(() => {
let mounted = true
const load = async () => {
setLoading(true)
try {
- const result = await import('../../api/deckApi').then(m => m.getDecksPage(0, 49))
+ // Load all decks (0-99 is the max limit = 100 decks)
+ const result = await import('../../api/deckApi').then(m => m.getDecksPage(0, 99))
if (!mounted) return
- // map backend deck shape to UI shape
- const mapped = result.decks.map(d => ({
+
+ console.log('Loaded decks:', result) // Debug
+
+ // Map backend deck shape to UI shape
+ const mapped = (result.decks || []).map(d => ({
id: d.id,
name: d.name,
type: d.type === 2 ? 'Question' : d.type === 1 ? 'Joker' : 'Luck',
@@ -89,7 +98,9 @@ const DeckManager = () => {
origin: d.ctype === 2 ? 'Vállalati' : d.ctype === 0 ? 'Mind' : 'Saját',
raw: d
}))
- setDecks(mapped)
+
+ console.log('Mapped decks:', mapped) // Debug
+ setAllDecks(mapped)
} catch (err) {
console.error('Failed to load decks', err)
} finally {
@@ -101,8 +112,7 @@ const DeckManager = () => {
}, [])
// Filter logic
- const sourceDecks = decks
- let filteredDecks = sourceDecks.filter((deck) => {
+ let filteredDecks = allDecks.filter((deck) => {
const typeMatch = selectedType === "All" || deck.type === selectedType
const originMatch = selectedOrigin === "Mind" || deck.origin === selectedOrigin
const searchMatch = !search || deck.name.toLowerCase().includes(search.toLowerCase())
@@ -123,6 +133,18 @@ const DeckManager = () => {
return 0
})
+ // Pagination logic - frontend only
+ const totalDecks = filteredDecks.length
+ const totalPages = Math.ceil(totalDecks / itemsPerPage)
+ const startIndex = (currentPage - 1) * itemsPerPage
+ const endIndex = startIndex + itemsPerPage
+ const paginatedDecks = filteredDecks.slice(startIndex, endIndex)
+
+ // Reset to page 1 when filters or items per page change
+ useEffect(() => {
+ setCurrentPage(1)
+ }, [selectedType, selectedOrigin, search, sortBy, itemsPerPage])
+
return (
@@ -263,6 +285,36 @@ const DeckManager = () => {
)}
+
+ {/* Items per page selector and pagination info */}
+
+
+
+ Elemek oldalanként:
+
+
+
+
+
+ {totalDecks > 0 ? (
+ <>
+ {startIndex + 1}-{Math.min(endIndex, totalDecks)} / {totalDecks} pakli
+ >
+ ) : (
+ <>0 pakli>
+ )}
+
+
+
{/* Decks Grid */}
{/* Create New Deck (Mockup) */}
@@ -280,7 +332,7 @@ const DeckManager = () => {
{!loading && filteredDecks.length === 0 && (
Nincsenek mentett paklik.
)}
- {!loading && filteredDecks.map((deck) => {
+ {!loading && paginatedDecks.map((deck) => {
const deckType = deckTypes.find((t) => t.label === deck.type)
const borderColor = deckType ? deckType.color : "var(--color-success)"
return (
@@ -317,6 +369,73 @@ const DeckManager = () => {
)
})}
+
+ {/* Pagination Controls */}
+ {totalPages > 1 && (
+
+
+
+
+ {[...Array(totalPages)].map((_, index) => {
+ const pageNum = index + 1
+ // Show first page, last page, current page and neighbors
+ if (
+ pageNum === 1 ||
+ pageNum === totalPages ||
+ (pageNum >= currentPage - 1 && pageNum <= currentPage + 1)
+ ) {
+ return (
+
+ )
+ } else if (
+ pageNum === currentPage - 2 ||
+ pageNum === currentPage + 2
+ ) {
+ return (
+
+ ...
+
+ )
+ }
+ return null
+ })}
+
+
+
+
+ )}
{/* Deck Info Popup */}
diff --git a/SerpentRace_Frontend/src/components/DeckCreator/TaskCardEditor.jsx b/SerpentRace_Frontend/src/components/DeckCreator/TaskCardEditor.jsx
index cace7ed8..018e4531 100644
--- a/SerpentRace_Frontend/src/components/DeckCreator/TaskCardEditor.jsx
+++ b/SerpentRace_Frontend/src/components/DeckCreator/TaskCardEditor.jsx
@@ -79,13 +79,16 @@ export default function TaskCardEditor({ card, onChange }) {
}
const updateAcceptedAnswer = (index, value) => {
- const newAnswers = [...card.acceptedAnswers]
+ const currentAnswers = card.acceptedAnswers || ['']
+ const newAnswers = [...currentAnswers]
newAnswers[index] = value
onChange({ acceptedAnswers: newAnswers })
}
const removeAcceptedAnswer = (index) => {
- const newAnswers = card.acceptedAnswers.filter((_, i) => i !== index)
+ const currentAnswers = card.acceptedAnswers || ['']
+ if (currentAnswers.length <= 1) return // Legalább egy válasz maradjon
+ const newAnswers = currentAnswers.filter((_, i) => i !== index)
onChange({ acceptedAnswers: newAnswers })
}
@@ -375,7 +378,7 @@ export default function TaskCardEditor({ card, onChange }) {
- {(card.acceptedAnswers || ['', '', '']).map((answer, index) => (
+ {(card.acceptedAnswers || ['']).map((answer, index) => (
- {(card.acceptedAnswers?.length || 0) > 1 && (
+ {(card.acceptedAnswers?.length || 1) > 1 && (