- Initialize SvelteKit project with Tailwind CSS and DaisyUI - Configure API base URL and environment variables - Create base API client with JWT token handling (src/lib/api/client.js) - Implement login/logout flow (src/lib/api/auth.js, src/routes/login/+page.svelte) - Create root layout with navigation (src/routes/+layout.svelte) - Set up protected route group with auth checks (src/routes/(app)/+layout.svelte) - Create dashboard homepage (src/routes/(app)/dashboard/+page.svelte) - Add auth state store with localStorage persistence (src/lib/stores/auth.js) All Phase 0 foundation items completed per implementation plan.
16 KiB
CLQMS Frontend Implementation Plan
Project Overview
CLQMS (Clinical Laboratory Quality Management System) frontend built with SvelteKit using the KISS (Keep It Simple) principle.
Architecture Decisions (KISS Principles)
- No TypeScript - Plain JavaScript to keep it simple
- Tailwind CSS & DaisyUI - Utility classes, minimal custom CSS
- Simple Fetch API - Manual wrapper functions, no codegen
- SvelteKit File-based Routing - Standard patterns
- Server-side auth checking - SvelteKit hooks for session validation
Project Structure
src/
├── lib/
│ ├── api/ # API service functions
│ │ ├── client.js # Base fetch wrapper with auth
│ │ ├── auth.js # Auth endpoints
│ │ ├── valuesets.js # ValueSet endpoints
│ │ ├── masterdata.js # Master data endpoints
│ │ ├── patients.js # Patient endpoints
│ │ └── ...
│ ├── components/ # Reusable Svelte components
│ │ ├── FormInput.svelte
│ │ ├── DataTable.svelte
│ │ ├── SelectDropdown.svelte
│ │ └── Layout.svelte
│ └── stores/ # Svelte stores
│ ├── auth.js # Auth state
│ └── valuesets.js # Cached lookup values
├── routes/
│ ├── +layout.svelte # Root layout with nav
│ ├── +page.svelte # Dashboard (home)
│ ├── login/
│ │ └── +page.svelte
│ ├── (app)/ # Group: protected routes
│ │ ├── +layout.svelte # Auth check
│ │ ├── patients/
│ │ ├── valuesets/
│ │ ├── masterdata/
│ │ └── ...
│ └── api/ # Internal API routes (if needed)
└── app.html
Implementation Phases
Phase 0: Foundation ✅ COMPLETED
Priority: High | Time Estimate: 1-2 hours | Status: Done
- Initialize SvelteKit project with Tailwind CSS
- Configure API base URL and environment variables
- Create base API client with JWT token handling
- Implement login/logout flow
- Create root layout with navigation
- Set up protected route group with auth checks
- Create dashboard homepage
Key Files:
src/lib/api/client.js- Base fetch wrappersrc/lib/api/auth.js- Auth endpointssrc/lib/stores/auth.js- Auth state managementsrc/routes/+layout.svelte- Root layoutsrc/routes/(app)/+layout.svelte- Protected layoutsrc/routes/login/+page.svelte- Login page
Phase 1: Foundation Data
Priority: High | Time Estimate: 4-6 hours
Why First: These are prerequisites for all other modules. ValueSets provide dropdown options; Master Data provides reference entities.
1a. ValueSets Module
- ValueSet definitions list page
- ValueSet definitions create/edit form
- ValueSet items management (CRUD)
- Cache frequently used value sets in stores
API Endpoints:
GET /api/valueset- List value set definitionsPOST /api/valuesetdef- Create value set definitionPUT /api/valuesetdef/{id}- Update value set definitionDELETE /api/valuesetdef/{id}- Delete value set definitionGET /api/valueset/items- List value set itemsPOST /api/valueset/items- Create value set itemPUT /api/valueset/items/{id}- Update value set itemDELETE /api/valueset/items/{id}- Delete value set itemPOST /api/valueset/refresh- Refresh cache
1b. Master Data - Locations & Contacts
- Locations list page with search
- Locations create/edit form
- Contacts (Physicians) list page
- Contacts create/edit form
API Endpoints:
GET /api/location- List locationsPOST /api/location- Create locationPATCH /api/location- Update locationDELETE /api/location- Delete locationGET /api/location/{id}- Get location detailsGET /api/contact- List contactsPOST /api/contact- Create contactPATCH /api/contact- Update contactDELETE /api/contact- Delete contactGET /api/contact/{id}- Get contact details
1c. Master Data - Supporting Entities
- Occupations management
- Medical Specialties management
- Counters management (for ID generation)
API Endpoints:
GET /api/occupation- List occupationsPOST /api/occupation- Create occupationPATCH /api/occupation- Update occupationGET /api/occupation/{id}- Get occupation detailsGET /api/medicalspecialty- List specialtiesPOST /api/medicalspecialty- Create specialtyPATCH /api/medicalspecialty- Update specialtyGET /api/medicalspecialty/{id}- Get specialty detailsGET /api/counter- List countersPOST /api/counter- Create counterPATCH /api/counter- Update counterDELETE /api/counter- Delete counterGET /api/counter/{id}- Get counter details
1d. Master Data - Geography
- Provinces list (read-only dropdown)
- Cities list with province filter
API Endpoints:
GET /api/areageo/provinces- List provincesGET /api/areageo/cities- List cities (with province_id filter)
Phase 2: Patient Management
Priority: High | Time Estimate: 3-4 hours
Dependencies: Master Data (locations, contacts, occupations, provinces/cities)
2a. Patient CRUD
- Patients list page with pagination and search
- Patient create form with validation
- Patient edit form
- Patient detail view
- Patient delete with confirmation
API Endpoints:
GET /api/patient- List patients (with pagination, search)POST /api/patient- Create patientPATCH /api/patient- Update patientDELETE /api/patient- Delete patientGET /api/patient/{id}- Get patient by IDGET /api/patient/check- Check if patient exists
2b. Advanced Patient Features
- Patient identifier management (KTP, PASS, SSN, etc.)
- Patient linking (family relationships)
- Custodian/guardian assignment
- Patient address management
Fields to Implement:
- PatientID, AlternatePID
- Prefix, NameFirst, NameMiddle, NameLast, NameMaiden, Suffix
- Sex, Birthdate, PlaceOfBirth, Citizenship
- Address fields (Street_1/2/3, ZIP, Province, City, Country)
- Contact (Phone, MobilePhone, EmailAddress1/2)
- Identifiers (PatIdt - type and number)
- Demographics (Race, MaritalStatus, Religion, Ethnic)
- Linked patients (LinkTo)
- Custodian
- DeathIndicator, TimeOfDeath
- Comments (PatCom)
Phase 3: Patient Visits
Priority: High | Time Estimate: 2-3 hours
Dependencies: Patients, Master Data (locations, contacts)
- Visits list page with filters
- Create visit form
- Edit visit form
- View visits by patient
- ADT workflow (Admit/Discharge/Transfer)
API Endpoints:
GET /api/patvisit- List visitsPOST /api/patvisit- Create visitPATCH /api/patvisit- Update visitDELETE /api/patvisit- Delete visitGET /api/patvisit/{id}- Get visit by IDGET /api/patvisit/patient/{patientId}- Get visits by patientPOST /api/patvisitadt- Create ADT visitPATCH /api/patvisitadt- Update ADT visit
Fields:
- VisitID, PatientID, VisitDate, VisitType
- SiteID, LocationID, DepartmentID
- AttendingPhysician, ReferringPhysician
Phase 4: Specimen Management
Priority: Medium | Time Estimate: 2-3 hours
Dependencies: ValueSets (specimen types, collection methods, statuses)
- Specimens list page
- Specimen create/edit forms
- Container definitions management
- Specimen preparation methods
- Specimen statuses
- Collection methods
API Endpoints:
GET /api/specimen- List specimensPOST /api/specimen- Create specimenPATCH /api/specimen- Update specimenGET /api/specimen/{id}- Get specimen detailsGET /api/specimen/container- List containersPOST /api/specimen/container- Create containerPATCH /api/specimen/container- Update containerGET /api/specimen/container/{id}- Get container detailsGET /api/specimen/prep- List preparationsPOST /api/specimen/prep- Create preparationPATCH /api/specimen/prep- Update preparationGET /api/specimen/prep/{id}- Get preparation detailsGET /api/specimen/status- List statusesPOST /api/specimen/status- Create statusPATCH /api/specimen/status- Update statusGET /api/specimen/status/{id}- Get status detailsGET /api/specimen/collection- List collection methodsPOST /api/specimen/collection- Create collection methodPATCH /api/specimen/collection- Update collection methodGET /api/specimen/collection/{id}- Get collection method details
Phase 5: Test Catalog
Priority: Medium | Time Estimate: 2-3 hours
Dependencies: Organization (disciplines, departments), ValueSets
- Test definitions list with filtering
- Create/edit test definitions
- Test mapping management (host/client codes)
API Endpoints:
GET /api/tests- List tests (with filters)POST /api/tests- Create testPATCH /api/tests- Update testGET /api/tests/{id}- Get test details
Test Types: TEST, PARAM, CALC, GROUP, TITLE
Phase 6: Orders
Priority: High | Time Estimate: 3-4 hours
Dependencies: Patients, Visits, Tests, Specimen, ValueSets (priorities, statuses)
- Orders list with status filtering
- Create order with test selection
- Order detail view
- Update order status
- Order items management
API Endpoints:
GET /api/ordertest- List orders (with filters)POST /api/ordertest- Create orderPATCH /api/ordertest- Update orderDELETE /api/ordertest- Delete orderGET /api/ordertest/{id}- Get order detailsPOST /api/ordertest/status- Update order status
Phase 7: Results & Dashboard
Priority: High | Time Estimate: 2-3 hours
Dependencies: Orders
- Dashboard with summary cards
- Results list with patient filtering
- Sample tracking view
API Endpoints:
GET /api/dashboard- Get dashboard summaryGET /api/result- Get patient resultsGET /api/sample- Get samples
Dashboard Metrics:
- pendingOrders
- todayResults
- criticalResults
- activePatients
Phase 8: Organization Structure
Priority: Medium | Time Estimate: 2-3 hours
- Accounts management
- Sites management
- Disciplines management
- Departments management
- Workstations management
API Endpoints:
GET /api/organization/account- List accountsPOST /api/organization/account- Create accountPATCH /api/organization/account- Update accountDELETE /api/organization/account- Delete accountGET /api/organization/account/{id}- Get account detailsGET /api/organization/site- List sitesPOST /api/organization/site- Create sitePATCH /api/organization/site- Update siteDELETE /api/organization/site- Delete siteGET /api/organization/site/{id}- Get site detailsGET /api/organization/discipline- List disciplinesPOST /api/organization/discipline- Create disciplinePATCH /api/organization/discipline- Update disciplineDELETE /api/organization/discipline- Delete disciplineGET /api/organization/discipline/{id}- Get discipline detailsGET /api/organization/department- List departmentsPOST /api/organization/department- Create departmentPATCH /api/organization/department- Update departmentDELETE /api/organization/department- Delete departmentGET /api/organization/department/{id}- Get department detailsGET /api/organization/workstation- List workstationsPOST /api/organization/workstation- Create workstationPATCH /api/organization/workstation- Update workstationDELETE /api/organization/workstation- Delete workstationGET /api/organization/workstation/{id}- Get workstation details
Phase 9: Edge API (Instrument Integration)
Priority: Low | Time Estimate: 2-3 hours
- Edge results viewer
- Pending orders for instruments
- Instrument status monitoring
API Endpoints:
GET /api/edge/orders- Fetch pending ordersPOST /api/edge/orders/{orderId}/ack- Acknowledge orderPOST /api/edge/status- Log instrument status
Reusable Components to Build
1. FormInput.svelte
Text input with label, validation, and error display.
<FormInput
label="Patient ID"
name="patientId"
value={patientId}
required
pattern="[A-Za-z0-9]+"
/>
2. SelectDropdown.svelte
Dropdown populated from ValueSets or API data.
<SelectDropdown
label="Gender"
name="sex"
value={sex}
options={genderOptions}
/>
3. DataTable.svelte
Sortable, paginated table with actions.
<DataTable
columns={['ID', 'Name', 'Status']}
data={patients}
onEdit={handleEdit}
onDelete={handleDelete}
pagination={true}
/>
4. SearchBar.svelte
Search input with debounce.
5. Modal.svelte
Reusable modal for confirmations and forms.
Code Patterns
API Client Pattern
// lib/api/client.js
const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost/clqms01';
export async function apiFetch(endpoint, options = {}) {
const token = get(authToken);
const res = await fetch(`${API_BASE}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...(token && { 'Authorization': `Bearer ${token}` }),
...options.headers
}
});
if (res.status === 401) {
// Handle unauthorized
authToken.set(null);
goto('/login');
return;
}
return res.json();
}
Form Handling Pattern
<script>
let formData = { name: '', email: '' };
let errors = {};
let loading = false;
async function handleSubmit() {
loading = true;
errors = {};
const result = await createItem(formData);
if (result.status === 'error') {
errors = result.errors || { general: result.message };
} else {
// Success - redirect or show message
}
loading = false;
}
</script>
<form on:submit|preventDefault={handleSubmit}>
<FormInput
label="Name"
bind:value={formData.name}
error={errors.name}
/>
<button type="submit" disabled={loading}>
{loading ? 'Saving...' : 'Save'}
</button>
</form>
Store Pattern for ValueSets
// lib/stores/valuesets.js
import { writable } from 'svelte/store';
export const valueSets = writable({});
export async function loadValueSet(code) {
const res = await fetch(`/api/valueset?VSetCode=${code}`);
const data = await res.json();
valueSets.update(vs => ({
...vs,
[code]: data.data || []
}));
}
// Usage in component:
// onMount(() => loadValueSet('GENDER'));
Environment Setup
Create .env file:
VITE_API_URL=http://localhost/clqms01
Getting Started
-
Initialize SvelteKit:
npm create svelte@latest clqms-fe cd clqms-fe npm install npx svelte-add@latest tailwindcss npm install -
Configure tailwind.config.js:
export default { content: ['./src/**/*.{html,js,svelte,ts}'], theme: { extend: {} }, plugins: [] }; -
Start with Phase 0:
- Create API client
- Set up auth stores
- Build login page
- Create protected layout
Navigation Structure
Dashboard (Home)
├── Master Data
│ ├── ValueSets
│ ├── Locations
│ ├── Contacts
│ ├── Occupations
│ ├── Medical Specialties
│ └── Counters
├── Organization
│ ├── Accounts
│ ├── Sites
│ ├── Disciplines
│ ├── Departments
│ └── Workstations
├── Patients
│ ├── All Patients
│ └── Patient Visits
├── Laboratory
│ ├── Specimens
│ ├── Tests
│ ├── Orders
│ └── Results
└── Edge
└── Instrument Status
Notes
- Use
+layout.server.jsfor server-side auth checks - Use SvelteKit's
invalidateAll()after mutations - Cache ValueSets in localStorage for better UX
- Implement optimistic updates where appropriate
- Use loading states for all async operations
- Add toast notifications for success/error feedback