@zonetrix/shared 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +200 -2
- package/dist/index.d.ts +200 -2
- package/dist/index.js +211 -0
- package/dist/index.mjs +201 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
type SeatState = "available" | "reserved" | "selected" | "unavailable" | "hidden";
|
|
5
5
|
type SeatShape = "circle" | "square" | "rounded-square";
|
|
6
|
-
type Tool = "select" | "seat" | "row" | "section" | "
|
|
6
|
+
type Tool = "select" | "seat" | "row" | "section" | "object";
|
|
7
7
|
type EditorMode = "edit" | "read";
|
|
8
|
+
type ObjectType = "stage" | "table" | "wall" | "barrier" | "dj-booth" | "bar" | "entry-exit" | "custom";
|
|
8
9
|
/**
|
|
9
10
|
* Seat data structure used in the editor and viewer
|
|
10
11
|
*/
|
|
@@ -50,6 +51,12 @@ interface StageConfig {
|
|
|
50
51
|
color?: string;
|
|
51
52
|
floorId?: string;
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Object configuration (extends StageConfig with object type support)
|
|
56
|
+
*/
|
|
57
|
+
interface ObjectConfig extends StageConfig {
|
|
58
|
+
objectType?: ObjectType;
|
|
59
|
+
}
|
|
53
60
|
/**
|
|
54
61
|
* Floor configuration for multi-floor venues
|
|
55
62
|
*/
|
|
@@ -247,4 +254,195 @@ declare function importConfigFromJSON(jsonString: string): SeatMapConfig;
|
|
|
247
254
|
*/
|
|
248
255
|
declare function downloadConfigAsFile(config: SeatMapConfig, filename?: string): void;
|
|
249
256
|
|
|
250
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Firebase Realtime Database type definitions for Seat Map Studio
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Firebase seat state (excludes 'selected' which is client-only, 'hidden' which is filtered)
|
|
263
|
+
*/
|
|
264
|
+
type FirebaseSeatState = 'available' | 'reserved' | 'unavailable';
|
|
265
|
+
/**
|
|
266
|
+
* Lightweight seat states map for high-frequency real-time updates
|
|
267
|
+
* Stored at: seat_states/{seatMapId}
|
|
268
|
+
*/
|
|
269
|
+
interface FirebaseSeatStates {
|
|
270
|
+
[seatId: string]: FirebaseSeatState;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Position in Firebase (same structure as app)
|
|
274
|
+
*/
|
|
275
|
+
interface FirebasePosition {
|
|
276
|
+
x: number;
|
|
277
|
+
y: number;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Seat data stored in Firebase
|
|
281
|
+
* Stored at: seatmaps/{seatMapId}/seats/{seatId}
|
|
282
|
+
*/
|
|
283
|
+
interface FirebaseSeat {
|
|
284
|
+
position: FirebasePosition;
|
|
285
|
+
shape: SeatShape;
|
|
286
|
+
state: FirebaseSeatState;
|
|
287
|
+
sectionName?: string;
|
|
288
|
+
rowLabel?: string;
|
|
289
|
+
columnLabel?: string;
|
|
290
|
+
seatNumber?: string;
|
|
291
|
+
price?: number;
|
|
292
|
+
floorId?: string;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Stage configuration in Firebase
|
|
296
|
+
* Stored at: seatmaps/{seatMapId}/config/stages/{stageId}
|
|
297
|
+
*/
|
|
298
|
+
interface FirebaseStage {
|
|
299
|
+
position: FirebasePosition;
|
|
300
|
+
config: {
|
|
301
|
+
label: string;
|
|
302
|
+
width: number;
|
|
303
|
+
height: number;
|
|
304
|
+
rotation?: number;
|
|
305
|
+
color?: string;
|
|
306
|
+
objectType?: ObjectType;
|
|
307
|
+
};
|
|
308
|
+
floorId?: string;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Canvas configuration in Firebase
|
|
312
|
+
* Stored at: seatmaps/{seatMapId}/config/canvas
|
|
313
|
+
*/
|
|
314
|
+
interface FirebaseCanvasConfig {
|
|
315
|
+
width: number;
|
|
316
|
+
height: number;
|
|
317
|
+
backgroundColor: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Seat map metadata in Firebase
|
|
321
|
+
* Stored at: seatmaps/{seatMapId}/meta
|
|
322
|
+
*/
|
|
323
|
+
interface FirebaseSeatMapMeta {
|
|
324
|
+
event_id: number;
|
|
325
|
+
sub_event_id: number;
|
|
326
|
+
name: string;
|
|
327
|
+
venue?: string;
|
|
328
|
+
capacity?: number;
|
|
329
|
+
updated_at: number;
|
|
330
|
+
version: string;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Design configuration in Firebase (excludes seats which are separate)
|
|
334
|
+
* Stored at: seatmaps/{seatMapId}/config
|
|
335
|
+
*/
|
|
336
|
+
interface FirebaseSeatMapConfig {
|
|
337
|
+
canvas: FirebaseCanvasConfig;
|
|
338
|
+
colors: ColorSettings;
|
|
339
|
+
floors?: Record<string, FloorConfig>;
|
|
340
|
+
stages?: Record<string, FirebaseStage>;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Complete seat map data structure in Firebase
|
|
344
|
+
* Stored at: seatmaps/{seatMapId}
|
|
345
|
+
*/
|
|
346
|
+
interface FirebaseSeatMap {
|
|
347
|
+
meta: FirebaseSeatMapMeta;
|
|
348
|
+
config: FirebaseSeatMapConfig;
|
|
349
|
+
seats: Record<string, FirebaseSeat>;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Index entry for seat map lookup by event
|
|
353
|
+
* Stored at: indexes/by_event/{eventId}/{seatMapId}
|
|
354
|
+
*/
|
|
355
|
+
type FirebaseIndexEntry = true;
|
|
356
|
+
/**
|
|
357
|
+
* Options for Firebase real-time hooks
|
|
358
|
+
*/
|
|
359
|
+
interface FirebaseHookOptions {
|
|
360
|
+
enabled?: boolean;
|
|
361
|
+
onError?: (error: Error) => void;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Result from Firebase seat states hook
|
|
365
|
+
*/
|
|
366
|
+
interface FirebaseSeatStatesResult {
|
|
367
|
+
states: FirebaseSeatStates | null;
|
|
368
|
+
loading: boolean;
|
|
369
|
+
error: Error | null;
|
|
370
|
+
lastUpdated: number | null;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Result from Firebase config hook
|
|
374
|
+
*/
|
|
375
|
+
interface FirebaseConfigResult {
|
|
376
|
+
config: FirebaseSeatMap | null;
|
|
377
|
+
loading: boolean;
|
|
378
|
+
error: Error | null;
|
|
379
|
+
refetch: () => Promise<void>;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Firebase Realtime Database path utilities
|
|
384
|
+
* Provides type-safe path builders for all Firebase nodes
|
|
385
|
+
*/
|
|
386
|
+
/**
|
|
387
|
+
* All Firebase database paths used by Seat Map Studio
|
|
388
|
+
*/
|
|
389
|
+
declare const FirebasePaths: {
|
|
390
|
+
readonly seatmap: (seatMapId: string) => `seatmaps/${string}`;
|
|
391
|
+
readonly seatmapMeta: (seatMapId: string) => `seatmaps/${string}/meta`;
|
|
392
|
+
readonly seatmapConfig: (seatMapId: string) => `seatmaps/${string}/config`;
|
|
393
|
+
readonly seatmapSeats: (seatMapId: string) => `seatmaps/${string}/seats`;
|
|
394
|
+
readonly seatmapSeat: (seatMapId: string, seatId: string) => `seatmaps/${string}/seats/${string}`;
|
|
395
|
+
readonly seatStates: (seatMapId: string) => `seat_states/${string}`;
|
|
396
|
+
readonly seatState: (seatMapId: string, seatId: string) => `seat_states/${string}/${string}`;
|
|
397
|
+
readonly indexByEvent: (eventId: number) => `indexes/by_event/${number}`;
|
|
398
|
+
readonly indexBySubEvent: (subEventId: number) => `indexes/by_sub_event/${number}`;
|
|
399
|
+
readonly indexEntry: (eventId: number, seatMapId: string) => `indexes/by_event/${number}/${string}`;
|
|
400
|
+
readonly indexSubEventEntry: (subEventId: number, seatMapId: string) => `indexes/by_sub_event/${number}/${string}`;
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Encode seat ID for Firebase path (Firebase doesn't allow certain characters)
|
|
404
|
+
* Replaces: . # $ [ ] /
|
|
405
|
+
*/
|
|
406
|
+
declare function encodeSeatId(seatId: string): string;
|
|
407
|
+
/**
|
|
408
|
+
* Decode seat ID from Firebase path
|
|
409
|
+
*/
|
|
410
|
+
declare function decodeSeatId(encodedId: string): string;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Converters between SeatMapConfig and Firebase data structures
|
|
414
|
+
*/
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Convert app SeatState to Firebase state (filters out 'selected' and 'hidden')
|
|
418
|
+
*/
|
|
419
|
+
declare function toFirebaseState(state: SeatState): FirebaseSeatState;
|
|
420
|
+
/**
|
|
421
|
+
* Convert Firebase state to app SeatState
|
|
422
|
+
*/
|
|
423
|
+
declare function fromFirebaseState(state: FirebaseSeatState): SeatState;
|
|
424
|
+
/**
|
|
425
|
+
* Convert SeatMapConfig to Firebase format
|
|
426
|
+
*/
|
|
427
|
+
declare function toFirebaseSeatMap(config: SeatMapConfig, eventId: number, subEventId: number): FirebaseSeatMap;
|
|
428
|
+
/**
|
|
429
|
+
* Convert Firebase data to SeatMapConfig
|
|
430
|
+
*/
|
|
431
|
+
declare function fromFirebaseSeatMap(firebase: FirebaseSeatMap, seatStates?: FirebaseSeatStates): SeatMapConfig;
|
|
432
|
+
/**
|
|
433
|
+
* Extract seat states from SeatMapConfig for the lightweight states node
|
|
434
|
+
*/
|
|
435
|
+
declare function extractSeatStates(config: SeatMapConfig): FirebaseSeatStates;
|
|
436
|
+
/**
|
|
437
|
+
* Merge Firebase seat states with locally-derived reserved/unavailable arrays
|
|
438
|
+
*/
|
|
439
|
+
declare function deriveSeatArraysFromStates(states: FirebaseSeatStates): {
|
|
440
|
+
reservedSeats: string[];
|
|
441
|
+
unavailableSeats: string[];
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* Create index updates for a seat map
|
|
445
|
+
*/
|
|
446
|
+
declare function createIndexUpdates(seatMapId: string, eventId: number, subEventId: number): Record<string, boolean>;
|
|
447
|
+
|
|
448
|
+
export { type AlignmentGuide, type BookingSelection, type CanvasConfig, type CanvasState, type ColorSettings, DEFAULT_COLORS, type EditorMode, type FirebaseCanvasConfig, type FirebaseConfigResult, type FirebaseHookOptions, type FirebaseIndexEntry, FirebasePaths, type FirebasePosition, type FirebaseSeat, type FirebaseSeatMap, type FirebaseSeatMapConfig, type FirebaseSeatMapMeta, type FirebaseSeatState, type FirebaseSeatStates, type FirebaseSeatStatesResult, type FirebaseStage, type ObjectConfig, type ObjectType, type RowPricing, type SeatData, type SeatMapConfig, type SeatMapMetadata, type SeatShape, type SeatState, type SectionConfig, type SerializedSeat, type SerializedSection, type SerializedStage, type StageConfig, type Tool, type ValidationResult, applySeatStateOverrides, calculateAvailableSeats, calculateCapacity, calculateSeatPrice, cloneConfig, createDefaultConfig, createIndexUpdates, decodeSeatId, deriveSeatArraysFromStates, downloadConfigAsFile, encodeSeatId, exportConfigAsJSON, extractSeatStates, formatDate, fromFirebaseSeatMap, fromFirebaseState, generateId, getSelectedSeats, importConfigFromJSON, toFirebaseSeatMap, toFirebaseState, updateConfigTimestamp, validateSeatMapConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
type SeatState = "available" | "reserved" | "selected" | "unavailable" | "hidden";
|
|
5
5
|
type SeatShape = "circle" | "square" | "rounded-square";
|
|
6
|
-
type Tool = "select" | "seat" | "row" | "section" | "
|
|
6
|
+
type Tool = "select" | "seat" | "row" | "section" | "object";
|
|
7
7
|
type EditorMode = "edit" | "read";
|
|
8
|
+
type ObjectType = "stage" | "table" | "wall" | "barrier" | "dj-booth" | "bar" | "entry-exit" | "custom";
|
|
8
9
|
/**
|
|
9
10
|
* Seat data structure used in the editor and viewer
|
|
10
11
|
*/
|
|
@@ -50,6 +51,12 @@ interface StageConfig {
|
|
|
50
51
|
color?: string;
|
|
51
52
|
floorId?: string;
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Object configuration (extends StageConfig with object type support)
|
|
56
|
+
*/
|
|
57
|
+
interface ObjectConfig extends StageConfig {
|
|
58
|
+
objectType?: ObjectType;
|
|
59
|
+
}
|
|
53
60
|
/**
|
|
54
61
|
* Floor configuration for multi-floor venues
|
|
55
62
|
*/
|
|
@@ -247,4 +254,195 @@ declare function importConfigFromJSON(jsonString: string): SeatMapConfig;
|
|
|
247
254
|
*/
|
|
248
255
|
declare function downloadConfigAsFile(config: SeatMapConfig, filename?: string): void;
|
|
249
256
|
|
|
250
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Firebase Realtime Database type definitions for Seat Map Studio
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Firebase seat state (excludes 'selected' which is client-only, 'hidden' which is filtered)
|
|
263
|
+
*/
|
|
264
|
+
type FirebaseSeatState = 'available' | 'reserved' | 'unavailable';
|
|
265
|
+
/**
|
|
266
|
+
* Lightweight seat states map for high-frequency real-time updates
|
|
267
|
+
* Stored at: seat_states/{seatMapId}
|
|
268
|
+
*/
|
|
269
|
+
interface FirebaseSeatStates {
|
|
270
|
+
[seatId: string]: FirebaseSeatState;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Position in Firebase (same structure as app)
|
|
274
|
+
*/
|
|
275
|
+
interface FirebasePosition {
|
|
276
|
+
x: number;
|
|
277
|
+
y: number;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Seat data stored in Firebase
|
|
281
|
+
* Stored at: seatmaps/{seatMapId}/seats/{seatId}
|
|
282
|
+
*/
|
|
283
|
+
interface FirebaseSeat {
|
|
284
|
+
position: FirebasePosition;
|
|
285
|
+
shape: SeatShape;
|
|
286
|
+
state: FirebaseSeatState;
|
|
287
|
+
sectionName?: string;
|
|
288
|
+
rowLabel?: string;
|
|
289
|
+
columnLabel?: string;
|
|
290
|
+
seatNumber?: string;
|
|
291
|
+
price?: number;
|
|
292
|
+
floorId?: string;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Stage configuration in Firebase
|
|
296
|
+
* Stored at: seatmaps/{seatMapId}/config/stages/{stageId}
|
|
297
|
+
*/
|
|
298
|
+
interface FirebaseStage {
|
|
299
|
+
position: FirebasePosition;
|
|
300
|
+
config: {
|
|
301
|
+
label: string;
|
|
302
|
+
width: number;
|
|
303
|
+
height: number;
|
|
304
|
+
rotation?: number;
|
|
305
|
+
color?: string;
|
|
306
|
+
objectType?: ObjectType;
|
|
307
|
+
};
|
|
308
|
+
floorId?: string;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Canvas configuration in Firebase
|
|
312
|
+
* Stored at: seatmaps/{seatMapId}/config/canvas
|
|
313
|
+
*/
|
|
314
|
+
interface FirebaseCanvasConfig {
|
|
315
|
+
width: number;
|
|
316
|
+
height: number;
|
|
317
|
+
backgroundColor: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Seat map metadata in Firebase
|
|
321
|
+
* Stored at: seatmaps/{seatMapId}/meta
|
|
322
|
+
*/
|
|
323
|
+
interface FirebaseSeatMapMeta {
|
|
324
|
+
event_id: number;
|
|
325
|
+
sub_event_id: number;
|
|
326
|
+
name: string;
|
|
327
|
+
venue?: string;
|
|
328
|
+
capacity?: number;
|
|
329
|
+
updated_at: number;
|
|
330
|
+
version: string;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Design configuration in Firebase (excludes seats which are separate)
|
|
334
|
+
* Stored at: seatmaps/{seatMapId}/config
|
|
335
|
+
*/
|
|
336
|
+
interface FirebaseSeatMapConfig {
|
|
337
|
+
canvas: FirebaseCanvasConfig;
|
|
338
|
+
colors: ColorSettings;
|
|
339
|
+
floors?: Record<string, FloorConfig>;
|
|
340
|
+
stages?: Record<string, FirebaseStage>;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Complete seat map data structure in Firebase
|
|
344
|
+
* Stored at: seatmaps/{seatMapId}
|
|
345
|
+
*/
|
|
346
|
+
interface FirebaseSeatMap {
|
|
347
|
+
meta: FirebaseSeatMapMeta;
|
|
348
|
+
config: FirebaseSeatMapConfig;
|
|
349
|
+
seats: Record<string, FirebaseSeat>;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Index entry for seat map lookup by event
|
|
353
|
+
* Stored at: indexes/by_event/{eventId}/{seatMapId}
|
|
354
|
+
*/
|
|
355
|
+
type FirebaseIndexEntry = true;
|
|
356
|
+
/**
|
|
357
|
+
* Options for Firebase real-time hooks
|
|
358
|
+
*/
|
|
359
|
+
interface FirebaseHookOptions {
|
|
360
|
+
enabled?: boolean;
|
|
361
|
+
onError?: (error: Error) => void;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Result from Firebase seat states hook
|
|
365
|
+
*/
|
|
366
|
+
interface FirebaseSeatStatesResult {
|
|
367
|
+
states: FirebaseSeatStates | null;
|
|
368
|
+
loading: boolean;
|
|
369
|
+
error: Error | null;
|
|
370
|
+
lastUpdated: number | null;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Result from Firebase config hook
|
|
374
|
+
*/
|
|
375
|
+
interface FirebaseConfigResult {
|
|
376
|
+
config: FirebaseSeatMap | null;
|
|
377
|
+
loading: boolean;
|
|
378
|
+
error: Error | null;
|
|
379
|
+
refetch: () => Promise<void>;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Firebase Realtime Database path utilities
|
|
384
|
+
* Provides type-safe path builders for all Firebase nodes
|
|
385
|
+
*/
|
|
386
|
+
/**
|
|
387
|
+
* All Firebase database paths used by Seat Map Studio
|
|
388
|
+
*/
|
|
389
|
+
declare const FirebasePaths: {
|
|
390
|
+
readonly seatmap: (seatMapId: string) => `seatmaps/${string}`;
|
|
391
|
+
readonly seatmapMeta: (seatMapId: string) => `seatmaps/${string}/meta`;
|
|
392
|
+
readonly seatmapConfig: (seatMapId: string) => `seatmaps/${string}/config`;
|
|
393
|
+
readonly seatmapSeats: (seatMapId: string) => `seatmaps/${string}/seats`;
|
|
394
|
+
readonly seatmapSeat: (seatMapId: string, seatId: string) => `seatmaps/${string}/seats/${string}`;
|
|
395
|
+
readonly seatStates: (seatMapId: string) => `seat_states/${string}`;
|
|
396
|
+
readonly seatState: (seatMapId: string, seatId: string) => `seat_states/${string}/${string}`;
|
|
397
|
+
readonly indexByEvent: (eventId: number) => `indexes/by_event/${number}`;
|
|
398
|
+
readonly indexBySubEvent: (subEventId: number) => `indexes/by_sub_event/${number}`;
|
|
399
|
+
readonly indexEntry: (eventId: number, seatMapId: string) => `indexes/by_event/${number}/${string}`;
|
|
400
|
+
readonly indexSubEventEntry: (subEventId: number, seatMapId: string) => `indexes/by_sub_event/${number}/${string}`;
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Encode seat ID for Firebase path (Firebase doesn't allow certain characters)
|
|
404
|
+
* Replaces: . # $ [ ] /
|
|
405
|
+
*/
|
|
406
|
+
declare function encodeSeatId(seatId: string): string;
|
|
407
|
+
/**
|
|
408
|
+
* Decode seat ID from Firebase path
|
|
409
|
+
*/
|
|
410
|
+
declare function decodeSeatId(encodedId: string): string;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Converters between SeatMapConfig and Firebase data structures
|
|
414
|
+
*/
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Convert app SeatState to Firebase state (filters out 'selected' and 'hidden')
|
|
418
|
+
*/
|
|
419
|
+
declare function toFirebaseState(state: SeatState): FirebaseSeatState;
|
|
420
|
+
/**
|
|
421
|
+
* Convert Firebase state to app SeatState
|
|
422
|
+
*/
|
|
423
|
+
declare function fromFirebaseState(state: FirebaseSeatState): SeatState;
|
|
424
|
+
/**
|
|
425
|
+
* Convert SeatMapConfig to Firebase format
|
|
426
|
+
*/
|
|
427
|
+
declare function toFirebaseSeatMap(config: SeatMapConfig, eventId: number, subEventId: number): FirebaseSeatMap;
|
|
428
|
+
/**
|
|
429
|
+
* Convert Firebase data to SeatMapConfig
|
|
430
|
+
*/
|
|
431
|
+
declare function fromFirebaseSeatMap(firebase: FirebaseSeatMap, seatStates?: FirebaseSeatStates): SeatMapConfig;
|
|
432
|
+
/**
|
|
433
|
+
* Extract seat states from SeatMapConfig for the lightweight states node
|
|
434
|
+
*/
|
|
435
|
+
declare function extractSeatStates(config: SeatMapConfig): FirebaseSeatStates;
|
|
436
|
+
/**
|
|
437
|
+
* Merge Firebase seat states with locally-derived reserved/unavailable arrays
|
|
438
|
+
*/
|
|
439
|
+
declare function deriveSeatArraysFromStates(states: FirebaseSeatStates): {
|
|
440
|
+
reservedSeats: string[];
|
|
441
|
+
unavailableSeats: string[];
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* Create index updates for a seat map
|
|
445
|
+
*/
|
|
446
|
+
declare function createIndexUpdates(seatMapId: string, eventId: number, subEventId: number): Record<string, boolean>;
|
|
447
|
+
|
|
448
|
+
export { type AlignmentGuide, type BookingSelection, type CanvasConfig, type CanvasState, type ColorSettings, DEFAULT_COLORS, type EditorMode, type FirebaseCanvasConfig, type FirebaseConfigResult, type FirebaseHookOptions, type FirebaseIndexEntry, FirebasePaths, type FirebasePosition, type FirebaseSeat, type FirebaseSeatMap, type FirebaseSeatMapConfig, type FirebaseSeatMapMeta, type FirebaseSeatState, type FirebaseSeatStates, type FirebaseSeatStatesResult, type FirebaseStage, type ObjectConfig, type ObjectType, type RowPricing, type SeatData, type SeatMapConfig, type SeatMapMetadata, type SeatShape, type SeatState, type SectionConfig, type SerializedSeat, type SerializedSection, type SerializedStage, type StageConfig, type Tool, type ValidationResult, applySeatStateOverrides, calculateAvailableSeats, calculateCapacity, calculateSeatPrice, cloneConfig, createDefaultConfig, createIndexUpdates, decodeSeatId, deriveSeatArraysFromStates, downloadConfigAsFile, encodeSeatId, exportConfigAsJSON, extractSeatStates, formatDate, fromFirebaseSeatMap, fromFirebaseState, generateId, getSelectedSeats, importConfigFromJSON, toFirebaseSeatMap, toFirebaseState, updateConfigTimestamp, validateSeatMapConfig };
|
package/dist/index.js
CHANGED
|
@@ -21,18 +21,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DEFAULT_COLORS: () => DEFAULT_COLORS,
|
|
24
|
+
FirebasePaths: () => FirebasePaths,
|
|
24
25
|
applySeatStateOverrides: () => applySeatStateOverrides,
|
|
25
26
|
calculateAvailableSeats: () => calculateAvailableSeats,
|
|
26
27
|
calculateCapacity: () => calculateCapacity,
|
|
27
28
|
calculateSeatPrice: () => calculateSeatPrice,
|
|
28
29
|
cloneConfig: () => cloneConfig,
|
|
29
30
|
createDefaultConfig: () => createDefaultConfig,
|
|
31
|
+
createIndexUpdates: () => createIndexUpdates,
|
|
32
|
+
decodeSeatId: () => decodeSeatId,
|
|
33
|
+
deriveSeatArraysFromStates: () => deriveSeatArraysFromStates,
|
|
30
34
|
downloadConfigAsFile: () => downloadConfigAsFile,
|
|
35
|
+
encodeSeatId: () => encodeSeatId,
|
|
31
36
|
exportConfigAsJSON: () => exportConfigAsJSON,
|
|
37
|
+
extractSeatStates: () => extractSeatStates,
|
|
32
38
|
formatDate: () => formatDate,
|
|
39
|
+
fromFirebaseSeatMap: () => fromFirebaseSeatMap,
|
|
40
|
+
fromFirebaseState: () => fromFirebaseState,
|
|
33
41
|
generateId: () => generateId,
|
|
34
42
|
getSelectedSeats: () => getSelectedSeats,
|
|
35
43
|
importConfigFromJSON: () => importConfigFromJSON,
|
|
44
|
+
toFirebaseSeatMap: () => toFirebaseSeatMap,
|
|
45
|
+
toFirebaseState: () => toFirebaseState,
|
|
36
46
|
updateConfigTimestamp: () => updateConfigTimestamp,
|
|
37
47
|
validateSeatMapConfig: () => validateSeatMapConfig
|
|
38
48
|
});
|
|
@@ -262,21 +272,222 @@ function downloadConfigAsFile(config, filename = "seat-map-config.json") {
|
|
|
262
272
|
document.body.removeChild(link);
|
|
263
273
|
URL.revokeObjectURL(url);
|
|
264
274
|
}
|
|
275
|
+
|
|
276
|
+
// src/firebase/schema.ts
|
|
277
|
+
var FirebasePaths = {
|
|
278
|
+
// Seat map nodes
|
|
279
|
+
seatmap: (seatMapId) => `seatmaps/${seatMapId}`,
|
|
280
|
+
seatmapMeta: (seatMapId) => `seatmaps/${seatMapId}/meta`,
|
|
281
|
+
seatmapConfig: (seatMapId) => `seatmaps/${seatMapId}/config`,
|
|
282
|
+
seatmapSeats: (seatMapId) => `seatmaps/${seatMapId}/seats`,
|
|
283
|
+
seatmapSeat: (seatMapId, seatId) => `seatmaps/${seatMapId}/seats/${seatId}`,
|
|
284
|
+
// Lightweight seat states node (for high-frequency updates)
|
|
285
|
+
seatStates: (seatMapId) => `seat_states/${seatMapId}`,
|
|
286
|
+
seatState: (seatMapId, seatId) => `seat_states/${seatMapId}/${seatId}`,
|
|
287
|
+
// Index nodes for efficient lookups
|
|
288
|
+
indexByEvent: (eventId) => `indexes/by_event/${eventId}`,
|
|
289
|
+
indexBySubEvent: (subEventId) => `indexes/by_sub_event/${subEventId}`,
|
|
290
|
+
indexEntry: (eventId, seatMapId) => `indexes/by_event/${eventId}/${seatMapId}`,
|
|
291
|
+
indexSubEventEntry: (subEventId, seatMapId) => `indexes/by_sub_event/${subEventId}/${seatMapId}`
|
|
292
|
+
};
|
|
293
|
+
function encodeSeatId(seatId) {
|
|
294
|
+
return seatId.replace(/\./g, "%2E").replace(/#/g, "%23").replace(/\$/g, "%24").replace(/\[/g, "%5B").replace(/\]/g, "%5D").replace(/\//g, "%2F");
|
|
295
|
+
}
|
|
296
|
+
function decodeSeatId(encodedId) {
|
|
297
|
+
return encodedId.replace(/%2E/g, ".").replace(/%23/g, "#").replace(/%24/g, "$").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/%2F/g, "/");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/firebase/converters.ts
|
|
301
|
+
function removeUndefined(obj) {
|
|
302
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
303
|
+
const result = {};
|
|
304
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
305
|
+
if (value !== void 0) {
|
|
306
|
+
result[key] = value;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
function toFirebaseState(state) {
|
|
312
|
+
if (state === "selected") return "available";
|
|
313
|
+
if (state === "hidden") return "unavailable";
|
|
314
|
+
return state;
|
|
315
|
+
}
|
|
316
|
+
function fromFirebaseState(state) {
|
|
317
|
+
return state;
|
|
318
|
+
}
|
|
319
|
+
function toFirebaseSeatMap(config, eventId, subEventId) {
|
|
320
|
+
const meta = removeUndefined({
|
|
321
|
+
event_id: eventId,
|
|
322
|
+
sub_event_id: subEventId,
|
|
323
|
+
name: config.metadata.name,
|
|
324
|
+
venue: config.metadata.venue,
|
|
325
|
+
capacity: config.metadata.capacity,
|
|
326
|
+
updated_at: Date.now(),
|
|
327
|
+
version: config.version
|
|
328
|
+
});
|
|
329
|
+
const seats = {};
|
|
330
|
+
for (const seat of config.seats) {
|
|
331
|
+
const encodedId = encodeSeatId(seat.id);
|
|
332
|
+
seats[encodedId] = removeUndefined({
|
|
333
|
+
position: seat.position,
|
|
334
|
+
shape: seat.shape,
|
|
335
|
+
state: toFirebaseState(seat.state),
|
|
336
|
+
sectionName: seat.sectionName,
|
|
337
|
+
rowLabel: seat.rowLabel,
|
|
338
|
+
columnLabel: seat.columnLabel,
|
|
339
|
+
seatNumber: seat.seatNumber,
|
|
340
|
+
price: seat.price,
|
|
341
|
+
floorId: seat.floorId
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
let stages = null;
|
|
345
|
+
if (config.stages && config.stages.length > 0) {
|
|
346
|
+
stages = {};
|
|
347
|
+
for (const stage of config.stages) {
|
|
348
|
+
stages[stage.id] = removeUndefined({
|
|
349
|
+
position: stage.position,
|
|
350
|
+
config: removeUndefined({
|
|
351
|
+
label: stage.config.label,
|
|
352
|
+
width: stage.config.width,
|
|
353
|
+
height: stage.config.height,
|
|
354
|
+
rotation: stage.config.rotation,
|
|
355
|
+
color: stage.config.color
|
|
356
|
+
}),
|
|
357
|
+
floorId: stage.floorId
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
let floors = null;
|
|
362
|
+
if (config.floors && config.floors.length > 0) {
|
|
363
|
+
floors = {};
|
|
364
|
+
for (const floor of config.floors) {
|
|
365
|
+
floors[floor.id] = {
|
|
366
|
+
id: floor.id,
|
|
367
|
+
name: floor.name,
|
|
368
|
+
order: floor.order,
|
|
369
|
+
...floor.color !== void 0 ? { color: floor.color } : {}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const firebaseConfig = {
|
|
374
|
+
canvas: config.canvas,
|
|
375
|
+
colors: config.colors
|
|
376
|
+
};
|
|
377
|
+
if (floors) {
|
|
378
|
+
firebaseConfig.floors = floors;
|
|
379
|
+
}
|
|
380
|
+
if (stages) {
|
|
381
|
+
firebaseConfig.stages = stages;
|
|
382
|
+
}
|
|
383
|
+
return {
|
|
384
|
+
meta,
|
|
385
|
+
config: firebaseConfig,
|
|
386
|
+
seats
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function fromFirebaseSeatMap(firebase, seatStates) {
|
|
390
|
+
const seats = Object.entries(firebase.seats || {}).map(
|
|
391
|
+
([encodedId, seat]) => {
|
|
392
|
+
const id = decodeSeatId(encodedId);
|
|
393
|
+
const state = seatStates?.[encodedId] ?? seatStates?.[id] ?? seat.state;
|
|
394
|
+
return {
|
|
395
|
+
id,
|
|
396
|
+
position: seat.position,
|
|
397
|
+
shape: seat.shape,
|
|
398
|
+
state: fromFirebaseState(state),
|
|
399
|
+
sectionName: seat.sectionName,
|
|
400
|
+
rowLabel: seat.rowLabel,
|
|
401
|
+
columnLabel: seat.columnLabel,
|
|
402
|
+
seatNumber: seat.seatNumber,
|
|
403
|
+
price: seat.price,
|
|
404
|
+
floorId: seat.floorId
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
const stages = firebase.config.stages ? Object.entries(firebase.config.stages).map(([id, stage]) => ({
|
|
409
|
+
id,
|
|
410
|
+
position: stage.position,
|
|
411
|
+
config: {
|
|
412
|
+
label: stage.config.label,
|
|
413
|
+
width: stage.config.width,
|
|
414
|
+
height: stage.config.height,
|
|
415
|
+
rotation: stage.config.rotation,
|
|
416
|
+
color: stage.config.color
|
|
417
|
+
},
|
|
418
|
+
floorId: stage.floorId
|
|
419
|
+
})) : void 0;
|
|
420
|
+
const floors = firebase.config.floors ? Object.values(firebase.config.floors).sort((a, b) => a.order - b.order) : void 0;
|
|
421
|
+
return {
|
|
422
|
+
version: firebase.meta.version,
|
|
423
|
+
metadata: {
|
|
424
|
+
name: firebase.meta.name,
|
|
425
|
+
venue: firebase.meta.venue,
|
|
426
|
+
capacity: firebase.meta.capacity,
|
|
427
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
428
|
+
// Not stored in Firebase
|
|
429
|
+
updatedAt: new Date(firebase.meta.updated_at).toISOString()
|
|
430
|
+
},
|
|
431
|
+
canvas: firebase.config.canvas,
|
|
432
|
+
colors: firebase.config.colors,
|
|
433
|
+
seats,
|
|
434
|
+
stages,
|
|
435
|
+
floors
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
function extractSeatStates(config) {
|
|
439
|
+
const states = {};
|
|
440
|
+
for (const seat of config.seats) {
|
|
441
|
+
if (seat.state === "hidden") continue;
|
|
442
|
+
const encodedId = encodeSeatId(seat.id);
|
|
443
|
+
states[encodedId] = toFirebaseState(seat.state);
|
|
444
|
+
}
|
|
445
|
+
return states;
|
|
446
|
+
}
|
|
447
|
+
function deriveSeatArraysFromStates(states) {
|
|
448
|
+
const reservedSeats = [];
|
|
449
|
+
const unavailableSeats = [];
|
|
450
|
+
for (const [encodedId, state] of Object.entries(states)) {
|
|
451
|
+
const id = decodeSeatId(encodedId);
|
|
452
|
+
if (state === "reserved") {
|
|
453
|
+
reservedSeats.push(id);
|
|
454
|
+
} else if (state === "unavailable") {
|
|
455
|
+
unavailableSeats.push(id);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return { reservedSeats, unavailableSeats };
|
|
459
|
+
}
|
|
460
|
+
function createIndexUpdates(seatMapId, eventId, subEventId) {
|
|
461
|
+
return {
|
|
462
|
+
[`indexes/by_event/${eventId}/${seatMapId}`]: true,
|
|
463
|
+
[`indexes/by_sub_event/${subEventId}/${seatMapId}`]: true
|
|
464
|
+
};
|
|
465
|
+
}
|
|
265
466
|
// Annotate the CommonJS export names for ESM import in node:
|
|
266
467
|
0 && (module.exports = {
|
|
267
468
|
DEFAULT_COLORS,
|
|
469
|
+
FirebasePaths,
|
|
268
470
|
applySeatStateOverrides,
|
|
269
471
|
calculateAvailableSeats,
|
|
270
472
|
calculateCapacity,
|
|
271
473
|
calculateSeatPrice,
|
|
272
474
|
cloneConfig,
|
|
273
475
|
createDefaultConfig,
|
|
476
|
+
createIndexUpdates,
|
|
477
|
+
decodeSeatId,
|
|
478
|
+
deriveSeatArraysFromStates,
|
|
274
479
|
downloadConfigAsFile,
|
|
480
|
+
encodeSeatId,
|
|
275
481
|
exportConfigAsJSON,
|
|
482
|
+
extractSeatStates,
|
|
276
483
|
formatDate,
|
|
484
|
+
fromFirebaseSeatMap,
|
|
485
|
+
fromFirebaseState,
|
|
277
486
|
generateId,
|
|
278
487
|
getSelectedSeats,
|
|
279
488
|
importConfigFromJSON,
|
|
489
|
+
toFirebaseSeatMap,
|
|
490
|
+
toFirebaseState,
|
|
280
491
|
updateConfigTimestamp,
|
|
281
492
|
validateSeatMapConfig
|
|
282
493
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -222,20 +222,221 @@ function downloadConfigAsFile(config, filename = "seat-map-config.json") {
|
|
|
222
222
|
document.body.removeChild(link);
|
|
223
223
|
URL.revokeObjectURL(url);
|
|
224
224
|
}
|
|
225
|
+
|
|
226
|
+
// src/firebase/schema.ts
|
|
227
|
+
var FirebasePaths = {
|
|
228
|
+
// Seat map nodes
|
|
229
|
+
seatmap: (seatMapId) => `seatmaps/${seatMapId}`,
|
|
230
|
+
seatmapMeta: (seatMapId) => `seatmaps/${seatMapId}/meta`,
|
|
231
|
+
seatmapConfig: (seatMapId) => `seatmaps/${seatMapId}/config`,
|
|
232
|
+
seatmapSeats: (seatMapId) => `seatmaps/${seatMapId}/seats`,
|
|
233
|
+
seatmapSeat: (seatMapId, seatId) => `seatmaps/${seatMapId}/seats/${seatId}`,
|
|
234
|
+
// Lightweight seat states node (for high-frequency updates)
|
|
235
|
+
seatStates: (seatMapId) => `seat_states/${seatMapId}`,
|
|
236
|
+
seatState: (seatMapId, seatId) => `seat_states/${seatMapId}/${seatId}`,
|
|
237
|
+
// Index nodes for efficient lookups
|
|
238
|
+
indexByEvent: (eventId) => `indexes/by_event/${eventId}`,
|
|
239
|
+
indexBySubEvent: (subEventId) => `indexes/by_sub_event/${subEventId}`,
|
|
240
|
+
indexEntry: (eventId, seatMapId) => `indexes/by_event/${eventId}/${seatMapId}`,
|
|
241
|
+
indexSubEventEntry: (subEventId, seatMapId) => `indexes/by_sub_event/${subEventId}/${seatMapId}`
|
|
242
|
+
};
|
|
243
|
+
function encodeSeatId(seatId) {
|
|
244
|
+
return seatId.replace(/\./g, "%2E").replace(/#/g, "%23").replace(/\$/g, "%24").replace(/\[/g, "%5B").replace(/\]/g, "%5D").replace(/\//g, "%2F");
|
|
245
|
+
}
|
|
246
|
+
function decodeSeatId(encodedId) {
|
|
247
|
+
return encodedId.replace(/%2E/g, ".").replace(/%23/g, "#").replace(/%24/g, "$").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/%2F/g, "/");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/firebase/converters.ts
|
|
251
|
+
function removeUndefined(obj) {
|
|
252
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
253
|
+
const result = {};
|
|
254
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
255
|
+
if (value !== void 0) {
|
|
256
|
+
result[key] = value;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
function toFirebaseState(state) {
|
|
262
|
+
if (state === "selected") return "available";
|
|
263
|
+
if (state === "hidden") return "unavailable";
|
|
264
|
+
return state;
|
|
265
|
+
}
|
|
266
|
+
function fromFirebaseState(state) {
|
|
267
|
+
return state;
|
|
268
|
+
}
|
|
269
|
+
function toFirebaseSeatMap(config, eventId, subEventId) {
|
|
270
|
+
const meta = removeUndefined({
|
|
271
|
+
event_id: eventId,
|
|
272
|
+
sub_event_id: subEventId,
|
|
273
|
+
name: config.metadata.name,
|
|
274
|
+
venue: config.metadata.venue,
|
|
275
|
+
capacity: config.metadata.capacity,
|
|
276
|
+
updated_at: Date.now(),
|
|
277
|
+
version: config.version
|
|
278
|
+
});
|
|
279
|
+
const seats = {};
|
|
280
|
+
for (const seat of config.seats) {
|
|
281
|
+
const encodedId = encodeSeatId(seat.id);
|
|
282
|
+
seats[encodedId] = removeUndefined({
|
|
283
|
+
position: seat.position,
|
|
284
|
+
shape: seat.shape,
|
|
285
|
+
state: toFirebaseState(seat.state),
|
|
286
|
+
sectionName: seat.sectionName,
|
|
287
|
+
rowLabel: seat.rowLabel,
|
|
288
|
+
columnLabel: seat.columnLabel,
|
|
289
|
+
seatNumber: seat.seatNumber,
|
|
290
|
+
price: seat.price,
|
|
291
|
+
floorId: seat.floorId
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
let stages = null;
|
|
295
|
+
if (config.stages && config.stages.length > 0) {
|
|
296
|
+
stages = {};
|
|
297
|
+
for (const stage of config.stages) {
|
|
298
|
+
stages[stage.id] = removeUndefined({
|
|
299
|
+
position: stage.position,
|
|
300
|
+
config: removeUndefined({
|
|
301
|
+
label: stage.config.label,
|
|
302
|
+
width: stage.config.width,
|
|
303
|
+
height: stage.config.height,
|
|
304
|
+
rotation: stage.config.rotation,
|
|
305
|
+
color: stage.config.color
|
|
306
|
+
}),
|
|
307
|
+
floorId: stage.floorId
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
let floors = null;
|
|
312
|
+
if (config.floors && config.floors.length > 0) {
|
|
313
|
+
floors = {};
|
|
314
|
+
for (const floor of config.floors) {
|
|
315
|
+
floors[floor.id] = {
|
|
316
|
+
id: floor.id,
|
|
317
|
+
name: floor.name,
|
|
318
|
+
order: floor.order,
|
|
319
|
+
...floor.color !== void 0 ? { color: floor.color } : {}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const firebaseConfig = {
|
|
324
|
+
canvas: config.canvas,
|
|
325
|
+
colors: config.colors
|
|
326
|
+
};
|
|
327
|
+
if (floors) {
|
|
328
|
+
firebaseConfig.floors = floors;
|
|
329
|
+
}
|
|
330
|
+
if (stages) {
|
|
331
|
+
firebaseConfig.stages = stages;
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
meta,
|
|
335
|
+
config: firebaseConfig,
|
|
336
|
+
seats
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
function fromFirebaseSeatMap(firebase, seatStates) {
|
|
340
|
+
const seats = Object.entries(firebase.seats || {}).map(
|
|
341
|
+
([encodedId, seat]) => {
|
|
342
|
+
const id = decodeSeatId(encodedId);
|
|
343
|
+
const state = seatStates?.[encodedId] ?? seatStates?.[id] ?? seat.state;
|
|
344
|
+
return {
|
|
345
|
+
id,
|
|
346
|
+
position: seat.position,
|
|
347
|
+
shape: seat.shape,
|
|
348
|
+
state: fromFirebaseState(state),
|
|
349
|
+
sectionName: seat.sectionName,
|
|
350
|
+
rowLabel: seat.rowLabel,
|
|
351
|
+
columnLabel: seat.columnLabel,
|
|
352
|
+
seatNumber: seat.seatNumber,
|
|
353
|
+
price: seat.price,
|
|
354
|
+
floorId: seat.floorId
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
const stages = firebase.config.stages ? Object.entries(firebase.config.stages).map(([id, stage]) => ({
|
|
359
|
+
id,
|
|
360
|
+
position: stage.position,
|
|
361
|
+
config: {
|
|
362
|
+
label: stage.config.label,
|
|
363
|
+
width: stage.config.width,
|
|
364
|
+
height: stage.config.height,
|
|
365
|
+
rotation: stage.config.rotation,
|
|
366
|
+
color: stage.config.color
|
|
367
|
+
},
|
|
368
|
+
floorId: stage.floorId
|
|
369
|
+
})) : void 0;
|
|
370
|
+
const floors = firebase.config.floors ? Object.values(firebase.config.floors).sort((a, b) => a.order - b.order) : void 0;
|
|
371
|
+
return {
|
|
372
|
+
version: firebase.meta.version,
|
|
373
|
+
metadata: {
|
|
374
|
+
name: firebase.meta.name,
|
|
375
|
+
venue: firebase.meta.venue,
|
|
376
|
+
capacity: firebase.meta.capacity,
|
|
377
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
378
|
+
// Not stored in Firebase
|
|
379
|
+
updatedAt: new Date(firebase.meta.updated_at).toISOString()
|
|
380
|
+
},
|
|
381
|
+
canvas: firebase.config.canvas,
|
|
382
|
+
colors: firebase.config.colors,
|
|
383
|
+
seats,
|
|
384
|
+
stages,
|
|
385
|
+
floors
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function extractSeatStates(config) {
|
|
389
|
+
const states = {};
|
|
390
|
+
for (const seat of config.seats) {
|
|
391
|
+
if (seat.state === "hidden") continue;
|
|
392
|
+
const encodedId = encodeSeatId(seat.id);
|
|
393
|
+
states[encodedId] = toFirebaseState(seat.state);
|
|
394
|
+
}
|
|
395
|
+
return states;
|
|
396
|
+
}
|
|
397
|
+
function deriveSeatArraysFromStates(states) {
|
|
398
|
+
const reservedSeats = [];
|
|
399
|
+
const unavailableSeats = [];
|
|
400
|
+
for (const [encodedId, state] of Object.entries(states)) {
|
|
401
|
+
const id = decodeSeatId(encodedId);
|
|
402
|
+
if (state === "reserved") {
|
|
403
|
+
reservedSeats.push(id);
|
|
404
|
+
} else if (state === "unavailable") {
|
|
405
|
+
unavailableSeats.push(id);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return { reservedSeats, unavailableSeats };
|
|
409
|
+
}
|
|
410
|
+
function createIndexUpdates(seatMapId, eventId, subEventId) {
|
|
411
|
+
return {
|
|
412
|
+
[`indexes/by_event/${eventId}/${seatMapId}`]: true,
|
|
413
|
+
[`indexes/by_sub_event/${subEventId}/${seatMapId}`]: true
|
|
414
|
+
};
|
|
415
|
+
}
|
|
225
416
|
export {
|
|
226
417
|
DEFAULT_COLORS,
|
|
418
|
+
FirebasePaths,
|
|
227
419
|
applySeatStateOverrides,
|
|
228
420
|
calculateAvailableSeats,
|
|
229
421
|
calculateCapacity,
|
|
230
422
|
calculateSeatPrice,
|
|
231
423
|
cloneConfig,
|
|
232
424
|
createDefaultConfig,
|
|
425
|
+
createIndexUpdates,
|
|
426
|
+
decodeSeatId,
|
|
427
|
+
deriveSeatArraysFromStates,
|
|
233
428
|
downloadConfigAsFile,
|
|
429
|
+
encodeSeatId,
|
|
234
430
|
exportConfigAsJSON,
|
|
431
|
+
extractSeatStates,
|
|
235
432
|
formatDate,
|
|
433
|
+
fromFirebaseSeatMap,
|
|
434
|
+
fromFirebaseState,
|
|
236
435
|
generateId,
|
|
237
436
|
getSelectedSeats,
|
|
238
437
|
importConfigFromJSON,
|
|
438
|
+
toFirebaseSeatMap,
|
|
439
|
+
toFirebaseState,
|
|
239
440
|
updateConfigTimestamp,
|
|
240
441
|
validateSeatMapConfig
|
|
241
442
|
};
|