# Emarikeje - Sistem Kehadiran Guru & Staf

Aplikasi web untuk pengurusan kehadiran (auto check-in/out geolokasi, alasan & pengesahan, laporan jam bekerja) dengan UI Bootstrap 5.

## Keperluan
- Node.js 18+
- MySQL/MariaDB (sesuai XAMPP)
- Port API lalai: 3001

## Setup Pantas
1. Semak `.env` (DB_HOST/DB_USER/DB_PASSWORD/DB_NAME).
2. Pasang pakej:
```bash
npm install
```
3. Jalankan migrasi & seed admin:
```bash
npm run migrate
npm run seed
```
4. Jalankan dev server:
```bash
npm run dev
```
5. UI:
- Login: http://localhost:3001/
- Dashboard: http://localhost:3001/dashboard.html
- Admin: http://localhost:3001/admin/users.html

Akaun admin contoh: `admin@example.com` / `Password123!`

## Endpoints Utama
- Auth: POST `/api/auth/login`, GET `/api/auth/me`
- Attendance: POST `/api/attendance/check`, POST `/api/attendance/:attendance_id/attachment`
- Approvals: GET `/api/approvals/pending`, POST `/api/approvals/:attendance_id`
- Settings: GET/PUT/DELETE `/api/settings/times`, GET/PUT `/api/settings/schedule/:user_id`
- Users: GET `/api/users`, POST `/api/users`, DELETE `/api/users/:id`, PUT `/api/users/:user_id/approvers`
- Reports: GET `/api/reports`, GET `/api/reports/export` (CSV)

## Ringkasan Logik
- Auto check-in/out jika dalam radius lokasi (default 50m) ikut masa.
- Lewat/awal/luar radius → `pending` + perlu sebab + notifikasi pegawai.
- Staf: jam bekerja `first in` → `last out`, banding `expected_hours` (kategori/override) → overtime jika lebih.
- Lampiran selfie disimpan di `uploads/` dan dihidang melalui `/uploads/...`.
- Audit log untuk tindakan penting.

## Zon Waktu
- `Asia/Kuala_Lumpur` digunakan untuk kiraan tarikh/masa.

## Keselamatan
- JWT + RBAC (admin/superuser untuk tetapan/pengguna), rate limit asas.
- Guna HTTPS pada produksi (reverse proxy Nginx/Caddy/Apache urus TLS).

## Deploy Ringkas (Nginx + PM2)
1. Build:
```bash
npm run build
```
2. Jalankan dengan PM2:
```bash
pm2 start dist/server.js --name emarikeje
pm2 save
```
3. Nginx (contoh ringkas):
```
server {
  listen 443 ssl;
  server_name your-domain.example;
  ssl_certificate /etc/letsencrypt/live/your-domain.example/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/your-domain.example/privkey.pem;

  location / {
    proxy_pass http://127.0.0.1:3001;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }
}
```

## Ujian Manual (contoh)
1. Guru A 07:55 dalam 30m → `on_time`.
2. Guru B 08:15 → `late` + sebab → `pending`.
3. Guru C tiada lokasi 08:00 → `pending`, hantar alasan + selfie.
4. Staf D 09:00/17:30 → 8.5 jam → overtime jika expected 8.0.
5. Manual tanpa lokasi → wajib selfie + alasan → perlu pengesahan.

## Struktur Direktori
- `src/` API (Express + TS)
- `public/` UI Bootstrap 5
- `uploads/` lampiran
- `sql/` migrasi SQL

## Nota Lanjutan
- Multi-sekolah: tambah baris `locations`, perluasan pemetaan user→lokasi.
- Mitigasi spoofing: rujuk `accuracy`; boleh paksa selfie jika mencurigakan.
