Refactor entity services with hybrid sync pattern

Introduces BaseEntityService and SyncPlugin to eliminate code duplication across entity services

Improves:
- Code reusability through inheritance and composition
- Sync infrastructure for all entity types
- Polymorphic sync status management
- Reduced boilerplate code by ~75%

Supports generic sync for Event, Booking, Customer, and Resource entities
This commit is contained in:
Janus C. H. Knudsen 2025-11-18 16:37:33 +01:00
parent 2aa9d06fab
commit 8e52d670d6
30 changed files with 1960 additions and 526 deletions

View file

@ -1,3 +1,5 @@
import { ISync } from './CalendarTypes';
/**
* Booking entity - represents customer service bookings ONLY
*
@ -18,7 +20,7 @@
*
* Matches backend Booking table structure
*/
export interface IBooking {
export interface IBooking extends ISync {
id: string;
customerId: string; // REQUIRED - booking is always for a customer
status: BookingStatus;

View file

@ -9,13 +9,35 @@ export type CalendarView = ViewPeriod;
export type SyncStatus = 'synced' | 'pending' | 'error';
/**
* EntityType - Discriminator for all syncable entities
*/
export type EntityType = 'Event' | 'Booking' | 'Customer' | 'Resource';
/**
* ISync - Interface composition for sync status tracking
* All syncable entities should extend this interface
*/
export interface ISync {
syncStatus: SyncStatus;
}
/**
* IDataEntity - Wrapper for entity data with typename discriminator
* Used in queue operations and API calls to preserve type information at runtime
*/
export interface IDataEntity {
typename: EntityType;
data: any;
}
export interface IRenderContext {
container: HTMLElement;
startDate: Date;
endDate: Date;
}
export interface ICalendarEvent {
export interface ICalendarEvent extends ISync {
id: string;
title: string;
description?: string;
@ -23,7 +45,6 @@ export interface ICalendarEvent {
end: Date;
type: CalendarEventType; // Event type - only 'customer' has associated booking
allDay: boolean;
syncStatus: SyncStatus;
// References (denormalized for IndexedDB performance)
bookingId?: string; // Reference to booking (only if type = 'customer')

View file

@ -1,8 +1,10 @@
import { ISync } from './CalendarTypes';
/**
* Customer entity
* Matches backend Customer table structure
*/
export interface ICustomer {
export interface ICustomer extends ISync {
id: string;
name: string;
phone: string;

View file

@ -1,8 +1,10 @@
import { ISync } from './CalendarTypes';
/**
* Resource entity - represents people, rooms, equipment, etc.
* Matches backend Resource table structure
*/
export interface IResource {
export interface IResource extends ISync {
id: string; // Primary key (e.g., "EMP001", "ROOM-A")
name: string; // Machine name (e.g., "karina.knudsen")
displayName: string; // Human-readable name (e.g., "Karina Knudsen")