diff --git a/driver-pwa/frontend/src/App.test.tsx b/driver-pwa/frontend/src/App.test.tsx
new file mode 100644
index 0000000..db011f2
--- /dev/null
+++ b/driver-pwa/frontend/src/App.test.tsx
@@ -0,0 +1,25 @@
+import { describe, it, expect, beforeEach } from "vitest";
+import { render, screen } from "@testing-library/react";
+import { MemoryRouter } from "react-router-dom";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import App from "./App";
+import { useAuth } from "@/store/auth";
+
+function renderAt(path: string) {
+ const qc = new QueryClient();
+ return render(
+
+
+
+
+
+ );
+}
+
+describe("routing guard", () => {
+ beforeEach(() => useAuth.getState().clear());
+ it("redirects to login when no token", () => {
+ renderAt("/");
+ expect(screen.getByText(/Вход в приложение/i)).toBeInTheDocument();
+ });
+});
diff --git a/driver-pwa/frontend/src/App.tsx b/driver-pwa/frontend/src/App.tsx
index 1bdfc74..d0b4dc0 100644
--- a/driver-pwa/frontend/src/App.tsx
+++ b/driver-pwa/frontend/src/App.tsx
@@ -1,3 +1,30 @@
+import type { ReactNode } from "react";
+import { Navigate, Route, Routes } from "react-router-dom";
+import { useAuth } from "@/store/auth";
+import { LoginPage } from "@/pages/LoginPage";
+import { OnboardingPage } from "@/pages/OnboardingPage";
+import { BalancePage } from "@/pages/BalancePage";
+import { TopupPage } from "@/pages/TopupPage";
+import { PaymentPage } from "@/pages/PaymentPage";
+import { HistoryPage } from "@/pages/HistoryPage";
+
+function RequireAuth({ children }: { children: ReactNode }) {
+ const token = useAuth((s) => s.token);
+ return token ? <>{children}> : ;
+}
+
export default function App() {
- return
Премиум Водитель
;
+ return (
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+ );
}
diff --git a/driver-pwa/frontend/src/components/AppHeader.tsx b/driver-pwa/frontend/src/components/AppHeader.tsx
new file mode 100644
index 0000000..1752530
--- /dev/null
+++ b/driver-pwa/frontend/src/components/AppHeader.tsx
@@ -0,0 +1,12 @@
+export function AppHeader({ initials }: { initials?: string }) {
+ return (
+
+ Премиум Водитель
+ {initials && (
+
+ {initials}
+
+ )}
+
+ );
+}
diff --git a/driver-pwa/frontend/src/components/Segment.tsx b/driver-pwa/frontend/src/components/Segment.tsx
new file mode 100644
index 0000000..633b095
--- /dev/null
+++ b/driver-pwa/frontend/src/components/Segment.tsx
@@ -0,0 +1,19 @@
+interface Props { value: string; options: { value: string; label: string }[]; onChange: (v: string) => void; }
+export function Segment({ value, options, onChange }: Props) {
+ return (
+
+ {options.map((o) => (
+
+ ))}
+
+ );
+}
diff --git a/driver-pwa/frontend/src/components/Spinner.tsx b/driver-pwa/frontend/src/components/Spinner.tsx
new file mode 100644
index 0000000..a4ae38e
--- /dev/null
+++ b/driver-pwa/frontend/src/components/Spinner.tsx
@@ -0,0 +1,3 @@
+export function Spinner() {
+ return ;
+}
diff --git a/driver-pwa/frontend/src/pages/BalancePage.tsx b/driver-pwa/frontend/src/pages/BalancePage.tsx
new file mode 100644
index 0000000..0ceefa4
--- /dev/null
+++ b/driver-pwa/frontend/src/pages/BalancePage.tsx
@@ -0,0 +1 @@
+export function BalancePage() { return null; }
diff --git a/driver-pwa/frontend/src/pages/HistoryPage.tsx b/driver-pwa/frontend/src/pages/HistoryPage.tsx
new file mode 100644
index 0000000..e963843
--- /dev/null
+++ b/driver-pwa/frontend/src/pages/HistoryPage.tsx
@@ -0,0 +1 @@
+export function HistoryPage() { return null; }
diff --git a/driver-pwa/frontend/src/pages/LoginPage.tsx b/driver-pwa/frontend/src/pages/LoginPage.tsx
new file mode 100644
index 0000000..363dac5
--- /dev/null
+++ b/driver-pwa/frontend/src/pages/LoginPage.tsx
@@ -0,0 +1,3 @@
+export function LoginPage() {
+ return Вход в приложение
;
+}
diff --git a/driver-pwa/frontend/src/pages/OnboardingPage.tsx b/driver-pwa/frontend/src/pages/OnboardingPage.tsx
new file mode 100644
index 0000000..ea25e3f
--- /dev/null
+++ b/driver-pwa/frontend/src/pages/OnboardingPage.tsx
@@ -0,0 +1 @@
+export function OnboardingPage() { return null; }
diff --git a/driver-pwa/frontend/src/pages/PaymentPage.tsx b/driver-pwa/frontend/src/pages/PaymentPage.tsx
new file mode 100644
index 0000000..c093dad
--- /dev/null
+++ b/driver-pwa/frontend/src/pages/PaymentPage.tsx
@@ -0,0 +1 @@
+export function PaymentPage() { return null; }
diff --git a/driver-pwa/frontend/src/pages/TopupPage.tsx b/driver-pwa/frontend/src/pages/TopupPage.tsx
new file mode 100644
index 0000000..5e3b567
--- /dev/null
+++ b/driver-pwa/frontend/src/pages/TopupPage.tsx
@@ -0,0 +1 @@
+export function TopupPage() { return null; }