# Employee Leave Eligibility API — Frontend Reference

## Overview

Replace the PDS (`/employee-information/api/v2/...`) leave eligibility calls with Timekeeping V2 endpoints. These endpoints are employee-centric and use the existing `setting_leave_classifications` + `setting_leave_classification_eligible_employees` tables.

## Base URL

| Environment | URL |
|---|---|
| Dev | `http://112.199.83.13:8002/api/v2` |
| Production | `http://112.199.83.13:8002/api/v2` (behind API Gateway) |

## Endpoints

### GET `/api/v2/employees/{employeeId}/leave-eligibilities`

Returns all active leave classifications with their eligibility status for the given employee.

**Path parameters:**
- `employeeId` (integer) — Employee's `id` from the `employees` table

**Response `200 OK`:**
```json
{
  "success": true,
  "data": {
    "employee_id": 123,
    "employee_no": "2025-001",
    "full_name": "Doe, John",
    "position": null,
    "division": null,
    "office": null,
    "email_address": "john.doe@example.com",
    "leave_classifications": [
      {
        "id": 1,
        "name": "VACATION LEAVE",
        "code": "VL",
        "is_eligible": true,
        "is_overridden": false,
        "available_balance": 15.0
      },
      {
        "id": 2,
        "name": "SICK LEAVE",
        "code": "SL",
        "is_eligible": false,
        "is_overridden": true,
        "available_balance": 0
      }
    ]
  }
}
```

**Fields:**
| Field | Type | Description |
|---|---|---|
| `id` | integer | Leave classification ID |
| `name` | string | Classification name (e.g., "VACATION LEAVE") |
| `code` | string or null | Short code (e.g., "VL", "SL") |
| `is_eligible` | boolean | Whether the employee is eligible for this leave |
| `is_overridden` | boolean | Whether eligibility was manually set by HR (vs. auto-derived from rules) |
| `available_balance` | float | Computed leave balance |

**Eligibility logic:**
- `is_overridden: true` + `is_eligible: true` — Explicitly assigned by HR via pivot
- `is_overridden: true` + `is_eligible: false` — Explicitly excluded by HR
- `is_overridden: false` — Auto-derived from rules (gender + employment status)

**Error `404`:**
```json
{
  "success": false,
  "message": "Employee not found.",
  "error_code": 404
}
```

---

### PUT `/api/v2/employees/{employeeId}/leave-eligibilities`

Full replacement sync — sets which leave classifications the employee is explicitly eligible for. Classifications not in the list are set to excluded.

**Path parameters:**
- `employeeId` (integer) — Employee's `id` from the `employees` table

**Request:**
```json
{
  "leave_classification_ids": [1, 3, 5, 8]
}
```

**Validation rules:**
- `leave_classification_ids` — required, must be an array
- `leave_classification_ids.*` — each element must be an integer

**Response `200 OK`:** Same shape as GET — returns the updated eligibility state.

**Error `422`:**
```json
{
  "success": false,
  "message": "Employee not found.",
  "error_code": 422
}
```

---

## Migration Guide: From PDS Endpoints

### Replace these PDS calls:

| Old PDS Call | New Timekeeping Call |
|---|---|
| `GET /employee-information/api/v2/leave-classifications` | ❌ Remove — use the combined GET below |
| `GET /employee-information/api/v2/employee/{employeeNo}/eligibilities` | `GET /api/v2/employees/{employeeId}/leave-eligibilities` |
| `POST/PATCH /employee-information/api/v2/employee/{employeeNo}/eligibilities` | `PUT /api/v2/employees/{employeeId}/leave-eligibilities` |

### Key differences:

1. **Combined response** — The new GET returns classifications + eligibilities in one call. Previously you needed two calls.
2. **Full replacement (PUT)** — Send the complete set of eligible classification IDs. The server handles adding/removing. No more POST vs PATCH decision.
3. **Use `employeeId` (integer)** — not `employeeNo` (string). The new endpoints use the internal `employees.id`.
4. **Simplified type model** — Each classification in the response has `is_eligible` and `is_overridden` booleans. No separate eligibility model needed.

### Suggested frontend types:

```typescript
export interface LeaveClassification {
  id: number;
  name: string;
  code: string | null;
  is_eligible: boolean;
  is_overridden: boolean;
  available_balance: number;
}

export interface EmployeeLeaveEligibilityData {
  employee_id: number;
  employee_no: string;
  full_name: string;
  position: string | null;
  division: string | null;
  office: string | null;
  email_address: string | null;
  leave_classifications: LeaveClassification[];
}

export interface LeaveEligibilityResponse {
  success: boolean;
  data: EmployeeLeaveEligibilityData;
  message: string;
}

export interface SyncLeaveEligibilityRequest {
  leave_classification_ids: number[];
}
```

### Suggested hook logic (replaces `useLeaveAndHolidayEligibility.ts`):

```typescript
// On page load
const response = await apiClient.get(
  `/api/v2/employees/${employeeId}/leave-eligibilities`
);
// response.data.data.leave_classifications → render checkboxes
// Map to local state: Map<classificationId, isEligible>

// On save
const checkedIds = Array.from(eligibilities.entries())
  .filter(([, isEligible]) => isEligible)
  .map(([id]) => id);

await apiClient.put(
  `/api/v2/employees/${employeeId}/leave-eligibilities`,
  { leave_classification_ids: checkedIds }
);
// Response contains updated state — use directly
```

### Remove these:
- `defaultLeaveClassifications` hardcoded fallback (in `types/leaveAndHolidayEligibility.ts`)
- `LeaveClassificationResponse` type (no longer needed as a separate response)
- `EmployeeLeaveEligibility` type (replaced by `LeaveClassification` with `is_eligible`)
- `EligibilityResponse` / `EligibilityRequest` types (replaced by `SyncLeaveEligibilityRequest`)

## Error Handling

Standard error response shape:
```json
{
  "success": false,
  "message": "Error description",
  "error_code": 422
}
```

Possible error codes:
| Code | Meaning |
|---|---|
| 404 | Employee not found |
| 422 | Validation failed (invalid classification IDs, missing field) |
| 500 | Internal server error |
