# CoProp Survey Progress — Frontend Integration Notes

The surveyor mobile app surfaces progress in two levels: a **summary list** of sites (which sites have been started and how far along), and a **detail view** per site-service (which lots are done, which are missing).

All responses follow `{ status, message, data }`. All dates are ISO-8601 UTC strings — convert to the tenant timezone for display using the `timezone` preference from the login response.

---

## Level 1 — Summary: sites × services

### `GET /co-prop`

Auth: Surveyor JWT.  
No query parameters.

Returns every (site, service type) pair where the authenticated surveyor has recorded **at least one reading in the current cycle**. The surveyor is used only to identify *which sites are relevant* — the counts reflect the **full site progress across all surveyors**, not just the authenticated one.

```json
{
  "status": true,
  "message": "CoProp Lists",
  "data": [
    {
      "id": 3,
      "name": "Block A",
      "fullname": "Block A — Résidence Belle Vue",
      "service_provider_id": 1,
      "open_site_service": [
        {
          "id": 7,
          "site_id": 3,
          "service_type_id": 1,
          "status": "active",
          "ServiceType": { "id": 1, "service_name": "Water" },
          "completed_count": 14,
          "total_count": 20
        }
      ]
    }
  ]
}
```

#### Key fields

| Field | Notes |
|---|---|
| `open_site_service` | Only services where **any** surveyor has at least one reading. Services not yet started are omitted. |
| `completed_count` | Lots recorded across **all surveyors** for this site + service type. |
| `total_count` | Total lots configured for this site + service type. |
| `SiteService` | **Ignore** — this key may appear in the raw response as a serialisation artefact from an earlier version. Use `open_site_service` exclusively. Will be removed in a future cleanup. |

#### Progress bar

```
progress = completed_count / total_count    // e.g. 14 / 20 = 70%
```

If `completed_count === total_count` the site-service is complete — offer the "close session" / billing flow.

---

## Level 2 — Detail: lots for a site-service

### `GET /lots?site_id={id}&service_type_id={id}`

Auth: Surveyor JWT.  
Required query params: `site_id` (integer), `service_type_id` (integer).

Returns completed lots (those with a reading in the current cycle) and the missing lots (those without one), in a single response. Use this to render the two-section detail view on tap.

```json
{
  "status": true,
  "message": "Lots Lists",
  "data": {
    "lotsList": {
      "current_page": 1,
      "data": [
        {
          "id": 42,
          "lot_no": "A-01",
          "previous_unit": 1200,
          "current_unit": 1387,
          "meter_image_upload_status": "uploaded",
          "survey_start_date": "2026-06-17T08:30:00.000000Z",
          "barcode": { "barcode": "METER-001" },
          "Lot": { "lot_no": "A-01" }
        }
      ],
      "per_page": 20,
      "total": 14,
      "last_page": 1,
      "next_page_url": null
    },
    "incompleteLots": [
      { "lot_no": "A-06" },
      { "lot_no": "A-07" }
    ],
    "incompleteLotsBarcodes": [
      { "lot_no": "A-06", "barcode": "METER-006" },
      { "lot_no": "A-07", "barcode": "METER-007" }
    ]
  }
}
```

#### Sections to render

**Completed** (`data.lotsList.data`) — paginated. Each row shows lot number, previous unit, current reading, and optionally the meter photo.

**Missing** (`data.incompleteLotsBarcodes`) — not paginated. Each entry gives `lot_no` and `barcode`. Tapping a missing lot should launch the reading flow pre-filled with that barcode.

#### `meter_image_upload_status`

| Value | Meaning | UI hint |
|---|---|---|
| `pending` | Reading saved; photo queued for upload | Show a spinner / "syncing" badge |
| `uploaded` | Photo on Dropbox; signed URL available | Show photo normally |
| `failed` | Upload failed after all retries | Show warning; retry option if available |

Photo is not available for signed-URL display until status is `uploaded`. Poll or rely on a push notification to update the status without blocking the surveyor.

#### Pagination

`lotsList` is paginated (`DEFAULT_PAGE` items per page, typically 20). Use `next_page_url` to fetch subsequent pages if `last_page > 1`. Append the same `site_id` and `service_type_id` params.

#### Survey date display

`survey_start_date` is stored in UTC. Display it in the tenant timezone:

```dart
// Flutter example
final utc = DateTime.parse(session['survey_start_date']); // already UTC
final local = utc.toLocal(); // or use the timezone package with preferences['timezone']
```

---

## Pending backend changes that affect this flow

These are known issues being addressed in a separate backend task:

1. **`completed_count` is currently scoped to the authenticated surveyor only.** The fix (in progress) will remove that filter so it reflects all surveyors. Until deployed, `completed_count` will undercount on sites shared between surveyors.

2. **`SiteService` key in the Level 1 response** leaks unfiltered service data. Ignore it; use `open_site_service` only.

---

## Flow diagram

```
Login → store preferences (timezone, date_format, etc.)
         │
         ▼
GET /co-prop
  ├─ for each site in data[]
  │    show: site.name
  │          open_site_service[].ServiceType.service_name
  │          completed_count / total_count  → progress bar
  │
  └─ tap a site-service row
         │
         ▼
    GET /lots?site_id=X&service_type_id=Y
      ├─ Section "Completed" → data.lotsList.data
      │    show: lot_no, previous_unit → current_unit, survey_start_date (tenant tz)
      │          meter_image_upload_status badge
      │
      └─ Section "Missing" → data.incompleteLotsBarcodes
           show: lot_no, barcode
           tap → reading flow (pre-fill barcode, POST /reading-unit)
```
