# Admin Updates — Interactive Contracts & Provider Rejections

> Last updated: 2026-09-30

This document covers two major updates to the Admin API:
1. Support for **Interactive Contract** orders in the admin dashboard.
2. The new **Provider Rejection Lifecycle & Cooldown**.

---

## 1. Interactive Contract Orders

When viewing a service order (`GET /v1/admin/service-orders/{id}`), if the order type is `interactive_contract`, the admin will now see a full breakdown of the contract stages.

### The `stages_data` Field

Admin response now includes `stages_data` exactly like the provider and client apps, but as a read-only observer.

```jsonc
"stages_data": [
  {
    "id": 1,
    "order": 1,
    "name": "Initial Review",
    "end_date": "2026-10-10",
    "amount": 500.00,
    "is_active": false,
    "is_client_confirmed": true,
    "client_confirmed_at": 1727800000,
    "parties_data": [
      {
        "id": 101,
        "full_name": "Ahmed Ali",
        "has_confirmed": true,
        "confirmed_at": 1727780000
      }
    ],
    "created_at": 1727500000
  }
]
```

**Admin Use Case:**
- Support agents can view exactly which stage an order is stuck on.
- Admins can see which specific party has not yet confirmed the current active stage.

### New Static Page Type
A new static page type was added to the `PageTypeEnum`:
- `interactive_contract_terms` (`InteractiveContractTerms`)

**Important:** This page is seeded automatically via `php artisan db:seed --class=InteractiveContractTermsSeeder`. Admins can edit this content from the dashboard like any other static page.

---

## 2. Provider Rejection Lifecycle & Cooldown

The provider registration approval flow has been updated to include a **cooldown period** for rejected providers.

### How it works:
1. Admin rejects a provider (`POST /admin/provider-requests/{id}/reject`) with a required `rejection_note`.
2. The provider's `account_status` becomes `rejected`.
3. The `rejection_note` and `rejected_at` timestamp are saved to the provider's profile.
4. The provider **cannot log in or reapply immediately**.
5. The system enforces a cooldown period before they can submit a new application.

### The Cooldown Setting
The cooldown duration is controlled by a new setting:
- **Key:** `provider_rejection_cooldown_days` (Enum: `SettingKeyEnum::ProviderRejectionCooldownDays`)
- **Type:** `Integer`
- **Default:** `90` (days)
- **Group:** `Provider`

Admins can modify this setting through the standard Settings API (`POST /v1/admin/settings`). Setting it to `0` disables the cooldown entirely.

### Admin Review of Re-applications
When a provider eventually re-applies (after the cooldown expires), their previous `rejection_note` and `rejected_at` remain visible to the admin. This ensures admins have the full historical context of why the provider was previously rejected when reviewing their new application.

---

## 3. Relevant Configuration Settings (Admin Reference)

To give admins full control over the order lifecycle and provider rules, several new settings have been added to the `SettingKeyEnum`. These can be modified via the Settings API:

| Setting Key | Type | Default | Description |
|---|---|---|---|
| `provider_rejection_cooldown_days` | Integer | `90` | Days a rejected provider must wait before they can submit a new registration request. (0 = disabled) |
| `service_order_pending_timeout_minutes` | Integer | (varies) | Auto-cancels an order if it stays `pending` without a provider accepting it within this timeframe. (0 = disabled) |
| `service_order_auto_complete_minutes` | Integer | (varies) | Auto-completes an order a set time after a provider marks it as `provider_finished`, transferring funds automatically. (0 = disabled) |
| `golden_guarantee_window_minutes` | Integer | (varies) | The time window a client has to file a Golden Guarantee complaint after the provider finishes the work. (0 = disabled) |
| `urgent_order_retry_interval_minutes` | Integer | (varies) | Minutes to wait before re-dispatching an unaccepted urgent order to more providers. |
| `urgent_order_cancel_after_minutes` | Integer | (varies) | Auto-cancels and refunds an urgent order if no provider accepts within this time limit. |
| `urgent_order_provider_commission_percentage` | Float | `85.0` | The percentage of the emergency authority price that goes to the provider for urgent orders. |

---

## 4. Chat API — Updates

> Last updated: 2026-10-01

### 4.1 Chat List Response (`GET /v1/admin/chats`)

The chat list now returns two additional objects on every chat item:

**`order_data`** — the order linked to this chat (present when the chat was created for a service or urgent order):
```jsonc
"order_data": {
  "id": 42,
  "order_number": "NK-S0042#",
  "status": "active",
  "type": "service"     // "service" | "urgent"
}
```
`null` when no order is linked.

**`latest_message`** — unified shape across admin and all clients:
```jsonc
"latest_message": {
  "id": 10,
  "message": "Hello",
  "is_mine": false,
  "read_at": null,
  "created_at": 1727600000,
  "attachment_data": {
    "url": "https://...",
    "type": "image"     // "image" | "audio" | "video" | "file"
  }
}
```
`attachment_data` is `null` when there is no attachment.

### 4.2 Chat Messages Response (`GET /v1/admin/chats/{id}`)

Individual message objects now return `attachment_data` with `url` and `type` only (same shape as above). The old `attachment_type` flag is removed.

### 4.3 Shared Resources (single source of truth)

| Resource | Used in |
|---|---|
| `Shared\ChatLatestMessageResource` | All chat list previews |
| `Shared\ChatOrderBriefResource` | `order_data` in all chat lists |
| `Shared\ChatLatestMessageResource` | All message list responses |
| `Media::normalized_type` accessor | All `type` fields in `attachment_data` |

Type normalization (`jpg` → `image`, `mp3` → `audio`, etc.) lives exclusively in `Media::getNormalizedTypeAttribute()`.

### 4.4 Search by Order Number

The admin chat list now supports filtering by `user_id` and `keyword` (existing). Order number search is available on service-orders and urgent-orders endpoints:
```
GET /v1/admin/service-orders?search=NK-S0042
GET /v1/admin/urgent-orders?search=NK-U0010
```

---

## 5. Contact Us — New Filters

> Endpoint: `GET /v1/admin/contacts`

Two new filters have been added to the contacts list:

### Filter by `is_replied`
```
GET /v1/admin/contacts?filters[is_replied]=1    → only replied contacts
GET /v1/admin/contacts?filters[is_replied]=0    → only unreplied/pending contacts
```

### Filter by `user_type` (who submitted)
```
GET /v1/admin/contacts?filters[user_type]=client    → contacts from client accounts
GET /v1/admin/contacts?filters[user_type]=provider  → contacts from provider accounts
```
> Contacts submitted by **guests** (not logged in, no `user_id`) are excluded when `user_type` is applied.

### Combined example
```
GET /v1/admin/contacts?filters[is_replied]=0&filters[user_type]=provider
```
Returns all unreplied contacts submitted by providers.

