Adds comprehensive mock data repositories and seeding infrastructure
Implements polymorphic data seeding mechanism for initial application setup - Adds Mock repositories for Event, Booking, Customer, and Resource entities - Creates DataSeeder to automatically populate IndexedDB from JSON sources - Enhances index.ts initialization process with data seeding step - Adds mock JSON data files for comprehensive test data Improves offline-first and development testing capabilities
This commit is contained in:
parent
871f5c5682
commit
5648c7c304
11 changed files with 1641 additions and 40 deletions
|
|
@ -1,33 +1,50 @@
|
|||
import { ICalendarEvent } from '../types/CalendarTypes';
|
||||
import { ICalendarEvent, EntityType } from '../types/CalendarTypes';
|
||||
import { CalendarEventType } from '../types/BookingTypes';
|
||||
import { IEventRepository, UpdateSource } from './IEventRepository';
|
||||
import { IApiRepository } from './IApiRepository';
|
||||
|
||||
interface RawEventData {
|
||||
// Core fields (required)
|
||||
id: string;
|
||||
title: string;
|
||||
start: string | Date;
|
||||
end: string | Date;
|
||||
type: string;
|
||||
color?: string;
|
||||
allDay?: boolean;
|
||||
|
||||
// Denormalized references (CRITICAL for booking architecture)
|
||||
bookingId?: string; // Reference to booking (customer events only)
|
||||
resourceId?: string; // Which resource owns this slot
|
||||
customerId?: string; // Customer reference (denormalized from booking)
|
||||
|
||||
// Optional fields
|
||||
description?: string; // Detailed event notes
|
||||
recurringId?: string; // For recurring events
|
||||
metadata?: Record<string, any>; // Flexible metadata
|
||||
|
||||
// Legacy (deprecated, keep for backward compatibility)
|
||||
color?: string; // UI-specific field
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* MockEventRepository - Loads event data from local JSON file (LEGACY)
|
||||
* MockEventRepository - Loads event data from local JSON file
|
||||
*
|
||||
* This repository implementation fetches mock event data from a static JSON file.
|
||||
* DEPRECATED: Use IndexedDBEventRepository for offline-first functionality.
|
||||
* Used for development and testing instead of API calls.
|
||||
*
|
||||
* Data Source: data/mock-events.json
|
||||
*
|
||||
* NOTE: Create/Update/Delete operations are not supported - throws errors.
|
||||
* This is intentional to encourage migration to IndexedDBEventRepository.
|
||||
* Only fetchAll() is implemented for loading initial mock data.
|
||||
*/
|
||||
export class MockEventRepository implements IEventRepository {
|
||||
export class MockEventRepository implements IApiRepository<ICalendarEvent> {
|
||||
public readonly entityType: EntityType = 'Event';
|
||||
private readonly dataUrl = 'data/mock-events.json';
|
||||
|
||||
public async loadEvents(): Promise<ICalendarEvent[]> {
|
||||
/**
|
||||
* Fetch all events from mock JSON file
|
||||
*/
|
||||
public async fetchAll(): Promise<ICalendarEvent[]> {
|
||||
try {
|
||||
const response = await fetch(this.dataUrl);
|
||||
|
||||
|
|
@ -46,36 +63,60 @@ export class MockEventRepository implements IEventRepository {
|
|||
|
||||
/**
|
||||
* NOT SUPPORTED - MockEventRepository is read-only
|
||||
* Use IndexedDBEventRepository instead
|
||||
*/
|
||||
public async createEvent(event: Omit<ICalendarEvent, 'id'>, source?: UpdateSource): Promise<ICalendarEvent> {
|
||||
throw new Error('MockEventRepository does not support createEvent. Use IndexedDBEventRepository instead.');
|
||||
public async sendCreate(event: ICalendarEvent): Promise<ICalendarEvent> {
|
||||
throw new Error('MockEventRepository does not support sendCreate. Mock data is read-only.');
|
||||
}
|
||||
|
||||
/**
|
||||
* NOT SUPPORTED - MockEventRepository is read-only
|
||||
* Use IndexedDBEventRepository instead
|
||||
*/
|
||||
public async updateEvent(id: string, updates: Partial<ICalendarEvent>, source?: UpdateSource): Promise<ICalendarEvent> {
|
||||
throw new Error('MockEventRepository does not support updateEvent. Use IndexedDBEventRepository instead.');
|
||||
public async sendUpdate(id: string, updates: Partial<ICalendarEvent>): Promise<ICalendarEvent> {
|
||||
throw new Error('MockEventRepository does not support sendUpdate. Mock data is read-only.');
|
||||
}
|
||||
|
||||
/**
|
||||
* NOT SUPPORTED - MockEventRepository is read-only
|
||||
* Use IndexedDBEventRepository instead
|
||||
*/
|
||||
public async deleteEvent(id: string, source?: UpdateSource): Promise<void> {
|
||||
throw new Error('MockEventRepository does not support deleteEvent. Use IndexedDBEventRepository instead.');
|
||||
public async sendDelete(id: string): Promise<void> {
|
||||
throw new Error('MockEventRepository does not support sendDelete. Mock data is read-only.');
|
||||
}
|
||||
|
||||
private processCalendarData(data: RawEventData[]): ICalendarEvent[] {
|
||||
return data.map((event): ICalendarEvent => ({
|
||||
...event,
|
||||
start: new Date(event.start),
|
||||
end: new Date(event.end),
|
||||
type: event.type as CalendarEventType,
|
||||
allDay: event.allDay || false,
|
||||
syncStatus: 'synced' as const
|
||||
}));
|
||||
return data.map((event): ICalendarEvent => {
|
||||
// Validate event type constraints
|
||||
if (event.type === 'customer') {
|
||||
if (!event.bookingId) {
|
||||
console.warn(`Customer event ${event.id} missing bookingId`);
|
||||
}
|
||||
if (!event.resourceId) {
|
||||
console.warn(`Customer event ${event.id} missing resourceId`);
|
||||
}
|
||||
if (!event.customerId) {
|
||||
console.warn(`Customer event ${event.id} missing customerId`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: event.id,
|
||||
title: event.title,
|
||||
description: event.description,
|
||||
start: new Date(event.start),
|
||||
end: new Date(event.end),
|
||||
type: event.type as CalendarEventType,
|
||||
allDay: event.allDay || false,
|
||||
|
||||
// Denormalized references (CRITICAL for booking architecture)
|
||||
bookingId: event.bookingId,
|
||||
resourceId: event.resourceId,
|
||||
customerId: event.customerId,
|
||||
|
||||
// Optional fields
|
||||
recurringId: event.recurringId,
|
||||
metadata: event.metadata,
|
||||
|
||||
syncStatus: 'synced' as const
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue