From 7739038f88dc967639732ead2d1f41fb422b0ba0 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 4 Apr 2026 16:53:47 +0200 Subject: [PATCH] Refactored layout --- src/App.tsx | 237 +++------------------- src/components/layout/AccountDropdown.tsx | 38 ++++ src/components/layout/Sidebar.tsx | 44 ++++ src/components/layout/TopBar.tsx | 34 ++++ src/components/layout/VersionDropdown.tsx | 55 +++++ 5 files changed, 199 insertions(+), 209 deletions(-) create mode 100644 src/components/layout/AccountDropdown.tsx create mode 100644 src/components/layout/Sidebar.tsx create mode 100644 src/components/layout/TopBar.tsx create mode 100644 src/components/layout/VersionDropdown.tsx diff --git a/src/App.tsx b/src/App.tsx index 0121e90..08ed4b0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,237 +1,56 @@ -import React, { useState, useEffect } from "react"; -import { - Play, - Puzzle, - Settings, - ChevronDown, - Check, - User, - LogOut, -} from "lucide-react"; -import { getVersions } from "./lib/saturn"; -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; -import Logo from "@/assets/logo.png"; - -// Utility for merging tailwind classes -function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -// Components +import { useEffect, useState } from "react"; +import Sidebar from "./components/layout/Sidebar"; +import TopBar from "./components/layout/TopBar"; import PlaySection from "./components/PlaySection"; import ModsSection from "./components/ModsSection"; import SettingsSection from "./components/SettingsSection"; +import { getVersions } from "./lib/saturn"; import { GameVersion } from "./lib/types"; type Section = "play" | "mods" | "settings"; -const App: React.FC = () => { - const [activeSection, setActiveSection] = useState
("play"); +export default function App() { + const [active, setActive] = useState
("play"); const [versions, setVersions] = useState([]); const [selectedVersion, setSelectedVersion] = useState( null, ); - const [isVersionDropdownOpen, setIsVersionDropdownOpen] = useState(false); - const [isAccountDropdownOpen, setIsAccountDropdownOpen] = useState(false); - const versionRef = React.useRef(null); - const accountRef = React.useRef(null); + const [versionOpen, setVersionOpen] = useState(false); + const [accountOpen, setAccountOpen] = useState(false); useEffect(() => { - const fetchVersions = async () => { - const v = await getVersions(); + getVersions().then((v) => { setVersions(v); - if (v.length > 0) setSelectedVersion(v[0]); - }; - fetchVersions(); - }, []); - - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - const target = event.target as Node; - - // Close version dropdown if clicked outside - if (versionRef.current && !versionRef.current.contains(target)) { - setIsVersionDropdownOpen(false); - } - - // Close account dropdown if clicked outside - if (accountRef.current && !accountRef.current.contains(target)) { - setIsAccountDropdownOpen(false); - } - } - - document.addEventListener("mousedown", handleClickOutside); - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; + if (v.length) setSelectedVersion(v[0]); + }); }, []); return ( -
- {/* Sidebar */} - - - {/* Main Content Area */} -
- {/* Top Bar */} -
- {/* Version Selector */} -
-
- {/* Glow */} -
- - -
- -
- {versions.map((v) => ( - - ))} -
-
- - {/* Account Selector */} -
- {/* Glow */} -
- - - -
-
-

SaturnDev

-

- dev@saturnclient.com -

-
- - -
-
-
- - {/* Content Sections */} -
- {activeSection === "play" && selectedVersion && ( +
+ {active === "play" && selectedVersion && ( )} - {activeSection === "mods" && selectedVersion && ( + {active === "mods" && selectedVersion && ( )} - {activeSection === "settings" && } + {active === "settings" && }
); -}; - -export default App; +} diff --git a/src/components/layout/AccountDropdown.tsx b/src/components/layout/AccountDropdown.tsx new file mode 100644 index 0000000..e02d679 --- /dev/null +++ b/src/components/layout/AccountDropdown.tsx @@ -0,0 +1,38 @@ +import { User, LogOut } from "lucide-react"; + +import { twMerge } from "tailwind-merge"; + +interface Props { + open: boolean; + setOpen: (v: boolean) => void; +} + +export default function AccountDropdown({ open, setOpen }: Props) { + return ( +
+ + +
+ + +
+
+ ); +} diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx new file mode 100644 index 0000000..6496327 --- /dev/null +++ b/src/components/layout/Sidebar.tsx @@ -0,0 +1,44 @@ +import { Play, Puzzle, Settings } from "lucide-react"; +import { twMerge } from "tailwind-merge"; + +type Section = "play" | "mods" | "settings"; + +interface Props { + active: Section; + setActive: (s: Section) => void; +} + +export default function Sidebar({ active, setActive }: Props) { + return ( + + ); +} diff --git a/src/components/layout/TopBar.tsx b/src/components/layout/TopBar.tsx new file mode 100644 index 0000000..da49cbb --- /dev/null +++ b/src/components/layout/TopBar.tsx @@ -0,0 +1,34 @@ +import VersionDropdown from "./VersionDropdown"; +import AccountDropdown from "./AccountDropdown"; +import { GameVersion } from "@/lib/types"; + +interface Props { + versions: GameVersion[]; + selectedVersion: GameVersion | null; + setSelectedVersion: (v: GameVersion) => void; + + versionOpen: boolean; + setVersionOpen: (v: boolean) => void; + + accountOpen: boolean; + setAccountOpen: (v: boolean) => void; +} + +export default function TopBar(props: Props) { + return ( +
+ + + +
+ ); +} diff --git a/src/components/layout/VersionDropdown.tsx b/src/components/layout/VersionDropdown.tsx new file mode 100644 index 0000000..f197a11 --- /dev/null +++ b/src/components/layout/VersionDropdown.tsx @@ -0,0 +1,55 @@ +import { ChevronDown, Check } from "lucide-react"; +import { GameVersion } from "@/lib/types"; +import { twMerge } from "tailwind-merge"; + +interface Props { + versions: GameVersion[]; + selected: GameVersion | null; + onSelect: (v: GameVersion) => void; + open: boolean; + setOpen: (v: boolean) => void; +} + +export default function VersionDropdown({ + versions, + selected, + onSelect, + open, + setOpen, +}: Props) { + return ( +
+ + +
+ {versions.map((v) => ( + + ))} +
+
+ ); +}