# Task 04 — Vihar Allocate Step

Step 2 of vihar creation: captain picks volunteers from the city pool.
Multi-select with filters and sort.

## File to create

```
apps/web/src/app/captain/vihars/[id]/allocate/page.tsx
```

## Layout

- Top: vihar summary banner — date, time, head saint, route. Read-only.
- Filters row: locality multi-select dropdown, search input by name/phone.
- Sort dropdown: "Name A–Z" / "Most experienced" / "Fewest vihars this month"
- Volunteer list: each row has avatar (initials), name, locality chip,
  lifetime vihar count, this-month count. Tap to toggle select. Selected rows
  have a saffron checkmark and saffron-tinted background.
- Sticky footer: "X volunteers selected" + buttons "← Back" / "Save & Share"

## Data sources

- Vihar: `GET /api/vihars/{id}`
- Volunteers: `GET /api/users?role=volunteer&isActive=true&pageSize=100`
- Localities: `GET /api/localities` (cached via React Query)

## Conflict warning

For each volunteer being considered, fetch their existing same-day
allocations:
```
GET /api/vihars?date=YYYY-MM-DD&page=1&pageSize=100
```
Cross-reference allocations. If a volunteer is on a vihar that overlaps
in time (start within ±2 hours of the current vihar's start), show a
small amber warning chip: "Already on another vihar at 5:30 AM". Don't
block selection — captain decides.

## Submit

On "Save & Share":
1. POST `/api/vihars/{id}/allocations` with `{ userIds: [1, 2, 5] }`.
2. On success, navigate to `/captain/vihars/{id}/share` (Task 05).

## UI notes

- The volunteer list can be 300+ rows. Use a virtualized list ONLY if
  performance suffers (try without first; modern phones handle 300 rows fine).
- Search is client-side filter on the loaded list — no server round-trip per
  keystroke.
- Sort happens client-side on the loaded list.
- "Most experienced" sort = lifetime vihar count desc.
- "Fewest vihars this month" sort = current-month vihar count asc.

## Acceptance

1. Navigate to allocate page after creating a vihar.
2. See the vihar summary banner.
3. Filter by locality — list shrinks.
4. Search "raj" — list shrinks further.
5. Sort by "Most experienced" — order changes.
6. Tap 3 volunteers — count in footer says "3 selected".
7. Submit — POST fires, navigate to share sheet.
8. Pick a volunteer who's already on another same-day vihar — see conflict chip.

## Gotchas

- Selection state is local component state; doesn't persist if user navigates
  away. That's fine for Phase 1.
- The lifetime/this-month counts come from `/api/users` response — make sure
  the users service includes them. If not, add to the `select` clause in
  `apps/api/src/modules/users/users.service.ts` `list()` method:
  ```
  _count: {
    select: {
      allocations: { where: { isActive: true, vihar: { status: { in: ['completed', 'auto_closed'] } } } }
    }
  }
  ```
- Empty `userIds` should not be allowed. Disable submit when zero selected.
- After allocate POST succeeds, also kick off the WhatsApp message URL fetch
  in the background so the share screen is instant.

## Out of scope

- Auto-suggesting volunteers based on locality proximity — Phase 2
- Volunteer accept/decline flow — Phase 2
- Sending invite immediately on allocation — captain shares manually via Task 05
