UI Aupdate

This commit is contained in:
2025-11-26 19:41:03 +03:00
parent 16c21a4e49
commit 732603559a
5 changed files with 115 additions and 60 deletions

View File

@@ -9,6 +9,9 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^7.1.0",
"@fortawesome/free-solid-svg-icons": "^7.1.0",
"@fortawesome/react-fontawesome": "^3.1.0",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"axios": "^1.5.1", "axios": "^1.5.1",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",

View File

@@ -9,6 +9,7 @@ function App() {
<Route path="/login" element={<LoginPage />} /> <Route path="/login" element={<LoginPage />} />
<Route element={<ProtectedRoute />}> <Route element={<ProtectedRoute />}>
<Route path="/admin" element={<AdminPage />} /> <Route path="/admin" element={<AdminPage />} />
<Route path="/jobs" element={<AdminPage />} />
</Route> </Route>
<Route path="*" element={<Navigate to="/admin" replace />} /> <Route path="*" element={<Navigate to="/admin" replace />} />
</Routes> </Routes>

View File

@@ -1,12 +1,26 @@
import { Moon, Sun } from "lucide-react"; import { Moon, Sun } from "lucide-react";
import { Button } from "./ui/button"; import { Button, type ButtonProps } from "./ui/button";
import { useTheme } from "../providers/theme-provider"; import { useTheme } from "../providers/theme-provider";
export function ThemeToggle() { export function ThemeToggle({
className,
size = "icon",
variant = "outline"
}: {
className?: string;
size?: ButtonProps["size"];
variant?: ButtonProps["variant"];
}) {
const { theme, toggleTheme } = useTheme(); const { theme, toggleTheme } = useTheme();
return ( return (
<Button variant="outline" size="icon" aria-label="Tema değiştir" onClick={toggleTheme}> <Button
variant={variant}
size={size}
aria-label="Tema değiştir"
onClick={toggleTheme}
className={className}
>
{theme === "light" ? <Moon className="h-5 w-5" /> : <Sun className="h-5 w-5" />} {theme === "light" ? <Moon className="h-5 w-5" /> : <Sun className="h-5 w-5" />}
</Button> </Button>
); );

View File

@@ -9,7 +9,7 @@
--card-foreground: 0 0% 4%; --card-foreground: 0 0% 4%;
--popover: 0 0% 100%; --popover: 0 0% 100%;
--popover-foreground: 0 0% 4%; --popover-foreground: 0 0% 4%;
--primary: 0 0% 4%; --primary: 180 1.2% 16.3%;
--primary-foreground: 0 0% 98%; --primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%; --secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%; --secondary-foreground: 0 0% 9%;

View File

@@ -1,12 +1,15 @@
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom"; import { NavLink, useNavigate } from "react-router-dom";
import { io, Socket } from "socket.io-client"; import { io, Socket } from "socket.io-client";
import { toast } from "sonner"; import { toast } from "sonner";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faHouse, faBriefcase, faArrowRightFromBracket, faUser } from "@fortawesome/free-solid-svg-icons";
import { Button } from "../components/ui/button"; import { Button } from "../components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card";
import { ThemeToggle } from "../components/ThemeToggle"; import { ThemeToggle } from "../components/ThemeToggle";
import { useAuth } from "../providers/auth-provider"; import { useAuth } from "../providers/auth-provider";
import { apiClient } from "../api/client"; import { apiClient } from "../api/client";
import { cn } from "../lib/utils";
export function AdminPage() { export function AdminPage() {
const { user, token, logout } = useAuth(); const { user, token, logout } = useAuth();
@@ -48,66 +51,100 @@ export function AdminPage() {
socket.emit("ping"); socket.emit("ping");
}; };
const navigation = [
{ label: "Home", to: "/admin", icon: faHouse },
{ label: "Jobs", to: "/jobs", icon: faBriefcase }
];
return ( return (
<div className="min-h-screen bg-background text-foreground"> <div className="min-h-screen bg-background text-foreground">
<header className="flex items-center justify-between border-b border-border px-6 py-4"> <div className="flex min-h-screen">
<div className="flex items-center gap-3"> <aside className="hidden w-64 flex-col border-r border-border bg-card/40 md:flex">
<div className="text-lg font-semibold">Yönetim Paneli</div> <div className="flex h-16 items-center border-b border-border px-6">
{user?.username && <span className="text-sm text-muted-foreground">Hoş geldin, {user.username}</span>} <span className="text-lg font-semibold tracking-tight">Wisecolt CI</span>
</div> </div>
<div className="flex items-center gap-3"> <nav className="flex-1 space-y-1 px-3 py-4">
<ThemeToggle /> {navigation.map((item) => (
<Button variant="outline" onClick={handleLogout}> <NavLink
Çıkış Yap key={item.to}
</Button> to={item.to}
</div> className={({ isActive }) =>
</header> cn(
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition",
<main className="mx-auto grid max-w-4xl gap-6 px-6 py-10 md:grid-cols-2"> isActive
<Card className="border-border card-shadow"> ? "bg-primary text-primary-foreground shadow-sm"
<CardHeader> : "text-muted-foreground hover:bg-accent hover:text-accent-foreground"
<CardTitle>Bağlantı</CardTitle> )
<CardDescription>Backend'e bağlanıp basit ping/pong testi yapın.</CardDescription> }
</CardHeader> >
<CardContent className="space-y-4"> <FontAwesomeIcon icon={item.icon} className="h-4 w-4" />
<Button onClick={sendPing} disabled={!socket}> <span>{item.label}</span>
Ping Gönder </NavLink>
</Button> ))}
<div className="rounded-md border border-border bg-muted/40 p-3 text-sm text-muted-foreground"> </nav>
<div className="mb-2 text-xs uppercase tracking-wide text-foreground">Socket Mesajları</div> <div className="mt-auto space-y-3 border-t border-border px-4 py-4">
<div className="space-y-1"> <div className="flex gap-3">
{messages.length === 0 && <div>Mesaj yok.</div>} <ThemeToggle size="icon" className="h-10 w-10 justify-center" />
{messages.map((msg, idx) => ( <div className="flex h-10 flex-1 items-center gap-3 rounded-md border border-border bg-background px-3">
<div key={idx} className="text-foreground/80"> <FontAwesomeIcon icon={faUser} className="h-4 w-4 text-muted-foreground" />
{msg} <span className="text-sm font-medium text-foreground">{user?.username ?? "-"}</span>
</div>
))}
</div> </div>
</div> </div>
</CardContent> <Button variant="outline" className="w-full justify-center gap-2" onClick={handleLogout}>
</Card> <FontAwesomeIcon icon={faArrowRightFromBracket} className="h-4 w-4" />
Çıkış Yap
</Button>
</div>
</aside>
<Card className="border-border card-shadow"> <main className="flex-1">
<CardHeader> <div className="mx-auto grid max-w-5xl gap-6 px-6 py-10 md:grid-cols-2">
<CardTitle>Durum</CardTitle> <Card className="border-border card-shadow">
<CardDescription>Auth & bağlantı bilgileri.</CardDescription> <CardHeader>
</CardHeader> <CardTitle>Bağlantı</CardTitle>
<CardContent className="space-y-3 text-sm text-muted-foreground"> <CardDescription>Backend'e bağlanıp basit ping/pong testi yapın.</CardDescription>
<div className="flex items-center justify-between"> </CardHeader>
<span>API URL</span> <CardContent className="space-y-4">
<span className="font-medium text-foreground">{socketUrl}</span> <Button onClick={sendPing} disabled={!socket}>
</div> Ping Gönder
<div className="flex items-center justify-between"> </Button>
<span>Kullanıcı</span> <div className="rounded-md border border-border bg-muted/40 p-3 text-sm text-muted-foreground">
<span className="font-medium text-foreground">{user?.username ?? "-"}</span> <div className="mb-2 text-xs uppercase tracking-wide text-foreground">Socket Mesajları</div>
</div> <div className="space-y-1">
<div className="flex items-center justify-between"> {messages.length === 0 && <div>Mesaj yok.</div>}
<span>Token</span> {messages.map((msg, idx) => (
<span className="truncate font-mono text-foreground/80">{token?.slice(0, 24) ?? "-"}...</span> <div key={idx} className="text-foreground/80">
</div> {msg}
</CardContent> </div>
</Card> ))}
</main> </div>
</div>
</CardContent>
</Card>
<Card className="border-border card-shadow">
<CardHeader>
<CardTitle>Durum</CardTitle>
<CardDescription>Auth & bağlantı bilgileri.</CardDescription>
</CardHeader>
<CardContent className="space-y-3 text-sm text-muted-foreground">
<div className="flex items-center justify-between">
<span>API URL</span>
<span className="font-medium text-foreground">{socketUrl}</span>
</div>
<div className="flex items-center justify-between">
<span>Kullanıcı</span>
<span className="font-medium text-foreground">{user?.username ?? "-"}</span>
</div>
<div className="flex items-center justify-between">
<span>Token</span>
<span className="truncate font-mono text-foreground/80">{token?.slice(0, 24) ?? "-"}...</span>
</div>
</CardContent>
</Card>
</div>
</main>
</div>
</div> </div>
); );
} }