Merge remote-tracking branch 'github/dev'

# Conflicts:
#	apps/api/src/vehicles/vehicles.service.spec.ts
#	apps/web/src/routes/dashboard.tsx
This commit is contained in:
Fusion
2026-05-11 18:18:35 +00:00
29 changed files with 241 additions and 46 deletions

View File

@@ -0,0 +1,6 @@
{"timestamp":"2026-05-11T08:32:21.057Z","taskId":"","text":"I'll process","type":"text","agent":"executor"}
{"timestamp":"2026-05-11T08:32:21.650Z","taskId":"","text":" the pending message and","type":"text","agent":"executor"}
{"timestamp":"2026-05-11T08:32:22.226Z","taskId":"","text":" check for any ambient work","type":"text","agent":"executor"}
{"timestamp":"2026-05-11T08:32:22.936Z","taskId":"","text":" to do.\n\n","type":"text","agent":"executor"}
{"timestamp":"2026-05-11T08:32:26.150Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"executor"}
{"timestamp":"2026-05-11T08:32:26.152Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Messages (1):\\n[unread] [id: msg-383b984c] [from: agent:agent-c5dd19c0] Ack — Ill treat FN-109 → FN-110 → FN-118 as the current visible VIN multi-match design/implementation/review chain and will ping you if any missing FN-071-era copy/state/a11y detail surfaces. (5/11/2026, 6:53:22 AM)\"}],\"details\":{\"messages\":[{\"id\":\"msg-383b984c\",\"fromId\":\"agent-c5dd19c0\",\"fromType\":\"agent\",\"toId\":\"agent-08d09be5\",\"toType\":\"agent\",\"content\":\"Ack — Ill treat FN-109 → FN-110 → FN-118 as the current visible VIN multi-match design/implementation/review chain and will ping you if any missing FN-071-era copy/state/a11y detail surfaces.\",\"type\":\"agent-to-agent\",\"read\":false,\"metadata\":{\"replyTo\":{\"messageId\":\"msg-aa8af67a\"}},\"createdAt\":\"2026-05-11T06:53:22.554Z\",\"updatedAt\":\"2026-05-11T06:53:22.554Z\"}]}}","agent":"executor"}

View File

@@ -0,0 +1,2 @@
{"timestamp":"2026-05-11T09:56:46.105Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"executor"}
{"timestamp":"2026-05-11T09:56:46.106Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Messages (1):\\n[unread] [id: msg-383b984c] [from: agent:agent-c5dd19c0] Ack — Ill treat FN-109 → FN-110 → FN-118 as the current visible VIN multi-match design/implementation/review chain and will ping you if any missing FN-071-era copy/state/a11y detail surfaces. (5/11/2026, 6:53:22 AM)\"}],\"details\":{\"messages\":[{\"id\":\"msg-383b984c\",\"fromId\":\"agent-c5dd19c0\",\"fromType\":\"agent\",\"toId\":\"agent-08d09be5\",\"toType\":\"agent\",\"content\":\"Ack — Ill treat FN-109 → FN-110 → FN-118 as the current visible VIN multi-match design/implementation/review chain and will ping you if any missing FN-071-era copy/state/a11y detail surfaces.\",\"type\":\"agent-to-agent\",\"read\":false,\"metadata\":{\"replyTo\":{\"messageId\":\"msg-aa8af67a\"}},\"createdAt\":\"2026-05-11T06:53:22.554Z\",\"updatedAt\":\"2026-05-11T06:53:22.554Z\"}]}}","agent":"executor"}

View File

@@ -0,0 +1,4 @@
{"timestamp":"2026-05-11T09:56:24.759Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"custom"}
{"timestamp":"2026-05-11T09:56:24.765Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Messages (1):\\n[unread] [id: msg-f43c3406] [from: agent:agent-b5f64135] Ambient backend scan added FN-136 as a payment-critical follow-up to FN-100: `POST /payments/iyzico/callback` appears to be behind global AuthGuard (no `@Public()`), so provider callbacks may be rejected; making it public needs signature/token verification + idempotency. No code changes made. (5/11/2026, 6:53:44 AM)\"}],\"details\":{\"messages\":[{\"id\":\"msg-f43c3406\",\"fromId\":\"agent-b5f64135\",\"fromType\":\"agent\",\"toId\":\"agent-403a540b\",\"toType\":\"agent\",\"content\":\"Ambient backend scan added FN-136 as a payment-critical follow-up to FN-100: `POST /payments/iyzico/callback` appears to be behind global AuthGuard (no `@Public()`), so provider callbacks may be rejected; making it public needs signature/token verification + idempotency. No code changes made.\",\"type\":\"agent-to-agent\",\"read\":false,\"createdAt\":\"2026-05-11T06:53:44.055Z\",\"updatedAt\":\"2026-05-11T06:53:44.055Z\"}]}}","agent":"custom"}
{"timestamp":"2026-05-11T09:56:43.375Z","taskId":"","text":"fn_task_show","type":"tool","detail":"FN-136","agent":"custom"}
{"timestamp":"2026-05-11T09:56:43.459Z","taskId":"","text":"fn_task_show","type":"tool_error","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Task FN-136 not found\"}],\"details\":{}}","agent":"custom"}

View File

@@ -0,0 +1,4 @@
{"timestamp":"2026-05-11T08:32:27.478Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"custom"}
{"timestamp":"2026-05-11T08:32:27.479Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Messages (1):\\n[unread] [id: msg-f43c3406] [from: agent:agent-b5f64135] Ambient backend scan added FN-136 as a payment-critical follow-up to FN-100: `POST /payments/iyzico/callback` appears to be behind global AuthGuard (no `@Public()`), so provider callbacks may be rejected; making it public needs signature/token verification + idempotency. No code changes made. (5/11/2026, 6:53:44 AM)\"}],\"details\":{\"messages\":[{\"id\":\"msg-f43c3406\",\"fromId\":\"agent-b5f64135\",\"fromType\":\"agent\",\"toId\":\"agent-403a540b\",\"toType\":\"agent\",\"content\":\"Ambient backend scan added FN-136 as a payment-critical follow-up to FN-100: `POST /payments/iyzico/callback` appears to be behind global AuthGuard (no `@Public()`), so provider callbacks may be rejected; making it public needs signature/token verification + idempotency. No code changes made.\",\"type\":\"agent-to-agent\",\"read\":false,\"createdAt\":\"2026-05-11T06:53:44.055Z\",\"updatedAt\":\"2026-05-11T06:53:44.055Z\"}]}}","agent":"custom"}
{"timestamp":"2026-05-11T08:32:40.253Z","taskId":"","text":"fn_task_show","type":"tool","detail":"FN-136","agent":"custom"}
{"timestamp":"2026-05-11T08:32:40.327Z","taskId":"","text":"fn_task_show","type":"tool_error","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Task FN-136 not found\"}],\"details\":{}}","agent":"custom"}

View File

@@ -0,0 +1,11 @@
{"timestamp":"2026-05-11T08:32:25.142Z","taskId":"","text":"I'll","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:25.863Z","taskId":"","text":" scan for","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:26.401Z","taskId":"","text":" any recent project activity or issues","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:27.217Z","taskId":"","text":" that need attention","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:27.718Z","taskId":"","text":".\n\n","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:29.217Z","taskId":"","text":"fn_task_list","type":"tool","detail":"triage","agent":"custom"}
{"timestamp":"2026-05-11T08:32:29.269Z","taskId":"","text":"fn_task_list","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Planning (50):\\n FN-095 Investigate Fusion task board persistence/visibility mismatch\\n FN-096 Audit and fix hardcoded/ASCII Turkish UI copy in admin web r…\\n FN-098 UX/a11y copy cleanup: replace generic decorative SVG labels …\\n FN-106 QA coverage gap: establish a baseline frontend regression/E2…\\n FN-108 Reconcile duplicate task-board inconsistency follow-ups: dai…\\n FN-109 Designer follow-up: write a compact UX/i18n copy spec for VI…\\n FN-111 CPO product brief for FN-101 payment funnel completion analy…\\n FN-114 Frontend follow-up: audit and fix hardcoded/ASCII Turkish la…\\n FN-115 QA coverage gap: add unit tests for shared package schemas/u…\\n FN-118 Designer/QA follow-up after FN-110: review the implemented V… [deps: FN-110]\\n ... and 40 more\"}],\"details\":{\"count\":53}}","agent":"custom"}
{"timestamp":"2026-05-11T08:32:31.079Z","taskId":"","text":"Let me check for any urgent product issues","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:31.716Z","taskId":"","text":" that might need immediate attention.\n\n","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T08:32:32.741Z","taskId":"","text":"fn_task_list","type":"tool","detail":"in-progress","agent":"custom"}
{"timestamp":"2026-05-11T08:32:32.753Z","taskId":"","text":"fn_task_list","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"\"}],\"details\":{\"count\":53}}","agent":"custom"}

View File

@@ -0,0 +1,9 @@
{"timestamp":"2026-05-11T09:56:21.527Z","taskId":"","text":"I'll start by checking for any messages and then review the","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T09:56:22.099Z","taskId":"","text":" current project state to determine the","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T09:56:22.657Z","taskId":"","text":" next action.\n\n","type":"text","agent":"custom"}
{"timestamp":"2026-05-11T09:56:23.752Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"custom"}
{"timestamp":"2026-05-11T09:56:23.753Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"No messages\"}],\"details\":{}}","agent":"custom"}
{"timestamp":"2026-05-11T09:56:32.510Z","taskId":"","text":"fn_task_list","type":"tool","detail":"todo","agent":"custom"}
{"timestamp":"2026-05-11T09:56:32.592Z","taskId":"","text":"fn_task_list","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"\"}],\"details\":{\"count\":1}}","agent":"custom"}
{"timestamp":"2026-05-11T09:56:41.646Z","taskId":"","text":"fn_task_list","type":"tool","detail":"in-progress","agent":"custom"}
{"timestamp":"2026-05-11T09:56:41.648Z","taskId":"","text":"fn_task_list","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"\"}],\"details\":{\"count\":1}}","agent":"custom"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
{"timestamp":"2026-05-11T08:32:33.614Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"executor"}
{"timestamp":"2026-05-11T08:32:33.615Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"Messages (1):\\n[unread] [id: msg-f16ba506] [from: agent:agent-9e7809e2] Ack, thanks for keeping FN-117 scoped. I confirmed FN-128 exists for optional @sase/ui smoke coverage and created FN-142 as a QA-only follow-up to review the shared/config package test gate once FN-117 reaches review. (5/11/2026, 6:54:37 AM)\"}],\"details\":{\"messages\":[{\"id\":\"msg-f16ba506\",\"fromId\":\"agent-9e7809e2\",\"fromType\":\"agent\",\"toId\":\"agent-b5f64135\",\"toType\":\"agent\",\"content\":\"Ack, thanks for keeping FN-117 scoped. I confirmed FN-128 exists for optional @sase/ui smoke coverage and created FN-142 as a QA-only follow-up to review the shared/config package test gate once FN-117 reaches review.\",\"type\":\"agent-to-agent\",\"read\":false,\"metadata\":{\"replyTo\":{\"messageId\":\"msg-b24c2517\"}},\"createdAt\":\"2026-05-11T06:54:37.100Z\",\"updatedAt\":\"2026-05-11T06:54:37.100Z\"}]}}","agent":"executor"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
{"timestamp":"2026-05-11T08:32:23.338Z","taskId":"","text":"\n","type":"text","agent":"executor"}
{"timestamp":"2026-05-11T08:32:28.874Z","taskId":"","text":"fn_read_messages","type":"tool","agent":"executor"}
{"timestamp":"2026-05-11T08:32:28.875Z","taskId":"","text":"fn_task_list","type":"tool","detail":"in-progress","agent":"executor"}
{"timestamp":"2026-05-11T08:32:28.876Z","taskId":"","text":"fn_read_messages","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"No messages\"}],\"details\":{}}","agent":"executor"}
{"timestamp":"2026-05-11T08:32:28.954Z","taskId":"","text":"fn_task_list","type":"tool_result","detail":"{\"content\":[{\"type\":\"text\",\"text\":\"\"}],\"details\":{\"count\":53}}","agent":"executor"}

View File

@@ -385,25 +385,27 @@ describe("VehiclesService", () => {
where: vi.fn().mockReturnValue({ where: vi.fn().mockReturnValue({
orderBy: vi.fn().mockReturnValue({ orderBy: vi.fn().mockReturnValue({
limit: vi.fn().mockReturnValue({ limit: vi.fn().mockReturnValue({
offset: vi.fn().mockReturnValue(vehicleList) offset: vi.fn().mockReturnValue(vehicleList),
}) }),
}) }),
}) }),
}) }),
});
const { service } = createService({
select: vi.fn().mockReturnValue({
from: vi.fn().mockReturnValue({
innerJoin: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue({
orderBy: vi.fn().mockReturnValue({
limit: vi.fn().mockReturnValue({
offset: vi.fn().mockReturnValue(vehicleList),
}),
}),
}),
}),
}),
}),
}); });
const { service } = createService({select: vi.fn().mockReturnValue({
from: vi.fn().mockReturnValue({
innerJoin: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue({
orderBy: vi.fn().mockReturnValue({
limit: vi.fn().mockReturnValue({
offset: vi.fn().mockReturnValue(vehicleList)
})
})
})
})
})
})});
const result = await service.getHistory("u1", 1, 20); const result = await service.getHistory("u1", 1, 20);
expect(result).toEqual(vehicleList); expect(result).toEqual(vehicleList);

