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)