# KiyoHR TimeX - Project Documentation (For Flutter Migration)

## 1) Project Overview

KiyoHR TimeX is a mobile-first face-attendance app built with Framework7 + Vue 3 and packaged with Capacitor (Android/iOS). The app supports:

- Email/password authentication
- App lock (PIN + biometrics)
- Face registration for employees
- Face-based attendance clock-in and clock-out
- Attendance history and monthly summary
- Forced app-update dialog
- Offline attendance queueing (IndexedDB)

## 2) Current Tech Stack

- Frontend: Vue 3 + Framework7 (`framework7-vue`)
- Build Tool: Vite
- State Management: Pinia
- HTTP: Axios
- Local DB: IndexedDB (`idb`)
- Face Recognition: `@vladmandic/face-api` (FaceNet embeddings)
- Mobile Runtime: Capacitor (`@capacitor/android`, `@capacitor/ios`)
- Device Features:
  - Camera (`@capacitor/camera` + `getUserMedia`)
  - Native biometrics (`capacitor-native-biometric`)
  - App lifecycle (`@capacitor/app`)

## 3) App Architecture Summary

- Entry: `src/main.js`
- App Shell + startup checks: `src/app.vue`
- Routes: `src/routes.js`
- API layer: `src/services/api.js`
- Auth/session/lock services:
  - `src/store/auth.js`
  - `src/services/session.js`
  - `src/services/lock.js`
- Face logic + embeddings:
  - `src/utils/face.js`
  - `src/store/face.js`
- Attendance submit/offline queue:
  - `src/store/attendance.js`
  - `src/utils/db.js`

## 4) Navigation & Screen List (UI Screens)

## Startup Flow

1. App checks session freshness.
2. If valid session, startup route goes to `/lock`.
3. If no/expired session, startup route goes to `/login`.
4. Forced update dialog may appear on top of app.

## Route-to-Screen Mapping

| Route | Screen Component | Purpose |
|---|---|---|
| `/login` | `LoginPage.vue` | Email/password login |
| `/lock` | `lock.vue` | Unlock app with biometrics or 4-digit PIN |
| `/dashboard` | `DashboardPage.vue` | Attendance status, quick actions |
| `/userspage` | `UsersPage.vue` | Pending face registrations (manager-only) |
| `/face/register/:userId?` | `FaceRegisterPage.vue` | Capture and register/replace face ID |
| `/capture/login` | `AttendenceLogin.vue` | Camera-based face match and clock-in |
| `/capture/logout` | `AttendanceLogout.vue` | Camera-based face match and clock-out |
| `/historypage` | `history.vue` | Monthly summary + daily attendance records |
| `/profilepage` | `profile.vue` | Profile, re-enroll face, preferences, logout |

## Reusable UI Components

- `BottomTab.vue`: bottom tab navigation (Dashboard, Users, Profile, History)
- `NavbarBrand.vue`: branded navbar title
- `AttendanceTimeRow.vue`: timeline row in history
- `ForceUpdateDialog.vue`: mandatory update modal
- `PendingFaceCard.vue`: pending employee face card

## 5) API Integrations Used

Base URL:

- `VITE_API_BASE` from env, fallback: `https://kiyohr.com/api/v1`

## Primary Backend Endpoints

| Method | Endpoint | Used In | Purpose |
|---|---|---|---|
| POST | `/hrms/login` | `LoginPage.vue` | Login with email/password |
| GET | `/users/missing-faces` | `store/face.js` | Fetch users missing face data |
| GET | `/face/sync` | `store/face.js`, attendance pages | Sync all registered face data |
| POST | `/face/register` | `FaceRegisterPage.vue` | Register/update user face |
| GET | `/users/{id}` | `FaceRegisterPage.vue` | Check whether user already has face data |
| POST | `/attendance/login` | face register + login capture + store | Mark clock-in attendance |
| POST | `/attendance/logout` | logout capture + store | Mark clock-out attendance |
| GET | `/hrm/today-attendance-details` | `DashboardPage.vue` | Get today clock in/out status |
| GET | `/self/summary-month?month=&year=` | `history.vue` | Monthly attendance summary + daily records |

