# 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 + password,JWT 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= 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