UI ve dokümantasyon boyunca "Job" terimleri "Test" olarak değiştirildi. Bu değişiklik, uygulamanın terminolojisini tutarlı hale getirmek ve kullanıcı arayüzünde daha doğru bir isimlendirme sağlamak için yapıldı. Tüm etiketler, başlıklar, bildirimler ve dokümantasyon güncellendi.
96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
import React, { useMemo, useState } from "react";
|
||
import { NavLink, Outlet, useNavigate } from "react-router-dom";
|
||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||
import {
|
||
faHouse,
|
||
faArrowRightFromBracket,
|
||
faUser,
|
||
faFlaskVial,
|
||
faRocket,
|
||
faGear
|
||
} from "@fortawesome/free-solid-svg-icons";
|
||
import { Button } from "./ui/button";
|
||
import { ThemeToggle } from "./ThemeToggle";
|
||
import { useAuth } from "../providers/auth-provider";
|
||
import { cn } from "../lib/utils";
|
||
|
||
export function DashboardLayout() {
|
||
const { user, logout } = useAuth();
|
||
const navigate = useNavigate();
|
||
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
||
|
||
const navigation = useMemo(
|
||
() => [
|
||
{ label: "Home", to: "/home", icon: faHouse },
|
||
{ label: "Tests", to: "/jobs", icon: faFlaskVial },
|
||
{ label: "Deployments", to: "/deployments", icon: faRocket },
|
||
{ label: "Settings", to: "/settings", icon: faGear }
|
||
],
|
||
[]
|
||
);
|
||
|
||
const handleLogout = () => {
|
||
setIsLoggingOut(true);
|
||
logout();
|
||
navigate("/login", { replace: true });
|
||
};
|
||
|
||
return (
|
||
<div className="min-h-screen bg-background text-foreground">
|
||
<div className="flex min-h-screen">
|
||
<aside className="fixed left-0 top-0 hidden h-screen w-64 flex-col border-r border-border bg-card/40 md:flex">
|
||
<div className="flex h-16 items-center border-b border-border px-6">
|
||
<span className="text-lg font-semibold tracking-tight">Wisecolt CI</span>
|
||
</div>
|
||
<nav className="flex-1 space-y-1 px-3 py-4">
|
||
{navigation.map((item) => (
|
||
<NavLink
|
||
key={item.to}
|
||
to={item.to}
|
||
className={({ isActive }) =>
|
||
cn(
|
||
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition",
|
||
isActive
|
||
? "bg-accent text-foreground shadow-sm"
|
||
: "text-muted-foreground hover:bg-accent hover:text-foreground"
|
||
)
|
||
}
|
||
>
|
||
<FontAwesomeIcon icon={item.icon} className="h-4 w-4" />
|
||
<span>{item.label}</span>
|
||
</NavLink>
|
||
))}
|
||
</nav>
|
||
<div className="mt-auto space-y-3 border-t border-border px-4 py-4">
|
||
<div className="flex gap-3">
|
||
<ThemeToggle size="icon" className="h-10 w-10 justify-center" />
|
||
<div className="flex h-10 flex-1 items-center gap-3 rounded-md border border-border bg-background px-3">
|
||
<FontAwesomeIcon icon={faUser} className="h-4 w-4 text-muted-foreground" />
|
||
<span className="text-sm font-medium text-foreground">{user?.username ?? "-"}</span>
|
||
</div>
|
||
</div>
|
||
<Button
|
||
variant="outline"
|
||
className="w-full justify-center gap-2"
|
||
onClick={handleLogout}
|
||
disabled={isLoggingOut}
|
||
title="Çıkış Yap"
|
||
>
|
||
<FontAwesomeIcon icon={faArrowRightFromBracket} className="h-4 w-4" />
|
||
Çıkış Yap
|
||
</Button>
|
||
</div>
|
||
</aside>
|
||
|
||
<main className="flex-1 overflow-y-auto md:ml-64 min-w-0">
|
||
<div className="mx-auto flex max-w-5xl flex-col gap-6 px-4 py-8 sm:px-6 lg:px-8">
|
||
<div className="grid gap-6">
|
||
<Outlet />
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|