Initial commit: AARS backend + frontend + holiday/leave phase 1+2

This commit is contained in:
IT Dog
2026-07-19 20:10:15 +08:00
commit bbc0048c24
49 changed files with 13375 additions and 0 deletions
+377
View File
@@ -0,0 +1,377 @@
# AARS - Attendance & Accident Record System
## 1. Concept & Vision
一個為中小企設計嘅出勤同意外記錄系統。介面乾淨、專業、易用,帶有香港本地特色(繁體中文、HKT時區)。兩大一頁式 dashboard,展示即時數據,所有記錄都可以 filter、sort、export。
目標係取代 Excel 試算表,做一個可以多人協作、數據唔會重複、report 一click 生成嘅系統。
---
## 2. Design Language
**Aesthetic:** 淺色專業商務風,白底配淺灰,帶有 System Blue 強調色。似 classic Notion / Linear 嗰種乾淨感覺,但再 warm 少少。
**Colors (TailwindCSS custom):**
- Primary: `#2563EB` (blue-600)
- Primary Dark: `#1D4ED8` (blue-700)
- Accent: `#06B6D4` (cyan-500)
- Background: `#F8FAFC` (slate-50)
- Card: `#FFFFFF`
- Border: `#E2E8F0` (slate-200)
- Text Primary: `#0F172A` (slate-900)
- Text Secondary: `#64748B` (slate-500)
- Success: `#10B981` (emerald-500)
- Warning: `#F59E0B` (amber-500)
- Danger: `#EF4444` (red-500)
**Typography:**
- Font: Inter (Google Fonts) + Noto Sans TC (繁體中文)
- Headings: 600-700 weight
- Body: 400-500 weight
**Spatial System:**
- Base unit: 4px
- Card padding: 24px
- Section gap: 32px
- Border radius: 8px (cards), 6px (buttons), 4px (inputs)
**Motion:**
- Page transitions: fade 150ms
- Hover states: 200ms ease
- Loading: pulse animation
- No bouncy/playful animations - keep it professional
---
## 3. Layout & Structure
```
┌─────────────────────────────────────────────────────┐
│ Header: Logo + Nav (Attendance | Accident) + User │
├─────────────────────────────────────────────────────┤
│ Page Content: │
│ ┌─ Dashboard ─┐ ┌─ List View ─┐ ┌─ Detail ─┐ │
│ │ Stats cards │ │ Table + Fn │ │ Edit form│ │
│ │ Charts │ │ Filter/Sort │ │ History │ │
│ └────────────┘ └─────────────┘ └─────────┘ │
└─────────────────────────────────────────────────────┘
```
**Pages:**
1. **Login** (`/login`) - Email + passwordJWT auth
2. **Dashboard** (`/`) - Stats cards + recent activity + quick actions
3. **Attendance List** (`/attendance`) - Table with all records
4. **Attendance Detail** (`/attendance/:id`) - View/Edit single record
5. **Accident List** (`/accident`) - Table with all records
6. **Accident Detail** (`/accident/:id`) - View/Edit single record
7. **Import** (`/import`) - Excel upload + mapping + preview
**Responsive:** Desktop-first,但 table 可以 horizontal scroll 喺 mobile
---
## 4. Features & Interactions
### 4.1 Authentication
- Login with email + password
- JWT token stored in localStorage
- Token expiry: 24 hours
- Auto-redirect to login if expired
### 4.2 Dashboard
**Attendance Section:**
- Total records count
- Today attendance count
- This month attendance count
- Records trend chart (last 7 days / 30 days)
**Accident Section:**
- Total records count
- This month accidents count
- Unresolved accidents count
- Recent accidents list (last 5)
### 4.3 List View
- Paginated table (20 per page)
- Columns: ID, Date, Employee Name, Department, Status, Actions
- **Filter:** By date range, department, status, search text
- **Sort:** Click column header to sort ASC/DESC
- **Actions:** View, Edit, Delete (soft delete)
- **Bulk Actions:** Select multiple → Delete / Export selected
- **Export:** PDF (single/all selected) / Excel (all filtered results)
### 4.4 Detail / Edit View
- Form with all fields
- Read-only view mode vs Edit mode
- **History tab:** Show who created/modified when
- **Save:** Validates + saves to SQLite
- **Cancel:** Returns to list without saving
### 4.5 Excel Import
- Upload Excel file (.xlsx, .xls)
- Auto-detect columns from first row
- **Field mapping:** Map Excel columns to system fields
- **Duplicate detection:** Check by unique key (Employee ID + Date for attendance, Date + Location for accident)
- **Preview:** Show first 10 rows with validation status
- **Options:**
- "Update existing" → skip duplicates or update
- "Create new only" → skip duplicates
- **Import button:** Bulk insert/update
- **Result:** Show success count, skipped (duplicates), errors
### 4.6 Field Management
- Default fields per section (pre-defined)
- **Add custom field:** Name, type (text/number/date/select), required
- Custom fields stored in JSON column
- Can be used in list view, detail view, export
### 4.7 Export
- **Excel:** All filtered results, includes all fields
- **PDF:** Formatted report with header, table, pagination
- Export respects current filter/sort state
---
## 5. Component Inventory
### 5.1 Header
- Logo (left): "AARS" text logo
- Nav tabs (center): "出勤 Attendance" | "意外 Accident"
- Active tab: blue underline
- User menu (right): Username + dropdown (Profile, Logout)
### 5.2 Stats Card
- Icon (colored circle bg) + metric value (large) + label (small)
- Hover: subtle shadow lift
### 5.3 Data Table
- Header row: grey bg, bold text
- Sortable columns: sort icon, click to toggle
- Row hover: light blue bg
- Checkbox column for bulk select
- Action buttons: View (blue), Edit (gray), Delete (red)
- Empty state: "No records found" + illustration
### 5.4 Filter Bar
- Date range picker (two inputs)
- Dropdown for department/status
- Text search input
- "Clear filters" button
- "Export" button
### 5.5 Form
- Label + input pairs, stacked
- Required indicator: red asterisk
- Input states: default, focus (blue ring), error (red border + message)
- Select dropdowns, date pickers
- Submit button (blue), Cancel button (gray outline)
### 5.6 Modal
- Centered overlay, white card
- Header + body + footer
- Close X button top right
- Backdrop click to close
### 5.7 Toast Notifications
- Success (green), Error (red), Info (blue)
- Auto-dismiss after 3s
- Bottom right corner
### 5.8 Import Wizard
- Step 1: Upload Excel
- Step 2: Map columns
- Step 3: Preview + validate
- Step 4: Confirm + import
- Progress indicator at top
---
## 6. Technical Approach
### 6.1 Backend (FastAPI)
```
backend/
├── main.py # FastAPI app entry
├── database.py # SQLite + SQLAlchemy
├── models.py # SQLAlchemy models
├── schemas.py # Pydantic schemas
├── auth.py # JWT auth
├── routers/
│ ├── attendance.py
│ ├── accident.py
│ ├── import.py
│ └── export.py
└── utils/
├── excel.py # openpyxl helpers
└── pdf.py # reportlab helpers
```
**API Endpoints:**
```
POST /api/auth/login
GET /api/auth/me
GET /api/attendance # List with filter/sort/paginate
POST /api/attendance # Create
GET /api/attendance/:id # Get one
PUT /api/attendance/:id # Update
DELETE /api/attendance/:id # Soft delete
GET /api/accident # List with filter/sort/paginate
POST /api/accident # Create
GET /api/accident/:id # Get one
PUT /api/accident/:id # Update
DELETE /api/accident/:id # Soft delete
POST /api/import/attendance # Excel import
POST /api/import/accident # Excel import
GET /api/export/attendance/excel
GET /api/export/attendance/pdf
GET /api/export/accident/excel
GET //api/export/accident/pdf
GET /api/dashboard/attendance # Stats
GET /api/dashboard/accident # Stats
GET /api/fields/attendance # Custom fields
POST /api/fields/attendance
GET /api/fields/accident
POST /api/fields/accident
```
### 6.2 Database Schema
**Users:**
```sql
id, email, password_hash, name, role, created_at, updated_at, is_active
```
**Attendance:**
```sql
id, employee_id, employee_name, department, date, check_in, check_out,
overtime_hours, leave_type, leave_hours, status, remarks,
custom_fields (JSON), created_by, created_at, updated_at, deleted_at
```
**Accident:**
```sql
id, date, time, location, employee_name, employee_id, department,
description, severity, medical_report, action_taken, responsible_person,
custom_fields (JSON), created_by, created_at, updated_at, deleted_at
```
**AttendanceCustomFields / AccidentCustomFields:**
```sql
id, field_name, field_type, required, options, order, created_at
```
### 6.3 Frontend (React + Vite)
```
frontend/
├── src/
│ ├── App.jsx
│ ├── main.jsx
│ ├── api.js # Axios API calls
│ ├── context/
│ │ └── AuthContext.jsx
│ ├── pages/
│ │ ├── Login.jsx
│ │ ├── Dashboard.jsx
│ │ ├── attendance/
│ │ │ ├── List.jsx
│ │ │ └── Detail.jsx
│ │ ├── accident/
│ │ │ ├── List.jsx
│ │ │ └── Detail.jsx
│ │ └── import/
│ │ └── Import.jsx
│ └── components/
│ ├── Layout.jsx
│ ├── DataTable.jsx
│ ├── FilterBar.jsx
│ ├── StatsCard.jsx
│ ├── Modal.jsx
│ └── Toast.jsx
├── index.html
├── tailwind.config.js
└── vite.config.js
```
### 6.4 Docker Setup
```yaml
# docker-compose.yml
services:
aars:
build: .
ports:
- "18775:8000"
volumes:
- ./data:/app/data
environment:
- TIMEZONE=Asia/Hong_Kong
- SECRET_KEY=<generated>
restart: unless-stopped
```
### 6.5 Key Libraries
- **Backend:** fastapi, uvicorn, sqlalchemy, pydantic, python-jose, passlib, openpyxl, reportlab
- **Frontend:** react, react-router-dom, axios, tailwindcss, recharts (charts), react-hot-toast
---
## 7. Default Fields
### Attendance Default Fields
| Field | Type | Required |
|-------|------|----------|
| employee_id | text | Yes |
| employee_name | text | Yes |
| department | select | Yes |
| date | date | Yes |
| check_in | time | No |
| check_out | time | No |
| overtime_hours | number | No |
| leave_type | select | No |
| leave_hours | number | No |
| status | select | Yes |
| remarks | text | No |
### Accident Default Fields
| Field | Type | Required |
|-------|------|----------|
| date | date | Yes |
| time | time | Yes |
| location | text | Yes |
| employee_name | text | Yes |
| employee_id | text | Yes |
| department | select | Yes |
| description | text | Yes |
| severity | select | Yes |
| medical_report | text | No |
| action_taken | text | No |
| responsible_person | text | No |
---
## 8. Security
- Passwords hashed with bcrypt
- JWT with 24h expiry
- CORS configured for known origins only
- Input sanitization on all endpoints
- Soft delete (never hard delete user data)
- Rate limiting on login endpoint
---
## 9. Out of Scope (v1)
- User management (create/edit users) - only admin can do this via direct DB
- Multi-company support
- Recurring attendance (scheduled check-in reminders)
- Document/photo upload for accidents
- Email notifications
- Mobile responsive redesign
- API for third-party integrations