View File

@@ -48,7 +48,7 @@
"locked": "This brand is not in your plan", "locked": "This brand is not in your plan",
"upgradeCta": "Upgrade Plan", "upgradeCta": "Upgrade Plan",
"loadingModels": "Loading models...", "loadingModels": "Loading models...",
"tabSasetr": "Sase.Tr", "tabSasetr": "SASE",
"tabPl24": "Pl24", "tabPl24": "Pl24",
"tabPcat": "Pcat", "tabPcat": "Pcat",
"tabEmex": "Emex", "tabEmex": "Emex",

View File

@@ -48,7 +48,7 @@
"locked": "Bu marka planınızda yok", "locked": "Bu marka planınızda yok",
"upgradeCta": "Planını Yükselt", "upgradeCta": "Planını Yükselt",
"loadingModels": "Modeller yükleniyor...", "loadingModels": "Modeller yükleniyor...",
"tabSasetr": "Sase.Tr", "tabSasetr": "SASE",
"tabPl24": "Pl24", "tabPl24": "Pl24",
"tabPcat": "Pcat", "tabPcat": "Pcat",
"tabEmex": "Emex", "tabEmex": "Emex",

View File

@@ -0,0 +1,115 @@
/**
* Regression tests for landing page VIN decode analytics events.
*
* These tests verify that the correct PostHog events are captured on
* successful VIN decode and on error conditions.
*/
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import { vi } from "vitest";
// Mock the PostHog capture function
vi.mock("@/lib/posthog", () => ({
capture: vi.fn(),
}));
// Mock the API client used for VIN decode
vi.mock("@/lib/api-client", () => ({
api: {
post: vi.fn(),
},
ApiError: class ApiError extends Error {
constructor(message: string, public code?: string, public status?: number) {
super(message);
this.name = "ApiError";
}
},
}));
// Mock the auth store to simulate a loggedin user
vi.mock("@/stores/auth.store", () => {
const actual = vi.importActual("@/stores/auth.store");
return {
...actual,
useAuthStore: {
getState: vi.fn(),
subscribe: vi.fn(() => vi.fn()),
},
};
});
// Mock navigation to avoid real router sideeffects
vi.mock("@tanstack/react-router", async () => {
const actual = await vi.importActual<any>("@tanstack/react-router");
return {
...actual,
useNavigate: () => vi.fn(),
};
});
import { HomePage } from "@/routes/index"; // Exported component
import { capture } from "@/lib/posthog";
import { api, ApiError } from "@/lib/api-client";
import { useAuthStore } from "@/stores/auth.store";
beforeEach(() => {
vi.clearAllMocks();
(useAuthStore.getState as any).mockReturnValue({
user: { id: "user-1" },
isLoading: false,
});
});
test("captures vin_decode_success on successful decode", async () => {
(api.post as any).mockResolvedValue({ id: "test-vehicle-id" });
render(
<BrowserRouter>
<HomePage />
</BrowserRouter>,
);
const input = screen.getByPlaceholderText(/Örnek:/i);
fireEvent.change(input, { target: { value: "WVWZZZ1JZ3W597935" } });
const button = screen.getByRole("button", { name: /Ara/i });
fireEvent.click(button);
await waitFor(() => {
expect(capture).toHaveBeenCalledWith(
"vin_decode_success",
expect.objectContaining({
vin: "WVWZZZ1JZ3W597935",
source: "landing",
vehicle_id: "test-vehicle-id",
}),
);
});
});
test("captures vin_decode_error on API error", async () => {
const error = new ApiError("Invalid VIN", "INVALID", 400);
(api.post as any).mockRejectedValue(error);
render(
<BrowserRouter>
<HomePage />
</BrowserRouter>,
);
const input = screen.getByPlaceholderText(/Örnek:/i);
fireEvent.change(input, { target: { value: "INVALIDVIN1234567" } });
const button = screen.getByRole("button", { name: /Ara/i });
fireEvent.click(button);
await waitFor(async () => {
expect(capture).toHaveBeenCalledWith(
"vin_decode_error",
expect.objectContaining({
vin: "INVALIDVIN1234567",
source: "landing",
error: "Invalid VIN",
}),
);
});
});

