Merge pull request 'navbarral footerrel mindennel egyutt' (#16) from walkehaladas into main

Reviewed-on: #16
This commit was merged in pull request #16.
This commit is contained in:
2025-07-12 17:33:14 +00:00
8 changed files with 356 additions and 17 deletions
+2
View File
@@ -8,6 +8,7 @@ import ForgotPassword from "./pages/Auth/ForgotPassword"
import ResetPassword from "./pages/Auth/ResetPassword" import ResetPassword from "./pages/Auth/ResetPassword"
import Landingpage from "./pages/Landing/Landingpage" import Landingpage from "./pages/Landing/Landingpage"
import Home from "./pages/Landing/Home" import Home from "./pages/Landing/Home"
import DeckManagerPage from "./pages/Decks/DeckManagerPage"
function App() { function App() {
const [isMobile, setIsMobile] = useState(false) const [isMobile, setIsMobile] = useState(false)
@@ -46,6 +47,7 @@ function App() {
<Route path="/test" element={<Test />} /> <Route path="/test" element={<Test />} />
<Route path="/" element={<Landingpage />} /> <Route path="/" element={<Landingpage />} />
<Route path="/home" element={<Home />} /> <Route path="/home" element={<Home />} />
<Route path="/decks" element={<DeckManagerPage />} />
{/* Add more routes as needed */} {/* Add more routes as needed */}
</Routes> </Routes>
</Router> </Router>
@@ -0,0 +1,292 @@
import React, { useState } from "react"
import {
FaPlus,
FaFilter,
FaCalendarAlt,
FaArrowUp,
FaArrowDown,
FaSortAlphaDown,
FaSortAlphaUp,
FaQuestionCircle,
} from "react-icons/fa"
import SearchBox from "../Search/SearchBox"
import PopUp from "../PopUp/PopUp"
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 [selectedType, setSelectedType] = useState("All")
const [selectedOrigin, setSelectedOrigin] = useState("Mind")
const [sortBy, setSortBy] = useState("date-desc")
const [search, setSearch] = useState("")
const [showSortHelp, setShowSortHelp] = useState(false)
// 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-6xl mx-auto px-4 py-10">
{/* Filters */}
<div className="flex flex-col md:flex-row gap-4 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 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"
style={{ borderTopColor: borderColor }}
>
<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>
</div>
)
}
export default DeckManager
@@ -23,7 +23,7 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
</div> </div>
<motion.h1 <motion.h1
className="text-4xl md:text-6xl font-bold text-white mb-6 leading-tight" className="text-3xl md:text-5xl font-bold text-white mb-4 leading-tight"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.4 }} transition={{ duration: 0.7, delay: 0.4 }}
@@ -32,7 +32,7 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
</motion.h1> </motion.h1>
<motion.p <motion.p
className="text-xl md:text-2xl text-gray-300 mb-6 max-w-3xl mx-auto leading-relaxed" className="text-lg md:text-xl text-gray-300 mb-4 max-w-3xl mx-auto leading-relaxed"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.6 }} transition={{ duration: 0.7, delay: 0.6 }}
@@ -41,7 +41,7 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
mindezt szórakozva! mindezt szórakozva!
</motion.p> </motion.p>
<motion.div <motion.div
className="text-2xl md:text-3xl font-bold text-emerald-400 mb-12" className="text-xl md:text-2xl font-bold text-emerald-400 mb-10"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.8 }} transition={{ duration: 0.7, delay: 0.8 }}
@@ -55,8 +55,8 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 1 }} transition={{ duration: 0.7, delay: 1 }}
> >
<ButtonGreen text="Játék" onClick={onNavigateToPlay} /> <ButtonGreen text="Játék" onClick={onNavigateToPlay} width="w-60" />
<ButtonGreen text="Regisztráció" onClick={onNavigateToAuth} /> <ButtonGreen text="Regisztráció" onClick={onNavigateToAuth} width="w-60" />
</motion.div> </motion.div>
</div> </div>
</motion.section> </motion.section>
@@ -71,7 +71,7 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
> >
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<motion.h2 <motion.h2
className="text-3xl md:text-4xl font-bold text-white text-center mb-16" className="text-2xl md:text-3xl font-bold text-white text-center mb-12"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }} whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }} viewport={{ once: true }}
@@ -92,8 +92,8 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
<div className="w-16 h-16 mx-auto mb-6 bg-emerald-500 rounded-full flex items-center justify-center"> <div className="w-16 h-16 mx-auto mb-6 bg-emerald-500 rounded-full flex items-center justify-center">
<FaUsers className="w-8 h-8 text-white" /> <FaUsers className="w-8 h-8 text-white" />
</div> </div>
<h3 className="text-xl font-semibold text-white mb-4">Közösségi élmény</h3> <h3 className="text-lg font-semibold text-white mb-2">Közösségi élmény</h3>
<p className="text-gray-300"> <p className="text-gray-300 text-sm">
Ismerkedj, nevess, tanulj! A SerpentRace összehozza a társaságot, legyen szó baráti Ismerkedj, nevess, tanulj! A SerpentRace összehozza a társaságot, legyen szó baráti
összejövetelről vagy csapatépítésről. összejövetelről vagy csapatépítésről.
</p> </p>
@@ -110,8 +110,8 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
<div className="w-16 h-16 mx-auto mb-6 bg-emerald-500 rounded-full flex items-center justify-center"> <div className="w-16 h-16 mx-auto mb-6 bg-emerald-500 rounded-full flex items-center justify-center">
<FaPaintBrush className="w-8 h-8 text-white" /> <FaPaintBrush className="w-8 h-8 text-white" />
</div> </div>
<h3 className="text-xl font-semibold text-white mb-4">Személyre szabható</h3> <h3 className="text-lg font-semibold text-white mb-2">Személyre szabható</h3>
<p className="text-gray-300"> <p className="text-gray-300 text-sm">
Kérdéskártyák, szabályok, design minden a te igényeidhez igazítható, akár céges brandinggel Kérdéskártyák, szabályok, design minden a te igényeidhez igazítható, akár céges brandinggel
is! is!
</p> </p>
@@ -128,8 +128,8 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
<div className="w-16 h-16 mx-auto mb-6 bg-emerald-500 rounded-full flex items-center justify-center"> <div className="w-16 h-16 mx-auto mb-6 bg-emerald-500 rounded-full flex items-center justify-center">
<FaHeadset className="w-8 h-8 text-white" /> <FaHeadset className="w-8 h-8 text-white" />
</div> </div>
<h3 className="text-xl font-semibold text-white mb-4">Folyamatos támogatás</h3> <h3 className="text-lg font-semibold text-white mb-2">Folyamatos támogatás</h3>
<p className="text-gray-300"> <p className="text-gray-300 text-sm">
Gyors, segítőkész ügyfélszolgálat ha bármilyen kérdésed vagy problémád van, mindig Gyors, segítőkész ügyfélszolgálat ha bármilyen kérdésed vagy problémád van, mindig
számíthatsz ránk! számíthatsz ránk!
</p> </p>
@@ -154,11 +154,11 @@ const LandingPage = ({ onNavigateToPlay, onNavigateToAuth }) => {
viewport={{ once: true }} viewport={{ once: true }}
transition={{ duration: 0.7, delay: 0.3 }} transition={{ duration: 0.7, delay: 0.3 }}
> >
<h2 className="text-3xl md:text-4xl font-bold text-white mb-6"> <h2 className="text-2xl md:text-3xl font-bold text-white mb-4">
Próbáld ki te is a SerpentRace-t! Próbáld ki te is a SerpentRace-t!
</h2> </h2>
<p className="text-xl text-gray-300 mb-8"> <p className="text-lg text-gray-300 mb-6">
Legyél részese egy új közösségi élménynek, vagy rendeld meg saját, személyre szabott Legyél részese egy új közösségi élménynek, vagy rendeld meg saját, személyre szabott
társasjátékodat mi mindenben segítünk! társasjátékodat mi mindenben segítünk!
</p> </p>
@@ -1,7 +1,7 @@
// src/components/PopUp/PopUp.jsx // src/components/PopUp/PopUp.jsx
// sima komponens, ami megjeleníti a popupot // sima komponens, ami megjeleníti a popupot
import React from "react"; import React from "react"
export default function PopUp({ children, onClose }) { export default function PopUp({ children, onClose }) {
return ( return (
@@ -17,5 +17,5 @@ export default function PopUp({ children, onClose }) {
{children} {children}
</div> </div>
</div> </div>
); )
} }
@@ -0,0 +1,22 @@
import React from "react"
import { FaSearch } from "react-icons/fa"
const SearchBox = ({ value, onChange, width = 220, placeholder = "Keresés...", className = "" }) => {
return (
<div
className={`flex items-center border-2 border-[color:var(--color-success)] rounded-lg bg-[color:var(--color-surface)]/40 px-2 ${className}`}
style={{ width }}
>
<FaSearch className="text-[color:var(--color-success)] mr-2" />
<input
type="text"
value={value}
onChange={onChange}
placeholder={placeholder}
className="flex-1 py-1 bg-transparent text-[color:var(--color-text)] border-none outline-none"
/>
</div>
)
}
export default SearchBox
+7
View File
@@ -24,9 +24,16 @@
--color-secondary: #8d8e83; --color-secondary: #8d8e83;
--color-accent: #0d0d0f; --color-accent: #0d0d0f;
/* 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 */
/* Háttérszínek */ /* Háttérszínek */
--color-background: #181d23; --color-background: #181d23;
--color-background-selected: #232a31;
--color-surface: #222d2f; --color-surface: #222d2f;
--color-surface-selected: #314045;
--color-card: #2c383b; --color-card: #2c383b;
/* Szövegszínek */ /* Szövegszínek */
@@ -0,0 +1,16 @@
// src/pages/Decks/DeckManagerPage.jsx
// Deck Management Page (with Navbar, no Footer)
import DeckManager from "../../components/Landingpage/DeckManager.jsx"
import Navbar from "../../components/Navbar/Navbar.jsx"
export default function DeckManagerPage() {
return (
<div className="w-full min-h-screen bg-background flex flex-col relative overflow-x-hidden">
<Navbar />
<main className="flex-1 flex flex-col items-center justify-start min-h-0">
<DeckManager />
</main>
</div>
)
}