feat(pwa): экран штрафов с фотографиями нарушений

Список с вкладками «Неоплаченные / Все» и суммой долга в шапке; в карточке —
фотография с камеры первой, до реквизитов: по ней водитель узнаёт свою машину и
свою поездку. Дальше сумма, скидка с датой (то, ради чего заходят вовремя),
скорость и разрешённый предел, постановление, камера, ссылка на PDF.

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 17:18:58 +10:00
co-authored by Claude Opus 5
parent 9187b5766e
commit f4a9da25cf
7 changed files with 375 additions and 5 deletions
@@ -38,6 +38,7 @@ function wrap() {
<Routes>
<Route path="/" element={<BalancePage />} />
<Route path="/topup" element={<p>экран пополнения</p>} />
<Route path="/fines" element={<p>экран штрафов</p>} />
</Routes>
</MemoryRouter>
</QueryClientProvider>
@@ -79,10 +80,16 @@ describe("главный экран", () => {
expect(screen.queryByText("Страховка")).not.toBeInTheDocument();
});
it("нажатие на строку долга ведёт сразу к оплате этой статьи", async () => {
it("аренда ведёт к оплате, а штрафы — в свой список", async () => {
wrap();
await userEvent.click(await screen.findByRole("button", { name: /Долг аренда/ }));
expect(await screen.findByText("экран пополнения")).toBeInTheDocument();
});
it("строка штрафов открывает список, а не оплату: «за что» важнее кнопки", async () => {
wrap();
await userEvent.click(await screen.findByRole("button", { name: /Долг по штрафам/ }));
expect(await screen.findByText("экран пополнения")).toBeInTheDocument();
expect(await screen.findByText("экран штрафов")).toBeInTheDocument();
});
it("категории для выбора живут в шторке «Пополнить»", async () => {