---
description: Rules for working with the Telegram Mini App frontend (webapp-next/)
globs:
  - webapp-next/**
---

# Frontend — Telegram Mini App (Next.js)

The Mini App lives in `webapp-next/`. It is built as a static export and served by FastAPI at `/app`.

## Stack

- **Next.js** (App Router, `output: 'export'`, `basePath: '/app'`)
- **TypeScript**
- **Tailwind CSS** — theme extended with custom tokens (surface, muted, accent, duty, today, etc.)
- **shadcn/ui** — Button, Card, Sheet, Popover, Tooltip, Skeleton, Badge
- **Zustand** — app store (month, lang, duties, calendar events, loading, view state)
- **@telegram-apps/sdk-react** — SDKProvider, useThemeParams, useLaunchParams, useMiniApp, useBackButton

## Structure

| Area | Location |
|------|----------|
| App entry, layout | `src/app/layout.tsx`, `src/app/page.tsx` |
| Providers | `src/components/providers/TelegramProvider.tsx` |
| Calendar | `src/components/calendar/` — CalendarHeader, CalendarGrid, CalendarDay, DayIndicators |
| Duty list | `src/components/duty/` — DutyList, DutyTimelineCard, DutyItem |
| Day detail | `src/components/day-detail/` — DayDetail (Sheet/Popover), DayDetailContent |
| Current duty view | `src/components/current-duty/CurrentDutyView.tsx` |
| Admin | `src/components/admin/` — useAdminPage, AdminDutyList, ReassignSheet |
| Contact links | `src/components/contact/ContactLinks.tsx` |
| State views | `src/components/states/` — LoadingState, ErrorState, AccessDenied |
| Hooks | `src/hooks/` — use-telegram-theme, use-telegram-auth, use-month-data, use-swipe, use-media-query, use-sticky-scroll, use-auto-refresh |
| Lib | `src/lib/` — api, calendar-data, date-utils, phone-format, constants, utils |
| i18n | `src/i18n/` — messages.ts, use-translation.ts |
| Store | `src/store/app-store.ts` |
| Types | `src/types/index.ts` |

## Conventions

- **Client components:** Use `'use client'` where hooks or browser APIs are used (layout loads config script; page and most UI are client).
- **Theme:** CSS variables in `globals.css`; `useTelegramTheme` maps Telegram theme params to `--tg-theme-*` and sets `data-theme` on `<html>`.
- **Auth:** `useTelegramAuth` provides initData for API; access gated for non-Telegram except localhost.
- **i18n:** `useTranslation()` from store lang; `window.__DT_LANG` set by `/app/config.js` (backend).
- **API:** `fetchDuties`, `fetchCalendarEvents` in `src/lib/api.ts`; pass initData, lang, AbortSignal; handle ACCESS_DENIED.
- **Heavy pages:** For feature-heavy routes (e.g. admin), use a custom hook (state, effects, callbacks) plus presentational components; keep the page as a thin layer (early returns + composition). Example: `admin/page.tsx` uses `useAdminPage`, `AdminDutyList`, and `ReassignSheet`.

## Testing

- **Runner:** Vitest in `webapp-next/`; environment: jsdom; React Testing Library.
- **Config:** `webapp-next/vitest.config.ts`; setup in `src/test/setup.ts`.
- **Run:** `cd webapp-next && npm test` (or `npm run test`). Build: `npm run build`.
- **Coverage:** Unit tests for lib (api, date-utils, calendar-data, i18n, etc.) and component tests for calendar, duty list, day detail, current duty, states.

## Design guideline

When adding or changing UI in the Mini App, **follow the [Mini App design guideline](../../docs/miniapp-design.md)**:

- Use only design tokens from `globals.css` and Tailwind/shadcn aliases (no hardcoded colours).
- Page wrappers: `content-safe`, `max-w-[var(--max-width-app)]`, viewport height; respect safe area for sheets/modals.
- Reuse component patterns (buttons, cards, calendar grid, timeline list) and left-stripe semantics (`border-l-duty`, `border-l-today`, etc.).
- Add ARIA labels and roles for interactive elements and grids; respect `prefers-reduced-motion` and `data-perf="low"` for animations.

Use the checklist in the design doc when introducing new screens or components.

Consider these rules when changing the Mini App or adding frontend features.
