Files
SerpentRace/SerpentRace_Frontend/src/components/DeckCreator/DeckManager.jsx
T
2025-10-18 17:50:39 +02:00

305 lines
12 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from "react"
import { useNavigate } from "react-router-dom"
import {
FaPlus,
FaFilter,
FaCalendarAlt,
FaArrowUp,
FaArrowDown,
FaSortAlphaDown,
FaSortAlphaUp,
FaQuestionCircle,
} from "react-icons/fa"
import SearchBox from "../Search/SearchBox"
import PopUp from "../PopUp/PopUp"
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)" },
]
const mockDecks = [
// Just for visual mockup
{ id: 1, name: "Party Luck", type: "Luck", created: "2025-07-01", origin: "Vállalati" },
{ id: 2, name: "Quiz Night", type: "Question", created: "2025-07-02", origin: "Saját" },
{ id: 3, name: "Fun Times", type: "Fun", created: "2025-07-03", origin: "Vállalati" },
{ id: 4, name: "Corporate Challenge", type: "Question", created: "2025-07-04", origin: "Vállalati" },
{ id: 5, name: "Randomizer", type: "Luck", created: "2025-07-05", origin: "Saját" },
{ id: 6, name: "Afterwork luck", type: "Luck", created: "2025-07-06", origin: "Saját" },
{ id: 7, name: "Serpent Quiz", type: "Question", created: "2025-07-07", origin: "Vállalati" },
{ id: 8, name: "Green Fortune", type: "Luck", created: "2025-07-08", origin: "Vállalati" },
{ id: 9, name: "Team Builder", type: "Fun", created: "2025-07-09", origin: "Saját" },
{ id: 10, name: "Knowledge Race", type: "Question", created: "2025-07-10", origin: "Saját" },
]
const origins = ["Mind", "Vállalati", "Saját"]
const sortOptions = [
{
value: "date-asc",
label: (
<>
<FaCalendarAlt className="inline mr-1" />
<FaArrowUp className="inline" />
</>
),
},
{
value: "date-desc",
label: (
<>
<FaCalendarAlt className="inline mr-1" />
<FaArrowDown className="inline" />
</>
),
},
{
value: "abc-asc",
label: (
<>
<FaSortAlphaDown className="inline" />
</>
),
},
{
value: "abc-desc",
label: (
<>
<FaSortAlphaUp className="inline" />
</>
),
},
]
const DeckManager = () => {
const navigate = useNavigate()
const [selectedType, setSelectedType] = useState("All")
const [selectedOrigin, setSelectedOrigin] = useState("Mind")
const [sortBy, setSortBy] = useState("date-desc")
const [search, setSearch] = useState("")
const [showSortHelp, setShowSortHelp] = useState(false)
const [selectedDeck, setSelectedDeck] = useState(null)
// Filter logic (mock)
let filteredDecks = mockDecks.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())
return typeMatch && originMatch && searchMatch
})
// Sort logic
filteredDecks = [...filteredDecks].sort((a, b) => {
if (sortBy === "date-asc") {
return a.created.localeCompare(b.created)
} else if (sortBy === "date-desc") {
return b.created.localeCompare(a.created)
} else if (sortBy === "abc-asc") {
return a.name.localeCompare(b.name)
} else if (sortBy === "abc-desc") {
return b.name.localeCompare(a.name)
}
return 0
})
return (
<div className="w-full flex flex-col bg-[color:var(--color-background)]">
<div className="w-full max-w-[1200px] mx-auto px-4 py-10">
{/* Filters */}
<div className="flex flex-col md:flex-row gap-3 justify-between items-center mb-10 bg-[color:var(--color-surface)]/80 backdrop-blur-lg rounded-2xl px-6 py-4 shadow-lg">
<div className="flex gap-2 items-center w-full md:w-auto">
<SearchBox
value={search}
onChange={(e) => setSearch(e.target.value)}
width={240}
placeholder="Keresés..."
className="mr-4"
/>
<FaFilter style={{ color: "var(--color-success)" }} className="mr-2" />
<span className="text-[color:var(--color-text)] font-semibold mr-2">Típus:</span>
<button
className={`px-3 py-1 rounded-lg font-medium transition-all duration-200 ${
selectedType === "All"
? "bg-[color:var(--color-surface-selected)] text-[color:var(--color-text)] border border-[color:var(--color-surface)]"
: "text-[color:var(--color-text)] bg-[color:var(--color-success)]/10 hover:bg-[color:var(--color-success)]/30"
}`}
onClick={() => setSelectedType("All")}
>
Mind
</button>
{deckTypes.map((type) => (
<button
key={type.label}
className={`px-3 py-1 rounded-lg font-medium transition-all duration-200 ml-1 ${
selectedType === type.label
? "text-[color:var(--color-text-inverse)] border border-[color:var(--color-surface)]"
: "text-[color:var(--color-text)] bg-[color:var(--color-success)]/10 hover:bg-[color:var(--color-success)]/30"
}`}
style={selectedType === type.label ? { background: type.color } : undefined}
onClick={() => setSelectedType(type.label)}
>
{type.label === "Luck"
? "Szerencse"
: type.label === "Question"
? "Kérdés"
: type.label === "Fun"
? "Szórakozás"
: type.label}
</button>
))}
<span className="text-[color:var(--color-text)] font-semibold mr-2 ml-2">Eredet:</span>
<select
className="px-3 py-1 rounded-lg bg-[color:var(--color-success)]/10 hover:bg-[color:var(--color-success)]/30 text-[color:var(--color-text)] border-none focus:ring-2 focus:ring-[color:var(--color-success)] outline-none"
style={{ backgroundColor: "rgba(0, 255, 0, 0.10)" }}
value={selectedOrigin}
onChange={(e) => setSelectedOrigin(e.target.value)}
>
{origins.map((origin) => (
<option
key={origin}
value={origin}
style={{ backgroundColor: "var(--color-surface)", color: "var(--color-text)" }}
>
{origin === "Mind"
? "Mind"
: origin === "Vállalati"
? "Vállalati"
: origin === "Saját"
? "Saját"
: origin}
</option>
))}
</select>
<span className="text-[color:var(--color-text)] font-semibold mr-2 ml-2 flex items-center gap-1">
Rendezés:
<button
type="button"
className="ml-1 text-[color:var(--color-success)] hover:text-[color:var(--color-text)] focus:outline-none"
onClick={() => setShowSortHelp(true)}
aria-label="Rendezési magyarázat megnyitása"
style={{ fontSize: 18, lineHeight: 1 }}
>
<FaQuestionCircle />
</button>
</span>
<select
className="px-3 py-1 rounded-lg bg-[color:var(--color-success)]/10 hover:bg-[color:var(--color-success)]/30 text-[color:var(--color-text)] border-none focus:ring-2 focus:ring-[color:var(--color-success)] outline-none flex items-center"
style={{ backgroundColor: "rgba(0, 255, 0, 0.10)" }}
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
aria-label="Rendezés"
>
<option
value="date-asc"
style={{ backgroundColor: "var(--color-surface)", color: "var(--color-text)" }}
>
📅
</option>
<option
value="date-desc"
style={{ backgroundColor: "var(--color-surface)", color: "var(--color-text)" }}
>
📅
</option>
<option
value="abc-asc"
style={{ backgroundColor: "var(--color-surface)", color: "var(--color-text)" }}
>
AZ
</option>
<option
value="abc-desc"
style={{ backgroundColor: "var(--color-surface)", color: "var(--color-text)" }}
>
ZA
</option>
</select>
{showSortHelp && (
<PopUp onClose={() => setShowSortHelp(false)}>
<h2 className="text-lg font-bold mb-4">Rendezési lehetőségek magyarázata</h2>
<ul className="space-y-2 text-[color:var(--color-night)]">
<li>
<span className="font-bold">📅</span> Dátum szerint növekvő sorrendben (legrégebbi
elöl)
</li>
<li>
<span className="font-bold">📅</span> Dátum szerint csökkenő sorrendben (legújabb elöl)
</li>
<li>
<span className="font-bold">AZ</span> Név szerint növekvő sorrendben (A-tól Z-ig)
</li>
<li>
<span className="font-bold">ZA</span> Név szerint csökkenő sorrendben (Z-től A-ig)
</li>
</ul>
<button
className="mt-6 px-4 py-2 rounded-lg bg-[color:var(--color-success)] text-[color:var(--color-text-inverse)] font-semibold hover:bg-[color:var(--color-success)]/80 transition"
onClick={() => setShowSortHelp(false)}
>
Bezárás
</button>
</PopUp>
)}
</div>
</div>
{/* Decks Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-8 mt-8">
{/* Create New Deck (Mockup) */}
<div
onClick={() => navigate("/deck-creator")}
className="flex flex-col items-center justify-center h-48 bg-[color:var(--color-card)] border-2 border-dashed border-[color:var(--color-success)] rounded-2xl cursor-pointer hover:bg-[color:var(--color-success)]/20 transition-all duration-200 shadow-lg"
>
<FaPlus style={{ color: "var(--color-success)" }} className="text-5xl mb-2" />
<span className="text-[color:var(--color-text)] font-semibold">Új pakli létrehozása</span>
</div>
{/* Existing Decks (Mockup) */}
{filteredDecks.map((deck) => {
const deckType = deckTypes.find((t) => t.label === deck.type)
const borderColor = deckType ? deckType.color : "var(--color-success)"
return (
<div
key={deck.id}
className="flex flex-col justify-between h-48 bg-[color:var(--color-card)] rounded-2xl p-6 shadow-lg border-t-4 hover:scale-105 transition-transform duration-200 cursor-pointer"
style={{ borderTopColor: borderColor }}
onClick={() => setSelectedDeck(deck)}
>
<div>
<span
className="inline-block px-3 py-1 rounded-full text-xs font-bold mb-2"
style={{
background: deckType?.color,
color: "var(--color-text-inverse)",
}}
>
{deck.type === "Luck"
? "Szerencse"
: deck.type === "Question"
? "Kérdés"
: deck.type === "Fun"
? "Szórakozás"
: deck.type}
</span>
<h2 className="text-xl font-bold text-[color:var(--color-text)] mb-1 truncate">
{deck.name}
</h2>
</div>
<div className="text-[color:var(--color-text-muted)] text-sm mt-2">
Létrehozva: {deck.created}
</div>
</div>
)
})}
</div>
</div>
{/* Deck Info Popup */}
{selectedDeck && <DeckInfoPopUp deck={selectedDeck} onClose={() => setSelectedDeck(null)} />}
</div>
)
}
export default DeckManager