From edca8f84cd33810ef4b15acd5f14008366b90d3c Mon Sep 17 00:00:00 2001 From: GitG0r0 <145980798+GitG0r0@users.noreply.github.com> Date: Wed, 22 Oct 2025 23:21:19 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20K=C3=A1rtya=20t=C3=ADpus=20kezel=C3=A9s?= =?UTF-8?q?=20jav=C3=ADt=C3=A1sa=20=C3=A9s=20joker=20k=C3=A1rty=C3=A1k=20m?= =?UTF-8?q?egjelen=C3=ADt=C3=A9se?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Hozzáadva react-toastify a notifyWarning használatához - Javítva a CardEditor fejléc hogy helyesen jelenítse meg az új kártya típusát - Javítva a CardsList 'szerkesztés folyamatban' rész hogy QUESTION/JOKER/LUCK értékeket használjon - Implementálva az automatikus nem megfelelő típusú kártyák törlése új kártya mentésekor - Hozzáadva hibakezelés a kártya mentési logikához - Joker típus címke változtatva 'Szórakozás'-ról 'Joker'-re - Joker kártya szín változtatva citromsárgára (#FFD700) - Docker watch mode volume konfiguráció javítása a hot reload-hoz --- SerpentRace_Docker/docker-compose.watch.yml | 4 +- SerpentRace_Frontend/package-lock.json | 23 ++++ SerpentRace_Frontend/package.json | 1 + .../src/components/DeckCreator/CardEditor.jsx | 111 +++++++++++------- .../src/components/DeckCreator/CardsList.jsx | 94 +++------------ .../src/components/DeckCreator/DeckHeader.jsx | 2 +- .../components/DeckCreator/DeckManager.jsx | 8 +- .../src/components/PopUp/DeckInfoPopUp.jsx | 2 +- SerpentRace_Frontend/src/index.css | 2 +- .../src/pages/DeckCreator/DeckCreator.jsx | 89 ++++++-------- 10 files changed, 160 insertions(+), 176 deletions(-) diff --git a/SerpentRace_Docker/docker-compose.watch.yml b/SerpentRace_Docker/docker-compose.watch.yml index b7e523ca..8d026a06 100644 --- a/SerpentRace_Docker/docker-compose.watch.yml +++ b/SerpentRace_Docker/docker-compose.watch.yml @@ -75,7 +75,9 @@ services: environment: - NODE_ENV=development - VITE_API_URL=http://localhost:3000 - volumes: [] + volumes: + - ../SerpentRace_Frontend:/app + - /app/node_modules develop: watch: - action: sync diff --git a/SerpentRace_Frontend/package-lock.json b/SerpentRace_Frontend/package-lock.json index e8e4cd88..02104eac 100644 --- a/SerpentRace_Frontend/package-lock.json +++ b/SerpentRace_Frontend/package-lock.json @@ -15,6 +15,7 @@ "react-dom": "^19.1.0", "react-icons": "^5.5.0", "react-router-dom": "^7.6.0", + "react-toastify": "^11.0.5", "tailwindcss": "^4.1.7" }, "devDependencies": { @@ -1816,6 +1817,15 @@ "node": ">=18" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3363,6 +3373,19 @@ "node": ">=18" } }, + "node_modules/react-toastify": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz", + "integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/SerpentRace_Frontend/package.json b/SerpentRace_Frontend/package.json index 5bb119a6..d06aa2d6 100644 --- a/SerpentRace_Frontend/package.json +++ b/SerpentRace_Frontend/package.json @@ -17,6 +17,7 @@ "react-dom": "^19.1.0", "react-icons": "^5.5.0", "react-router-dom": "^7.6.0", + "react-toastify": "^11.0.5", "tailwindcss": "^4.1.7" }, "devDependencies": { diff --git a/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx b/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx index 9d853d24..ff6e2293 100644 --- a/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx +++ b/SerpentRace_Frontend/src/components/DeckCreator/CardEditor.jsx @@ -58,38 +58,55 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance // Kártya adatok inicializálása useEffect(() => { - if (isCreating && cardType) { - setCardData(getDefaultCardData(cardType)) - } else if (card) { - setCardData({ ...card }) - } else { + try { + if (isCreating && cardType) { + const defaultData = getDefaultCardData(cardType) + setCardData(defaultData) + } else if (card) { + setCardData({ ...card }) + } else { + setCardData(null) + } + } catch (error) { + console.error('Kártya inicializálási hiba:', error) setCardData(null) } }, [card, isCreating, cardType]) const validateCard = (data) => { - if (data.type === 'QUESTION') { - if (!data.question && !data.statement) { - notifyError("Kérdés vagy állítás megadása kötelező!") + try { + if (!data || !data.type) { + notifyError("Érvénytelen kártya adatok!") return false } - if (data.subType === 'quiz' && data.options.some(opt => !opt.trim())) { - notifyError("Minden válaszlehetőséget ki kell tölteni!") - return false - } - } else if (data.type === 'JOKER') { - if (!data.text || !data.text.trim()) { - notifyError("Joker kártya szövege nem lehet üres!") - return false - } - } else if (data.type === 'LUCK') { - if (!data.text || !data.text.trim()) { - notifyError("Szerencse kártya szövege nem lehet üres!") - return false + + if (data.type === 'QUESTION') { + if (!data.question && !data.statement) { + notifyError("Kérdés vagy állítás megadása kötelező!") + 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 + } + } else if (data.type === 'JOKER') { + if (!data.text || !data.text.trim()) { + notifyError("Joker kártya szövege nem lehet üres!") + return false + } + } else if (data.type === 'LUCK') { + if (!data.text || !data.text.trim()) { + notifyError("Szerencse kártya szövege nem lehet üres!") + return false + } } + + return true + } catch (error) { + console.error('Validálási hiba:', error) + notifyError("Hiba történt a kártya ellenőrzése során") + return false } - - return true } const updateCardData = (updates) => { @@ -97,16 +114,14 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance } const handleSave = () => { - if (!cardData) return + if (!cardData) { + notifyError("Nincs mentendő kártya adat!") + return + } if (!validateCard(cardData)) return - try { - onSave(cardData) - notifySuccess('Kártya sikeresen mentve!') - } catch (error) { - notifyError('Hiba történt a kártya mentése során: ' + (error?.message || String(error))) - } + onSave(cardData) } // Ha nincs kiválasztott kártya vagy új kártya létrehozás @@ -129,6 +144,29 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance return (
+ {/* Type Mismatch Warning */} + {cardData?.type && cardType && cardData.type !== cardType && !isCreating && ( +
+
+
⚠️
+
+
+ Figyelmeztetés: Nem megfelelő kártya típus +
+
+ {`Ez egy ${ + cardData.type === 'QUESTION' ? 'Feladat' : + cardData.type === 'JOKER' ? 'Joker' : 'Szerencse' + } kártya, de a pakli típusa ${ + cardType === 'QUESTION' ? 'Feladat' : + cardType === 'JOKER' ? 'Joker' : 'Szerencse' + }.`} +
+
+
+
+ )} + {/* Header */}
@@ -140,17 +178,10 @@ export default function CardEditor({ card, isCreating, cardType, onSave, onCance

-<<<<<<< HEAD {isCreating ? 'Új' : 'Szerkesztés'} {' '} - {cardData.type === 'QUESTION' && 'Feladat kártya'} - {cardData.type === 'JOKER' && 'Joker kártya'} - {cardData.type === 'LUCK' && 'Szerencse kártya'} -======= - {isCreating ? 'Új' : 'Szerkesztés'} {' '} - {cardData.type === 'QUESTION' && 'Feladat kártya'} - {cardData.type === 'JOKER' && 'Joker kártya'} - {cardData.type === 'LUCK' && 'Szerencse kártya'} ->>>>>>> main + {(isCreating ? cardType : cardData.type) === 'QUESTION' && 'Feladat kártya'} + {(isCreating ? cardType : cardData.type) === 'JOKER' && 'Joker kártya'} + {(isCreating ? cardType : cardData.type) === 'LUCK' && 'Szerencse kártya'}

{cardData.type === 'QUESTION' && cardData.subType && ( diff --git a/SerpentRace_Frontend/src/components/DeckCreator/CardsList.jsx b/SerpentRace_Frontend/src/components/DeckCreator/CardsList.jsx index f56d8dfe..b391b5cc 100644 --- a/SerpentRace_Frontend/src/components/DeckCreator/CardsList.jsx +++ b/SerpentRace_Frontend/src/components/DeckCreator/CardsList.jsx @@ -27,20 +27,12 @@ const cardSubTypeLabels = { text: "Szöveges válasz" } -<<<<<<< HEAD export default function CardsList({ cards, selectedCard, deckType, onSelectCard, - onCreateCard, -======= -export default function CardsList({ - cards, - selectedCard, - onSelectCard, onCreateCard, ->>>>>>> main onDeleteCard, isCreatingCard, newCardType @@ -48,7 +40,6 @@ export default function CardsList({ const [confirmingDelete, setConfirmingDelete] = useState(null) const getCardPreview = (card) => { -<<<<<<< HEAD if (card.type === 'QUESTION') { return card.question || card.statement || 'Új feladat kártya' } @@ -57,44 +48,22 @@ export default function CardsList({ } if (card.type === 'LUCK') { return card.text || 'Új szerencse kártya' -======= - if (card.type === 'QUESTION') { - return card.question || card.statement || 'Új feladat kártya' - } - if (card.type === 'JOKER') { - return card.text || 'Új joker kártya' - } - if (card.type === 'LUCK') { - return card.text || 'Új szerencse kártya' ->>>>>>> main } return "Ismeretlen kártya" } const getCardTypeLabel = (card) => { -<<<<<<< HEAD if (card.type === 'QUESTION') { -======= - if (card.type === "task") { ->>>>>>> main if (card.subType) { return cardSubTypeLabels[card.subType] || "Feladat" } return "Feladat" } -<<<<<<< HEAD if (card.type === 'JOKER') { return 'Joker' } if (card.type === 'LUCK') { return 'Szerencse' -======= - if (card.type === "joker") { - return "Joker" - } - if (card.type === "luck") { - return "Szerencse" ->>>>>>> main } return "Ismeretlen" } @@ -119,11 +88,14 @@ export default function CardsList({ 🃏 Kártyák -<<<<<<< HEAD {/* New Card Button */} -======= - {/* New Card Dropdown */} -
- - - {/* Dropdown Menu */} -
- - - - - -
-
->>>>>>> main
{/* Cards List */} @@ -185,7 +121,7 @@ export default function CardsList({ )}
- Új {newCardType === "task" ? "feladat" : newCardType === "joker" ? "joker" : "szerencse"} kártya + Új {newCardType === "QUESTION" ? "feladat" : newCardType === "JOKER" ? "joker" : "szerencse"} kártya
Szerkesztés folyamatban... @@ -205,14 +141,24 @@ export default function CardsList({ key={card.id} onClick={() => onSelectCard(card)} className={` - p-4 rounded-xl border cursor-pointer transition-all duration-200 hover:scale-105 group + p-4 rounded-xl border cursor-pointer transition-all duration-200 hover:scale-105 group relative ${ isSelected ? "bg-[color:var(--color-success)]/10 border-[color:var(--color-success)] shadow-lg" : "bg-[color:var(--color-background)]/50 border-[color:var(--color-surface-selected)] hover:bg-[color:var(--color-background)]/80" } + ${card.type !== deckType ? "opacity-70" : ""} `} > + {card.type !== deckType && ( +
+
+
+ + ⚠️ Nem megfelelő típus + +
+ )} {/* Card Header */}
@@ -320,15 +266,9 @@ export default function CardsList({ {cards.length > 0 && (
-<<<<<<< HEAD 📋 {cards.filter(c => c.type === 'QUESTION').length} 🃏 {cards.filter(c => c.type === 'JOKER').length} 🎲 {cards.filter(c => c.type === 'LUCK').length} -======= - 📋 {cards.filter(c => c.type === 'QUESTION').length} - 🃏 {cards.filter(c => c.type === 'JOKER').length} - 🎲 {cards.filter(c => c.type === 'LUCK').length} ->>>>>>> main
)}
diff --git a/SerpentRace_Frontend/src/components/DeckCreator/DeckHeader.jsx b/SerpentRace_Frontend/src/components/DeckCreator/DeckHeader.jsx index 79dda370..b285dd5e 100644 --- a/SerpentRace_Frontend/src/components/DeckCreator/DeckHeader.jsx +++ b/SerpentRace_Frontend/src/components/DeckCreator/DeckHeader.jsx @@ -7,7 +7,7 @@ import { FaSave, FaArrowLeft, FaGlobe, FaLock, FaQuestionCircle, FaDice, FaLaugh const deckTypes = [ { value: "QUESTION", label: "Kérdés", icon: FaQuestionCircle, color: "var(--color-question)" }, { value: "LUCK", label: "Szerencse", icon: FaDice, color: "var(--color-luck)" }, - { value: "JOKER", label: "Szórakozás", icon: FaLaughBeam, color: "var(--color-fun)" } + { value: "JOKER", label: "Joker", icon: FaLaughBeam, color: "var(--color-fun)" } ] const privacyOptions = [ diff --git a/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx b/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx index 0b1eddac..6aa60f09 100644 --- a/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx +++ b/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx @@ -17,7 +17,7 @@ import DeckInfoPopUp from "../PopUp/DeckInfoPopUp" const deckTypes = [ { label: "Luck", color: "var(--color-luck)" }, { label: "Question", color: "var(--color-question)" }, - { label: "Fun", color: "var(--color-fun)" }, + { label: "Joker", color: "var(--color-fun)" }, ] // initial state will be fetched from backend @@ -163,8 +163,8 @@ const DeckManager = () => { ? "Szerencse" : type.label === "Question" ? "Kérdés" - : type.label === "Fun" - ? "Szórakozás" + : type.label === "Joker" + ? "Joker" : type.label} ))} @@ -303,7 +303,7 @@ const DeckManager = () => { : deck.type === "Question" ? "Kérdés" : deck.type === "Fun" - ? "Szórakozás" + ? "Joker" : deck.type}

diff --git a/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx b/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx index 9d5ed97f..1db050ea 100644 --- a/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx +++ b/SerpentRace_Frontend/src/components/PopUp/DeckInfoPopUp.jsx @@ -32,7 +32,7 @@ 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: "Szórakozás", color: "var(--color-fun)" } + "Fun": { label: "Joker", color: "var(--color-fun)" } } const currentDeckType = deckTypes[deck.type] || { label: deck.type, color: "var(--color-success)" } diff --git a/SerpentRace_Frontend/src/index.css b/SerpentRace_Frontend/src/index.css index a73bc306..e6db465c 100644 --- a/SerpentRace_Frontend/src/index.css +++ b/SerpentRace_Frontend/src/index.css @@ -31,7 +31,7 @@ /* Deck típus színek */ --color-luck: #5fa985; /* zöld, mint a success */ --color-question: #4f7be6; /* új kék, illik az oldalhoz */ - --color-fun: #e15b64; /* piros, mint az error */ + --color-fun: #FFD700; /* citromsárga a joker kártyákhoz */ /* Háttérszínek */ --color-background: #181d23; diff --git a/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx b/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx index 0b68151e..f3d382b3 100644 --- a/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx +++ b/SerpentRace_Frontend/src/pages/DeckCreator/DeckCreator.jsx @@ -8,7 +8,7 @@ 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 { notifySuccess, notifyError } from "../../components/Toastify/toastifyServices" +import { notifySuccess, notifyError, notifyWarning } from "../../components/Toastify/toastifyServices" export default function DeckCreator() { const { deckId } = useParams() // URL-ből deck ID (új deck esetén undefined) @@ -32,11 +32,7 @@ export default function DeckCreator() { // Betöltés API-ból useEffect(() => { if (deckId) { -<<<<<<< HEAD - // TODO: Betöltés API-ból -======= loadDeck(deckId) ->>>>>>> main } else { setDeck({ id: null, @@ -64,15 +60,6 @@ export default function DeckCreator() { } const saved = await createDeck(payload) -<<<<<<< HEAD - setDeck(prev => ({ - ...prev, - id: saved.id ?? prev.id, - creationdate: saved.creationdate ?? prev.creationdate, - updatedate: saved.updatedate ?? prev.updatedate - })) - alert('✅ Deck sikeresen mentve!') -======= setDeck(prev => ({ ...prev, id: saved.id ?? prev.id, @@ -82,7 +69,6 @@ export default function DeckCreator() { console.log('Deck saved (backend):', saved) notifySuccess('Deck sikeresen mentve!') ->>>>>>> main } catch (error) { console.error('Mentési hiba:', error) notifyError('Hiba történt a mentés során: ' + (error?.response?.data?.error || error.message || String(error))) @@ -108,46 +94,47 @@ export default function DeckCreator() { } const handleSaveCard = (cardData) => { -<<<<<<< HEAD - const updatedCard = { - ...cardData, - id: isCreatingCard ? Date.now() : cardData.id -======= - if (isCreatingCard) { - // Új kártya hozzáadása - const newCard = { + try { + const updatedCard = { ...cardData, - id: Date.now(), // Temporary ID + id: isCreatingCard ? Date.now() : cardData.id } - setDeck(prev => ({ - ...prev, - cards: [...prev.cards, newCard] - })) + + setDeck(prev => { + // Ellenőrizzük, vannak-e nem megfelelő típusú kártyák + 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 + if (isCreatingCard && cardData.type === prev.type && invalidCards.length > 0) { + notifyWarning(`${invalidCards.length} db nem megfelelő típusú kártya törlésre került`) + + return { + ...prev, + cards: [ + ...prev.cards.filter(card => card.type === prev.type), + updatedCard + ] + } + } + + // Alap mentési logika + return { + ...prev, + cards: isCreatingCard + ? [...prev.cards, updatedCard] + : prev.cards.map(card => card.id === updatedCard.id ? updatedCard : card) + } + }) + + setSelectedCard(updatedCard) setIsCreatingCard(false) setNewCardType(null) - setSelectedCard(newCard) - } else { - // Meglévő kártya frissítése - setDeck(prev => ({ - ...prev, - cards: prev.cards.map(card => - card.id === cardData.id ? cardData : card - ) - })) - setSelectedCard(cardData) ->>>>>>> main + + notifySuccess('Kártya sikeresen mentve!') + } catch (error) { + console.error('Kártya mentési hiba:', error) + notifyError('Hiba történt a kártya mentése során') } - - setDeck(prev => ({ - ...prev, - cards: isCreatingCard - ? [...prev.cards, updatedCard] - : prev.cards.map(card => card.id === updatedCard.id ? updatedCard : card) - })) - - setSelectedCard(updatedCard) - setIsCreatingCard(false) - setNewCardType(null) } // 🔧 Itt is confirm() volt — most a CardsList popupja kezeli a megerősítést @@ -196,7 +183,7 @@ export default function DeckCreator() { { setIsCreatingCard(false)