# Site Preferences API

Allows an admin user to choose which sites appear across their views. This is a **convenience filter, not a permission system** — it only affects what the authenticated user sees for themselves.

All responses follow the shape `{ status, message, data }`.

---

## Overview

By default, an admin sees **no sites** until they save a preference. The typical integration flow is:

1. On first load (or empty state), call **`GET /all-sites`** to fetch every available site in the tenant.
2. Show the user a multi-select picker.
3. When they confirm their selection, call **`PUT /user/site-preferences`** with the chosen IDs.
4. All subsequent API calls that return sites (sessions, reports, dashboards) will automatically reflect the selection — no extra filtering needed on the frontend.

To let the user change their selection later, open the picker again pre-populated from **`GET /user/site-preferences`**.

---

## Authentication

All endpoints require a valid JWT token in the `Authorization` header.

```
Authorization: Bearer <token>
```

These endpoints are scoped to the **Admin role (role_id: 2)** only.

---

## Endpoints

### 1. Get all sites (for the picker)

Returns every active site in the tenant, **ignoring** the user's saved preferences. Use this to populate the site selector UI.

```
GET /all-sites
```

#### Response `200`

```json
{
  "status": true,
  "message": "All sites",
  "data": [
    { "id": 1, "name": "SITE-A", "fullname": "Site Alpha" },
    { "id": 2, "name": "SITE-B", "fullname": "Site Beta" },
    { "id": 3, "name": "SITE-C", "fullname": "Site Charlie" }
  ]
}
```

> **Note:** Results are ordered alphabetically by `name`. Soft-deleted sites are excluded.

---

### 2. Get current preferences

Returns the sites the authenticated user has currently selected. Returns an **empty `data` array** if no preferences have been saved yet.

```
GET /user/site-preferences
```

#### Response `200` — preferences saved

```json
{
  "status": true,
  "message": "Site preferences",
  "data": [
    { "id": 1, "name": "SITE-A", "fullname": "Site Alpha" },
    { "id": 3, "name": "SITE-C", "fullname": "Site Charlie" }
  ]
}
```

#### Response `200` — no preferences saved yet

```json
{
  "status": true,
  "message": "Site preferences",
  "data": []
}
```

> Use this endpoint to pre-populate the picker when the user reopens it.

---

### 3. Update preferences

Replaces the user's entire site selection. The response returns the updated preference list (same shape as `GET /user/site-preferences`).

```
PUT /user/site-preferences
Content-Type: application/json
```

#### Request body

```json
{
  "site_ids": [1, 3]
}
```

| Field | Type | Required | Notes |
|---|---|---|---|
| `site_ids` | `integer[]` | Yes | Array of site IDs. Must all belong to the user's tenant. Pass `[]` to clear all preferences. |

#### Response `200` — success

```json
{
  "status": true,
  "message": "Site preferences",
  "data": [
    { "id": 1, "name": "SITE-A", "fullname": "Site Alpha" },
    { "id": 3, "name": "SITE-C", "fullname": "Site Charlie" }
  ]
}
```

#### Response `400` — invalid site IDs

```json
{
  "status": false,
  "message": "One or more sites are invalid"
}
```

#### Response `422` — validation failure

```json
{
  "message": "The site_ids field must be present.",
  "errors": {
    "site_ids": ["The site_ids field must be present."]
  }
}
```

#### Clearing all preferences

Pass an empty array to remove all preferences. The user will see **nothing** until they select sites again.

```json
{
  "site_ids": []
}
```

---

## Empty state behaviour

| User state | What they see |
|---|---|
| No preferences saved | No sites (empty lists, zero counts) |
| Preferences saved | Only their selected sites |
| Admin clears all (`site_ids: []`) | No sites again until they re-select |

**Recommended UX:** When `GET /user/site-preferences` returns an empty `data` array, redirect the user to the site selector before showing any data views. This avoids confusing empty states.

---

## Integration example (JavaScript)

```js
const BASE = '/api';
const headers = {
  'Authorization': `Bearer ${token}`,
  'Content-Type': 'application/json',
};

// Load all available sites for the picker
async function fetchAllSites() {
  const res = await fetch(`${BASE}/all-sites`, { headers });
  const { data } = await res.json();
  return data; // [{ id, name, fullname }, ...]
}

// Load current selection to pre-populate the picker
async function fetchPreferences() {
  const res = await fetch(`${BASE}/user/site-preferences`, { headers });
  const { data } = await res.json();
  return data; // [{ id, name, fullname }, ...] or []
}

// Save the user's selection
async function savePreferences(siteIds = []) {
  const res = await fetch(`${BASE}/user/site-preferences`, {
    method: 'PUT',
    headers,
    body: JSON.stringify({ site_ids: siteIds }),
  });
  return res.json(); // { status, message, data }
}
```

---

## Error responses

All endpoints share these common error responses.

| Status | Meaning |
|---|---|
| `401` | Missing or invalid JWT token |
| `403` | Authenticated user is not an Admin (role 2) |
| `422` | Request body failed validation |
| `500` | Unexpected server error — `message` will contain detail |

```json
{
  "status": false,
  "message": "<error detail>"
}
```

---

## Superadmin support endpoints

These endpoints are only accessible to Superadmin users (role_id: 1) and are intended for support purposes only — not part of the normal user-facing flow.

### View a user's preferences

```
GET /user-site-preferences?user_id=42
```

#### Response `200`

```json
{
  "status": true,
  "message": "User site preferences",
  "data": {
    "user_id": 42,
    "user_name": "Jane Admin",
    "has_preferences": true,
    "sites": [
      { "id": 1, "name": "SITE-A", "fullname": "Site Alpha" }
    ]
  }
}
```

### View all sites for a tenant (unscoped)

```
GET /all-sites?service_provider_id=5
```

#### Response `200`

```json
{
  "status": true,
  "message": "All sites",
  "data": [
    { "id": 1, "name": "SITE-A", "fullname": "Site Alpha" },
    { "id": 2, "name": "SITE-B", "fullname": "Site Beta" }
  ]
}
```
