UI Aupdate
This commit is contained in:
@@ -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",
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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%;
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user