# Staff API

## Create Staff

`POST /api/staff`

Create a new staff profile.

### Headers
- `Authorization: Bearer <token>`
- `Content-Type: multipart/form-data`

### Body (multipart/form-data)

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Staff name |
| role | string | Yes | One of: `Founder`, `Doctor`, `Both` |
| title | string | Yes | e.g. `Dr.`, `Prof.` |
| qualifications | string[] | No | Array of qualifications |
| biography | string | No | Biography text |
| specialties | string[] | No | Array of specialties |
| displayOrder | int | No | Sort order (default: 0) |
| isActive | boolean | No | Visibility on website (default: true) |
| image | file | Yes | Profile photo (allowed: png, avif, webp, jpg, jpeg, gif, mp4, mp3, mov, pdf, doc, docx, xls, xlsx, ppt, pptx, txt, csv, zip. Max 10MB) |

### Response

```json
{
  "message": "Staff create success",
  "success": true,
  "data": {
    "_id": "...",
    "name": "John Doe",
    "role": "Doctor",
    "title": "Dr.",
    "qualifications": ["M.B.,B.S", "M.Med.Sc"],
    "biography": "...",
    "specialties": ["Cardiology"],
    "imageUrl": "https://cherryk.s3.ap-southeast-1.amazonaws.com/Staff/Image/1687154298_portrait.jpg",
    "displayOrder": 1,
    "isActive": true,
    "isDeleted": false,
    "createdAt": "...",
    "updatedAt": "..."
  }
}
```

---

## Get Staff

`GET /api/staff/:id`

Retrieve a single staff profile.

### Headers
- `Authorization: Bearer <token>`

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Staff MongoId |

### Response

```json
{
  "success": true,
  "data": { "...": "..." }
}
```

### Errors
- `404` — Staff not found

---

## Update Staff

`PUT /api/staff/:id`

Update an existing staff profile. To replace the photo, upload a new file.

### Headers
- `Authorization: Bearer <token>`
- `Content-Type: multipart/form-data`

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Staff MongoId |

### Body (multipart/form-data)

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | No | Staff name |
| role | string | No | One of: `Founder`, `Doctor`, `Both` |
| title | string | No | e.g. `Dr.`, `Prof.` |
| qualifications | string[] | No | Array of qualifications |
| biography | string | No | Biography text |
| specialties | string[] | No | Array of specialties |
| displayOrder | int | No | Sort order |
| isActive | boolean | No | Visibility on website |
| image | file | No | New profile photo (replaces old one; old file deleted from S3) |

> **Image replacement:** Uploading a new `image` file automatically replaces the old photo. The old file is deleted from S3.

### Errors
- `404` — Staff not found

---

## Delete Staff (Soft Delete)

`DELETE /api/staff/:id`

Soft-delete a staff profile (sets `isDeleted` to `true`). Also deletes the associated image from S3.

### Headers
- `Authorization: Bearer <token>`

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Staff MongoId |

### Response

```json
{
  "success": true,
  "data": { "isDeleted": true }
}
```

### Errors
- `404` — Staff not found

---

## Activate Staff

`POST /api/staff/:id`

Restore a soft-deleted staff profile (sets `isDeleted` to `false`).

### Headers
- `Authorization: Bearer <token>`

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Staff MongoId |

### Response

```json
{
  "success": true,
  "data": { "isDeleted": false }
}
```

### Errors
- `404` — Staff not found

---

## Activate Staff (Visibility)

`POST /api/staff/:id/activate`

Set a staff profile's `isActive` to `true` (show on website).

### Headers
- `Authorization: Bearer <token>`

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Staff MongoId |

### Response

```json
{
  "success": true,
  "data": { "isActive": true }
}
```

### Errors
- `404` — Staff not found

---

## Deactivate Staff (Visibility)

`POST /api/staff/:id/deactivate`

Set a staff profile's `isActive` to `false` (hide from website).

### Headers
- `Authorization: Bearer <token>`

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Staff MongoId |

### Response

```json
{
  "success": true,
  "data": { "isActive": false }
}
```

### Errors
- `404` — Staff not found

---

## List All Staff (Paginated)

`GET /api/staffs`

Get a paginated list of active (non-deleted) staff profiles.

### Headers
- `Authorization: Bearer <token>`

### Query Parameters

| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| keyword | string | No | — | Search by name (case-insensitive) |
| role | string | No | — | Filter by role: `Founder`, `Doctor`, `Both` |
| isActive | boolean | No | — | Filter by website visibility |
| limit | int | No | 10 | Items per page (max 100) |
| page | int | No | 1 | Page number (starts at 1) |

Results are sorted by `displayOrder` ascending, then `name` ascending.

### Response

```json
{
  "success": true,
  "count": 0,
  "_metadata": {
    "current_page": 1,
    "per_page": 10,
    "page_count": 0,
    "total_count": 0
  },
  "list": []
}
```

Results are now paginated using `page` (1-based) and `limit`. `skip` is calculated internally.

---

## Sort Staff

`PUT /api/staffs/sort`

Bulk-update the sort order of active (non-deleted, visible) staff profiles.

### Headers
- `Authorization: Bearer <token>`
- `Content-Type: application/json`

### Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| items | array | Yes | Array of sort items |
| items[]._id | string | Yes | Staff MongoId |
| items[].displayOrder | int | Yes | New sort position (non-negative) |

### Response

```json
{
  "success": true,
  "message": "Sort order updated"
}
```

### Errors
- `500` — Server error

Only items where `isDeleted: false` and `isActive: true` will be updated; others are silently skipped.

---

## List Website Staff (Public)

`GET /api/website/staffs`

Public endpoint for the Cherry-K website. Returns active staff profiles (no auth, no pagination). Optionally filter by role.

### Query Parameters

| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| role | string | No | — | Filter by role: `Founder`, `Doctor`, `Both` |

### Response

```json
{
  "success": true,
  "data": [
    {
      "_id": "...",
      "name": "John Doe",
      "role": "Doctor",
      "title": "Dr.",
      "qualifications": ["M.B.,B.S", "M.Med.Sc"],
      "biography": "...",
      "specialties": ["Cardiology"],
      "imageUrl": "https://cherryk.s3.ap-southeast-1.amazonaws.com/Staff/Image/1687154298_portrait.jpg",
      "displayOrder": 1,
      "isActive": true,
      "isDeleted": false,
      "createdAt": "...",
      "updatedAt": "..."
    }
  ]
}
```

### Errors
- `404` — No staff found

Filters: `isDeleted: false`, `isActive: true`. Sorted by `displayOrder` ascending, then `name` ascending.
