diff --git a/SerpentRace_Frontend/src/api/deckApi.js b/SerpentRace_Frontend/src/api/deckApi.js index f67cd22f..77dbf91e 100644 --- a/SerpentRace_Frontend/src/api/deckApi.js +++ b/SerpentRace_Frontend/src/api/deckApi.js @@ -20,6 +20,28 @@ export const getDecksPage = async (from = 0, to = 49) => { } } -export default { - createDeck +// Get a specific deck by ID (authenticated) +export const getDeckById = async (deckId) => { + try { + const response = await apiClient.get(`/decks/${deckId}`) + return response.data + } catch (err) { + throw err + } +} + +// Update an existing deck (authenticated) +export const updateDeck = async (deckId, deck) => { + try { + const response = await apiClient.patch(`/decks/${deckId}`, deck) + return response.data + } catch (err) { + throw err + } +} + +export default { + createDeck, + getDeckById, + updateDeck } diff --git a/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx b/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx index 1db050ea..e6fc13e7 100644 --- a/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx +++ b/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx @@ -1,4 +1,5 @@ import React, { useEffect } from "react" +import { useNavigate } from "react-router-dom" import { FaUser, FaLock, @@ -12,11 +13,13 @@ import { } from "react-icons/fa" export default function DeckInfoPopUp({ deck, onClose }) { + const navigate = useNavigate() + if (!deck) return null // Debug: Log the deck structure to see what we're working with console.log('Deck in popup:', deck) - console.log('Cards:', deck.cards) + console.log('Raw deck data:', deck.raw) // Scroll blokkolás amikor a popup nyitva van useEffect(() => { @@ -29,50 +32,98 @@ export default function DeckInfoPopUp({ deck, onClose }) { } }, []) - const deckTypes = { - "Luck": { label: "Szerencse", color: "var(--color-luck)" }, - "Question": { label: "Kérdés", color: "var(--color-question)" }, - "Fun": { label: "Joker", color: "var(--color-fun)" } + // Backend enum mapping + const deckTypeMapping = { + 0: { label: "Szerencse", color: "var(--color-luck)" }, // LUCK + 1: { label: "Joker", color: "var(--color-fun)" }, // JOKER + 2: { label: "Kérdés", color: "var(--color-question)" } // QUESTION } - const currentDeckType = deckTypes[deck.type] || { label: deck.type, color: "var(--color-success)" } + const ctypeMapping = { + 0: "Publikus", // PUBLIC + 1: "Privát", // PRIVATE + 2: "Vállalati" // ORGANIZATION + } - // Use real deck data with safe fallbacks - const creator = deck.creatorName || deck.creator || (deck.user && deck.user.name) || "Ismeretlen" - const privacy = deck.origin === "Vállalati" || deck.ctype === 1 || deck.privacy === 'public' ? "Publikus" : "Privát" + const stateMapping = { + 0: "Aktív", // ACTIVE + 1: "Törölt" // SOFT_DELETE + } - // Get data from raw if available + // Get data from raw (backend data) const rawData = deck.raw || deck - // Use played number from raw data for answers count - const questionsCount = rawData.cardCount || 0 - const answersCount = rawData.playedNumber || 0 + // Type info + const deckTypeInfo = deckTypeMapping[rawData.type] || { label: "Ismeretlen", color: "var(--color-success)" } + + // Privacy/CType + const privacy = ctypeMapping[rawData.ctype] || "Ismeretlen" + + // State + const state = stateMapping[rawData.state] || "Ismeretlen" + + // Creator + const creator = rawData.user?.name || rawData.creatorName || rawData.creator || "Ismeretlen" + + // Card count + const cardCount = rawData.cardCount || 0 + + // Played count + const playedNumber = rawData.playedNumber || 0 - console.log('Calculated counts:', { questionsCount, answersCount, rawData }) + console.log('Mapped data:', { + type: rawData.type, + deckTypeInfo, + ctype: rawData.ctype, + privacy, + state, + cardCount, + playedNumber + }) const mockData = { - ...deck, + name: rawData.name || deck.name || "Névtelen pakli", creator, privacy, - questionsCount, - answersCount + state, + questionsCount: cardCount, + answersCount: playedNumber, + created: rawData.creationdate || rawData.created || deck.created || new Date().toISOString(), + description: rawData.description || "" } const formatDate = (dateString) => { - const date = new Date(dateString) - return date.toLocaleDateString('hu-HU', { - year: 'numeric', - month: 'long', - day: 'numeric' - }) + try { + const date = new Date(dateString) + return date.toLocaleDateString('hu-HU', { + year: 'numeric', + month: 'long', + day: 'numeric' + }) + } catch (e) { + return dateString + } } const handleOpenDeck = () => { + // TODO: Megnyitás funkció - később implementálható alert("⚠️ A pakli megnyitás funkció még fejlesztés alatt áll!") } const handleEditDeck = () => { - alert("⚠️ A pakli szerkesztés funkció még fejlesztés alatt áll!") + // Get the deck ID from raw data + const deckId = rawData.id || deck.id + + if (!deckId) { + alert("⚠️ Hiba: A pakli azonosítója nem található!") + return + } + + // Navigate to deck creator with the deck ID + navigate(`/deck-creator/${deckId}`) + + // Close the popup + onClose() } return ( @@ -86,7 +137,7 @@ export default function DeckInfoPopUp({ deck, onClose }) { {/* Header with deck type color */}
{/* Close button */} @@ -108,13 +159,18 @@ export default function DeckInfoPopUp({ deck, onClose }) { - {currentDeckType.label} + {deckTypeInfo.label} + {mockData.description && ( +

+ {mockData.description} +

+ )} {/* Data grid */} @@ -149,13 +205,13 @@ export default function DeckInfoPopUp({ deck, onClose }) {
- +
Típus
-
{currentDeckType.label}
+
{deckTypeInfo.label}
@@ -172,25 +228,25 @@ export default function DeckInfoPopUp({ deck, onClose }) { {/* Questions and Answers in one row */}
- {/* Questions */} + {/* Card Count (Kártyák) */}
-
Kérdések
+
Kártyák
{mockData.questionsCount}
- {/* Answers */} + {/* Played Count (Játszva) */}
-
Válaszok
-
{mockData.answersCount}
+
Játszva
+
{mockData.answersCount}×
diff --git a/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx b/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx index 25e62beb..feb9a112 100644 --- a/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx +++ b/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx @@ -7,7 +7,7 @@ import Navbar from "../../components/Navbar/Navbar.jsx" import DeckHeader from "../../components/DeckCreator/DeckHeader.jsx" import CardsList from "../../components/DeckCreator/CardsList.jsx" import CardEditor from "../../components/DeckCreator/CardEditor.jsx" -import { createDeck } from '../../api/deckApi' +import { createDeck, getDeckById, updateDeck } from '../../api/deckApi' import { notifySuccess, notifyError, notifyWarning } from "../../components/Toastify/toastifyServices" export default function DeckCreator() { @@ -28,6 +28,7 @@ export default function DeckCreator() { const [selectedCard, setSelectedCard] = useState(null) const [isCreatingCard, setIsCreatingCard] = useState(false) const [newCardType, setNewCardType] = useState(null) + const [isLoading, setIsLoading] = useState(false) // Betöltés API-ból useEffect(() => { @@ -46,16 +47,44 @@ export default function DeckCreator() { }, [deckId]) const loadDeck = async (id) => { - // Mock adatok – később backendből jön majd - const mockDeck = { - id, - name: "Demo Deck", - type: "QUESTION", - privacy: "public", - description: "Ez egy teszt deck", - cards: [] + setIsLoading(true) + try { + const deckData = await getDeckById(id) + console.log('Loaded deck:', deckData) + + // Type mapping from backend to frontend + const typeMapping = { + 0: 'LUCK', + 1: 'JOKER', + 2: 'QUESTION' + } + + // CType mapping from backend to frontend + const ctypeMapping = { + 0: 'public', + 1: 'private', + 2: 'organization' + } + + setDeck({ + id: deckData.id, + name: deckData.name || "Névtelen pakli", + type: typeMapping[deckData.type] || 'QUESTION', + privacy: ctypeMapping[deckData.ctype] || 'private', + description: deckData.description || "", + cards: deckData.cards || [], + creationdate: deckData.creationdate, + updatedate: deckData.updatedate + }) + + // Success notification removed - silent load for better UX + } catch (error) { + console.error('Pakli betöltési hiba:', error) + notifyError('Hiba történt a pakli betöltése során: ' + (error?.response?.data?.error || error.message)) + navigate('/decks') + } finally { + setIsLoading(false) } - setDeck(mockDeck) } const handleDeckUpdate = (updates) => { @@ -71,15 +100,42 @@ export default function DeckCreator() { 'QUESTION': 2 } + const ctypeMapping = { + 'public': 0, + 'private': 1, + 'organization': 2 + } + const payload = { name: deck.name?.trim() || "Névtelen pakli", type: typeMapping[deck.type] ?? 2, - ctype: deck.privacy === 'public' ? 'PUBLIC' : 'PRIVATE', - description: deck.description || "", + ctype: ctypeMapping[deck.privacy] ?? 1, cards: deck.cards || [] } + + // Note: description field is not sent to backend as it's not supported yet - const saved = await createDeck(payload) + console.log('=== DECK SAVE DEBUG ===') + console.log('Deck ID:', deck.id) + console.log('Deck object:', deck) + console.log('Payload to send:', payload) + console.log('Is Update?', !!deck.id) + + let saved + if (deck.id) { + // Update existing deck + console.log('Calling updateDeck with ID:', deck.id) + saved = await updateDeck(deck.id, payload) + console.log('Update response:', saved) + notifySuccess('Pakli sikeresen frissítve!') + } else { + // Create new deck + console.log('Calling createDeck') + saved = await createDeck(payload) + console.log('Create response:', saved) + notifySuccess('Pakli sikeresen létrehozva!') + } + setDeck(prev => ({ ...prev, id: saved.id ?? prev.id, @@ -88,10 +144,19 @@ export default function DeckCreator() { })) console.log('Deck saved (backend):', saved) - notifySuccess('Pakli sikeresen elmentve!') } catch (error) { - console.error('Mentési hiba:', error) - notifyError('Hiba történt a mentés során: ' + (error?.response?.data?.error || error.message)) + console.error('=== DECK SAVE ERROR ===') + console.error('Full error:', error) + console.error('Error response:', error?.response) + console.error('Error response data:', error?.response?.data) + console.error('Error message:', error?.message) + + const errorMessage = error?.response?.data?.error + || error?.response?.data?.message + || error?.message + || 'Ismeretlen hiba történt' + + notifyError('Hiba történt a mentés során: ' + errorMessage) } } @@ -193,17 +258,30 @@ export default function DeckCreator() {
-
- {/* Deck Header */} - + {isLoading ? ( +
+
+
+
+ Pakli betöltése... +
+
+ Kérlek várj, amíg betöltjük a pakli adatait. +
+
+
+ ) : ( +
+ {/* Deck Header */} + - {/* Main Content */} -
+ {/* Main Content */} +
{/* Left Panel - Cards List */}
-
+
+ )}
) }