# Yaltopia Tickets App — Agent Guide

## First Read

Read these before writing any code:
- `app/_layout.tsx` — root stack, guards, heartbeat, fonts, theme
- `lib/api.ts` — API services & endpoint definitions
- `lib/api-middlewares.ts` — auth injection + token refresh logic
- `lib/routes.ts` — all route definitions with guard metadata
- `lib/auth-store.ts` — zustand persisted auth state

## Commands

```
npm run start       # expo start
npm run android     # expo run:android
npm run ios         # expo run:ios
npm run web         # expo start --web
```

No lint, typecheck, or test scripts exist. No `postinstall` hook beyond `patch-package`.

## Project Structure

- **`app/`** — expo-router file-based screens; entry point is `expo-router/entry` (set in `package.json` `main`)
- **`app/(tabs)/`** — 5 bottom tabs: index (Home), payments, scan, proforma, news
- **`lib/`** — API client (`api.ts`), middleware (`api-middlewares.ts`), stores, guards, routes, permissions, theme, utils
- **`components/`** — shared UI; `components/ui/` has shadcn-style primitives (button, text, card)
- **Path alias**: `@/` → project root (tsconfig paths)

## Key Conventions

- **Navigating**: `useSirouRouter<AppRoutes>().go("routeName", { params })` — NOT expo-router's `router.push`. Import `AppRoutes` from `@/lib/routes`.
- **API calls**: Use the `@simple-api` client (`api.{service}.{endpoint}({ body, params, query, headers })`). For file uploads (scan), use raw `fetch` with FormData.
- **Auth tokens**: Never manually inject Bearer. `authMiddleware` does it automatically + proactively refreshes near-expiry tokens via `refreshTokens()` singleton promise.
- **Phone numbers**: Ethiopian `+251` is auto-prepended. Input fields accept the 9-digit number without prefix.
- **Toast**: `import { toast } from "@/lib/toast-store"` then `toast.success("Title", "Message")`, `.error()`, `.warning()`, `.info()`.
- **Form screens** use inline `StyleSheet.create` for input styles and `useInputColors()` custom hook for theming. No form validation library.

## UI Patterns (look at existing screens)

- **Tab bar**: Floating pill, `absolute`, `bottom: 25`, `marginHorizontal: 20`, `borderRadius: 32` (see `app/(tabs)/_layout.tsx`)
- **Primary color**: `#ea580c` (orange) — used as `text-primary`, `bg-primary`, `color="#ea580c"`
- **Cards**: `<Card>` + `<CardContent>` from `@/components/ui/card`, often wrapped in `<ShadowWrapper level="xs">`
- **Text**: `<Text variant="h1|h2|h3|h4|p|muted|small">` from `@/components/ui/text`
- **Buttons**: `<Button variant="default|outline|destructive|ghost|secondary" size="default|sm|lg|icon">`
- **Status badges**: `text-[9px] font-semibold uppercase tracking-widest` with semi-transparent bg
- **Section labels**: `font-bold text-xs uppercase tracking-widest`
- **Filter pills**: `rounded-[4px] px-4 py-1.5`
- **Bottom sheet pickers**: `<PickerModal>` + `<SelectOption>` from `@/components/PickerModal`
- **Confirmation modals**: `<ActionModal>` from `@/components/ActionModal`
- **Empty states**: `<EmptyState>` with `previewLines`, `actionLabel`, `onActionPress`
- **No gradients** anywhere (enforced by AGENTS.md). Use solid colors.

## State Stores (zustand)

| Store | File | Persisted? | Key |
|---|---|---|---|
| `useAuthStore` | `lib/auth-store.ts` | Yes (AsyncStorage) | `yaltopia-auth-storage` |
| `useLanguageStore` | `lib/language-store.ts` | Yes (AsyncStorage) | `app-language` |
| `useToast` | `lib/toast-store.ts` | No | — |

Theme is persisted via `saveTheme()`/`loadTheme()` in `lib/theme.ts` using AsyncStorage key `app_theme_preference`. Not a zustand store.

## API Endpoints (lib/api.ts)

`BASE_URL = https://api.yaltopiaticket.com/`

Services: `auth`, `invoices`, `payments`, `proforma`, `scan`, `users`, `company`, `news`, `notifications`, `rbac`, `support`, `faq`

Middleware pipeline: logger → transformer → refresh (401 retry) → auth (Bear token + proactive refresh)

## Route Guards (@sirou)

Routes are defined in `lib/routes.ts` with guards metadata (strings `"auth"` or `"guest"`). Guards are pure functions in `lib/auth-guards.ts`. `GlobalGuard` in `app/_layout.tsx` runs supplementary auth/guest checks.

## Scan Flow

Camera → capture → preview → press "Extract" → raw `fetch` POST to `/scan/invoice` or `/scan/payment-receipt` with FormData → parse OCR result → `api.invoices.create()` with mapped data → navigate to detail.

## Notes

- **Google Sign-In** is lazy-loaded in a try/catch block — native module may not be available in Expo Go.
- **SMS scanning** (`react-native-get-sms-android`) is Android-only and also lazy-loaded.
- **No local database** — pure API-consumed app.
- RBAC permissions in `lib/permissions.ts` — roles: ADMIN, BUSINESS_OWNER, EMPLOYEE, ACCOUNTANT, CUSTOMER_SERVICE, AUDITOR, VIEWER.
- CSS variables in `global.css` power NativeWind theme. `darkMode: "class"` in tailwind config.

## Design Context

Before any UI work, read these two files for design strategy + visual system:
- **`PRODUCT.md`** — register, users, brand personality, design principles, anti-references
- **`DESIGN.md`** — colors, typography, components, elevation, do's and don'ts
- **`.impeccable/design.json`** — machine-readable design tokens with tonal ramps and component snippets

Key rules:
- Primary orange `#E46212` on ≤20% of surfaces. Flat-by-default (no shadows on cards/buttons). One typeface (DM Sans, weight creates hierarchy). True white backgrounds, not tinted.

## UI Build Process

When building UI, ALWAYS use both skills together:
1. **yimpeccable** (`.agents/skills/yimpeccable/`) — run `$impeccable <command>` per its reference. Provides design guidance, register context, color/typography/layout rules.
2. **ui-ux-pro-max** (`.opencode/skills/ui-ux-pro-max/`) — run `python3 .opencode/skills/ui-ux-pro-max/scripts/search.py "<query>" --design-system` or domain-specific searches. Provides design system recommendations, color palettes, font pairings, UX guidelines.

Always load both skill files and follow their workflows on any UI task.
