Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
- Added a comment line to main.ts for deployment verification purposes
134 lines
4.5 KiB
TypeScript
134 lines
4.5 KiB
TypeScript
import { useAuth } from "@/hooks/use-auth";
|
||
import { capturePageView, identifyUser, resetUser } from "@/lib/posthog";
|
||
import { Toaster } from "@/lib/toast";
|
||
import { getUserSettings } from "@/lib/user-settings";
|
||
import { Button } from "@sase/ui";
|
||
import type { QueryClient } from "@tanstack/react-query";
|
||
import { Link, Outlet, createRootRouteWithContext, useLocation } from "@tanstack/react-router";
|
||
import { ArrowLeft, Home, Search } from "lucide-react";
|
||
import { useEffect } from "react";
|
||
|
||
interface RouterContext {
|
||
queryClient: QueryClient;
|
||
}
|
||
|
||
export const Route = createRootRouteWithContext<RouterContext>()({
|
||
component: RootComponent,
|
||
notFoundComponent: NotFoundComponent,
|
||
});
|
||
|
||
function NotFoundComponent() {
|
||
return (
|
||
<main className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-6 py-12">
|
||
{/* Ambient brand glow */}
|
||
<div className="pointer-events-none absolute -left-32 top-1/4 h-[500px] w-[500px] rounded-full bg-brand/8 blur-[140px]" />
|
||
<div className="pointer-events-none absolute -right-32 bottom-1/4 h-[400px] w-[400px] rounded-full bg-brand/5 blur-[120px]" />
|
||
|
||
<div className="relative max-w-xl text-center">
|
||
<p className="font-mono text-sm font-medium uppercase tracking-[0.2em] text-muted-foreground">
|
||
404 — sayfa bulunamadı
|
||
</p>
|
||
<h1 className="mt-6 font-[family-name:var(--font-display)] text-6xl font-bold tracking-tight sm:text-7xl">
|
||
Yanlış parça,
|
||
<br />
|
||
<span className="text-muted-foreground">yanlış adres.</span>
|
||
</h1>
|
||
<p className="mx-auto mt-6 max-w-md text-base text-muted-foreground">
|
||
Aradığın sayfa silinmiş ya da hiç olmamış olabilir. Aşağıdan ana sayfaya dönebilir veya
|
||
doğrudan şase aramaya gidebilirsin.
|
||
</p>
|
||
|
||
<div className="mt-10 flex flex-col items-center justify-center gap-3 sm:flex-row">
|
||
<Link to="/">
|
||
<Button variant="outline" className="rounded-full">
|
||
<ArrowLeft className="size-4" />
|
||
Ana sayfaya dön
|
||
</Button>
|
||
</Link>
|
||
<Link to="/dashboard/search">
|
||
<Button variant="brand" className="rounded-full">
|
||
<Search className="size-4" />
|
||
Şase aramaya git
|
||
</Button>
|
||
</Link>
|
||
</div>
|
||
|
||
<div className="mt-12 flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm text-muted-foreground">
|
||
<Link
|
||
to="/"
|
||
className="inline-flex items-center gap-1.5 transition-colors hover:text-foreground"
|
||
>
|
||
<Home className="size-3.5" />
|
||
Anasayfa
|
||
</Link>
|
||
<span className="size-1 rounded-full bg-border" aria-hidden="true" />
|
||
<Link to="/pricing" className="transition-colors hover:text-foreground">
|
||
Fiyatlandırma
|
||
</Link>
|
||
<span className="size-1 rounded-full bg-border" aria-hidden="true" />
|
||
<Link to="/demo" className="transition-colors hover:text-foreground">
|
||
Demo
|
||
</Link>
|
||
<span className="size-1 rounded-full bg-border" aria-hidden="true" />
|
||
<Link to="/contact" className="transition-colors hover:text-foreground">
|
||
İletişim
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
);
|
||
}
|
||
|
||
function applyTheme(theme: "light" | "dark" | "system") {
|
||
const isDark =
|
||
theme === "dark" ||
|
||
(theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||
document.documentElement.classList.toggle("dark", isDark);
|
||
}
|
||
|
||
function RootComponent() {
|
||
const location = useLocation();
|
||
const { user } = useAuth();
|
||
|
||
// Pageview tracking
|
||
useEffect(() => {
|
||
capturePageView(location.pathname);
|
||
}, [location.pathname]);
|
||
|
||
// User identification
|
||
useEffect(() => {
|
||
if (user) {
|
||
identifyUser({
|
||
id: user.id,
|
||
email: user.email,
|
||
name: user.name,
|
||
role: user.role,
|
||
});
|
||
} else {
|
||
resetUser();
|
||
}
|
||
}, [user]);
|
||
|
||
useEffect(() => {
|
||
const theme = getUserSettings().theme ?? "dark";
|
||
applyTheme(theme);
|
||
|
||
if (theme === "system") {
|
||
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
||
const handler = () => applyTheme("system");
|
||
mq.addEventListener("change", handler);
|
||
return () => mq.removeEventListener("change", handler);
|
||
}
|
||
}, []);
|
||
|
||
return (
|
||
<>
|
||
<a href="#main-content" className="skip-link">
|
||
İçeriğe atla
|
||
</a>
|
||
<Outlet />
|
||
<Toaster position="top-center" />
|
||
</>
|
||
);
|
||
}
|