Files
mechanic-pwa/driver-pwa/frontend/src/App.tsx
T
tremble7681andClaude Opus 5 f4a9da25cf feat(pwa): экран штрафов с фотографиями нарушений
Список с вкладками «Неоплаченные / Все» и суммой долга в шапке; в карточке —
фотография с камеры первой, до реквизитов: по ней водитель узнаёт свою машину и
свою поездку. Дальше сумма, скидка с датой (то, ради чего заходят вовремя),
скорость и разрешённый предел, постановление, камера, ссылка на PDF.

Строка «Долг по штрафам» на главном экране теперь ведёт сюда, а не сразу к
оплате: платить, не поняв за что, человек не станет. Аренда по-прежнему ведёт к
оплате — за тем её и открывают.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 17:18:58 +10:00

57 lines
3.0 KiB
TypeScript

import type { ReactNode } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { useAuth } from "@/store/auth";
import { useStaff } from "@/store/staff";
import { ImpersonationBar } from "@/components/ImpersonationBar";
import { LoginPage } from "@/pages/LoginPage";
import { TgWaitPage } from "@/pages/TgWaitPage";
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";
import { DevLoginPage } from "@/pages/DevLoginPage";
import { DebugPage } from "@/pages/DebugPage";
import { MockPayPage } from "@/pages/MockPayPage";
import { FinesPage } from "@/pages/FinesPage";
import { FineDetailPage } from "@/pages/FineDetailPage";
function RequireAuth({ children }: { children: ReactNode }) {
const token = useAuth((s) => s.token);
return token ? <>{children}</> : <Navigate to="/login" replace />;
}
/** Отладка существует только для сотрудника: либо он вошёл учёткой CRM, либо
* прямо сейчас смотрит от лица водителя. Обычному водителю адрес /debug ничего
* не даёт — его уводит на главную. */
function RequireStaff({ children }: { children: ReactNode }) {
const impersonated = useAuth((s) => s.impersonated);
const staffToken = useStaff((s) => s.token);
return impersonated || staffToken ? <>{children}</> : <Navigate to="/" replace />;
}
export default function App() {
return (
<div className="mx-auto max-w-md min-h-full px-4 pt-3 pb-8">
{/* Плашка живёт над маршрутами: чей экран открыт, видно на каждом из них,
а не только там, где про неё вспомнили. Сама решает, показываться ли. */}
<ImpersonationBar />
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/dev" element={<DevLoginPage />} />
<Route path="/tg-wait" element={<TgWaitPage />} />
<Route path="/onboarding" element={<OnboardingPage />} />
<Route path="/" element={<RequireAuth><BalancePage /></RequireAuth>} />
<Route path="/topup" element={<RequireAuth><TopupPage /></RequireAuth>} />
<Route path="/pay/:orderId" element={<RequireAuth><PaymentPage /></RequireAuth>} />
<Route path="/mock-pay/:orderId" element={<RequireAuth><MockPayPage /></RequireAuth>} />
<Route path="/history" element={<RequireAuth><HistoryPage /></RequireAuth>} />
<Route path="/fines" element={<RequireAuth><FinesPage /></RequireAuth>} />
<Route path="/fines/:fineId" element={<RequireAuth><FineDetailPage /></RequireAuth>} />
<Route path="/debug" element={<RequireAuth><RequireStaff><DebugPage /></RequireStaff></RequireAuth>} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</div>
);
}