hrms-checkin/CLAUDE.md

6.9 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is an HRMS (Human Resource Management System) check-in/check-out web application built for the Bangkok Metropolitan Administration (BMA). The application allows employees to record their work attendance using geolocation verification and camera features.

Tech Stack:

  • Vue 3 with Composition API and TypeScript 4.7.4
  • Vite for build tooling
  • Quasar Framework for UI components
  • Pinia for state management
  • Vue Router for routing
  • Keycloak for authentication
  • ArcGIS API and Google Maps for location features
  • PWA capabilities with offline support
  • Docker deployment with nginx

Development Server: Runs on port 3008

Common Commands

# Development
npm run dev                    # Start dev server on port 3008

# Building
npm run build                  # Build for production
npm run preview                # Preview production build on port 3008

# Testing
npm run test:unit              # Run unit tests with vitest
npm run test:e2e               # Run e2e tests with cypress
npm run test:e2e:dev           # Run cypress in dev mode

# Code Quality
npm run lint                   # Lint and auto-fix code
npm run format                 # Format code with prettier
npm run type-check             # TypeScript type checking

# Docker
docker buildx build --platform=linux/amd64 -f docker/Dockerfile . -t hrms-checkin:0.1

Architecture

Directory Structure

src/
├── api/               # API layer modules (checkin, history, message)
├── components/        # Reusable Vue components
├── composables/       # Vue composables (e.g., usePermissions)
├── interface/         # TypeScript type definitions
│   └── response/      # API response types
├── plugins/           # Vue plugins (auth, http, keycloak)
├── router/            # Vue Router configuration
├── stores/            # Pinia stores for state management
├── style/             # Global styles and Quasar variables
├── utils/             # Utility functions
└── views/             # Page-level Vue components

Key Architecture Patterns

Authentication Flow:

  • Uses Keycloak for SSO authentication
  • Tokens stored in cookies with BMAHRISCKI_KEYCLOAK_IDENTITY key
  • Auth state managed in src/plugins/auth.ts
  • Router guards enforce authentication on protected routes
  • 401 responses trigger automatic logout via axios interceptor

State Management:

  • stores/mixin.ts - Global utilities (Thai date formatting, dialogs, loaders, error handling)
  • stores/chekin.ts - Check-in history and status management
  • stores/privacy.ts - Privacy consent management
  • stores/positionKeycloak.ts - User position/role data

API Layer:

  • Base axios instance in src/plugins/http.ts with automatic token injection
  • API endpoints organized by feature in src/api/
  • Environment-specific API URLs configured in src/api/index.ts
  • Production API URL set via VITE_API_URI_CONFIG env variable

Routing:

  • Main layout (MainView) wraps authenticated routes
  • Protected routes require meta.Auth: true
  • Auth check runs in router beforeEach guard
  • Public routes: /login, /auth, /reset-password, /history

Geolocation & Maps:

  • ArcGIS JS API for advanced mapping features
  • Google Maps integration for location services
  • Camera integration for check-in photo verification
  • Privacy consent required before accessing camera/location

Date/Time Handling:

  • Thai Buddhist calendar (BE) conversion (+543 years)
  • Thai month names (full and abbreviated)
  • date-fns-tz for timezone handling (Asia/Bangkok)
  • Fiscal year calculation (October start)

Component Conventions

  • Components use Quasar UI components (q-btn, q-dialog, etc.)
  • Thai language throughout the UI
  • Custom dialogs use CustomDialog.vue component
  • Loading states use Quasar's QSpinnerCube
  • Error dialogs prevent overlap with activeErrorDialog tracking

Localization

  • Quasar configured with Thai language (quasar/lang/th)
  • All UI text in Thai
  • Date formatting uses date2Thai() and monthYear2Thai() from mixin store
  • Status labels translated: ABSENT→'ขาดราชการ', NORMAL→'ปกติ', LATE→'สาย'

Environment Variables

Required in .env.production:

  • VITE_API_URI_CONFIG - Production API base URL
  • VITE_URL_SSO - Keycloak SSO logout URL
  • VITE_URL_USER - User service URL for redirects
  • VITE_URL_LANDING - Landing page URL

Note: .env.local uses : instead of = for variable assignment (non-standard format that works with the current setup)

  • VITE_API_URI_CONFIG - Production API base URL
  • VITE_URL_SSO - Keycloak SSO logout URL
  • VITE_URL_USER - User service URL for redirects

PWA Configuration

  • Auto-update registration with vite-plugin-pwa
  • Manifest: "HRMS-Checkin" / "HRMS Checkin"
  • Icons: 192x192 and 512x512 PNG
  • Service worker registered in src/registerServiceWorker.ts

Import Aliases

  • @ is configured as an alias for the src/ directory
  • Use this for all imports from within the source directory

Environment Variable Substitution (Docker)

The Docker build uses a multi-stage pattern:

  1. Build stage: Node.js Alpine builds the static assets with npm run build
  2. Production stage: nginx serves the static files
  • Environment variables (VITE_API_URI_CONFIG, VITE_URL_SSO, VITE_URL_LANDING, VITE_URL_USER) are substituted at container runtime via entrypoint.sh using sed
  • Built JS files contain placeholder values that get replaced with actual values at startup

Testing Patterns

  • Unit tests: *.spec.{js,ts} - Run with Vitest in jsdom environment
  • E2E tests: *.cy.{js,ts} - Run with Cypress
  • E2E test server runs on port 4173 (via start-server-and-test)

HTTP Interceptor Behavior

  • The axios interceptor in http.ts detects 401/403 responses but automatic logout is currently disabled (commented out)
  • 401 handling is done manually in messageError() from the mixin store

Development Notes

When adding new features:

  1. Create API functions in src/api/
  2. Define TypeScript interfaces in src/interface/response/
  3. Use Pinia stores for complex state, composables for reusable logic
  4. Follow Thai localization patterns for user-facing text
  5. Ensure privacy consent flow for camera/location features

When working with dates:

  • Always use date2Thai() or convertDateToAPI() from mixin store
  • Dates stored in BE format (year + 543)
  • API expects yyyy-MM-dd or yyyy-MM-dd HH:mm:ss format

When handling errors:

  • Use messageError() from mixin store for consistent error dialogs
  • 401 errors trigger automatic logout
  • Dialog overlap prevention built into error handling

When running tests:

  • Unit tests use Vitest with jsdom environment
  • E2E tests use Cypress with baseUrl: http://localhost:4173
  • Test files follow pattern: *.cy.{js,ts} or *.spec.{js,ts}