Files
sase.tr/apps/web/src/routes/__root.tsx
Sase Dev f2126754a6 feat: add OEM code copy tracking, PostHog analytics, Postal email integration
- Add oem_code_copies table and analytics module for tracking part code copies
- Integrate PostHog for frontend product analytics (VIN decode, OEM copy events)
- Switch email service from stub to Postal API with proper error handling
- Add copy button to parts panel with clipboard + server-side logging
- Add admin copy-logs page with filtering and top-copied-codes view
- Add VIN report endpoint for users to flag unrecognized chassis numbers
- Add Postal email env vars to config schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:09:07 +00:00

67 lines
1.7 KiB
TypeScript

import { createRootRouteWithContext, Outlet, useLocation } from "@tanstack/react-router";
import { Toaster } from "@/lib/toast";
import type { QueryClient } from "@tanstack/react-query";
import { useEffect } from "react";
import { getUserSettings } from "@/lib/user-settings";
import { capturePageView, identifyUser, resetUser } from "@/lib/posthog";
import { useAuth } from "@/hooks/use-auth";
interface RouterContext {
queryClient: QueryClient;
}
export const Route = createRootRouteWithContext<RouterContext>()({
component: RootComponent,
});
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?.id]);
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 (
<>
<Outlet />
<Toaster position="top-center" />
</>
);
}