## Version/Update Endpoint Status

- Current app uses a mocked version check response in `HRMS.checkAppVersion()`.
- Planned real endpoint (commented in code): `POST /app/version-check`.

## Additional External URLs Used

- `https://api.ipify.org?format=json` (client public IP detection)
- `https://cdn.jsdelivr.net/npm/@vladmandic/face-api/model/` (Face API models)
- `https://ui-avatars.com/api/...` (default avatars)

## 6) Key API Payload Patterns

## Login

`POST /hrms/login`

```json
{
  "email": "user@company.com",
  "password": "********"
}
```

## Register Face

`POST /face/register`

```json
{
  "user_id": "123",
  "company_id": "456",
  "face_data": "data:image/jpeg;base64,...",
  "overwrite": true,
  "is_update": true
}
```

## Attendance Login/Logout

`POST /attendance/login` and `POST /attendance/logout`

```json
{
  "user_id": 123,
  "company_id": 456,
  "employee_number": "EMP001",
  "ip_address": "x.x.x.x",
  "browser": "user-agent-string",
  "device_type": "mobile",
  "platform": "Android",
  "user_agent": "full-user-agent"
}
```

## 7) Local Storage / Offline / Session

- `localStorage`:
  - Auth state (`auth`)
  - Session token + login timestamp (`auth_token`, `login_timestamp`)
  - App lock PIN (obfuscated)
  - Notification preference toggle
- `sessionStorage`:
  - unlock state (`app_unlocked`)
- IndexedDB (`kiyohr-face-db`):
  - `faces` store (cached faces)
  - `pending` store (queued offline attendance actions)

## 8) Security & Behavioral Notes

- Axios request interceptor injects Bearer token.
- 401/403 auto-logout and redirect to login.
- Session max age: 30 days.
- Non-managers cannot mark attendance for others.
- Managers restricted to same-company employees.
- Duplicate-face check runs client-side using embedding similarity before register API.

## 9) Flutter Migration Blueprint

## Suggested Flutter Stack

- State: Riverpod (or Bloc, if team standard)
- Routing: `go_router`
- HTTP: `dio`
- Local DB:
  - `isar` or `drift` for structured local data
  - `shared_preferences` or secure storage for token/PIN
- Biometrics: `local_auth`
- Camera: `camera` package
- Face Recognition:
  - Option A: server-side matching only (recommended for consistency)
  - Option B: on-device embedding with ML Kit/TFLite + cosine matching

## Module Mapping (Vue -> Flutter)

- `services/api.js` -> `lib/data/network/api_client.dart` + repositories
- `store/auth.js` -> `auth_provider.dart`
- `store/face.js` -> `face_provider.dart`
- `store/attendance.js` -> `attendance_provider.dart`
- `utils/face.js` -> `face_engine_service.dart`
- pages -> Flutter screens under `lib/features/*/presentation`

## Migration Priorities

1. Auth + session + lock flow parity (`/login` -> `/lock` -> dashboard)
2. Face sync/cache + match flow parity
3. Attendance login/logout parity with same payload keys
4. History summary UI + parsing of flexible backend response keys
5. Forced update dialog + store redirect
6. Offline queue and flush behavior

## 10) QA Checklist For Migration

- Login success/failure behavior matches current app
- Session expiry redirects correctly
- Biometrics and PIN unlock both supported
- Manager vs non-manager attendance restrictions preserved
- Face duplicate prevention behavior preserved
- Offline attendance queue works and auto flushes on reconnect
- Monthly history values align with backend for multiple months
- Forced update blocks usage when required version is higher

## 11) Notes For Documentation Consumers

- There are legacy/alternate files such as `src/pages/login.vue` not currently routed by `src/routes.js`.
- Current documentation is based on actual routed components and active service/store usage.
- Use `KiyoHR_Face_Attendance_API.postman_collection.json` for API test references.