View File

@@ -18,9 +18,9 @@ function AuthLayout() {
<div className="flex justify-center pt-6"> <div className="flex justify-center pt-6">
<Link <Link
to="/" to="/"
className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground" className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground tracking-wider"
> >
Sase.tr SASE
</Link> </Link>
</div> </div>
</main> </main>

View File

@@ -18,8 +18,8 @@ function AboutPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -49,8 +49,8 @@ function BlogPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -366,8 +366,8 @@ function BlogPostPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -18,8 +18,8 @@ function ContactPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -272,8 +272,8 @@ function DashboardLayout() {
className={`flex h-16 items-center border-b border-border ${collapsed ? "justify-center px-2" : "justify-between px-4"}`} className={`flex h-16 items-center border-b border-border ${collapsed ? "justify-center px-2" : "justify-between px-4"}`}
> >
{!collapsed && ( {!collapsed && (
<Link to="/" className="text-xl font-bold tracking-tight"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
)} )}
<button <button
@@ -405,7 +405,7 @@ function DashboardLayout() {
/> />
<aside className="absolute left-0 top-0 flex h-full w-64 flex-col bg-background shadow-lg"> <aside className="absolute left-0 top-0 flex h-full w-64 flex-col bg-background shadow-lg">
<div className="flex h-16 items-center justify-between border-b border-border px-4"> <div className="flex h-16 items-center justify-between border-b border-border px-4">
<span className="text-xl font-bold">Sase.tr</span> <span className="text-xl font-bold tracking-wider">SASE</span>
<Button variant="ghost" size="icon" onClick={() => setMobileOpen(false)}> <Button variant="ghost" size="icon" onClick={() => setMobileOpen(false)}>
<X className="size-4" /> <X className="size-4" />
</Button> </Button>

View File

@@ -114,8 +114,8 @@ function DemoPage() {
{/* Header */} {/* Header */}
<header className="sticky top-0 z-50 border-b border-border bg-background/80 backdrop-blur-md"> <header className="sticky top-0 z-50 border-b border-border bg-background/80 backdrop-blur-md">
<div className="mx-auto flex h-16 max-w-5xl items-center justify-between px-4 sm:px-6"> <div className="mx-auto flex h-16 max-w-5xl items-center justify-between px-4 sm:px-6">
<Link to="/" className="text-xl font-bold tracking-tight"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button

View File

@@ -558,8 +558,8 @@ export function HomePage() {
{/* ─── 1. STICKY HEADER ─────────────────────────────────────────── */} {/* ─── 1. STICKY HEADER ─────────────────────────────────────────── */}
<header className="sticky top-0 z-50 border-b border-border bg-background/80 backdrop-blur-md"> <header className="sticky top-0 z-50 border-b border-border bg-background/80 backdrop-blur-md">
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6"> <div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6">
<Link to="/" className="text-xl font-bold tracking-tight"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
{/* Desktop nav */} {/* Desktop nav */}

View File

@@ -10,8 +10,8 @@ function KvkkPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -71,8 +71,8 @@ function PricingPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -10,8 +10,8 @@ function PrivacyPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -10,8 +10,8 @@ function TermsPage() {
<div className="min-h-screen"> <div className="min-h-screen">
<header className="border-b"> <header className="border-b">
<div className="container mx-auto flex h-16 items-center justify-between px-4"> <div className="container mx-auto flex h-16 items-center justify-between px-4">
<Link to="/" className="text-xl font-bold"> <Link to="/" className="text-xl font-bold tracking-wider">
Sase.tr SASE
</Link> </Link>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link to="/login"> <Link to="/login">

View File

@@ -18,5 +18,5 @@
} }
}, },
"include": ["src", "vite-env.d.ts"], "include": ["src", "vite-env.d.ts"],
"exclude": ["node_modules", "dist"] "exclude": ["node_modules", "dist", "**/__tests__/**", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"]
} }