@blackcode_sa/metaestetics-api 1.6.3 → 1.6.4

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.
Files changed (34) hide show
  1. package/dist/admin/index.d.mts +228 -25
  2. package/dist/admin/index.d.ts +228 -25
  3. package/dist/admin/index.js +35867 -2493
  4. package/dist/admin/index.mjs +35856 -2464
  5. package/dist/backoffice/index.d.mts +252 -1
  6. package/dist/backoffice/index.d.ts +252 -1
  7. package/dist/backoffice/index.js +86 -12
  8. package/dist/backoffice/index.mjs +86 -13
  9. package/dist/index.d.mts +1400 -554
  10. package/dist/index.d.ts +1400 -554
  11. package/dist/index.js +1325 -683
  12. package/dist/index.mjs +1358 -710
  13. package/package.json +1 -1
  14. package/src/admin/index.ts +15 -1
  15. package/src/admin/notifications/notifications.admin.ts +1 -1
  16. package/src/admin/requirements/README.md +128 -0
  17. package/src/admin/requirements/patient-requirements.admin.service.ts +482 -0
  18. package/src/index.ts +16 -1
  19. package/src/services/appointment/appointment.service.ts +315 -86
  20. package/src/services/clinic/clinic-admin.service.ts +3 -0
  21. package/src/services/clinic/clinic-group.service.ts +8 -0
  22. package/src/services/documentation-templates/documentation-template.service.ts +24 -16
  23. package/src/services/documentation-templates/filled-document.service.ts +253 -136
  24. package/src/services/patient/patientRequirements.service.ts +285 -0
  25. package/src/types/appointment/index.ts +134 -10
  26. package/src/types/documentation-templates/index.ts +34 -2
  27. package/src/types/notifications/README.md +77 -0
  28. package/src/types/notifications/index.ts +154 -27
  29. package/src/types/patient/patient-requirements.ts +81 -0
  30. package/src/validations/appointment.schema.ts +300 -62
  31. package/src/validations/documentation-templates/template.schema.ts +55 -0
  32. package/src/validations/documentation-templates.schema.ts +9 -14
  33. package/src/validations/notification.schema.ts +3 -3
  34. package/src/validations/patient/patient-requirements.schema.ts +75 -0
package/dist/index.js CHANGED
@@ -81,9 +81,13 @@ __export(index_exports, {
81
81
  PATIENT_LOCATION_INFO_COLLECTION: () => PATIENT_LOCATION_INFO_COLLECTION,
82
82
  PATIENT_MEDICAL_HISTORY_COLLECTION: () => PATIENT_MEDICAL_HISTORY_COLLECTION,
83
83
  PATIENT_MEDICAL_INFO_COLLECTION: () => PATIENT_MEDICAL_INFO_COLLECTION,
84
+ PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME: () => PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME,
84
85
  PATIENT_SENSITIVE_INFO_COLLECTION: () => PATIENT_SENSITIVE_INFO_COLLECTION,
85
86
  PRACTITIONERS_COLLECTION: () => PRACTITIONERS_COLLECTION,
86
87
  PROCEDURES_COLLECTION: () => PROCEDURES_COLLECTION,
88
+ PatientInstructionStatus: () => PatientInstructionStatus,
89
+ PatientRequirementOverallStatus: () => PatientRequirementOverallStatus,
90
+ PatientRequirementsService: () => PatientRequirementsService,
87
91
  PatientService: () => PatientService,
88
92
  PaymentStatus: () => PaymentStatus,
89
93
  PracticeType: () => PracticeType,
@@ -148,6 +152,7 @@ __export(index_exports, {
148
152
  createDefaultClinicGroupSchema: () => createDefaultClinicGroupSchema,
149
153
  createDocumentTemplateSchema: () => createDocumentTemplateSchema,
150
154
  createDraftPractitionerSchema: () => createDraftPractitionerSchema,
155
+ createFilledDocumentDataSchema: () => createFilledDocumentDataSchema,
151
156
  createPatientLocationInfoSchema: () => createPatientLocationInfoSchema,
152
157
  createPatientMedicalInfoSchema: () => createPatientMedicalInfoSchema,
153
158
  createPatientProfileSchema: () => createPatientProfileSchema,
@@ -163,6 +168,8 @@ __export(index_exports, {
163
168
  documentTemplateSchema: () => documentTemplateSchema,
164
169
  emailSchema: () => emailSchema,
165
170
  emergencyContactSchema: () => emergencyContactSchema,
171
+ filledDocumentSchema: () => filledDocumentSchema,
172
+ filledDocumentStatusSchema: () => filledDocumentStatusSchema,
166
173
  gamificationSchema: () => gamificationSchema,
167
174
  getFirebaseApp: () => getFirebaseApp,
168
175
  getFirebaseAuth: () => getFirebaseAuth,
@@ -212,6 +219,7 @@ __export(index_exports, {
212
219
  updateClinicSchema: () => updateClinicSchema,
213
220
  updateContraindicationSchema: () => updateContraindicationSchema,
214
221
  updateDocumentTemplateSchema: () => updateDocumentTemplateSchema,
222
+ updateFilledDocumentDataSchema: () => updateFilledDocumentDataSchema,
215
223
  updateMedicationSchema: () => updateMedicationSchema,
216
224
  updatePatientMedicalInfoSchema: () => updatePatientMedicalInfoSchema,
217
225
  updateVitalStatsSchema: () => updateVitalStatsSchema,
@@ -224,19 +232,20 @@ __export(index_exports, {
224
232
  module.exports = __toCommonJS(index_exports);
225
233
 
226
234
  // src/validations/appointment.schema.ts
227
- var import_zod = require("zod");
235
+ var import_zod2 = require("zod");
228
236
 
229
237
  // src/types/appointment/index.ts
230
238
  var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
231
- AppointmentStatus2["SCHEDULED"] = "scheduled";
239
+ AppointmentStatus2["PENDING"] = "pending";
232
240
  AppointmentStatus2["CONFIRMED"] = "confirmed";
233
241
  AppointmentStatus2["CHECKED_IN"] = "checked_in";
234
242
  AppointmentStatus2["IN_PROGRESS"] = "in_progress";
235
243
  AppointmentStatus2["COMPLETED"] = "completed";
236
244
  AppointmentStatus2["CANCELED_PATIENT"] = "canceled_patient";
245
+ AppointmentStatus2["CANCELED_PATIENT_RESCHEDULED"] = "canceled_patient_rescheduled";
237
246
  AppointmentStatus2["CANCELED_CLINIC"] = "canceled_clinic";
238
247
  AppointmentStatus2["NO_SHOW"] = "no_show";
239
- AppointmentStatus2["RESCHEDULED"] = "rescheduled";
248
+ AppointmentStatus2["RESCHEDULED_BY_CLINIC"] = "rescheduled_by_clinic";
240
249
  return AppointmentStatus2;
241
250
  })(AppointmentStatus || {});
242
251
  var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
@@ -247,82 +256,444 @@ var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
247
256
  PaymentStatus3["NOT_APPLICABLE"] = "not_applicable";
248
257
  return PaymentStatus3;
249
258
  })(PaymentStatus || {});
259
+ var MediaType = /* @__PURE__ */ ((MediaType2) => {
260
+ MediaType2["BEFORE_PHOTO"] = "before_photo";
261
+ MediaType2["AFTER_PHOTO"] = "after_photo";
262
+ MediaType2["CONSENT_SCAN"] = "consent_scan";
263
+ MediaType2["OTHER_DOCUMENT"] = "other_document";
264
+ return MediaType2;
265
+ })(MediaType || {});
250
266
  var APPOINTMENTS_COLLECTION = "appointments";
251
267
 
268
+ // src/validations/documentation-templates/template.schema.ts
269
+ var import_zod = require("zod");
270
+
271
+ // src/types/documentation-templates/index.ts
272
+ var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
273
+ var FILLED_DOCUMENTS_COLLECTION = "filled-documents";
274
+ var USER_FORMS_SUBCOLLECTION = "user-forms";
275
+ var DOCTOR_FORMS_SUBCOLLECTION = "doctor-forms";
276
+ var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
277
+ DocumentElementType2["HEADING"] = "heading";
278
+ DocumentElementType2["PARAGRAPH"] = "paragraph";
279
+ DocumentElementType2["LIST"] = "list";
280
+ DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
281
+ DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
282
+ DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
283
+ DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
284
+ DocumentElementType2["RATING_SCALE"] = "rating_scale";
285
+ DocumentElementType2["TEXT_INPUT"] = "text_input";
286
+ DocumentElementType2["DATE_PICKER"] = "date_picker";
287
+ DocumentElementType2["SIGNATURE"] = "signature";
288
+ DocumentElementType2["DITIGAL_SIGNATURE"] = "digital_signature";
289
+ DocumentElementType2["FILE_UPLOAD"] = "file_upload";
290
+ return DocumentElementType2;
291
+ })(DocumentElementType || {});
292
+ var ListType = /* @__PURE__ */ ((ListType2) => {
293
+ ListType2["ORDERED"] = "ordered";
294
+ ListType2["UNORDERED"] = "unordered";
295
+ return ListType2;
296
+ })(ListType || {});
297
+ var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
298
+ HeadingLevel2["H1"] = "h1";
299
+ HeadingLevel2["H2"] = "h2";
300
+ HeadingLevel2["H3"] = "h3";
301
+ HeadingLevel2["H4"] = "h4";
302
+ HeadingLevel2["H5"] = "h5";
303
+ HeadingLevel2["H6"] = "h6";
304
+ return HeadingLevel2;
305
+ })(HeadingLevel || {});
306
+ var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
307
+ DynamicVariable2["PATIENT_NAME"] = "[PATIENT_NAME]";
308
+ DynamicVariable2["DOCTOR_NAME"] = "[DOCTOR_NAME]";
309
+ DynamicVariable2["CLINIC_NAME"] = "[CLINIC_NAME]";
310
+ DynamicVariable2["PATIENT_BIRTHDAY"] = "[PATIENT_BIRTHDAY]";
311
+ DynamicVariable2["APPOINTMENT_DATE"] = "[APPOINTMENT_DATE]";
312
+ DynamicVariable2["CURRENT_DATE"] = "[CURRENT_DATE]";
313
+ DynamicVariable2["PROCEDURE_NAME"] = "[PROCEDURE_NAME]";
314
+ DynamicVariable2["PROCEDURE_DESCRIPTION"] = "[PROCEDURE_DESCRIPTION]";
315
+ DynamicVariable2["PROCEDURE_COST"] = "[PROCEDURE_COST]";
316
+ DynamicVariable2["PROCEDURE_DURATION"] = "[PROCEDURE_DURATION]";
317
+ DynamicVariable2["PROCEDURE_RISK"] = "[PROCEDURE_RISK]";
318
+ return DynamicVariable2;
319
+ })(DynamicVariable || {});
320
+ var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
321
+ FilledDocumentStatus2["DRAFT"] = "draft";
322
+ FilledDocumentStatus2["SKIPPED"] = "skipped";
323
+ FilledDocumentStatus2["PENDING"] = "pending";
324
+ FilledDocumentStatus2["COMPLETED"] = "completed";
325
+ FilledDocumentStatus2["SIGNED"] = "signed";
326
+ FilledDocumentStatus2["REJECTED"] = "rejected";
327
+ return FilledDocumentStatus2;
328
+ })(FilledDocumentStatus || {});
329
+
330
+ // src/validations/documentation-templates/template.schema.ts
331
+ var baseElementSchema = import_zod.z.object({
332
+ id: import_zod.z.string().optional(),
333
+ // Make id optional so we can omit it later
334
+ type: import_zod.z.nativeEnum(DocumentElementType),
335
+ required: import_zod.z.boolean().optional()
336
+ });
337
+ var headingElementSchema = baseElementSchema.extend({
338
+ type: import_zod.z.literal("heading" /* HEADING */),
339
+ text: import_zod.z.string().min(1).max(200),
340
+ level: import_zod.z.nativeEnum(HeadingLevel)
341
+ });
342
+ var paragraphElementSchema = baseElementSchema.extend({
343
+ type: import_zod.z.literal("paragraph" /* PARAGRAPH */),
344
+ text: import_zod.z.string().min(1).max(5e3)
345
+ });
346
+ var listElementSchema = baseElementSchema.extend({
347
+ type: import_zod.z.literal("list" /* LIST */),
348
+ items: import_zod.z.array(import_zod.z.string().min(1).max(500)).min(1).max(100),
349
+ listType: import_zod.z.nativeEnum(ListType)
350
+ });
351
+ var dynamicTextElementSchema = baseElementSchema.extend({
352
+ type: import_zod.z.literal("dynamic_text" /* DYNAMIC_TEXT */),
353
+ text: import_zod.z.string().min(1).max(5e3)
354
+ });
355
+ var binaryChoiceElementSchema = baseElementSchema.extend({
356
+ type: import_zod.z.literal("binary_choice" /* BINARY_CHOICE */),
357
+ question: import_zod.z.string().min(1).max(500),
358
+ defaultValue: import_zod.z.boolean().optional()
359
+ });
360
+ var multipleChoiceElementSchema = baseElementSchema.extend({
361
+ type: import_zod.z.literal("multiple_choice" /* MULTIPLE_CHOICE */),
362
+ question: import_zod.z.string().min(1).max(500),
363
+ options: import_zod.z.array(import_zod.z.string().min(1).max(200)).min(2).max(50),
364
+ defaultValues: import_zod.z.array(import_zod.z.string()).optional()
365
+ });
366
+ var singleChoiceElementSchema = baseElementSchema.extend({
367
+ type: import_zod.z.literal("single_choice" /* SINGLE_CHOICE */),
368
+ question: import_zod.z.string().min(1).max(500),
369
+ options: import_zod.z.array(import_zod.z.string().min(1).max(200)).min(2).max(50),
370
+ defaultValue: import_zod.z.string().optional()
371
+ });
372
+ var ratingScaleElementSchema = baseElementSchema.extend({
373
+ type: import_zod.z.literal("rating_scale" /* RATING_SCALE */),
374
+ question: import_zod.z.string().min(1).max(500),
375
+ min: import_zod.z.number().int().min(0).max(10),
376
+ max: import_zod.z.number().int().min(1).max(10),
377
+ labels: import_zod.z.record(import_zod.z.string()).optional(),
378
+ defaultValue: import_zod.z.number().int().optional()
379
+ });
380
+ var textInputElementSchema = baseElementSchema.extend({
381
+ type: import_zod.z.literal("text_input" /* TEXT_INPUT */),
382
+ label: import_zod.z.string().min(1).max(200),
383
+ placeholder: import_zod.z.string().max(200).optional(),
384
+ multiline: import_zod.z.boolean().optional(),
385
+ defaultValue: import_zod.z.string().optional()
386
+ });
387
+ var datePickerElementSchema = baseElementSchema.extend({
388
+ type: import_zod.z.literal("date_picker" /* DATE_PICKER */),
389
+ label: import_zod.z.string().min(1).max(200),
390
+ defaultValue: import_zod.z.string().optional()
391
+ // ISO date string
392
+ });
393
+ var signatureElementSchema = baseElementSchema.extend({
394
+ type: import_zod.z.literal("signature" /* SIGNATURE */),
395
+ label: import_zod.z.string().min(1).max(200)
396
+ });
397
+ var digitalSignatureElementSchema = baseElementSchema.extend({
398
+ type: import_zod.z.literal("digital_signature" /* DITIGAL_SIGNATURE */),
399
+ // Matching your type enum
400
+ label: import_zod.z.string().min(1).max(200)
401
+ });
402
+ var fileUploadElementSchema = baseElementSchema.extend({
403
+ type: import_zod.z.literal("file_upload" /* FILE_UPLOAD */),
404
+ label: import_zod.z.string().min(1).max(200),
405
+ allowedFileTypes: import_zod.z.array(import_zod.z.string()).optional(),
406
+ maxFileSizeMB: import_zod.z.number().positive().optional()
407
+ });
408
+ var documentElementSchema = import_zod.z.discriminatedUnion("type", [
409
+ headingElementSchema,
410
+ paragraphElementSchema,
411
+ listElementSchema,
412
+ dynamicTextElementSchema,
413
+ binaryChoiceElementSchema,
414
+ multipleChoiceElementSchema,
415
+ singleChoiceElementSchema,
416
+ ratingScaleElementSchema,
417
+ textInputElementSchema,
418
+ datePickerElementSchema,
419
+ signatureElementSchema,
420
+ digitalSignatureElementSchema,
421
+ fileUploadElementSchema
422
+ ]);
423
+ var documentElementWithoutIdSchema = import_zod.z.discriminatedUnion("type", [
424
+ headingElementSchema.omit({ id: true }),
425
+ paragraphElementSchema.omit({ id: true }),
426
+ listElementSchema.omit({ id: true }),
427
+ dynamicTextElementSchema.omit({ id: true }),
428
+ binaryChoiceElementSchema.omit({ id: true }),
429
+ multipleChoiceElementSchema.omit({ id: true }),
430
+ singleChoiceElementSchema.omit({ id: true }),
431
+ ratingScaleElementSchema.omit({ id: true }),
432
+ textInputElementSchema.omit({ id: true }),
433
+ datePickerElementSchema.omit({ id: true }),
434
+ signatureElementSchema.omit({ id: true }),
435
+ digitalSignatureElementSchema.omit({ id: true }),
436
+ fileUploadElementSchema.omit({ id: true })
437
+ ]);
438
+ var createDocumentTemplateSchema = import_zod.z.object({
439
+ title: import_zod.z.string().min(1).max(200),
440
+ description: import_zod.z.string().max(1e3).optional(),
441
+ elements: import_zod.z.array(documentElementWithoutIdSchema).min(1).max(100),
442
+ tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
443
+ isUserForm: import_zod.z.boolean().optional().default(false),
444
+ isRequired: import_zod.z.boolean().optional().default(false),
445
+ sortingOrder: import_zod.z.number().int().optional().default(0)
446
+ });
447
+ var updateDocumentTemplateSchema = import_zod.z.object({
448
+ title: import_zod.z.string().min(1).max(200).optional(),
449
+ description: import_zod.z.string().max(1e3).optional(),
450
+ elements: import_zod.z.array(documentElementWithoutIdSchema).min(1).max(100).optional(),
451
+ tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
452
+ isActive: import_zod.z.boolean().optional(),
453
+ isUserForm: import_zod.z.boolean().optional(),
454
+ isRequired: import_zod.z.boolean().optional(),
455
+ sortingOrder: import_zod.z.number().int().optional()
456
+ });
457
+ var documentTemplateSchema = import_zod.z.object({
458
+ id: import_zod.z.string(),
459
+ title: import_zod.z.string().min(1).max(200),
460
+ description: import_zod.z.string().max(1e3).optional(),
461
+ createdAt: import_zod.z.number(),
462
+ updatedAt: import_zod.z.number(),
463
+ createdBy: import_zod.z.string(),
464
+ elements: import_zod.z.array(documentElementSchema),
465
+ tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
466
+ version: import_zod.z.number().int().positive(),
467
+ isActive: import_zod.z.boolean(),
468
+ isUserForm: import_zod.z.boolean().optional().default(false),
469
+ isRequired: import_zod.z.boolean().optional().default(false),
470
+ sortingOrder: import_zod.z.number().int().optional().default(0)
471
+ });
472
+ var filledDocumentStatusSchema = import_zod.z.nativeEnum(FilledDocumentStatus);
473
+ var filledDocumentSchema = import_zod.z.object({
474
+ id: import_zod.z.string(),
475
+ templateId: import_zod.z.string(),
476
+ templateVersion: import_zod.z.number(),
477
+ isUserForm: import_zod.z.boolean(),
478
+ procedureId: import_zod.z.string(),
479
+ appointmentId: import_zod.z.string(),
480
+ patientId: import_zod.z.string(),
481
+ practitionerId: import_zod.z.string(),
482
+ clinicId: import_zod.z.string(),
483
+ createdAt: import_zod.z.number(),
484
+ updatedAt: import_zod.z.number(),
485
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()),
486
+ status: filledDocumentStatusSchema
487
+ });
488
+ var createFilledDocumentDataSchema = import_zod.z.object({
489
+ templateId: import_zod.z.string(),
490
+ procedureId: import_zod.z.string(),
491
+ appointmentId: import_zod.z.string(),
492
+ patientId: import_zod.z.string(),
493
+ practitionerId: import_zod.z.string(),
494
+ clinicId: import_zod.z.string(),
495
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional().default({}),
496
+ status: filledDocumentStatusSchema.optional().default("draft" /* DRAFT */)
497
+ });
498
+ var updateFilledDocumentDataSchema = import_zod.z.object({
499
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
500
+ status: filledDocumentStatusSchema.optional()
501
+ });
502
+
252
503
  // src/validations/appointment.schema.ts
253
- var createAppointmentSchema = import_zod.z.object({
254
- calendarEventId: import_zod.z.string().min(1, "Calendar event ID is required"),
255
- clinicBranchId: import_zod.z.string().min(1, "Clinic branch ID is required"),
256
- practitionerId: import_zod.z.string().min(1, "Practitioner ID is required"),
257
- patientId: import_zod.z.string().min(1, "Patient ID is required"),
258
- procedureId: import_zod.z.string().min(1, "Procedure ID is required"),
259
- appointmentStartTime: import_zod.z.any().refine(
260
- (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
261
- "Appointment start time must be a valid timestamp"
504
+ var MIN_STRING_LENGTH = 1;
505
+ var MAX_STRING_LENGTH = 1024;
506
+ var MAX_STRING_LENGTH_LONG = 4096;
507
+ var MAX_ARRAY_LENGTH = 100;
508
+ var appointmentStatusSchema = import_zod2.z.nativeEnum(AppointmentStatus);
509
+ var paymentStatusSchema = import_zod2.z.nativeEnum(PaymentStatus);
510
+ var mediaTypeSchema = import_zod2.z.nativeEnum(MediaType);
511
+ var appointmentMediaItemSchema = import_zod2.z.object({
512
+ id: import_zod2.z.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
513
+ type: mediaTypeSchema,
514
+ url: import_zod2.z.string().url("Media URL must be a valid URL"),
515
+ fileName: import_zod2.z.string().optional(),
516
+ uploadedAt: import_zod2.z.any().refine(
517
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
518
+ "uploadedAt must be a valid timestamp or Date object"
519
+ ),
520
+ uploadedBy: import_zod2.z.string().min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
521
+ description: import_zod2.z.string().max(MAX_STRING_LENGTH, "Description too long").optional()
522
+ });
523
+ var procedureExtendedInfoSchema = import_zod2.z.object({
524
+ id: import_zod2.z.string().min(MIN_STRING_LENGTH),
525
+ name: import_zod2.z.string().min(MIN_STRING_LENGTH),
526
+ description: import_zod2.z.string(),
527
+ cost: import_zod2.z.number().min(0),
528
+ duration: import_zod2.z.number().min(0),
529
+ procedureFamily: import_zod2.z.any(),
530
+ procedureCategoryId: import_zod2.z.string(),
531
+ procedureCategoryName: import_zod2.z.string(),
532
+ procedureSubCategoryId: import_zod2.z.string(),
533
+ procedureSubCategoryName: import_zod2.z.string(),
534
+ procedureTechnologyId: import_zod2.z.string(),
535
+ procedureTechnologyName: import_zod2.z.string(),
536
+ procedureProductBrandId: import_zod2.z.string(),
537
+ procedureProductBrandName: import_zod2.z.string(),
538
+ procedureProductId: import_zod2.z.string(),
539
+ procedureProductName: import_zod2.z.string()
540
+ });
541
+ var linkedFormInfoSchema = import_zod2.z.object({
542
+ formId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form ID is required"),
543
+ templateId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Template ID is required"),
544
+ templateVersion: import_zod2.z.number().int().positive("Template version must be a positive integer"),
545
+ title: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form title is required"),
546
+ isUserForm: import_zod2.z.boolean(),
547
+ status: filledDocumentStatusSchema,
548
+ path: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form path is required"),
549
+ submittedAt: import_zod2.z.any().refine(
550
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
551
+ "submittedAt must be a valid timestamp or Date object"
552
+ ).optional(),
553
+ completedAt: import_zod2.z.any().refine(
554
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
555
+ "completedAt must be a valid timestamp or Date object"
556
+ ).optional()
557
+ });
558
+ var patientReviewInfoSchema = import_zod2.z.object({
559
+ reviewId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Review ID is required"),
560
+ rating: import_zod2.z.number().min(1).max(5, "Rating must be between 1 and 5"),
561
+ comment: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Comment too long").optional(),
562
+ reviewedAt: import_zod2.z.any().refine(
563
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
564
+ "reviewedAt must be a valid timestamp or Date object"
565
+ )
566
+ });
567
+ var finalizedDetailsSchema = import_zod2.z.object({
568
+ by: import_zod2.z.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
569
+ at: import_zod2.z.any().refine(
570
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
571
+ "Finalized at must be a valid timestamp or Date object"
572
+ ),
573
+ notes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
574
+ });
575
+ var createAppointmentSchema = import_zod2.z.object({
576
+ calendarEventId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Calendar event ID is required"),
577
+ clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
578
+ practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
579
+ patientId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
580
+ procedureId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
581
+ appointmentStartTime: import_zod2.z.any().refine(
582
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
583
+ "Appointment start time must be a valid timestamp or Date object"
262
584
  ),
263
- appointmentEndTime: import_zod.z.any().refine(
264
- (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
265
- "Appointment end time must be a valid timestamp"
585
+ appointmentEndTime: import_zod2.z.any().refine(
586
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
587
+ "Appointment end time must be a valid timestamp or Date object"
266
588
  ),
267
- cost: import_zod.z.number().min(0, "Cost must be a non-negative number"),
268
- currency: import_zod.z.string().min(1, "Currency is required"),
269
- patientNotes: import_zod.z.string().nullable().optional(),
270
- initialStatus: import_zod.z.nativeEnum(AppointmentStatus, {
271
- errorMap: () => ({ message: "Invalid appointment status" })
272
- }),
273
- initialPaymentStatus: import_zod.z.nativeEnum(PaymentStatus, {
274
- errorMap: () => ({ message: "Invalid payment status" })
275
- }).optional().default("unpaid" /* UNPAID */)
589
+ cost: import_zod2.z.number().min(0, "Cost must be a non-negative number"),
590
+ currency: import_zod2.z.string().min(1, "Currency is required"),
591
+ patientNotes: import_zod2.z.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
592
+ initialStatus: appointmentStatusSchema,
593
+ initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */)
594
+ }).refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
595
+ message: "Appointment end time must be after start time",
596
+ path: ["appointmentEndTime"]
276
597
  });
277
- var updateAppointmentSchema = import_zod.z.object({
278
- status: import_zod.z.nativeEnum(AppointmentStatus, {
279
- errorMap: () => ({ message: "Invalid appointment status" })
280
- }).optional(),
281
- confirmationTime: import_zod.z.any().refine(
282
- (val) => val === null || val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
283
- "Confirmation time must be a valid timestamp or null"
598
+ var updateAppointmentSchema = import_zod2.z.object({
599
+ status: appointmentStatusSchema.optional(),
600
+ confirmationTime: import_zod2.z.any().optional().nullable(),
601
+ cancellationTime: import_zod2.z.any().optional().nullable(),
602
+ rescheduleTime: import_zod2.z.any().optional().nullable(),
603
+ procedureActualStartTime: import_zod2.z.any().optional().nullable(),
604
+ actualDurationMinutes: import_zod2.z.number().int().positive("Duration must be a positive integer").optional(),
605
+ cancellationReason: import_zod2.z.string().max(MAX_STRING_LENGTH, "Cancellation reason too long").nullable().optional(),
606
+ canceledBy: import_zod2.z.enum(["patient", "clinic", "practitioner", "system"]).optional(),
607
+ internalNotes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Internal notes too long").nullable().optional(),
608
+ patientNotes: import_zod2.z.any().optional().nullable(),
609
+ paymentStatus: paymentStatusSchema.optional(),
610
+ paymentTransactionId: import_zod2.z.any().optional().nullable(),
611
+ completedPreRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
612
+ completedPostRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
613
+ pendingUserFormsIds: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
614
+ appointmentStartTime: import_zod2.z.any().refine(
615
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
616
+ "Appointment start time must be a valid timestamp or Date object"
284
617
  ).optional(),
285
- actualDurationMinutes: import_zod.z.number().positive("Duration must be positive").optional(),
286
- cancellationReason: import_zod.z.string().nullable().optional(),
287
- canceledBy: import_zod.z.enum(["patient", "clinic", "practitioner", "system"]).optional(),
288
- internalNotes: import_zod.z.string().nullable().optional(),
289
- paymentStatus: import_zod.z.nativeEnum(PaymentStatus, {
290
- errorMap: () => ({ message: "Invalid payment status" })
291
- }).optional(),
292
- paymentTransactionId: import_zod.z.string().nullable().optional(),
293
- completedPreRequirements: import_zod.z.array(import_zod.z.string()).optional(),
294
- completedPostRequirements: import_zod.z.array(import_zod.z.string()).optional()
618
+ appointmentEndTime: import_zod2.z.any().refine(
619
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
620
+ "Appointment end time must be a valid timestamp or Date object"
621
+ ).optional(),
622
+ calendarEventId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
623
+ cost: import_zod2.z.number().min(0).optional(),
624
+ clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
625
+ practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
626
+ linkedForms: import_zod2.z.union([import_zod2.z.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), import_zod2.z.any()]).optional(),
627
+ media: import_zod2.z.union([
628
+ import_zod2.z.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
629
+ import_zod2.z.any()
630
+ ]).optional(),
631
+ reviewInfo: import_zod2.z.union([patientReviewInfoSchema.nullable(), import_zod2.z.any()]).optional(),
632
+ finalizedDetails: import_zod2.z.union([finalizedDetailsSchema.nullable(), import_zod2.z.any()]).optional(),
633
+ isArchived: import_zod2.z.boolean().optional(),
634
+ updatedAt: import_zod2.z.any().optional()
295
635
  }).refine(
296
636
  (data) => {
297
- if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */) {
637
+ if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */ || data.status === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
298
638
  return !!data.cancellationReason && !!data.canceledBy;
299
639
  }
300
640
  return true;
301
641
  },
302
642
  {
303
- message: "Cancellation reason and canceled by must be provided when canceling an appointment",
643
+ message: "Cancellation reason and canceled by must be provided when canceling an appointment with patient or clinic origin.",
304
644
  path: ["status"]
305
645
  }
646
+ ).refine(
647
+ (data) => {
648
+ if (data.appointmentStartTime && data.appointmentEndTime) {
649
+ return data.appointmentEndTime > data.appointmentStartTime;
650
+ }
651
+ return true;
652
+ },
653
+ {
654
+ message: "Appointment end time must be after start time if both are provided",
655
+ path: ["appointmentEndTime"]
656
+ }
306
657
  );
307
- var searchAppointmentsSchema = import_zod.z.object({
308
- patientId: import_zod.z.string().optional(),
309
- practitionerId: import_zod.z.string().optional(),
310
- clinicBranchId: import_zod.z.string().optional(),
311
- startDate: import_zod.z.date().optional(),
312
- endDate: import_zod.z.date().optional(),
313
- status: import_zod.z.union([
314
- import_zod.z.nativeEnum(AppointmentStatus),
315
- import_zod.z.array(import_zod.z.nativeEnum(AppointmentStatus))
658
+ var searchAppointmentsSchema = import_zod2.z.object({
659
+ patientId: import_zod2.z.string().optional(),
660
+ practitionerId: import_zod2.z.string().optional(),
661
+ clinicBranchId: import_zod2.z.string().optional(),
662
+ startDate: import_zod2.z.any().refine(
663
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
664
+ "Start date must be a valid timestamp or Date object"
665
+ ).optional(),
666
+ endDate: import_zod2.z.any().refine(
667
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
668
+ "End date must be a valid timestamp or Date object"
669
+ ).optional(),
670
+ status: import_zod2.z.union([
671
+ appointmentStatusSchema,
672
+ import_zod2.z.array(appointmentStatusSchema).nonempty()
316
673
  ]).optional(),
317
- limit: import_zod.z.number().positive().optional(),
318
- startAfter: import_zod.z.any().optional()
674
+ limit: import_zod2.z.number().positive().int().optional().default(20),
675
+ startAfter: import_zod2.z.any().optional()
319
676
  }).refine(
320
677
  (data) => {
321
- return !!(data.patientId || data.practitionerId || data.clinicBranchId);
678
+ if (!data.startDate && !data.endDate && !data.status) {
679
+ return !!(data.patientId || data.practitionerId || data.clinicBranchId);
680
+ }
681
+ return true;
682
+ },
683
+ {
684
+ message: "At least one of patientId, practitionerId, or clinicBranchId must be provided if no date or status filters are set.",
685
+ path: ["patientId"]
686
+ }
687
+ ).refine(
688
+ (data) => {
689
+ if (data.startDate && data.endDate) {
690
+ return data.endDate >= data.startDate;
691
+ }
692
+ return true;
322
693
  },
323
694
  {
324
- message: "At least one of patientId, practitionerId, or clinicBranchId must be provided",
325
- path: ["searchCriteria"]
695
+ message: "End date must be after or the same as start date",
696
+ path: ["endDate"]
326
697
  }
327
698
  );
328
699
 
@@ -371,54 +742,6 @@ var getFirebaseApp = async () => {
371
742
  var import_auth5 = require("firebase/auth");
372
743
  var import_firestore22 = require("firebase/firestore");
373
744
 
374
- // src/types/documentation-templates/index.ts
375
- var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
376
- var FILLED_DOCUMENTS_COLLECTION = "filled-documents";
377
- var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
378
- DocumentElementType2["HEADING"] = "heading";
379
- DocumentElementType2["PARAGRAPH"] = "paragraph";
380
- DocumentElementType2["LIST"] = "list";
381
- DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
382
- DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
383
- DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
384
- DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
385
- DocumentElementType2["RATING_SCALE"] = "rating_scale";
386
- DocumentElementType2["TEXT_INPUT"] = "text_input";
387
- DocumentElementType2["DATE_PICKER"] = "date_picker";
388
- DocumentElementType2["SIGNATURE"] = "signature";
389
- DocumentElementType2["FILE_UPLOAD"] = "file_upload";
390
- return DocumentElementType2;
391
- })(DocumentElementType || {});
392
- var ListType = /* @__PURE__ */ ((ListType2) => {
393
- ListType2["ORDERED"] = "ordered";
394
- ListType2["UNORDERED"] = "unordered";
395
- return ListType2;
396
- })(ListType || {});
397
- var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
398
- HeadingLevel2["H1"] = "h1";
399
- HeadingLevel2["H2"] = "h2";
400
- HeadingLevel2["H3"] = "h3";
401
- HeadingLevel2["H4"] = "h4";
402
- HeadingLevel2["H5"] = "h5";
403
- HeadingLevel2["H6"] = "h6";
404
- return HeadingLevel2;
405
- })(HeadingLevel || {});
406
- var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
407
- DynamicVariable2["PATIENT_NAME"] = "[PATIENT_NAME]";
408
- DynamicVariable2["DOCTOR_NAME"] = "[DOCTOR_NAME]";
409
- DynamicVariable2["CLINIC_NAME"] = "[CLINIC_NAME]";
410
- DynamicVariable2["PATIENT_BIRTHDAY"] = "[PATIENT_BIRTHDAY]";
411
- DynamicVariable2["APPOINTMENT_DATE"] = "[APPOINTMENT_DATE]";
412
- DynamicVariable2["CURRENT_DATE"] = "[CURRENT_DATE]";
413
- return DynamicVariable2;
414
- })(DynamicVariable || {});
415
- var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
416
- FilledDocumentStatus2["DRAFT"] = "draft";
417
- FilledDocumentStatus2["COMPLETED"] = "completed";
418
- FilledDocumentStatus2["SIGNED"] = "signed";
419
- return FilledDocumentStatus2;
420
- })(FilledDocumentStatus || {});
421
-
422
745
  // src/types/calendar/index.ts
423
746
  var CalendarEventStatus = /* @__PURE__ */ ((CalendarEventStatus4) => {
424
747
  CalendarEventStatus4["PENDING"] = "pending";
@@ -465,136 +788,6 @@ var import_zod19 = require("zod");
465
788
 
466
789
  // src/validations/schemas.ts
467
790
  var import_zod3 = require("zod");
468
-
469
- // src/validations/documentation-templates/template.schema.ts
470
- var import_zod2 = require("zod");
471
- var baseElementSchema = import_zod2.z.object({
472
- id: import_zod2.z.string().optional(),
473
- // Make id optional so we can omit it later
474
- type: import_zod2.z.nativeEnum(DocumentElementType),
475
- required: import_zod2.z.boolean().optional()
476
- });
477
- var headingElementSchema = baseElementSchema.extend({
478
- type: import_zod2.z.literal("heading" /* HEADING */),
479
- text: import_zod2.z.string().min(1).max(200),
480
- level: import_zod2.z.nativeEnum(HeadingLevel)
481
- });
482
- var paragraphElementSchema = baseElementSchema.extend({
483
- type: import_zod2.z.literal("paragraph" /* PARAGRAPH */),
484
- text: import_zod2.z.string().min(1).max(5e3)
485
- });
486
- var listElementSchema = baseElementSchema.extend({
487
- type: import_zod2.z.literal("list" /* LIST */),
488
- items: import_zod2.z.array(import_zod2.z.string().min(1).max(500)).min(1).max(100),
489
- listType: import_zod2.z.nativeEnum(ListType)
490
- });
491
- var dynamicTextElementSchema = baseElementSchema.extend({
492
- type: import_zod2.z.literal("dynamic_text" /* DYNAMIC_TEXT */),
493
- text: import_zod2.z.string().min(1).max(5e3)
494
- });
495
- var binaryChoiceElementSchema = baseElementSchema.extend({
496
- type: import_zod2.z.literal("binary_choice" /* BINARY_CHOICE */),
497
- question: import_zod2.z.string().min(1).max(500),
498
- defaultValue: import_zod2.z.boolean().optional()
499
- });
500
- var multipleChoiceElementSchema = baseElementSchema.extend({
501
- type: import_zod2.z.literal("multiple_choice" /* MULTIPLE_CHOICE */),
502
- question: import_zod2.z.string().min(1).max(500),
503
- options: import_zod2.z.array(import_zod2.z.string().min(1).max(200)).min(2).max(50),
504
- defaultValues: import_zod2.z.array(import_zod2.z.string()).optional()
505
- });
506
- var singleChoiceElementSchema = baseElementSchema.extend({
507
- type: import_zod2.z.literal("single_choice" /* SINGLE_CHOICE */),
508
- question: import_zod2.z.string().min(1).max(500),
509
- options: import_zod2.z.array(import_zod2.z.string().min(1).max(200)).min(2).max(50),
510
- defaultValue: import_zod2.z.string().optional()
511
- });
512
- var ratingScaleElementSchema = baseElementSchema.extend({
513
- type: import_zod2.z.literal("rating_scale" /* RATING_SCALE */),
514
- question: import_zod2.z.string().min(1).max(500),
515
- min: import_zod2.z.number().int().min(0).max(10),
516
- max: import_zod2.z.number().int().min(1).max(10),
517
- labels: import_zod2.z.record(import_zod2.z.string()).optional(),
518
- defaultValue: import_zod2.z.number().int().optional()
519
- });
520
- var textInputElementSchema = baseElementSchema.extend({
521
- type: import_zod2.z.literal("text_input" /* TEXT_INPUT */),
522
- label: import_zod2.z.string().min(1).max(200),
523
- placeholder: import_zod2.z.string().max(200).optional(),
524
- multiline: import_zod2.z.boolean().optional(),
525
- defaultValue: import_zod2.z.string().optional()
526
- });
527
- var datePickerElementSchema = baseElementSchema.extend({
528
- type: import_zod2.z.literal("date_picker" /* DATE_PICKER */),
529
- label: import_zod2.z.string().min(1).max(200),
530
- defaultValue: import_zod2.z.string().optional()
531
- // ISO date string
532
- });
533
- var signatureElementSchema = baseElementSchema.extend({
534
- type: import_zod2.z.literal("signature" /* SIGNATURE */),
535
- label: import_zod2.z.string().min(1).max(200)
536
- });
537
- var fileUploadElementSchema = baseElementSchema.extend({
538
- type: import_zod2.z.literal("file_upload" /* FILE_UPLOAD */),
539
- label: import_zod2.z.string().min(1).max(200),
540
- allowedFileTypes: import_zod2.z.array(import_zod2.z.string()).optional(),
541
- maxFileSizeMB: import_zod2.z.number().positive().optional()
542
- });
543
- var documentElementSchema = import_zod2.z.discriminatedUnion("type", [
544
- headingElementSchema,
545
- paragraphElementSchema,
546
- listElementSchema,
547
- dynamicTextElementSchema,
548
- binaryChoiceElementSchema,
549
- multipleChoiceElementSchema,
550
- singleChoiceElementSchema,
551
- ratingScaleElementSchema,
552
- textInputElementSchema,
553
- datePickerElementSchema,
554
- signatureElementSchema,
555
- fileUploadElementSchema
556
- ]);
557
- var documentElementWithoutIdSchema = import_zod2.z.discriminatedUnion("type", [
558
- headingElementSchema.omit({ id: true }),
559
- paragraphElementSchema.omit({ id: true }),
560
- listElementSchema.omit({ id: true }),
561
- dynamicTextElementSchema.omit({ id: true }),
562
- binaryChoiceElementSchema.omit({ id: true }),
563
- multipleChoiceElementSchema.omit({ id: true }),
564
- singleChoiceElementSchema.omit({ id: true }),
565
- ratingScaleElementSchema.omit({ id: true }),
566
- textInputElementSchema.omit({ id: true }),
567
- datePickerElementSchema.omit({ id: true }),
568
- signatureElementSchema.omit({ id: true }),
569
- fileUploadElementSchema.omit({ id: true })
570
- ]);
571
- var createDocumentTemplateSchema = import_zod2.z.object({
572
- title: import_zod2.z.string().min(1).max(200),
573
- description: import_zod2.z.string().max(1e3).optional(),
574
- elements: import_zod2.z.array(documentElementWithoutIdSchema).min(1).max(100),
575
- tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional()
576
- });
577
- var updateDocumentTemplateSchema = import_zod2.z.object({
578
- title: import_zod2.z.string().min(1).max(200).optional(),
579
- description: import_zod2.z.string().max(1e3).optional(),
580
- elements: import_zod2.z.array(documentElementWithoutIdSchema).min(1).max(100).optional(),
581
- tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional(),
582
- isActive: import_zod2.z.boolean().optional()
583
- });
584
- var documentTemplateSchema = import_zod2.z.object({
585
- id: import_zod2.z.string(),
586
- title: import_zod2.z.string().min(1).max(200),
587
- description: import_zod2.z.string().max(1e3).optional(),
588
- createdAt: import_zod2.z.number(),
589
- updatedAt: import_zod2.z.number(),
590
- createdBy: import_zod2.z.string(),
591
- elements: import_zod2.z.array(documentElementSchema),
592
- tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional(),
593
- version: import_zod2.z.number().int().positive(),
594
- isActive: import_zod2.z.boolean()
595
- });
596
-
597
- // src/validations/schemas.ts
598
791
  var emailSchema = import_zod3.z.string().email("Invalid email format").min(5, "Email must be at least 5 characters").max(255, "Email must be less than 255 characters");
599
792
  var passwordSchema = import_zod3.z.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters").regex(
600
793
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d\w\W]{8,}$/,
@@ -1607,9 +1800,9 @@ var addAllergyUtil = async (db, patientId, data, userRef) => {
1607
1800
  var updateAllergyUtil = async (db, patientId, data, userRef) => {
1608
1801
  const validatedData = updateAllergySchema.parse(data);
1609
1802
  const { allergyIndex, ...updateData } = validatedData;
1610
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1611
- if (!doc32.exists()) throw new Error("Medical info not found");
1612
- const medicalInfo = doc32.data();
1803
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1804
+ if (!doc33.exists()) throw new Error("Medical info not found");
1805
+ const medicalInfo = doc33.data();
1613
1806
  if (allergyIndex >= medicalInfo.allergies.length) {
1614
1807
  throw new Error("Invalid allergy index");
1615
1808
  }
@@ -1625,9 +1818,9 @@ var updateAllergyUtil = async (db, patientId, data, userRef) => {
1625
1818
  });
1626
1819
  };
1627
1820
  var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1628
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1629
- if (!doc32.exists()) throw new Error("Medical info not found");
1630
- const medicalInfo = doc32.data();
1821
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1822
+ if (!doc33.exists()) throw new Error("Medical info not found");
1823
+ const medicalInfo = doc33.data();
1631
1824
  if (allergyIndex >= medicalInfo.allergies.length) {
1632
1825
  throw new Error("Invalid allergy index");
1633
1826
  }
@@ -1652,9 +1845,9 @@ var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
1652
1845
  var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1653
1846
  const validatedData = updateBlockingConditionSchema.parse(data);
1654
1847
  const { conditionIndex, ...updateData } = validatedData;
1655
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1656
- if (!doc32.exists()) throw new Error("Medical info not found");
1657
- const medicalInfo = doc32.data();
1848
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1849
+ if (!doc33.exists()) throw new Error("Medical info not found");
1850
+ const medicalInfo = doc33.data();
1658
1851
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
1659
1852
  throw new Error("Invalid blocking condition index");
1660
1853
  }
@@ -1670,9 +1863,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1670
1863
  });
1671
1864
  };
1672
1865
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef) => {
1673
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1674
- if (!doc32.exists()) throw new Error("Medical info not found");
1675
- const medicalInfo = doc32.data();
1866
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1867
+ if (!doc33.exists()) throw new Error("Medical info not found");
1868
+ const medicalInfo = doc33.data();
1676
1869
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
1677
1870
  throw new Error("Invalid blocking condition index");
1678
1871
  }
@@ -1697,9 +1890,9 @@ var addContraindicationUtil = async (db, patientId, data, userRef) => {
1697
1890
  var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1698
1891
  const validatedData = updateContraindicationSchema.parse(data);
1699
1892
  const { contraindicationIndex, ...updateData } = validatedData;
1700
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1701
- if (!doc32.exists()) throw new Error("Medical info not found");
1702
- const medicalInfo = doc32.data();
1893
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1894
+ if (!doc33.exists()) throw new Error("Medical info not found");
1895
+ const medicalInfo = doc33.data();
1703
1896
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
1704
1897
  throw new Error("Invalid contraindication index");
1705
1898
  }
@@ -1715,9 +1908,9 @@ var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1715
1908
  });
1716
1909
  };
1717
1910
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, userRef) => {
1718
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1719
- if (!doc32.exists()) throw new Error("Medical info not found");
1720
- const medicalInfo = doc32.data();
1911
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1912
+ if (!doc33.exists()) throw new Error("Medical info not found");
1913
+ const medicalInfo = doc33.data();
1721
1914
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
1722
1915
  throw new Error("Invalid contraindication index");
1723
1916
  }
@@ -1742,9 +1935,9 @@ var addMedicationUtil = async (db, patientId, data, userRef) => {
1742
1935
  var updateMedicationUtil = async (db, patientId, data, userRef) => {
1743
1936
  const validatedData = updateMedicationSchema.parse(data);
1744
1937
  const { medicationIndex, ...updateData } = validatedData;
1745
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1746
- if (!doc32.exists()) throw new Error("Medical info not found");
1747
- const medicalInfo = doc32.data();
1938
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1939
+ if (!doc33.exists()) throw new Error("Medical info not found");
1940
+ const medicalInfo = doc33.data();
1748
1941
  if (medicationIndex >= medicalInfo.currentMedications.length) {
1749
1942
  throw new Error("Invalid medication index");
1750
1943
  }
@@ -1760,9 +1953,9 @@ var updateMedicationUtil = async (db, patientId, data, userRef) => {
1760
1953
  });
1761
1954
  };
1762
1955
  var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
1763
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1764
- if (!doc32.exists()) throw new Error("Medical info not found");
1765
- const medicalInfo = doc32.data();
1956
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1957
+ if (!doc33.exists()) throw new Error("Medical info not found");
1958
+ const medicalInfo = doc33.data();
1766
1959
  if (medicationIndex >= medicalInfo.currentMedications.length) {
1767
1960
  throw new Error("Invalid medication index");
1768
1961
  }
@@ -2040,7 +2233,7 @@ var searchPatientsUtil = async (db, params, requester) => {
2040
2233
  try {
2041
2234
  const finalQuery = (0, import_firestore6.query)(patientsCollectionRef, ...constraints);
2042
2235
  const querySnapshot = await (0, import_firestore6.getDocs)(finalQuery);
2043
- const patients = querySnapshot.docs.map((doc32) => doc32.data());
2236
+ const patients = querySnapshot.docs.map((doc33) => doc33.data());
2044
2237
  console.log(`[searchPatientsUtil] Found ${patients.length} patients matching criteria.`);
2045
2238
  return patients;
2046
2239
  } catch (error) {
@@ -2064,8 +2257,8 @@ var getAllPatientsUtil = async (db, options) => {
2064
2257
  }
2065
2258
  const patientsSnapshot = await (0, import_firestore6.getDocs)(q);
2066
2259
  const patients = [];
2067
- patientsSnapshot.forEach((doc32) => {
2068
- patients.push(doc32.data());
2260
+ patientsSnapshot.forEach((doc33) => {
2261
+ patients.push(doc33.data());
2069
2262
  });
2070
2263
  console.log(`[getAllPatientsUtil] Found ${patients.length} patients`);
2071
2264
  return patients;
@@ -2277,8 +2470,8 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
2277
2470
  }
2278
2471
  const patientsSnapshot = await (0, import_firestore9.getDocs)(q);
2279
2472
  const patients = [];
2280
- patientsSnapshot.forEach((doc32) => {
2281
- patients.push(doc32.data());
2473
+ patientsSnapshot.forEach((doc33) => {
2474
+ patients.push(doc33.data());
2282
2475
  });
2283
2476
  console.log(
2284
2477
  `[getPatientsByPractitionerUtil] Found ${patients.length} patients for practitioner ID: ${practitionerId}`
@@ -2366,8 +2559,8 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
2366
2559
  }
2367
2560
  const patientsSnapshot = await (0, import_firestore10.getDocs)(q);
2368
2561
  const patients = [];
2369
- patientsSnapshot.forEach((doc32) => {
2370
- patients.push(doc32.data());
2562
+ patientsSnapshot.forEach((doc33) => {
2563
+ patients.push(doc33.data());
2371
2564
  });
2372
2565
  console.log(
2373
2566
  `[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
@@ -3480,7 +3673,7 @@ async function getClinicAdminsByGroup(db, clinicGroupId) {
3480
3673
  (0, import_firestore13.where)("clinicGroupId", "==", clinicGroupId)
3481
3674
  );
3482
3675
  const querySnapshot = await (0, import_firestore13.getDocs)(q);
3483
- return querySnapshot.docs.map((doc32) => doc32.data());
3676
+ return querySnapshot.docs.map((doc33) => doc33.data());
3484
3677
  }
3485
3678
  async function updateClinicAdmin(db, adminId, data) {
3486
3679
  const admin = await getClinicAdmin(db, adminId);
@@ -3741,6 +3934,8 @@ var ClinicAdminService = class extends BaseService {
3741
3934
  this.getClinicService()
3742
3935
  );
3743
3936
  }
3937
+ // TODO: Add more methods for clinic admins for managing permissions, editing profiles by the admin, or by the clinic group owner and so on
3938
+ // Generally refactor admin permissions and clinic group permissions and systems for admin management
3744
3939
  };
3745
3940
 
3746
3941
  // src/services/practitioner/practitioner.service.ts
@@ -4177,7 +4372,7 @@ var PractitionerService = class extends BaseService {
4177
4372
  (0, import_firestore15.where)("expiresAt", ">", import_firestore15.Timestamp.now())
4178
4373
  );
4179
4374
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4180
- return querySnapshot.docs.map((doc32) => doc32.data());
4375
+ return querySnapshot.docs.map((doc33) => doc33.data());
4181
4376
  }
4182
4377
  /**
4183
4378
  * Gets a token by its string value and validates it
@@ -4260,7 +4455,7 @@ var PractitionerService = class extends BaseService {
4260
4455
  (0, import_firestore15.where)("status", "==", "active" /* ACTIVE */)
4261
4456
  );
4262
4457
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4263
- return querySnapshot.docs.map((doc32) => doc32.data());
4458
+ return querySnapshot.docs.map((doc33) => doc33.data());
4264
4459
  }
4265
4460
  /**
4266
4461
  * Dohvata sve zdravstvene radnike za određenu kliniku
@@ -4272,7 +4467,7 @@ var PractitionerService = class extends BaseService {
4272
4467
  (0, import_firestore15.where)("isActive", "==", true)
4273
4468
  );
4274
4469
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4275
- return querySnapshot.docs.map((doc32) => doc32.data());
4470
+ return querySnapshot.docs.map((doc33) => doc33.data());
4276
4471
  }
4277
4472
  /**
4278
4473
  * Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
@@ -4284,7 +4479,7 @@ var PractitionerService = class extends BaseService {
4284
4479
  (0, import_firestore15.where)("status", "==", "draft" /* DRAFT */)
4285
4480
  );
4286
4481
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4287
- return querySnapshot.docs.map((doc32) => doc32.data());
4482
+ return querySnapshot.docs.map((doc33) => doc33.data());
4288
4483
  }
4289
4484
  /**
4290
4485
  * Updates a practitioner
@@ -4466,7 +4661,7 @@ var PractitionerService = class extends BaseService {
4466
4661
  );
4467
4662
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4468
4663
  const practitioners = querySnapshot.docs.map(
4469
- (doc32) => doc32.data()
4664
+ (doc33) => doc33.data()
4470
4665
  );
4471
4666
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
4472
4667
  return {
@@ -4537,8 +4732,8 @@ var PractitionerService = class extends BaseService {
4537
4732
  console.log(
4538
4733
  `[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
4539
4734
  );
4540
- let practitioners = querySnapshot.docs.map((doc32) => {
4541
- return { ...doc32.data(), id: doc32.id };
4735
+ let practitioners = querySnapshot.docs.map((doc33) => {
4736
+ return { ...doc33.data(), id: doc33.id };
4542
4737
  });
4543
4738
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
4544
4739
  if (filters.nameSearch && filters.nameSearch.trim() !== "") {
@@ -4792,7 +4987,7 @@ var UserService = class extends BaseService {
4792
4987
  ];
4793
4988
  const q = (0, import_firestore16.query)((0, import_firestore16.collection)(this.db, USERS_COLLECTION), ...constraints);
4794
4989
  const querySnapshot = await (0, import_firestore16.getDocs)(q);
4795
- const users = querySnapshot.docs.map((doc32) => doc32.data());
4990
+ const users = querySnapshot.docs.map((doc33) => doc33.data());
4796
4991
  return Promise.all(users.map((userData) => userSchema.parse(userData)));
4797
4992
  }
4798
4993
  /**
@@ -5156,7 +5351,7 @@ async function getAllActiveGroups(db) {
5156
5351
  (0, import_firestore17.where)("isActive", "==", true)
5157
5352
  );
5158
5353
  const querySnapshot = await (0, import_firestore17.getDocs)(q);
5159
- return querySnapshot.docs.map((doc32) => doc32.data());
5354
+ return querySnapshot.docs.map((doc33) => doc33.data());
5160
5355
  }
5161
5356
  async function updateClinicGroup(db, groupId, data, app) {
5162
5357
  console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
@@ -5528,6 +5723,11 @@ var ClinicGroupService = class extends BaseService {
5528
5723
  this.app
5529
5724
  );
5530
5725
  }
5726
+ // TODO: Add a method to get all admin tokens for a clinic group (not just active ones)
5727
+ // TODO: Refactor admin token methods not to add tokens to the clinicGroup document,
5728
+ // but to add them to a subcollection called adminTokens that belongs to a specific clinicGroup document
5729
+ // TODO: Add granular control over admin permissions, e.g. only allow admins to manage certain clinics to tokens directly
5730
+ // TODO: Generally refactor admin tokens and invites, also create cloud function to send invites and send updates when sombody uses the token
5531
5731
  };
5532
5732
 
5533
5733
  // src/services/clinic/clinic.service.ts
@@ -5554,7 +5754,7 @@ async function getClinicsByGroup(db, groupId) {
5554
5754
  (0, import_firestore18.where)("isActive", "==", true)
5555
5755
  );
5556
5756
  const querySnapshot = await (0, import_firestore18.getDocs)(q);
5557
- return querySnapshot.docs.map((doc32) => doc32.data());
5757
+ return querySnapshot.docs.map((doc33) => doc33.data());
5558
5758
  }
5559
5759
  async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
5560
5760
  console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
@@ -5748,7 +5948,7 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
5748
5948
  }
5749
5949
  const q = (0, import_firestore18.query)((0, import_firestore18.collection)(db, CLINICS_COLLECTION), ...constraints);
5750
5950
  const querySnapshot = await (0, import_firestore18.getDocs)(q);
5751
- return querySnapshot.docs.map((doc32) => doc32.data());
5951
+ return querySnapshot.docs.map((doc33) => doc33.data());
5752
5952
  }
5753
5953
  async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
5754
5954
  return getClinicsByAdmin(
@@ -5793,11 +5993,11 @@ async function getAllClinics(db, pagination, lastDoc) {
5793
5993
  }
5794
5994
  const clinicsSnapshot = await (0, import_firestore18.getDocs)(clinicsQuery);
5795
5995
  const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
5796
- const clinics = clinicsSnapshot.docs.map((doc32) => {
5797
- const data = doc32.data();
5996
+ const clinics = clinicsSnapshot.docs.map((doc33) => {
5997
+ const data = doc33.data();
5798
5998
  return {
5799
5999
  ...data,
5800
- id: doc32.id
6000
+ id: doc33.id
5801
6001
  };
5802
6002
  });
5803
6003
  return {
@@ -5824,8 +6024,8 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
5824
6024
  ];
5825
6025
  const q = (0, import_firestore18.query)((0, import_firestore18.collection)(db, CLINICS_COLLECTION), ...constraints);
5826
6026
  const querySnapshot = await (0, import_firestore18.getDocs)(q);
5827
- for (const doc32 of querySnapshot.docs) {
5828
- const clinic = doc32.data();
6027
+ for (const doc33 of querySnapshot.docs) {
6028
+ const clinic = doc33.data();
5829
6029
  const distance = (0, import_geofire_common4.distanceBetween)(
5830
6030
  [center.latitude, center.longitude],
5831
6031
  [clinic.location.latitude, clinic.location.longitude]
@@ -5942,8 +6142,8 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
5942
6142
  }
5943
6143
  const q = (0, import_firestore19.query)((0, import_firestore19.collection)(db, CLINICS_COLLECTION), ...constraints);
5944
6144
  const querySnapshot = await (0, import_firestore19.getDocs)(q);
5945
- for (const doc32 of querySnapshot.docs) {
5946
- const clinic = doc32.data();
6145
+ for (const doc33 of querySnapshot.docs) {
6146
+ const clinic = doc33.data();
5947
6147
  const distance = (0, import_geofire_common5.distanceBetween)(
5948
6148
  [center.latitude, center.longitude],
5949
6149
  [clinic.location.latitude, clinic.location.longitude]
@@ -6031,8 +6231,8 @@ async function getClinicsByFilters(db, filters) {
6031
6231
  console.log(
6032
6232
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
6033
6233
  );
6034
- for (const doc32 of querySnapshot.docs) {
6035
- const clinic = { ...doc32.data(), id: doc32.id };
6234
+ for (const doc33 of querySnapshot.docs) {
6235
+ const clinic = { ...doc33.data(), id: doc33.id };
6036
6236
  const distance = (0, import_geofire_common6.distanceBetween)(
6037
6237
  [center.latitude, center.longitude],
6038
6238
  [clinic.location.latitude, clinic.location.longitude]
@@ -6088,8 +6288,8 @@ async function getClinicsByFilters(db, filters) {
6088
6288
  console.log(
6089
6289
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
6090
6290
  );
6091
- const clinics = querySnapshot.docs.map((doc32) => {
6092
- return { ...doc32.data(), id: doc32.id };
6291
+ const clinics = querySnapshot.docs.map((doc33) => {
6292
+ return { ...doc33.data(), id: doc33.id };
6093
6293
  });
6094
6294
  let filteredClinics = clinics;
6095
6295
  if (filters.center) {
@@ -7301,17 +7501,28 @@ var import_firestore23 = require("firebase/firestore");
7301
7501
 
7302
7502
  // src/types/notifications/index.ts
7303
7503
  var NotificationType = /* @__PURE__ */ ((NotificationType3) => {
7304
- NotificationType3["PRE_REQUIREMENT"] = "preRequirement";
7305
- NotificationType3["POST_REQUIREMENT"] = "postRequirement";
7306
7504
  NotificationType3["APPOINTMENT_REMINDER"] = "appointmentReminder";
7307
- NotificationType3["APPOINTMENT_NOTIFICATION"] = "appointmentNotification";
7505
+ NotificationType3["APPOINTMENT_STATUS_CHANGE"] = "appointmentStatusChange";
7506
+ NotificationType3["APPOINTMENT_RESCHEDULED_PROPOSAL"] = "appointmentRescheduledProposal";
7507
+ NotificationType3["APPOINTMENT_CANCELLED"] = "appointmentCancelled";
7508
+ NotificationType3["REQUIREMENT_INSTRUCTION_DUE"] = "requirementInstructionDue";
7509
+ NotificationType3["FORM_REMINDER"] = "formReminder";
7510
+ NotificationType3["FORM_SUBMISSION_CONFIRMATION"] = "formSubmissionConfirmation";
7511
+ NotificationType3["REVIEW_REQUEST"] = "reviewRequest";
7512
+ NotificationType3["PAYMENT_DUE"] = "paymentDue";
7513
+ NotificationType3["PAYMENT_CONFIRMATION"] = "paymentConfirmation";
7514
+ NotificationType3["PAYMENT_FAILED"] = "paymentFailed";
7515
+ NotificationType3["GENERAL_MESSAGE"] = "generalMessage";
7516
+ NotificationType3["ACCOUNT_NOTIFICATION"] = "accountNotification";
7308
7517
  return NotificationType3;
7309
7518
  })(NotificationType || {});
7310
7519
  var NOTIFICATIONS_COLLECTION = "notifications";
7311
7520
  var NotificationStatus = /* @__PURE__ */ ((NotificationStatus2) => {
7312
7521
  NotificationStatus2["PENDING"] = "pending";
7522
+ NotificationStatus2["PROCESSING"] = "processing";
7313
7523
  NotificationStatus2["SENT"] = "sent";
7314
7524
  NotificationStatus2["FAILED"] = "failed";
7525
+ NotificationStatus2["DELIVERED"] = "delivered";
7315
7526
  NotificationStatus2["CANCELLED"] = "cancelled";
7316
7527
  NotificationStatus2["PARTIAL_SUCCESS"] = "partialSuccess";
7317
7528
  return NotificationStatus2;
@@ -7367,9 +7578,9 @@ var NotificationService = class extends BaseService {
7367
7578
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7368
7579
  );
7369
7580
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7370
- return querySnapshot.docs.map((doc32) => ({
7371
- id: doc32.id,
7372
- ...doc32.data()
7581
+ return querySnapshot.docs.map((doc33) => ({
7582
+ id: doc33.id,
7583
+ ...doc33.data()
7373
7584
  }));
7374
7585
  }
7375
7586
  /**
@@ -7383,9 +7594,9 @@ var NotificationService = class extends BaseService {
7383
7594
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7384
7595
  );
7385
7596
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7386
- return querySnapshot.docs.map((doc32) => ({
7387
- id: doc32.id,
7388
- ...doc32.data()
7597
+ return querySnapshot.docs.map((doc33) => ({
7598
+ id: doc33.id,
7599
+ ...doc33.data()
7389
7600
  }));
7390
7601
  }
7391
7602
  /**
@@ -7457,9 +7668,9 @@ var NotificationService = class extends BaseService {
7457
7668
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7458
7669
  );
7459
7670
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7460
- return querySnapshot.docs.map((doc32) => ({
7461
- id: doc32.id,
7462
- ...doc32.data()
7671
+ return querySnapshot.docs.map((doc33) => ({
7672
+ id: doc33.id,
7673
+ ...doc33.data()
7463
7674
  }));
7464
7675
  }
7465
7676
  /**
@@ -7472,9 +7683,9 @@ var NotificationService = class extends BaseService {
7472
7683
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7473
7684
  );
7474
7685
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7475
- return querySnapshot.docs.map((doc32) => ({
7476
- id: doc32.id,
7477
- ...doc32.data()
7686
+ return querySnapshot.docs.map((doc33) => ({
7687
+ id: doc33.id,
7688
+ ...doc33.data()
7478
7689
  }));
7479
7690
  }
7480
7691
  };
@@ -7691,7 +7902,7 @@ var ProcedureService = class extends BaseService {
7691
7902
  (0, import_firestore24.where)("isActive", "==", true)
7692
7903
  );
7693
7904
  const snapshot = await (0, import_firestore24.getDocs)(q);
7694
- return snapshot.docs.map((doc32) => doc32.data());
7905
+ return snapshot.docs.map((doc33) => doc33.data());
7695
7906
  }
7696
7907
  /**
7697
7908
  * Gets all procedures for a practitioner
@@ -7705,7 +7916,7 @@ var ProcedureService = class extends BaseService {
7705
7916
  (0, import_firestore24.where)("isActive", "==", true)
7706
7917
  );
7707
7918
  const snapshot = await (0, import_firestore24.getDocs)(q);
7708
- return snapshot.docs.map((doc32) => doc32.data());
7919
+ return snapshot.docs.map((doc33) => doc33.data());
7709
7920
  }
7710
7921
  /**
7711
7922
  * Updates a procedure
@@ -7888,20 +8099,20 @@ var ProcedureService = class extends BaseService {
7888
8099
  const proceduresCollection = (0, import_firestore24.collection)(this.db, PROCEDURES_COLLECTION);
7889
8100
  let proceduresQuery = (0, import_firestore24.query)(proceduresCollection);
7890
8101
  if (pagination && pagination > 0) {
7891
- const { limit: limit11, startAfter: startAfter11 } = await import("firebase/firestore");
8102
+ const { limit: limit12, startAfter: startAfter12 } = await import("firebase/firestore");
7892
8103
  if (lastDoc) {
7893
8104
  proceduresQuery = (0, import_firestore24.query)(
7894
8105
  proceduresCollection,
7895
8106
  (0, import_firestore24.orderBy)("name"),
7896
8107
  // Use imported orderBy
7897
- startAfter11(lastDoc),
7898
- limit11(pagination)
8108
+ startAfter12(lastDoc),
8109
+ limit12(pagination)
7899
8110
  );
7900
8111
  } else {
7901
8112
  proceduresQuery = (0, import_firestore24.query)(
7902
8113
  proceduresCollection,
7903
8114
  (0, import_firestore24.orderBy)("name"),
7904
- limit11(pagination)
8115
+ limit12(pagination)
7905
8116
  );
7906
8117
  }
7907
8118
  } else {
@@ -7909,11 +8120,11 @@ var ProcedureService = class extends BaseService {
7909
8120
  }
7910
8121
  const proceduresSnapshot = await (0, import_firestore24.getDocs)(proceduresQuery);
7911
8122
  const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
7912
- const procedures = proceduresSnapshot.docs.map((doc32) => {
7913
- const data = doc32.data();
8123
+ const procedures = proceduresSnapshot.docs.map((doc33) => {
8124
+ const data = doc33.data();
7914
8125
  return {
7915
8126
  ...data,
7916
- id: doc32.id
8127
+ id: doc33.id
7917
8128
  // Ensure ID is present
7918
8129
  };
7919
8130
  });
@@ -7995,8 +8206,8 @@ var ProcedureService = class extends BaseService {
7995
8206
  console.log(
7996
8207
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
7997
8208
  );
7998
- for (const doc32 of querySnapshot.docs) {
7999
- const procedure = { ...doc32.data(), id: doc32.id };
8209
+ for (const doc33 of querySnapshot.docs) {
8210
+ const procedure = { ...doc33.data(), id: doc33.id };
8000
8211
  const distance = (0, import_geofire_common8.distanceBetween)(
8001
8212
  [center.latitude, center.longitude],
8002
8213
  [
@@ -8047,8 +8258,8 @@ var ProcedureService = class extends BaseService {
8047
8258
  console.log(
8048
8259
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
8049
8260
  );
8050
- const procedures = querySnapshot.docs.map((doc32) => {
8051
- return { ...doc32.data(), id: doc32.id };
8261
+ const procedures = querySnapshot.docs.map((doc33) => {
8262
+ return { ...doc33.data(), id: doc33.id };
8052
8263
  });
8053
8264
  if (filters.location) {
8054
8265
  const center = filters.location;
@@ -8188,7 +8399,10 @@ var DocumentationTemplateService = class extends BaseService {
8188
8399
  createdBy: userId,
8189
8400
  version: 1,
8190
8401
  isActive: true,
8191
- tags: validatedData.tags || []
8402
+ tags: validatedData.tags || [],
8403
+ isUserForm: validatedData.isUserForm || false,
8404
+ isRequired: validatedData.isRequired || false,
8405
+ sortingOrder: validatedData.sortingOrder || 0
8192
8406
  };
8193
8407
  const docRef = (0, import_firestore25.doc)(this.collectionRef, templateId);
8194
8408
  await (0, import_firestore25.setDoc)(docRef, template);
@@ -8223,21 +8437,31 @@ var DocumentationTemplateService = class extends BaseService {
8223
8437
  if (validatedData.elements) {
8224
8438
  updatedElements = validatedData.elements.map((element) => ({
8225
8439
  ...element,
8226
- id: this.generateId()
8440
+ id: element.id || this.generateId()
8227
8441
  }));
8228
8442
  }
8229
- const updateData = {
8230
- ...validatedData,
8443
+ const updatePayload = {
8231
8444
  elements: updatedElements,
8232
8445
  updatedAt: Date.now(),
8233
8446
  version: template.version + 1
8234
8447
  };
8448
+ if (validatedData.title !== void 0)
8449
+ updatePayload.title = validatedData.title;
8450
+ if (validatedData.description !== void 0)
8451
+ updatePayload.description = validatedData.description;
8452
+ if (validatedData.isActive !== void 0)
8453
+ updatePayload.isActive = validatedData.isActive;
8454
+ if (validatedData.tags !== void 0)
8455
+ updatePayload.tags = validatedData.tags;
8456
+ if (validatedData.isUserForm !== void 0)
8457
+ updatePayload.isUserForm = validatedData.isUserForm;
8458
+ if (validatedData.isRequired !== void 0)
8459
+ updatePayload.isRequired = validatedData.isRequired;
8460
+ if (validatedData.sortingOrder !== void 0)
8461
+ updatePayload.sortingOrder = validatedData.sortingOrder;
8235
8462
  const docRef = (0, import_firestore25.doc)(this.collectionRef, templateId);
8236
- await (0, import_firestore25.updateDoc)(docRef, updateData);
8237
- return {
8238
- ...template,
8239
- ...updateData
8240
- };
8463
+ await (0, import_firestore25.updateDoc)(docRef, updatePayload);
8464
+ return { ...template, ...updatePayload };
8241
8465
  }
8242
8466
  /**
8243
8467
  * Delete a document template
@@ -8266,9 +8490,9 @@ var DocumentationTemplateService = class extends BaseService {
8266
8490
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8267
8491
  const templates = [];
8268
8492
  let lastVisible = null;
8269
- querySnapshot.forEach((doc32) => {
8270
- templates.push(doc32.data());
8271
- lastVisible = doc32;
8493
+ querySnapshot.forEach((doc33) => {
8494
+ templates.push(doc33.data());
8495
+ lastVisible = doc33;
8272
8496
  });
8273
8497
  return {
8274
8498
  templates,
@@ -8296,9 +8520,9 @@ var DocumentationTemplateService = class extends BaseService {
8296
8520
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8297
8521
  const templates = [];
8298
8522
  let lastVisible = null;
8299
- querySnapshot.forEach((doc32) => {
8300
- templates.push(doc32.data());
8301
- lastVisible = doc32;
8523
+ querySnapshot.forEach((doc33) => {
8524
+ templates.push(doc33.data());
8525
+ lastVisible = doc33;
8302
8526
  });
8303
8527
  return {
8304
8528
  templates,
@@ -8325,9 +8549,9 @@ var DocumentationTemplateService = class extends BaseService {
8325
8549
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8326
8550
  const templates = [];
8327
8551
  let lastVisible = null;
8328
- querySnapshot.forEach((doc32) => {
8329
- templates.push(doc32.data());
8330
- lastVisible = doc32;
8552
+ querySnapshot.forEach((doc33) => {
8553
+ templates.push(doc33.data());
8554
+ lastVisible = doc33;
8331
8555
  });
8332
8556
  return {
8333
8557
  templates,
@@ -8341,50 +8565,80 @@ var import_firestore26 = require("firebase/firestore");
8341
8565
  var FilledDocumentService = class extends BaseService {
8342
8566
  constructor(...args) {
8343
8567
  super(...args);
8344
- this.collectionRef = (0, import_firestore26.collection)(
8345
- this.db,
8346
- FILLED_DOCUMENTS_COLLECTION
8347
- );
8348
8568
  this.templateService = new DocumentationTemplateService(...args);
8349
8569
  }
8570
+ getFormSubcollectionPath(isUserForm) {
8571
+ return isUserForm ? USER_FORMS_SUBCOLLECTION : DOCTOR_FORMS_SUBCOLLECTION;
8572
+ }
8350
8573
  /**
8351
- * Create a new filled document
8352
- * @param templateId - ID of the template to use
8353
- * @param patientId - ID of the patient
8354
- * @param practitionerId - ID of the practitioner
8355
- * @param clinicId - ID of the clinic
8356
- * @returns The created filled document
8574
+ * Create a new filled document within an appointment's subcollection.
8575
+ * @param templateId - ID of the template to use.
8576
+ * @param appointmentId - ID of the appointment this form belongs to.
8577
+ * @param procedureId - ID of the procedure associated with this form.
8578
+ * @param patientId - ID of the patient.
8579
+ * @param practitionerId - ID of the practitioner (can be system/generic if patient is filling).
8580
+ * @param clinicId - ID of the clinic.
8581
+ * @param initialValues - Optional initial values for the form elements.
8582
+ * @param initialStatus - Optional initial status for the form.
8583
+ * @returns The created filled document.
8357
8584
  */
8358
- async createFilledDocument(templateId, patientId, practitionerId, clinicId) {
8585
+ async createFilledDocumentForAppointment(templateId, appointmentId, procedureId, patientId, practitionerId, clinicId, initialValues = {}, initialStatus = "draft" /* DRAFT */) {
8359
8586
  const template = await this.templateService.getTemplateById(templateId);
8360
8587
  if (!template) {
8361
8588
  throw new Error(`Template with ID ${templateId} not found`);
8362
8589
  }
8363
8590
  const documentId3 = this.generateId();
8364
8591
  const now = Date.now();
8592
+ const isUserForm = template.isUserForm || false;
8593
+ const formSubcollection = this.getFormSubcollectionPath(isUserForm);
8365
8594
  const filledDocument = {
8366
8595
  id: documentId3,
8367
8596
  templateId,
8368
8597
  templateVersion: template.version,
8598
+ isUserForm,
8599
+ // Set based on template
8600
+ isRequired: template.isRequired || false,
8601
+ // Inherit isRequired from the template
8602
+ appointmentId,
8603
+ // NEW
8604
+ procedureId,
8605
+ // NEW
8369
8606
  patientId,
8370
8607
  practitionerId,
8371
8608
  clinicId,
8372
8609
  createdAt: now,
8373
8610
  updatedAt: now,
8374
- values: {},
8375
- status: "draft" /* DRAFT */
8611
+ values: initialValues,
8612
+ status: initialStatus
8376
8613
  };
8377
- const docRef = (0, import_firestore26.doc)(this.collectionRef, documentId3);
8614
+ const docRef = (0, import_firestore26.doc)(
8615
+ this.db,
8616
+ APPOINTMENTS_COLLECTION,
8617
+ // Replaced "appointments"
8618
+ appointmentId,
8619
+ formSubcollection,
8620
+ documentId3
8621
+ );
8378
8622
  await (0, import_firestore26.setDoc)(docRef, filledDocument);
8379
8623
  return filledDocument;
8380
8624
  }
8381
8625
  /**
8382
- * Get a filled document by ID
8383
- * @param documentId - ID of the filled document to retrieve
8384
- * @returns The filled document or null if not found
8626
+ * Get a specific filled document from an appointment's subcollection.
8627
+ * @param appointmentId - ID of the appointment.
8628
+ * @param formId - ID of the filled document.
8629
+ * @param isUserForm - Boolean indicating if it's a user form or doctor form.
8630
+ * @returns The filled document or null if not found.
8385
8631
  */
8386
- async getFilledDocumentById(documentId3) {
8387
- const docRef = (0, import_firestore26.doc)(this.collectionRef, documentId3);
8632
+ async getFilledDocumentFromAppointmentById(appointmentId, formId, isUserForm) {
8633
+ const formSubcollection = this.getFormSubcollectionPath(isUserForm);
8634
+ const docRef = (0, import_firestore26.doc)(
8635
+ this.db,
8636
+ APPOINTMENTS_COLLECTION,
8637
+ // Replaced "appointments"
8638
+ appointmentId,
8639
+ formSubcollection,
8640
+ formId
8641
+ );
8388
8642
  const docSnap = await (0, import_firestore26.getDoc)(docRef);
8389
8643
  if (!docSnap.exists()) {
8390
8644
  return null;
@@ -8392,178 +8646,183 @@ var FilledDocumentService = class extends BaseService {
8392
8646
  return docSnap.data();
8393
8647
  }
8394
8648
  /**
8395
- * Update values in a filled document
8396
- * @param documentId - ID of the filled document to update
8397
- * @param values - Updated values for elements
8398
- * @param status - Optional new status for the document
8399
- * @returns The updated filled document
8649
+ * Update values or status in a filled document within an appointment's subcollection.
8650
+ * @param appointmentId - ID of the appointment.
8651
+ * @param formId - ID of the filled document to update.
8652
+ * @param isUserForm - Boolean indicating if it's a user form or doctor form.
8653
+ * @param values - Updated values for elements.
8654
+ * @param status - Optional new status for the document.
8655
+ * @returns The updated filled document.
8400
8656
  */
8401
- async updateFilledDocument(documentId3, values, status) {
8402
- const filledDocument = await this.getFilledDocumentById(documentId3);
8403
- if (!filledDocument) {
8404
- throw new Error(`Filled document with ID ${documentId3} not found`);
8657
+ async updateFilledDocumentInAppointment(appointmentId, formId, isUserForm, values, status) {
8658
+ const formSubcollection = this.getFormSubcollectionPath(isUserForm);
8659
+ const docRef = (0, import_firestore26.doc)(
8660
+ this.db,
8661
+ APPOINTMENTS_COLLECTION,
8662
+ // Replaced "appointments"
8663
+ appointmentId,
8664
+ formSubcollection,
8665
+ formId
8666
+ );
8667
+ const existingDoc = await this.getFilledDocumentFromAppointmentById(
8668
+ appointmentId,
8669
+ formId,
8670
+ isUserForm
8671
+ );
8672
+ if (!existingDoc) {
8673
+ throw new Error(
8674
+ `Filled document with ID ${formId} not found in appointment ${appointmentId} ${formSubcollection}`
8675
+ );
8405
8676
  }
8406
- const updateData = {
8407
- values: {
8408
- ...filledDocument.values,
8409
- ...values
8410
- },
8677
+ const updatePayload = {
8411
8678
  updatedAt: Date.now()
8412
8679
  };
8680
+ if (values) {
8681
+ updatePayload.values = {
8682
+ ...existingDoc.values,
8683
+ ...values
8684
+ };
8685
+ }
8413
8686
  if (status) {
8414
- updateData.status = status;
8687
+ updatePayload.status = status;
8415
8688
  }
8416
- const docRef = (0, import_firestore26.doc)(this.collectionRef, documentId3);
8417
- await (0, import_firestore26.updateDoc)(docRef, updateData);
8418
- return {
8419
- ...filledDocument,
8420
- ...updateData
8421
- };
8689
+ if (Object.keys(updatePayload).length === 1 && "updatedAt" in updatePayload) {
8690
+ }
8691
+ await (0, import_firestore26.updateDoc)(docRef, updatePayload);
8692
+ return { ...existingDoc, ...updatePayload };
8422
8693
  }
8423
8694
  /**
8424
- * Get filled documents for a patient
8425
- * @param patientId - ID of the patient
8426
- * @param pageSize - Number of documents to retrieve
8427
- * @param lastDoc - Last document from previous page for pagination
8428
- * @returns Array of filled documents and the last document for pagination
8695
+ * Get all filled user forms for a specific appointment.
8696
+ * @param appointmentId ID of the appointment.
8697
+ * @param pageSize Number of documents to retrieve.
8698
+ * @param lastDoc Last document from previous page for pagination.
8429
8699
  */
8430
- async getFilledDocumentsByPatient(patientId, pageSize = 20, lastDoc) {
8700
+ async getFilledUserFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
8701
+ const subcollectionRef = (0, import_firestore26.collection)(
8702
+ this.db,
8703
+ APPOINTMENTS_COLLECTION,
8704
+ // Replaced "appointments"
8705
+ appointmentId,
8706
+ USER_FORMS_SUBCOLLECTION
8707
+ );
8431
8708
  let q = (0, import_firestore26.query)(
8432
- this.collectionRef,
8433
- (0, import_firestore26.where)("patientId", "==", patientId),
8709
+ subcollectionRef,
8434
8710
  (0, import_firestore26.orderBy)("updatedAt", "desc"),
8435
8711
  (0, import_firestore26.limit)(pageSize)
8436
8712
  );
8437
8713
  if (lastDoc) {
8438
8714
  q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8439
8715
  }
8440
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8441
- const documents = [];
8442
- let lastVisible = null;
8443
- querySnapshot.forEach((doc32) => {
8444
- documents.push(doc32.data());
8445
- lastVisible = doc32;
8446
- });
8447
- return {
8448
- documents,
8449
- lastDoc: lastVisible
8450
- };
8716
+ return this.executeQuery(q);
8451
8717
  }
8452
8718
  /**
8453
- * Get filled documents for a practitioner
8454
- * @param practitionerId - ID of the practitioner
8455
- * @param pageSize - Number of documents to retrieve
8456
- * @param lastDoc - Last document from previous page for pagination
8457
- * @returns Array of filled documents and the last document for pagination
8719
+ * Get all filled doctor forms for a specific appointment.
8720
+ * @param appointmentId ID of the appointment.
8721
+ * @param pageSize Number of documents to retrieve.
8722
+ * @param lastDoc Last document from previous page for pagination.
8458
8723
  */
8459
- async getFilledDocumentsByPractitioner(practitionerId, pageSize = 20, lastDoc) {
8724
+ async getFilledDoctorFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
8725
+ const subcollectionRef = (0, import_firestore26.collection)(
8726
+ this.db,
8727
+ APPOINTMENTS_COLLECTION,
8728
+ // Replaced "appointments"
8729
+ appointmentId,
8730
+ DOCTOR_FORMS_SUBCOLLECTION
8731
+ );
8460
8732
  let q = (0, import_firestore26.query)(
8461
- this.collectionRef,
8462
- (0, import_firestore26.where)("practitionerId", "==", practitionerId),
8733
+ subcollectionRef,
8463
8734
  (0, import_firestore26.orderBy)("updatedAt", "desc"),
8464
8735
  (0, import_firestore26.limit)(pageSize)
8465
8736
  );
8466
8737
  if (lastDoc) {
8467
8738
  q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8468
8739
  }
8740
+ return this.executeQuery(q);
8741
+ }
8742
+ // Helper to execute query and return documents + lastDoc
8743
+ async executeQuery(q) {
8469
8744
  const querySnapshot = await (0, import_firestore26.getDocs)(q);
8470
8745
  const documents = [];
8471
8746
  let lastVisible = null;
8472
- querySnapshot.forEach((doc32) => {
8473
- documents.push(doc32.data());
8474
- lastVisible = doc32;
8747
+ querySnapshot.forEach((doc33) => {
8748
+ documents.push(doc33.data());
8749
+ lastVisible = doc33;
8475
8750
  });
8476
8751
  return {
8477
8752
  documents,
8478
8753
  lastDoc: lastVisible
8479
8754
  };
8480
8755
  }
8756
+ // IMPORTANT: The following methods that query across all patients/practitioners/clinics
8757
+ // (e.g., getFilledDocumentsByPatient, getFilledDocumentsByPractitioner)
8758
+ // will NOT work correctly if FILLED_DOCUMENTS_COLLECTION is no longer a top-level collection
8759
+ // and data is only in appointment subcollections. You would need to use
8760
+ // Firestore Collection Group Queries for that, which require an index and a different query approach.
8761
+ // These methods are left here for now but would need significant rework or removal.
8762
+ /**
8763
+ * Get filled documents for a patient (NEEDS REWORK for subcollections or Collection Group Query)
8764
+ * @param patientId - ID of the patient
8765
+ * @param pageSize - Number of documents to retrieve
8766
+ * @param lastDoc - Last document from previous page for pagination
8767
+ * @returns Array of filled documents and the last document for pagination
8768
+ */
8769
+ async getFilledDocumentsByPatient(patientId, pageSize = 20, lastDoc) {
8770
+ console.warn(
8771
+ "getFilledDocumentsByPatient needs rework for subcollection model or Collection Group Queries."
8772
+ );
8773
+ return { documents: [], lastDoc: null };
8774
+ }
8481
8775
  /**
8482
- * Get filled documents for a clinic
8776
+ * Get filled documents for a practitioner (NEEDS REWORK for subcollections or Collection Group Query)
8777
+ * @param practitionerId - ID of the practitioner
8778
+ * @param pageSize - Number of documents to retrieve
8779
+ * @param lastDoc - Last document from previous page for pagination
8780
+ * @returns Array of filled documents and the last document for pagination
8781
+ */
8782
+ async getFilledDocumentsByPractitioner(practitionerId, pageSize = 20, lastDoc) {
8783
+ console.warn(
8784
+ "getFilledDocumentsByPractitioner needs rework for subcollection model or Collection Group Queries."
8785
+ );
8786
+ return { documents: [], lastDoc: null };
8787
+ }
8788
+ /**
8789
+ * Get filled documents for a clinic (NEEDS REWORK for subcollections or Collection Group Query)
8483
8790
  * @param clinicId - ID of the clinic
8484
8791
  * @param pageSize - Number of documents to retrieve
8485
8792
  * @param lastDoc - Last document from previous page for pagination
8486
8793
  * @returns Array of filled documents and the last document for pagination
8487
8794
  */
8488
8795
  async getFilledDocumentsByClinic(clinicId, pageSize = 20, lastDoc) {
8489
- let q = (0, import_firestore26.query)(
8490
- this.collectionRef,
8491
- (0, import_firestore26.where)("clinicId", "==", clinicId),
8492
- (0, import_firestore26.orderBy)("updatedAt", "desc"),
8493
- (0, import_firestore26.limit)(pageSize)
8796
+ console.warn(
8797
+ "getFilledDocumentsByClinic needs rework for subcollection model or Collection Group Queries."
8494
8798
  );
8495
- if (lastDoc) {
8496
- q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8497
- }
8498
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8499
- const documents = [];
8500
- let lastVisible = null;
8501
- querySnapshot.forEach((doc32) => {
8502
- documents.push(doc32.data());
8503
- lastVisible = doc32;
8504
- });
8505
- return {
8506
- documents,
8507
- lastDoc: lastVisible
8508
- };
8799
+ return { documents: [], lastDoc: null };
8509
8800
  }
8510
8801
  /**
8511
- * Get filled documents by template
8802
+ * Get filled documents by template (NEEDS REWORK for subcollections or Collection Group Query)
8512
8803
  * @param templateId - ID of the template
8513
8804
  * @param pageSize - Number of documents to retrieve
8514
8805
  * @param lastDoc - Last document from previous page for pagination
8515
8806
  * @returns Array of filled documents and the last document for pagination
8516
8807
  */
8517
8808
  async getFilledDocumentsByTemplate(templateId, pageSize = 20, lastDoc) {
8518
- let q = (0, import_firestore26.query)(
8519
- this.collectionRef,
8520
- (0, import_firestore26.where)("templateId", "==", templateId),
8521
- (0, import_firestore26.orderBy)("updatedAt", "desc"),
8522
- (0, import_firestore26.limit)(pageSize)
8809
+ console.warn(
8810
+ "getFilledDocumentsByTemplate needs rework for subcollection model or Collection Group Queries."
8523
8811
  );
8524
- if (lastDoc) {
8525
- q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8526
- }
8527
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8528
- const documents = [];
8529
- let lastVisible = null;
8530
- querySnapshot.forEach((doc32) => {
8531
- documents.push(doc32.data());
8532
- lastVisible = doc32;
8533
- });
8534
- return {
8535
- documents,
8536
- lastDoc: lastVisible
8537
- };
8812
+ return { documents: [], lastDoc: null };
8538
8813
  }
8539
8814
  /**
8540
- * Get filled documents by status
8815
+ * Get filled documents by status (NEEDS REWORK for subcollections or Collection Group Query)
8541
8816
  * @param status - Status to filter by
8542
8817
  * @param pageSize - Number of documents to retrieve
8543
8818
  * @param lastDoc - Last document from previous page for pagination
8544
8819
  * @returns Array of filled documents and the last document for pagination
8545
8820
  */
8546
8821
  async getFilledDocumentsByStatus(status, pageSize = 20, lastDoc) {
8547
- let q = (0, import_firestore26.query)(
8548
- this.collectionRef,
8549
- (0, import_firestore26.where)("status", "==", status),
8550
- (0, import_firestore26.orderBy)("updatedAt", "desc"),
8551
- (0, import_firestore26.limit)(pageSize)
8822
+ console.warn(
8823
+ "getFilledDocumentsByStatus needs rework for subcollection model or Collection Group Queries."
8552
8824
  );
8553
- if (lastDoc) {
8554
- q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8555
- }
8556
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8557
- const documents = [];
8558
- let lastVisible = null;
8559
- querySnapshot.forEach((doc32) => {
8560
- documents.push(doc32.data());
8561
- lastVisible = doc32;
8562
- });
8563
- return {
8564
- documents,
8565
- lastDoc: lastVisible
8566
- };
8825
+ return { documents: [], lastDoc: null };
8567
8826
  }
8568
8827
  };
8569
8828
 
@@ -9055,7 +9314,7 @@ async function searchCalendarEventsUtil(db, params) {
9055
9314
  const finalQuery = (0, import_firestore33.query)(collectionRef, ...constraints);
9056
9315
  const querySnapshot = await (0, import_firestore33.getDocs)(finalQuery);
9057
9316
  const events = querySnapshot.docs.map(
9058
- (doc32) => ({ id: doc32.id, ...doc32.data() })
9317
+ (doc33) => ({ id: doc33.id, ...doc33.data() })
9059
9318
  );
9060
9319
  return events;
9061
9320
  } catch (error) {
@@ -9137,7 +9396,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
9137
9396
  );
9138
9397
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
9139
9398
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
9140
- return querySnapshot.docs.map((doc32) => doc32.data());
9399
+ return querySnapshot.docs.map((doc33) => doc33.data());
9141
9400
  }
9142
9401
  async function getPatientSyncedCalendarUtil(db, patientId, calendarId) {
9143
9402
  const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
@@ -9154,7 +9413,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
9154
9413
  );
9155
9414
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
9156
9415
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
9157
- return querySnapshot.docs.map((doc32) => doc32.data());
9416
+ return querySnapshot.docs.map((doc33) => doc33.data());
9158
9417
  }
9159
9418
  async function getClinicSyncedCalendarUtil(db, clinicId, calendarId) {
9160
9419
  const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
@@ -9171,7 +9430,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
9171
9430
  );
9172
9431
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
9173
9432
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
9174
- return querySnapshot.docs.map((doc32) => doc32.data());
9433
+ return querySnapshot.docs.map((doc33) => doc33.data());
9175
9434
  }
9176
9435
  async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendarId, updateData) {
9177
9436
  const calendarRef = getPractitionerSyncedCalendarDocRef(
@@ -10526,9 +10785,9 @@ var CalendarServiceV2 = class extends BaseService {
10526
10785
  (0, import_firestore37.where)("eventTime.start", "<=", import_firestore36.Timestamp.fromDate(endDate))
10527
10786
  );
10528
10787
  const eventsSnapshot = await (0, import_firestore37.getDocs)(q);
10529
- const events = eventsSnapshot.docs.map((doc32) => ({
10530
- id: doc32.id,
10531
- ...doc32.data()
10788
+ const events = eventsSnapshot.docs.map((doc33) => ({
10789
+ id: doc33.id,
10790
+ ...doc33.data()
10532
10791
  }));
10533
10792
  const calendars = await this.syncedCalendarsService.getPractitionerSyncedCalendars(
10534
10793
  doctorId
@@ -11160,7 +11419,7 @@ var CalendarServiceV2 = class extends BaseService {
11160
11419
  ])
11161
11420
  );
11162
11421
  const querySnapshot = await (0, import_firestore37.getDocs)(q);
11163
- return querySnapshot.docs.map((doc32) => doc32.data());
11422
+ return querySnapshot.docs.map((doc33) => doc33.data());
11164
11423
  }
11165
11424
  /**
11166
11425
  * Calculates available time slots based on working hours, schedule and existing appointments
@@ -11427,7 +11686,7 @@ var ReviewService = class extends BaseService {
11427
11686
  (0, import_firestore38.where)("patientId", "==", patientId)
11428
11687
  );
11429
11688
  const snapshot = await (0, import_firestore38.getDocs)(q);
11430
- return snapshot.docs.map((doc32) => doc32.data());
11689
+ return snapshot.docs.map((doc33) => doc33.data());
11431
11690
  }
11432
11691
  /**
11433
11692
  * Gets all reviews for a specific clinic
@@ -11440,7 +11699,7 @@ var ReviewService = class extends BaseService {
11440
11699
  (0, import_firestore38.where)("clinicReview.clinicId", "==", clinicId)
11441
11700
  );
11442
11701
  const snapshot = await (0, import_firestore38.getDocs)(q);
11443
- return snapshot.docs.map((doc32) => doc32.data());
11702
+ return snapshot.docs.map((doc33) => doc33.data());
11444
11703
  }
11445
11704
  /**
11446
11705
  * Gets all reviews for a specific practitioner
@@ -11453,7 +11712,7 @@ var ReviewService = class extends BaseService {
11453
11712
  (0, import_firestore38.where)("practitionerReview.practitionerId", "==", practitionerId)
11454
11713
  );
11455
11714
  const snapshot = await (0, import_firestore38.getDocs)(q);
11456
- return snapshot.docs.map((doc32) => doc32.data());
11715
+ return snapshot.docs.map((doc33) => doc33.data());
11457
11716
  }
11458
11717
  /**
11459
11718
  * Gets all reviews for a specific procedure
@@ -11466,7 +11725,7 @@ var ReviewService = class extends BaseService {
11466
11725
  (0, import_firestore38.where)("procedureReview.procedureId", "==", procedureId)
11467
11726
  );
11468
11727
  const snapshot = await (0, import_firestore38.getDocs)(q);
11469
- return snapshot.docs.map((doc32) => doc32.data());
11728
+ return snapshot.docs.map((doc33) => doc33.data());
11470
11729
  }
11471
11730
  /**
11472
11731
  * Gets all reviews for a specific appointment
@@ -12165,7 +12424,7 @@ async function updateCalendarEventStatus(db, calendarEventId, appointmentStatus)
12165
12424
  case "canceled_clinic" /* CANCELED_CLINIC */:
12166
12425
  calendarStatus = "canceled";
12167
12426
  break;
12168
- case "rescheduled" /* RESCHEDULED */:
12427
+ case AppointmentStatus.RESCHEDULED:
12169
12428
  calendarStatus = "rescheduled";
12170
12429
  break;
12171
12430
  case "completed" /* COMPLETED */:
@@ -12239,7 +12498,7 @@ async function searchAppointmentsUtil(db, params) {
12239
12498
  const q = (0, import_firestore39.query)((0, import_firestore39.collection)(db, APPOINTMENTS_COLLECTION), ...constraints);
12240
12499
  const querySnapshot = await (0, import_firestore39.getDocs)(q);
12241
12500
  const appointments = querySnapshot.docs.map(
12242
- (doc32) => doc32.data()
12501
+ (doc33) => doc33.data()
12243
12502
  );
12244
12503
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
12245
12504
  return { appointments, lastDoc };
@@ -12262,12 +12521,13 @@ var AppointmentService = class extends BaseService {
12262
12521
  * @param practitionerService Practitioner service instance
12263
12522
  * @param clinicService Clinic service instance
12264
12523
  */
12265
- constructor(db, auth, app, calendarService, patientService, practitionerService, clinicService) {
12524
+ constructor(db, auth, app, calendarService, patientService, practitionerService, clinicService, filledDocumentService) {
12266
12525
  super(db, auth, app);
12267
12526
  this.calendarService = calendarService;
12268
12527
  this.patientService = patientService;
12269
12528
  this.practitionerService = practitionerService;
12270
12529
  this.clinicService = clinicService;
12530
+ this.filledDocumentService = filledDocumentService;
12271
12531
  this.functions = (0, import_functions.getFunctions)(app, "europe-west6");
12272
12532
  }
12273
12533
  /**
@@ -12623,152 +12883,331 @@ var AppointmentService = class extends BaseService {
12623
12883
  *
12624
12884
  * @param appointmentId ID of the appointment
12625
12885
  * @param newStatus New status to set
12626
- * @param cancellationReason Required if canceling the appointment
12627
- * @param canceledBy Required if canceling the appointment
12886
+ * @param details Optional details for the status change
12628
12887
  * @returns The updated appointment
12629
12888
  */
12630
- async updateAppointmentStatus(appointmentId, newStatus, cancellationReason, canceledBy) {
12889
+ async updateAppointmentStatus(appointmentId, newStatus, details) {
12631
12890
  console.log(
12632
12891
  `[APPOINTMENT_SERVICE] Updating status of appointment ${appointmentId} to ${newStatus}`
12633
12892
  );
12634
- const updateData = { status: newStatus };
12635
- if (newStatus === "canceled_clinic" /* CANCELED_CLINIC */ || newStatus === "canceled_patient" /* CANCELED_PATIENT */) {
12636
- if (!cancellationReason) {
12637
- throw new Error(
12638
- "Cancellation reason is required when canceling an appointment"
12639
- );
12893
+ const updateData = {
12894
+ status: newStatus,
12895
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12896
+ };
12897
+ if (newStatus === "canceled_clinic" /* CANCELED_CLINIC */ || newStatus === "canceled_patient" /* CANCELED_PATIENT */ || newStatus === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
12898
+ if (!(details == null ? void 0 : details.cancellationReason)) {
12899
+ throw new Error("Cancellation reason is required when canceling.");
12640
12900
  }
12641
- if (!canceledBy) {
12642
- throw new Error(
12643
- "Canceled by is required when canceling an appointment"
12644
- );
12901
+ if (!(details == null ? void 0 : details.canceledBy)) {
12902
+ throw new Error("Canceled by is required when canceling.");
12645
12903
  }
12646
- updateData.cancellationReason = cancellationReason;
12647
- updateData.canceledBy = canceledBy;
12904
+ updateData.cancellationReason = details.cancellationReason;
12905
+ updateData.canceledBy = details.canceledBy;
12906
+ updateData.cancellationTime = import_firestore40.Timestamp.now();
12648
12907
  }
12649
12908
  if (newStatus === "confirmed" /* CONFIRMED */) {
12650
12909
  updateData.confirmationTime = import_firestore40.Timestamp.now();
12651
12910
  }
12911
+ if (newStatus === "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
12912
+ updateData.rescheduleTime = import_firestore40.Timestamp.now();
12913
+ }
12652
12914
  return this.updateAppointment(appointmentId, updateData);
12653
12915
  }
12654
12916
  /**
12655
- * Confirms an appointment.
12656
- *
12657
- * @param appointmentId ID of the appointment to confirm
12658
- * @returns The confirmed appointment
12917
+ * Confirms a PENDING appointment by an Admin/Clinic.
12659
12918
  */
12660
- async confirmAppointment(appointmentId) {
12919
+ async confirmAppointmentAdmin(appointmentId) {
12661
12920
  console.log(
12662
- `[APPOINTMENT_SERVICE] Confirming appointment: ${appointmentId}`
12921
+ `[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`
12663
12922
  );
12923
+ const appointment = await this.getAppointmentById(appointmentId);
12924
+ if (!appointment)
12925
+ throw new Error(`Appointment ${appointmentId} not found.`);
12926
+ if (appointment.status !== "pending" /* PENDING */) {
12927
+ throw new Error(
12928
+ `Appointment ${appointmentId} is not in PENDING state to be confirmed.`
12929
+ );
12930
+ }
12664
12931
  return this.updateAppointmentStatus(
12665
12932
  appointmentId,
12666
12933
  "confirmed" /* CONFIRMED */
12667
12934
  );
12668
12935
  }
12669
12936
  /**
12670
- * Cancels an appointment from the clinic side.
12671
- *
12672
- * @param appointmentId ID of the appointment to cancel
12673
- * @param reason Reason for cancellation
12674
- * @returns The canceled appointment
12937
+ * Cancels an appointment by the User (Patient).
12938
+ */
12939
+ async cancelAppointmentUser(appointmentId, reason) {
12940
+ console.log(
12941
+ `[APPOINTMENT_SERVICE] User canceling appointment: ${appointmentId}`
12942
+ );
12943
+ return this.updateAppointmentStatus(
12944
+ appointmentId,
12945
+ "canceled_patient" /* CANCELED_PATIENT */,
12946
+ {
12947
+ cancellationReason: reason,
12948
+ canceledBy: "patient"
12949
+ }
12950
+ );
12951
+ }
12952
+ /**
12953
+ * Cancels an appointment by an Admin/Clinic.
12675
12954
  */
12676
- async cancelAppointmentByClinic(appointmentId, reason) {
12955
+ async cancelAppointmentAdmin(appointmentId, reason) {
12677
12956
  console.log(
12678
- `[APPOINTMENT_SERVICE] Canceling appointment by clinic: ${appointmentId}`
12957
+ `[APPOINTMENT_SERVICE] Admin canceling appointment: ${appointmentId}`
12679
12958
  );
12680
12959
  return this.updateAppointmentStatus(
12681
12960
  appointmentId,
12682
12961
  "canceled_clinic" /* CANCELED_CLINIC */,
12683
- reason,
12684
- "clinic"
12962
+ {
12963
+ cancellationReason: reason,
12964
+ canceledBy: "clinic"
12965
+ }
12685
12966
  );
12686
12967
  }
12687
12968
  /**
12688
- * Cancels an appointment from the patient side.
12689
- *
12690
- * @param appointmentId ID of the appointment to cancel
12691
- * @param reason Reason for cancellation
12692
- * @returns The canceled appointment
12969
+ * Admin proposes to reschedule an appointment.
12970
+ * Sets status to RESCHEDULED_BY_CLINIC and updates times.
12971
+ */
12972
+ async rescheduleAppointmentAdmin(appointmentId, newStartTime, newEndTime) {
12973
+ console.log(
12974
+ `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${appointmentId}`
12975
+ );
12976
+ if (newEndTime.toMillis() <= newStartTime.toMillis()) {
12977
+ throw new Error("New end time must be after new start time.");
12978
+ }
12979
+ const updateData = {
12980
+ status: "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */,
12981
+ appointmentStartTime: newStartTime,
12982
+ appointmentEndTime: newEndTime,
12983
+ rescheduleTime: import_firestore40.Timestamp.now(),
12984
+ confirmationTime: null,
12985
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12986
+ };
12987
+ return this.updateAppointment(appointmentId, updateData);
12988
+ }
12989
+ /**
12990
+ * User confirms a reschedule proposed by the clinic.
12991
+ * Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
12693
12992
  */
12694
- async cancelAppointmentByPatient(appointmentId, reason) {
12993
+ async rescheduleAppointmentConfirmUser(appointmentId) {
12695
12994
  console.log(
12696
- `[APPOINTMENT_SERVICE] Canceling appointment by patient: ${appointmentId}`
12995
+ `[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`
12697
12996
  );
12997
+ const appointment = await this.getAppointmentById(appointmentId);
12998
+ if (!appointment)
12999
+ throw new Error(`Appointment ${appointmentId} not found.`);
13000
+ if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
13001
+ throw new Error(
13002
+ `Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
13003
+ );
13004
+ }
12698
13005
  return this.updateAppointmentStatus(
12699
13006
  appointmentId,
12700
- "canceled_patient" /* CANCELED_PATIENT */,
12701
- reason,
12702
- "patient"
13007
+ "confirmed" /* CONFIRMED */
12703
13008
  );
12704
13009
  }
12705
13010
  /**
12706
- * Marks an appointment as checked in.
12707
- *
12708
- * @param appointmentId ID of the appointment
12709
- * @returns The updated appointment
13011
+ * User rejects a reschedule proposed by the clinic.
13012
+ * Status changes from RESCHEDULED_BY_CLINIC to CANCELED_PATIENT_RESCHEDULED.
12710
13013
  */
12711
- async checkInAppointment(appointmentId) {
13014
+ async rescheduleAppointmentRejectUser(appointmentId, reason) {
12712
13015
  console.log(
12713
- `[APPOINTMENT_SERVICE] Checking in appointment: ${appointmentId}`
13016
+ `[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`
12714
13017
  );
13018
+ const appointment = await this.getAppointmentById(appointmentId);
13019
+ if (!appointment)
13020
+ throw new Error(`Appointment ${appointmentId} not found.`);
13021
+ if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
13022
+ throw new Error(
13023
+ `Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
13024
+ );
13025
+ }
12715
13026
  return this.updateAppointmentStatus(
12716
13027
  appointmentId,
12717
- "checked_in" /* CHECKED_IN */
13028
+ "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */,
13029
+ {
13030
+ cancellationReason: reason,
13031
+ canceledBy: "patient"
13032
+ }
12718
13033
  );
12719
13034
  }
12720
13035
  /**
12721
- * Marks an appointment as in progress.
12722
- *
12723
- * @param appointmentId ID of the appointment
12724
- * @returns The updated appointment
13036
+ * Admin checks in a patient for their appointment.
13037
+ * Requires all pending user forms to be completed.
12725
13038
  */
12726
- async startAppointment(appointmentId) {
12727
- console.log(`[APPOINTMENT_SERVICE] Starting appointment: ${appointmentId}`);
13039
+ async checkInPatientAdmin(appointmentId) {
13040
+ console.log(
13041
+ `[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`
13042
+ );
13043
+ const appointment = await this.getAppointmentById(appointmentId);
13044
+ if (!appointment)
13045
+ throw new Error(`Appointment ${appointmentId} not found.`);
13046
+ if (appointment.pendingUserFormsIds && appointment.pendingUserFormsIds.length > 0) {
13047
+ throw new Error(
13048
+ `Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(
13049
+ ", "
13050
+ )}`
13051
+ );
13052
+ }
13053
+ if (appointment.status !== "confirmed" /* CONFIRMED */ && appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
13054
+ console.warn(
13055
+ `Checking in appointment ${appointmentId} with status ${appointment.status}. Ensure this is intended.`
13056
+ );
13057
+ }
12728
13058
  return this.updateAppointmentStatus(
12729
13059
  appointmentId,
12730
- "in_progress" /* IN_PROGRESS */
13060
+ "checked_in" /* CHECKED_IN */
12731
13061
  );
12732
13062
  }
12733
13063
  /**
12734
- * Marks an appointment as completed.
12735
- *
12736
- * @param appointmentId ID of the appointment
12737
- * @param actualDurationMinutes Actual duration of the appointment in minutes
12738
- * @returns The updated appointment
13064
+ * Doctor starts the appointment procedure.
12739
13065
  */
12740
- async completeAppointment(appointmentId, actualDurationMinutes) {
13066
+ async startAppointmentDoctor(appointmentId) {
12741
13067
  console.log(
12742
- `[APPOINTMENT_SERVICE] Completing appointment: ${appointmentId}`
13068
+ `[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`
12743
13069
  );
13070
+ const appointment = await this.getAppointmentById(appointmentId);
13071
+ if (!appointment)
13072
+ throw new Error(`Appointment ${appointmentId} not found.`);
13073
+ if (appointment.status !== "checked_in" /* CHECKED_IN */) {
13074
+ throw new Error(
13075
+ `Appointment ${appointmentId} must be CHECKED_IN to start.`
13076
+ );
13077
+ }
13078
+ const updateData = {
13079
+ status: "in_progress" /* IN_PROGRESS */,
13080
+ procedureActualStartTime: import_firestore40.Timestamp.now(),
13081
+ // Set actual start time
13082
+ updatedAt: (0, import_firestore40.serverTimestamp)()
13083
+ };
13084
+ return this.updateAppointment(appointmentId, updateData);
13085
+ }
13086
+ /**
13087
+ * Doctor completes and finalizes the appointment.
13088
+ */
13089
+ async completeAppointmentDoctor(appointmentId, finalizationNotes, actualDurationMinutesInput) {
13090
+ console.log(
13091
+ `[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`
13092
+ );
13093
+ const currentUser = this.auth.currentUser;
13094
+ if (!currentUser)
13095
+ throw new Error("Authentication required to complete appointment.");
13096
+ const appointment = await this.getAppointmentById(appointmentId);
13097
+ if (!appointment)
13098
+ throw new Error(`Appointment ${appointmentId} not found.`);
13099
+ let calculatedDurationMinutes = actualDurationMinutesInput;
13100
+ const procedureCompletionTime = import_firestore40.Timestamp.now();
13101
+ if (calculatedDurationMinutes === void 0 && appointment.procedureActualStartTime) {
13102
+ const startTimeMillis = appointment.procedureActualStartTime.toMillis();
13103
+ const endTimeMillis = procedureCompletionTime.toMillis();
13104
+ if (endTimeMillis > startTimeMillis) {
13105
+ calculatedDurationMinutes = Math.round(
13106
+ (endTimeMillis - startTimeMillis) / 6e4
13107
+ );
13108
+ }
13109
+ }
12744
13110
  const updateData = {
12745
13111
  status: "completed" /* COMPLETED */,
12746
- actualDurationMinutes
13112
+ actualDurationMinutes: calculatedDurationMinutes,
13113
+ // Use calculated or provided duration
13114
+ finalizedDetails: {
13115
+ by: currentUser.uid,
13116
+ // This is used ID, not practitioner's profile ID (just so we know who completed the appointment)
13117
+ at: procedureCompletionTime,
13118
+ // Use consistent completion timestamp
13119
+ notes: finalizationNotes
13120
+ },
13121
+ // Optionally update appointmentEndTime to the actual completion time
13122
+ // appointmentEndTime: procedureCompletionTime,
13123
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12747
13124
  };
12748
13125
  return this.updateAppointment(appointmentId, updateData);
12749
13126
  }
12750
13127
  /**
12751
- * Marks an appointment as no-show.
12752
- *
12753
- * @param appointmentId ID of the appointment
12754
- * @returns The updated appointment
13128
+ * Admin marks an appointment as No-Show.
12755
13129
  */
12756
- async markNoShow(appointmentId) {
13130
+ async markNoShowAdmin(appointmentId) {
12757
13131
  console.log(
12758
- `[APPOINTMENT_SERVICE] Marking appointment as no-show: ${appointmentId}`
13132
+ `[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`
12759
13133
  );
13134
+ const appointment = await this.getAppointmentById(appointmentId);
13135
+ if (!appointment)
13136
+ throw new Error(`Appointment ${appointmentId} not found.`);
13137
+ if (import_firestore40.Timestamp.now().toMillis() < appointment.appointmentStartTime.toMillis()) {
13138
+ throw new Error("Cannot mark no-show before appointment start time.");
13139
+ }
12760
13140
  return this.updateAppointmentStatus(
12761
13141
  appointmentId,
12762
- "no_show" /* NO_SHOW */
13142
+ "no_show" /* NO_SHOW */,
13143
+ {
13144
+ cancellationReason: "Patient did not show up for the appointment.",
13145
+ canceledBy: "clinic"
13146
+ }
12763
13147
  );
12764
13148
  }
13149
+ /**
13150
+ * Adds a media item to an appointment.
13151
+ */
13152
+ async addMediaToAppointment(appointmentId, mediaItemData) {
13153
+ console.log(
13154
+ `[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`
13155
+ );
13156
+ const currentUser = this.auth.currentUser;
13157
+ if (!currentUser) throw new Error("Authentication required.");
13158
+ const newMediaItem = {
13159
+ ...mediaItemData,
13160
+ id: this.generateId(),
13161
+ uploadedAt: import_firestore40.Timestamp.now(),
13162
+ uploadedBy: currentUser.uid
13163
+ };
13164
+ const updateData = {
13165
+ media: (0, import_firestore40.arrayUnion)(newMediaItem),
13166
+ updatedAt: (0, import_firestore40.serverTimestamp)()
13167
+ };
13168
+ return this.updateAppointment(appointmentId, updateData);
13169
+ }
13170
+ /**
13171
+ * Removes a media item from an appointment.
13172
+ */
13173
+ async removeMediaFromAppointment(appointmentId, mediaItemId) {
13174
+ console.log(
13175
+ `[APPOINTMENT_SERVICE] Removing media ${mediaItemId} from appointment ${appointmentId}`
13176
+ );
13177
+ const appointment = await this.getAppointmentById(appointmentId);
13178
+ if (!appointment || !appointment.media) {
13179
+ throw new Error("Appointment or media list not found.");
13180
+ }
13181
+ const mediaToRemove = appointment.media.find((m) => m.id === mediaItemId);
13182
+ if (!mediaToRemove) {
13183
+ throw new Error(`Media item ${mediaItemId} not found in appointment.`);
13184
+ }
13185
+ const updateData = {
13186
+ media: (0, import_firestore40.arrayRemove)(mediaToRemove),
13187
+ updatedAt: (0, import_firestore40.serverTimestamp)()
13188
+ };
13189
+ return this.updateAppointment(appointmentId, updateData);
13190
+ }
13191
+ /**
13192
+ * Adds or updates review information for an appointment.
13193
+ */
13194
+ async addReviewToAppointment(appointmentId, reviewData) {
13195
+ console.log(
13196
+ `[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`
13197
+ );
13198
+ const newReviewInfo = {
13199
+ ...reviewData,
13200
+ reviewId: this.generateId(),
13201
+ reviewedAt: import_firestore40.Timestamp.now()
13202
+ };
13203
+ const updateData = {
13204
+ reviewInfo: newReviewInfo,
13205
+ updatedAt: (0, import_firestore40.serverTimestamp)()
13206
+ };
13207
+ return this.updateAppointment(appointmentId, updateData);
13208
+ }
12765
13209
  /**
12766
13210
  * Updates the payment status of an appointment.
12767
- *
12768
- * @param appointmentId ID of the appointment
12769
- * @param paymentStatus New payment status
12770
- * @param paymentTransactionId Optional transaction ID for the payment
12771
- * @returns The updated appointment
12772
13211
  */
12773
13212
  async updatePaymentStatus(appointmentId, paymentStatus, paymentTransactionId) {
12774
13213
  console.log(
@@ -12776,7 +13215,8 @@ var AppointmentService = class extends BaseService {
12776
13215
  );
12777
13216
  const updateData = {
12778
13217
  paymentStatus,
12779
- paymentTransactionId: paymentTransactionId || null
13218
+ paymentTransactionId: paymentTransactionId || null,
13219
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12780
13220
  };
12781
13221
  return this.updateAppointment(appointmentId, updateData);
12782
13222
  }
@@ -12849,9 +13289,203 @@ var AppointmentService = class extends BaseService {
12849
13289
  }
12850
13290
  };
12851
13291
 
12852
- // src/backoffice/services/brand.service.ts
13292
+ // src/services/patient/patientRequirements.service.ts
12853
13293
  var import_firestore41 = require("firebase/firestore");
12854
13294
 
13295
+ // src/types/patient/patient-requirements.ts
13296
+ var PatientInstructionStatus = /* @__PURE__ */ ((PatientInstructionStatus2) => {
13297
+ PatientInstructionStatus2["PENDING_NOTIFICATION"] = "pendingNotification";
13298
+ PatientInstructionStatus2["ACTION_DUE"] = "actionDue";
13299
+ PatientInstructionStatus2["ACTION_TAKEN"] = "actionTaken";
13300
+ PatientInstructionStatus2["MISSED"] = "missed";
13301
+ PatientInstructionStatus2["CANCELLED"] = "cancelled";
13302
+ PatientInstructionStatus2["SKIPPED"] = "skipped";
13303
+ return PatientInstructionStatus2;
13304
+ })(PatientInstructionStatus || {});
13305
+ var PatientRequirementOverallStatus = /* @__PURE__ */ ((PatientRequirementOverallStatus2) => {
13306
+ PatientRequirementOverallStatus2["ACTIVE"] = "active";
13307
+ PatientRequirementOverallStatus2["ALL_INSTRUCTIONS_MET"] = "allInstructionsMet";
13308
+ PatientRequirementOverallStatus2["PARTIALLY_COMPLETED"] = "partiallyCompleted";
13309
+ PatientRequirementOverallStatus2["FAILED"] = "failed";
13310
+ PatientRequirementOverallStatus2["CANCELLED_APPOINTMENT"] = "cancelledAppointment";
13311
+ PatientRequirementOverallStatus2["SUPERSEDED_RESCHEDULE"] = "supersededReschedule";
13312
+ PatientRequirementOverallStatus2["FAILED_TO_PROCESS"] = "failedToProcess";
13313
+ return PatientRequirementOverallStatus2;
13314
+ })(PatientRequirementOverallStatus || {});
13315
+ var PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME = "patientRequirements";
13316
+
13317
+ // src/services/patient/patientRequirements.service.ts
13318
+ var PatientRequirementsService = class extends BaseService {
13319
+ constructor(db, auth, app) {
13320
+ super(db, auth, app);
13321
+ }
13322
+ getPatientRequirementsCollectionRef(patientId) {
13323
+ return (0, import_firestore41.collection)(
13324
+ this.db,
13325
+ `patients/${patientId}/${PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME}`
13326
+ );
13327
+ }
13328
+ getPatientRequirementDocRef(patientId, instanceId) {
13329
+ return (0, import_firestore41.doc)(
13330
+ this.getPatientRequirementsCollectionRef(patientId),
13331
+ instanceId
13332
+ );
13333
+ }
13334
+ /**
13335
+ * Gets a specific patient requirement instance by its ID.
13336
+ * @param patientId - The ID of the patient.
13337
+ * @param instanceId - The ID of the requirement instance.
13338
+ * @returns The patient requirement instance or null if not found.
13339
+ */
13340
+ async getPatientRequirementInstance(patientId, instanceId) {
13341
+ const docRef = this.getPatientRequirementDocRef(patientId, instanceId);
13342
+ const docSnap = await (0, import_firestore41.getDoc)(docRef);
13343
+ if (!docSnap.exists()) {
13344
+ return null;
13345
+ }
13346
+ const data = docSnap.data();
13347
+ return { id: docSnap.id, ...data };
13348
+ }
13349
+ /**
13350
+ * Retrieves patient requirement instances based on specified filters.
13351
+ * This is a flexible query method.
13352
+ *
13353
+ * @param patientId - The ID of the patient.
13354
+ * @param filters - Optional filters for appointmentId, overall statuses, instruction statuses, and due timeframes.
13355
+ * @param pageLimit - Optional limit for pagination.
13356
+ * @param lastVisible - Optional last document snapshot for pagination.
13357
+ * @returns A promise resolving to an array of matching patient requirement instances and the last document snapshot.
13358
+ */
13359
+ async getAllPatientRequirementInstances(patientId, filters, pageLimit = 20, lastVisible) {
13360
+ const collRef = this.getPatientRequirementsCollectionRef(patientId);
13361
+ let q = (0, import_firestore41.query)(collRef, (0, import_firestore41.orderBy)("createdAt", "desc"));
13362
+ const queryConstraints = [];
13363
+ if ((filters == null ? void 0 : filters.appointmentId) && filters.appointmentId !== "all") {
13364
+ queryConstraints.push(
13365
+ (0, import_firestore41.where)("appointmentId", "==", filters.appointmentId)
13366
+ );
13367
+ }
13368
+ if ((filters == null ? void 0 : filters.statuses) && filters.statuses.length > 0) {
13369
+ queryConstraints.push((0, import_firestore41.where)("overallStatus", "in", filters.statuses));
13370
+ }
13371
+ if (lastVisible) {
13372
+ queryConstraints.push((0, import_firestore41.startAfter)(lastVisible));
13373
+ }
13374
+ queryConstraints.push((0, import_firestore41.limit)(pageLimit));
13375
+ q = (0, import_firestore41.query)(collRef, ...queryConstraints);
13376
+ const snapshot = await (0, import_firestore41.getDocs)(q);
13377
+ let requirements = snapshot.docs.map((docSnap) => {
13378
+ const data = docSnap.data();
13379
+ return { id: docSnap.id, ...data };
13380
+ });
13381
+ if ((filters == null ? void 0 : filters.instructionStatuses) && filters.instructionStatuses.length > 0) {
13382
+ requirements = requirements.filter(
13383
+ (req) => req.instructions.some(
13384
+ (instr) => filters.instructionStatuses.includes(instr.status)
13385
+ )
13386
+ );
13387
+ }
13388
+ if (filters == null ? void 0 : filters.dueBefore) {
13389
+ const dueBeforeMillis = filters.dueBefore.toMillis();
13390
+ requirements = requirements.filter(
13391
+ (req) => req.instructions.some(
13392
+ (instr) => instr.dueTime.toMillis() < dueBeforeMillis
13393
+ )
13394
+ );
13395
+ }
13396
+ if (filters == null ? void 0 : filters.dueAfter) {
13397
+ const dueAfterMillis = filters.dueAfter.toMillis();
13398
+ requirements = requirements.filter(
13399
+ (req) => req.instructions.some(
13400
+ (instr) => instr.dueTime.toMillis() > dueAfterMillis
13401
+ )
13402
+ );
13403
+ }
13404
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1] || null;
13405
+ return { requirements, lastDoc: newLastVisible };
13406
+ }
13407
+ /**
13408
+ * Marks a specific instruction within a PatientRequirementInstance as ACTION_TAKEN.
13409
+ * If all instructions are actioned, updates the overallStatus of the instance.
13410
+ *
13411
+ * @param patientId - The ID of the patient.
13412
+ * @param instanceId - The ID of the PatientRequirementInstance.
13413
+ * @param instructionId - The ID of the instruction to complete.
13414
+ * @returns The updated PatientRequirementInstance.
13415
+ * @throws Error if the instance or instruction is not found, or if the instruction is not in a completable state.
13416
+ */
13417
+ async completeInstruction(patientId, instanceId, instructionId) {
13418
+ const instanceRef = this.getPatientRequirementDocRef(patientId, instanceId);
13419
+ const instanceSnap = await (0, import_firestore41.getDoc)(instanceRef);
13420
+ if (!instanceSnap.exists()) {
13421
+ throw new Error(
13422
+ `PatientRequirementInstance ${instanceId} not found for patient ${patientId}.`
13423
+ );
13424
+ }
13425
+ const instanceData = instanceSnap.data();
13426
+ const instance = { id: instanceSnap.id, ...instanceData };
13427
+ const instructionIndex = instance.instructions.findIndex(
13428
+ (instr) => instr.instructionId === instructionId
13429
+ );
13430
+ if (instructionIndex === -1) {
13431
+ throw new Error(
13432
+ `Instruction ${instructionId} not found in instance ${instanceId}.`
13433
+ );
13434
+ }
13435
+ const instructionToUpdate = instance.instructions[instructionIndex];
13436
+ if (instructionToUpdate.status !== "pendingNotification" /* PENDING_NOTIFICATION */ && instructionToUpdate.status !== "actionDue" /* ACTION_DUE */ && instructionToUpdate.status !== "missed" /* MISSED */) {
13437
+ if (instructionToUpdate.status === "actionTaken" /* ACTION_TAKEN */) {
13438
+ console.warn(
13439
+ `Instruction ${instructionId} is already marked as ACTION_TAKEN.`
13440
+ );
13441
+ return instance;
13442
+ }
13443
+ throw new Error(
13444
+ `Instruction ${instructionId} is in status ${instructionToUpdate.status} and cannot be marked as completed.`
13445
+ );
13446
+ }
13447
+ const now = import_firestore41.Timestamp.now();
13448
+ const updatedInstructions = [...instance.instructions];
13449
+ updatedInstructions[instructionIndex] = {
13450
+ ...instructionToUpdate,
13451
+ status: "actionTaken" /* ACTION_TAKEN */,
13452
+ actionTakenAt: now,
13453
+ updatedAt: now
13454
+ };
13455
+ const allActionTaken = updatedInstructions.every(
13456
+ (instr) => instr.status === "actionTaken" /* ACTION_TAKEN */
13457
+ );
13458
+ let newOverallStatus = instance.overallStatus;
13459
+ if (allActionTaken) {
13460
+ newOverallStatus = "allInstructionsMet" /* ALL_INSTRUCTIONS_MET */;
13461
+ } else if (updatedInstructions.some(
13462
+ (instr) => instr.status === "actionTaken" /* ACTION_TAKEN */
13463
+ )) {
13464
+ newOverallStatus = "partiallyCompleted" /* PARTIALLY_COMPLETED */;
13465
+ }
13466
+ const updatePayload = {
13467
+ // Using a general type for updateDoc payload
13468
+ instructions: updatedInstructions,
13469
+ updatedAt: now
13470
+ };
13471
+ if (newOverallStatus !== instance.overallStatus) {
13472
+ updatePayload.overallStatus = newOverallStatus;
13473
+ }
13474
+ await (0, import_firestore41.updateDoc)(instanceRef, updatePayload);
13475
+ return {
13476
+ ...instance,
13477
+ instructions: updatedInstructions,
13478
+ updatedAt: now,
13479
+ overallStatus: newOverallStatus
13480
+ };
13481
+ }
13482
+ // Note: As per the request, full CRUD (create, direct update of instance, delete) is not part of this light service,
13483
+ // as those will be handled by Cloud Functions reacting to appointment lifecycle events.
13484
+ };
13485
+
13486
+ // src/backoffice/services/brand.service.ts
13487
+ var import_firestore42 = require("firebase/firestore");
13488
+
12855
13489
  // src/backoffice/types/brand.types.ts
12856
13490
  var BRANDS_COLLECTION = "brands";
12857
13491
 
@@ -12861,7 +13495,7 @@ var BrandService = class extends BaseService {
12861
13495
  * Gets reference to brands collection
12862
13496
  */
12863
13497
  getBrandsRef() {
12864
- return (0, import_firestore41.collection)(this.db, BRANDS_COLLECTION);
13498
+ return (0, import_firestore42.collection)(this.db, BRANDS_COLLECTION);
12865
13499
  }
12866
13500
  /**
12867
13501
  * Creates a new brand
@@ -12874,19 +13508,19 @@ var BrandService = class extends BaseService {
12874
13508
  updatedAt: now,
12875
13509
  isActive: true
12876
13510
  };
12877
- const docRef = await (0, import_firestore41.addDoc)(this.getBrandsRef(), newBrand);
13511
+ const docRef = await (0, import_firestore42.addDoc)(this.getBrandsRef(), newBrand);
12878
13512
  return { id: docRef.id, ...newBrand };
12879
13513
  }
12880
13514
  /**
12881
13515
  * Gets all active brands
12882
13516
  */
12883
13517
  async getAll() {
12884
- const q = (0, import_firestore41.query)(this.getBrandsRef(), (0, import_firestore41.where)("isActive", "==", true));
12885
- const snapshot = await (0, import_firestore41.getDocs)(q);
13518
+ const q = (0, import_firestore42.query)(this.getBrandsRef(), (0, import_firestore42.where)("isActive", "==", true));
13519
+ const snapshot = await (0, import_firestore42.getDocs)(q);
12886
13520
  return snapshot.docs.map(
12887
- (doc32) => ({
12888
- id: doc32.id,
12889
- ...doc32.data()
13521
+ (doc33) => ({
13522
+ id: doc33.id,
13523
+ ...doc33.data()
12890
13524
  })
12891
13525
  );
12892
13526
  }
@@ -12898,8 +13532,8 @@ var BrandService = class extends BaseService {
12898
13532
  ...brand,
12899
13533
  updatedAt: /* @__PURE__ */ new Date()
12900
13534
  };
12901
- const docRef = (0, import_firestore41.doc)(this.getBrandsRef(), brandId);
12902
- await (0, import_firestore41.updateDoc)(docRef, updateData);
13535
+ const docRef = (0, import_firestore42.doc)(this.getBrandsRef(), brandId);
13536
+ await (0, import_firestore42.updateDoc)(docRef, updateData);
12903
13537
  return this.getById(brandId);
12904
13538
  }
12905
13539
  /**
@@ -12914,8 +13548,8 @@ var BrandService = class extends BaseService {
12914
13548
  * Gets a brand by ID
12915
13549
  */
12916
13550
  async getById(brandId) {
12917
- const docRef = (0, import_firestore41.doc)(this.getBrandsRef(), brandId);
12918
- const docSnap = await (0, import_firestore41.getDoc)(docRef);
13551
+ const docRef = (0, import_firestore42.doc)(this.getBrandsRef(), brandId);
13552
+ const docSnap = await (0, import_firestore42.getDoc)(docRef);
12919
13553
  if (!docSnap.exists()) return null;
12920
13554
  return {
12921
13555
  id: docSnap.id,
@@ -12925,7 +13559,7 @@ var BrandService = class extends BaseService {
12925
13559
  };
12926
13560
 
12927
13561
  // src/backoffice/services/category.service.ts
12928
- var import_firestore42 = require("firebase/firestore");
13562
+ var import_firestore43 = require("firebase/firestore");
12929
13563
 
12930
13564
  // src/backoffice/types/category.types.ts
12931
13565
  var CATEGORIES_COLLECTION = "backoffice_categories";
@@ -12936,7 +13570,7 @@ var CategoryService = class extends BaseService {
12936
13570
  * Referenca na Firestore kolekciju kategorija
12937
13571
  */
12938
13572
  get categoriesRef() {
12939
- return (0, import_firestore42.collection)(this.db, CATEGORIES_COLLECTION);
13573
+ return (0, import_firestore43.collection)(this.db, CATEGORIES_COLLECTION);
12940
13574
  }
12941
13575
  /**
12942
13576
  * Kreira novu kategoriju u sistemu
@@ -12951,7 +13585,7 @@ var CategoryService = class extends BaseService {
12951
13585
  updatedAt: now,
12952
13586
  isActive: true
12953
13587
  };
12954
- const docRef = await (0, import_firestore42.addDoc)(this.categoriesRef, newCategory);
13588
+ const docRef = await (0, import_firestore43.addDoc)(this.categoriesRef, newCategory);
12955
13589
  return { id: docRef.id, ...newCategory };
12956
13590
  }
12957
13591
  /**
@@ -12959,12 +13593,12 @@ var CategoryService = class extends BaseService {
12959
13593
  * @returns Lista aktivnih kategorija
12960
13594
  */
12961
13595
  async getAll() {
12962
- const q = (0, import_firestore42.query)(this.categoriesRef, (0, import_firestore42.where)("isActive", "==", true));
12963
- const snapshot = await (0, import_firestore42.getDocs)(q);
13596
+ const q = (0, import_firestore43.query)(this.categoriesRef, (0, import_firestore43.where)("isActive", "==", true));
13597
+ const snapshot = await (0, import_firestore43.getDocs)(q);
12964
13598
  return snapshot.docs.map(
12965
- (doc32) => ({
12966
- id: doc32.id,
12967
- ...doc32.data()
13599
+ (doc33) => ({
13600
+ id: doc33.id,
13601
+ ...doc33.data()
12968
13602
  })
12969
13603
  );
12970
13604
  }
@@ -12974,16 +13608,16 @@ var CategoryService = class extends BaseService {
12974
13608
  * @returns Lista kategorija koje pripadaju traženoj familiji
12975
13609
  */
12976
13610
  async getAllByFamily(family) {
12977
- const q = (0, import_firestore42.query)(
13611
+ const q = (0, import_firestore43.query)(
12978
13612
  this.categoriesRef,
12979
- (0, import_firestore42.where)("family", "==", family),
12980
- (0, import_firestore42.where)("isActive", "==", true)
13613
+ (0, import_firestore43.where)("family", "==", family),
13614
+ (0, import_firestore43.where)("isActive", "==", true)
12981
13615
  );
12982
- const snapshot = await (0, import_firestore42.getDocs)(q);
13616
+ const snapshot = await (0, import_firestore43.getDocs)(q);
12983
13617
  return snapshot.docs.map(
12984
- (doc32) => ({
12985
- id: doc32.id,
12986
- ...doc32.data()
13618
+ (doc33) => ({
13619
+ id: doc33.id,
13620
+ ...doc33.data()
12987
13621
  })
12988
13622
  );
12989
13623
  }
@@ -12998,8 +13632,8 @@ var CategoryService = class extends BaseService {
12998
13632
  ...category,
12999
13633
  updatedAt: /* @__PURE__ */ new Date()
13000
13634
  };
13001
- const docRef = (0, import_firestore42.doc)(this.categoriesRef, id);
13002
- await (0, import_firestore42.updateDoc)(docRef, updateData);
13635
+ const docRef = (0, import_firestore43.doc)(this.categoriesRef, id);
13636
+ await (0, import_firestore43.updateDoc)(docRef, updateData);
13003
13637
  return this.getById(id);
13004
13638
  }
13005
13639
  /**
@@ -13015,8 +13649,8 @@ var CategoryService = class extends BaseService {
13015
13649
  * @returns Kategorija ili null ako ne postoji
13016
13650
  */
13017
13651
  async getById(id) {
13018
- const docRef = (0, import_firestore42.doc)(this.categoriesRef, id);
13019
- const docSnap = await (0, import_firestore42.getDoc)(docRef);
13652
+ const docRef = (0, import_firestore43.doc)(this.categoriesRef, id);
13653
+ const docSnap = await (0, import_firestore43.getDoc)(docRef);
13020
13654
  if (!docSnap.exists()) return null;
13021
13655
  return {
13022
13656
  id: docSnap.id,
@@ -13026,7 +13660,7 @@ var CategoryService = class extends BaseService {
13026
13660
  };
13027
13661
 
13028
13662
  // src/backoffice/services/subcategory.service.ts
13029
- var import_firestore43 = require("firebase/firestore");
13663
+ var import_firestore44 = require("firebase/firestore");
13030
13664
 
13031
13665
  // src/backoffice/types/subcategory.types.ts
13032
13666
  var SUBCATEGORIES_COLLECTION = "subcategories";
@@ -13038,7 +13672,7 @@ var SubcategoryService = class extends BaseService {
13038
13672
  * @param categoryId - ID roditeljske kategorije
13039
13673
  */
13040
13674
  getSubcategoriesRef(categoryId) {
13041
- return (0, import_firestore43.collection)(
13675
+ return (0, import_firestore44.collection)(
13042
13676
  this.db,
13043
13677
  CATEGORIES_COLLECTION,
13044
13678
  categoryId,
@@ -13060,7 +13694,7 @@ var SubcategoryService = class extends BaseService {
13060
13694
  updatedAt: now,
13061
13695
  isActive: true
13062
13696
  };
13063
- const docRef = await (0, import_firestore43.addDoc)(
13697
+ const docRef = await (0, import_firestore44.addDoc)(
13064
13698
  this.getSubcategoriesRef(categoryId),
13065
13699
  newSubcategory
13066
13700
  );
@@ -13072,15 +13706,15 @@ var SubcategoryService = class extends BaseService {
13072
13706
  * @returns Lista aktivnih podkategorija
13073
13707
  */
13074
13708
  async getAllByCategoryId(categoryId) {
13075
- const q = (0, import_firestore43.query)(
13709
+ const q = (0, import_firestore44.query)(
13076
13710
  this.getSubcategoriesRef(categoryId),
13077
- (0, import_firestore43.where)("isActive", "==", true)
13711
+ (0, import_firestore44.where)("isActive", "==", true)
13078
13712
  );
13079
- const snapshot = await (0, import_firestore43.getDocs)(q);
13713
+ const snapshot = await (0, import_firestore44.getDocs)(q);
13080
13714
  return snapshot.docs.map(
13081
- (doc32) => ({
13082
- id: doc32.id,
13083
- ...doc32.data()
13715
+ (doc33) => ({
13716
+ id: doc33.id,
13717
+ ...doc33.data()
13084
13718
  })
13085
13719
  );
13086
13720
  }
@@ -13096,8 +13730,8 @@ var SubcategoryService = class extends BaseService {
13096
13730
  ...subcategory,
13097
13731
  updatedAt: /* @__PURE__ */ new Date()
13098
13732
  };
13099
- const docRef = (0, import_firestore43.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13100
- await (0, import_firestore43.updateDoc)(docRef, updateData);
13733
+ const docRef = (0, import_firestore44.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13734
+ await (0, import_firestore44.updateDoc)(docRef, updateData);
13101
13735
  return this.getById(categoryId, subcategoryId);
13102
13736
  }
13103
13737
  /**
@@ -13115,8 +13749,8 @@ var SubcategoryService = class extends BaseService {
13115
13749
  * @returns Podkategorija ili null ako ne postoji
13116
13750
  */
13117
13751
  async getById(categoryId, subcategoryId) {
13118
- const docRef = (0, import_firestore43.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13119
- const docSnap = await (0, import_firestore43.getDoc)(docRef);
13752
+ const docRef = (0, import_firestore44.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13753
+ const docSnap = await (0, import_firestore44.getDoc)(docRef);
13120
13754
  if (!docSnap.exists()) return null;
13121
13755
  return {
13122
13756
  id: docSnap.id,
@@ -13126,7 +13760,7 @@ var SubcategoryService = class extends BaseService {
13126
13760
  };
13127
13761
 
13128
13762
  // src/backoffice/services/technology.service.ts
13129
- var import_firestore44 = require("firebase/firestore");
13763
+ var import_firestore45 = require("firebase/firestore");
13130
13764
  var DEFAULT_CERTIFICATION_REQUIREMENT = {
13131
13765
  minimumLevel: "aesthetician" /* AESTHETICIAN */,
13132
13766
  requiredSpecialties: []
@@ -13136,7 +13770,7 @@ var TechnologyService = class extends BaseService {
13136
13770
  * Vraća referencu na Firestore kolekciju tehnologija
13137
13771
  */
13138
13772
  getTechnologiesRef() {
13139
- return (0, import_firestore44.collection)(this.db, TECHNOLOGIES_COLLECTION);
13773
+ return (0, import_firestore45.collection)(this.db, TECHNOLOGIES_COLLECTION);
13140
13774
  }
13141
13775
  /**
13142
13776
  * Kreira novu tehnologiju
@@ -13159,7 +13793,7 @@ var TechnologyService = class extends BaseService {
13159
13793
  benefits: technology.benefits || [],
13160
13794
  certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT
13161
13795
  };
13162
- const docRef = await (0, import_firestore44.addDoc)(this.getTechnologiesRef(), newTechnology);
13796
+ const docRef = await (0, import_firestore45.addDoc)(this.getTechnologiesRef(), newTechnology);
13163
13797
  return { id: docRef.id, ...newTechnology };
13164
13798
  }
13165
13799
  /**
@@ -13167,12 +13801,12 @@ var TechnologyService = class extends BaseService {
13167
13801
  * @returns Lista aktivnih tehnologija
13168
13802
  */
13169
13803
  async getAll() {
13170
- const q = (0, import_firestore44.query)(this.getTechnologiesRef(), (0, import_firestore44.where)("isActive", "==", true));
13171
- const snapshot = await (0, import_firestore44.getDocs)(q);
13804
+ const q = (0, import_firestore45.query)(this.getTechnologiesRef(), (0, import_firestore45.where)("isActive", "==", true));
13805
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13172
13806
  return snapshot.docs.map(
13173
- (doc32) => ({
13174
- id: doc32.id,
13175
- ...doc32.data()
13807
+ (doc33) => ({
13808
+ id: doc33.id,
13809
+ ...doc33.data()
13176
13810
  })
13177
13811
  );
13178
13812
  }
@@ -13182,16 +13816,16 @@ var TechnologyService = class extends BaseService {
13182
13816
  * @returns Lista aktivnih tehnologija
13183
13817
  */
13184
13818
  async getAllByFamily(family) {
13185
- const q = (0, import_firestore44.query)(
13819
+ const q = (0, import_firestore45.query)(
13186
13820
  this.getTechnologiesRef(),
13187
- (0, import_firestore44.where)("isActive", "==", true),
13188
- (0, import_firestore44.where)("family", "==", family)
13821
+ (0, import_firestore45.where)("isActive", "==", true),
13822
+ (0, import_firestore45.where)("family", "==", family)
13189
13823
  );
13190
- const snapshot = await (0, import_firestore44.getDocs)(q);
13824
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13191
13825
  return snapshot.docs.map(
13192
- (doc32) => ({
13193
- id: doc32.id,
13194
- ...doc32.data()
13826
+ (doc33) => ({
13827
+ id: doc33.id,
13828
+ ...doc33.data()
13195
13829
  })
13196
13830
  );
13197
13831
  }
@@ -13201,16 +13835,16 @@ var TechnologyService = class extends BaseService {
13201
13835
  * @returns Lista aktivnih tehnologija
13202
13836
  */
13203
13837
  async getAllByCategoryId(categoryId) {
13204
- const q = (0, import_firestore44.query)(
13838
+ const q = (0, import_firestore45.query)(
13205
13839
  this.getTechnologiesRef(),
13206
- (0, import_firestore44.where)("isActive", "==", true),
13207
- (0, import_firestore44.where)("categoryId", "==", categoryId)
13840
+ (0, import_firestore45.where)("isActive", "==", true),
13841
+ (0, import_firestore45.where)("categoryId", "==", categoryId)
13208
13842
  );
13209
- const snapshot = await (0, import_firestore44.getDocs)(q);
13843
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13210
13844
  return snapshot.docs.map(
13211
- (doc32) => ({
13212
- id: doc32.id,
13213
- ...doc32.data()
13845
+ (doc33) => ({
13846
+ id: doc33.id,
13847
+ ...doc33.data()
13214
13848
  })
13215
13849
  );
13216
13850
  }
@@ -13220,16 +13854,16 @@ var TechnologyService = class extends BaseService {
13220
13854
  * @returns Lista aktivnih tehnologija
13221
13855
  */
13222
13856
  async getAllBySubcategoryId(subcategoryId) {
13223
- const q = (0, import_firestore44.query)(
13857
+ const q = (0, import_firestore45.query)(
13224
13858
  this.getTechnologiesRef(),
13225
- (0, import_firestore44.where)("isActive", "==", true),
13226
- (0, import_firestore44.where)("subcategoryId", "==", subcategoryId)
13859
+ (0, import_firestore45.where)("isActive", "==", true),
13860
+ (0, import_firestore45.where)("subcategoryId", "==", subcategoryId)
13227
13861
  );
13228
- const snapshot = await (0, import_firestore44.getDocs)(q);
13862
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13229
13863
  return snapshot.docs.map(
13230
- (doc32) => ({
13231
- id: doc32.id,
13232
- ...doc32.data()
13864
+ (doc33) => ({
13865
+ id: doc33.id,
13866
+ ...doc33.data()
13233
13867
  })
13234
13868
  );
13235
13869
  }
@@ -13244,8 +13878,8 @@ var TechnologyService = class extends BaseService {
13244
13878
  ...technology,
13245
13879
  updatedAt: /* @__PURE__ */ new Date()
13246
13880
  };
13247
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13248
- await (0, import_firestore44.updateDoc)(docRef, updateData);
13881
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13882
+ await (0, import_firestore45.updateDoc)(docRef, updateData);
13249
13883
  return this.getById(technologyId);
13250
13884
  }
13251
13885
  /**
@@ -13263,8 +13897,8 @@ var TechnologyService = class extends BaseService {
13263
13897
  * @returns Tehnologija ili null ako ne postoji
13264
13898
  */
13265
13899
  async getById(technologyId) {
13266
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13267
- const docSnap = await (0, import_firestore44.getDoc)(docRef);
13900
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13901
+ const docSnap = await (0, import_firestore45.getDoc)(docRef);
13268
13902
  if (!docSnap.exists()) return null;
13269
13903
  return {
13270
13904
  id: docSnap.id,
@@ -13278,10 +13912,10 @@ var TechnologyService = class extends BaseService {
13278
13912
  * @returns Ažurirana tehnologija sa novim zahtevom
13279
13913
  */
13280
13914
  async addRequirement(technologyId, requirement) {
13281
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13915
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13282
13916
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
13283
- await (0, import_firestore44.updateDoc)(docRef, {
13284
- [requirementType]: (0, import_firestore44.arrayUnion)(requirement),
13917
+ await (0, import_firestore45.updateDoc)(docRef, {
13918
+ [requirementType]: (0, import_firestore45.arrayUnion)(requirement),
13285
13919
  updatedAt: /* @__PURE__ */ new Date()
13286
13920
  });
13287
13921
  return this.getById(technologyId);
@@ -13293,10 +13927,10 @@ var TechnologyService = class extends BaseService {
13293
13927
  * @returns Ažurirana tehnologija bez uklonjenog zahteva
13294
13928
  */
13295
13929
  async removeRequirement(technologyId, requirement) {
13296
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13930
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13297
13931
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
13298
- await (0, import_firestore44.updateDoc)(docRef, {
13299
- [requirementType]: (0, import_firestore44.arrayRemove)(requirement),
13932
+ await (0, import_firestore45.updateDoc)(docRef, {
13933
+ [requirementType]: (0, import_firestore45.arrayRemove)(requirement),
13300
13934
  updatedAt: /* @__PURE__ */ new Date()
13301
13935
  });
13302
13936
  return this.getById(technologyId);
@@ -13333,9 +13967,9 @@ var TechnologyService = class extends BaseService {
13333
13967
  * @returns Ažurirana tehnologija
13334
13968
  */
13335
13969
  async addBlockingCondition(technologyId, condition) {
13336
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13337
- await (0, import_firestore44.updateDoc)(docRef, {
13338
- blockingConditions: (0, import_firestore44.arrayUnion)(condition),
13970
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13971
+ await (0, import_firestore45.updateDoc)(docRef, {
13972
+ blockingConditions: (0, import_firestore45.arrayUnion)(condition),
13339
13973
  updatedAt: /* @__PURE__ */ new Date()
13340
13974
  });
13341
13975
  return this.getById(technologyId);
@@ -13347,9 +13981,9 @@ var TechnologyService = class extends BaseService {
13347
13981
  * @returns Ažurirana tehnologija
13348
13982
  */
13349
13983
  async removeBlockingCondition(technologyId, condition) {
13350
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13351
- await (0, import_firestore44.updateDoc)(docRef, {
13352
- blockingConditions: (0, import_firestore44.arrayRemove)(condition),
13984
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13985
+ await (0, import_firestore45.updateDoc)(docRef, {
13986
+ blockingConditions: (0, import_firestore45.arrayRemove)(condition),
13353
13987
  updatedAt: /* @__PURE__ */ new Date()
13354
13988
  });
13355
13989
  return this.getById(technologyId);
@@ -13361,9 +13995,9 @@ var TechnologyService = class extends BaseService {
13361
13995
  * @returns Ažurirana tehnologija
13362
13996
  */
13363
13997
  async addContraindication(technologyId, contraindication) {
13364
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13365
- await (0, import_firestore44.updateDoc)(docRef, {
13366
- contraindications: (0, import_firestore44.arrayUnion)(contraindication),
13998
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13999
+ await (0, import_firestore45.updateDoc)(docRef, {
14000
+ contraindications: (0, import_firestore45.arrayUnion)(contraindication),
13367
14001
  updatedAt: /* @__PURE__ */ new Date()
13368
14002
  });
13369
14003
  return this.getById(technologyId);
@@ -13375,9 +14009,9 @@ var TechnologyService = class extends BaseService {
13375
14009
  * @returns Ažurirana tehnologija
13376
14010
  */
13377
14011
  async removeContraindication(technologyId, contraindication) {
13378
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13379
- await (0, import_firestore44.updateDoc)(docRef, {
13380
- contraindications: (0, import_firestore44.arrayRemove)(contraindication),
14012
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
14013
+ await (0, import_firestore45.updateDoc)(docRef, {
14014
+ contraindications: (0, import_firestore45.arrayRemove)(contraindication),
13381
14015
  updatedAt: /* @__PURE__ */ new Date()
13382
14016
  });
13383
14017
  return this.getById(technologyId);
@@ -13389,9 +14023,9 @@ var TechnologyService = class extends BaseService {
13389
14023
  * @returns Ažurirana tehnologija
13390
14024
  */
13391
14025
  async addBenefit(technologyId, benefit) {
13392
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13393
- await (0, import_firestore44.updateDoc)(docRef, {
13394
- benefits: (0, import_firestore44.arrayUnion)(benefit),
14026
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
14027
+ await (0, import_firestore45.updateDoc)(docRef, {
14028
+ benefits: (0, import_firestore45.arrayUnion)(benefit),
13395
14029
  updatedAt: /* @__PURE__ */ new Date()
13396
14030
  });
13397
14031
  return this.getById(technologyId);
@@ -13403,9 +14037,9 @@ var TechnologyService = class extends BaseService {
13403
14037
  * @returns Ažurirana tehnologija
13404
14038
  */
13405
14039
  async removeBenefit(technologyId, benefit) {
13406
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13407
- await (0, import_firestore44.updateDoc)(docRef, {
13408
- benefits: (0, import_firestore44.arrayRemove)(benefit),
14040
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
14041
+ await (0, import_firestore45.updateDoc)(docRef, {
14042
+ benefits: (0, import_firestore45.arrayRemove)(benefit),
13409
14043
  updatedAt: /* @__PURE__ */ new Date()
13410
14044
  });
13411
14045
  return this.getById(technologyId);
@@ -13444,8 +14078,8 @@ var TechnologyService = class extends BaseService {
13444
14078
  * @returns Ažurirana tehnologija
13445
14079
  */
13446
14080
  async updateCertificationRequirement(technologyId, certificationRequirement) {
13447
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13448
- await (0, import_firestore44.updateDoc)(docRef, {
14081
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
14082
+ await (0, import_firestore45.updateDoc)(docRef, {
13449
14083
  certificationRequirement,
13450
14084
  updatedAt: /* @__PURE__ */ new Date()
13451
14085
  });
@@ -13545,7 +14179,7 @@ var TechnologyService = class extends BaseService {
13545
14179
  };
13546
14180
 
13547
14181
  // src/backoffice/services/product.service.ts
13548
- var import_firestore45 = require("firebase/firestore");
14182
+ var import_firestore46 = require("firebase/firestore");
13549
14183
 
13550
14184
  // src/backoffice/types/product.types.ts
13551
14185
  var PRODUCTS_COLLECTION = "products";
@@ -13558,7 +14192,7 @@ var ProductService = class extends BaseService {
13558
14192
  * @returns Firestore collection reference
13559
14193
  */
13560
14194
  getProductsRef(technologyId) {
13561
- return (0, import_firestore45.collection)(
14195
+ return (0, import_firestore46.collection)(
13562
14196
  this.db,
13563
14197
  TECHNOLOGIES_COLLECTION,
13564
14198
  technologyId,
@@ -13578,7 +14212,7 @@ var ProductService = class extends BaseService {
13578
14212
  updatedAt: now,
13579
14213
  isActive: true
13580
14214
  };
13581
- const productRef = await (0, import_firestore45.addDoc)(
14215
+ const productRef = await (0, import_firestore46.addDoc)(
13582
14216
  this.getProductsRef(technologyId),
13583
14217
  newProduct
13584
14218
  );
@@ -13588,15 +14222,15 @@ var ProductService = class extends BaseService {
13588
14222
  * Gets all products for a technology
13589
14223
  */
13590
14224
  async getAllByTechnology(technologyId) {
13591
- const q = (0, import_firestore45.query)(
14225
+ const q = (0, import_firestore46.query)(
13592
14226
  this.getProductsRef(technologyId),
13593
- (0, import_firestore45.where)("isActive", "==", true)
14227
+ (0, import_firestore46.where)("isActive", "==", true)
13594
14228
  );
13595
- const snapshot = await (0, import_firestore45.getDocs)(q);
14229
+ const snapshot = await (0, import_firestore46.getDocs)(q);
13596
14230
  return snapshot.docs.map(
13597
- (doc32) => ({
13598
- id: doc32.id,
13599
- ...doc32.data()
14231
+ (doc33) => ({
14232
+ id: doc33.id,
14233
+ ...doc33.data()
13600
14234
  })
13601
14235
  );
13602
14236
  }
@@ -13604,21 +14238,21 @@ var ProductService = class extends BaseService {
13604
14238
  * Gets all products for a brand by filtering through all technologies
13605
14239
  */
13606
14240
  async getAllByBrand(brandId) {
13607
- const allTechnologiesRef = (0, import_firestore45.collection)(this.db, TECHNOLOGIES_COLLECTION);
13608
- const technologiesSnapshot = await (0, import_firestore45.getDocs)(allTechnologiesRef);
14241
+ const allTechnologiesRef = (0, import_firestore46.collection)(this.db, TECHNOLOGIES_COLLECTION);
14242
+ const technologiesSnapshot = await (0, import_firestore46.getDocs)(allTechnologiesRef);
13609
14243
  const products = [];
13610
14244
  for (const techDoc of technologiesSnapshot.docs) {
13611
- const q = (0, import_firestore45.query)(
14245
+ const q = (0, import_firestore46.query)(
13612
14246
  this.getProductsRef(techDoc.id),
13613
- (0, import_firestore45.where)("brandId", "==", brandId),
13614
- (0, import_firestore45.where)("isActive", "==", true)
14247
+ (0, import_firestore46.where)("brandId", "==", brandId),
14248
+ (0, import_firestore46.where)("isActive", "==", true)
13615
14249
  );
13616
- const snapshot = await (0, import_firestore45.getDocs)(q);
14250
+ const snapshot = await (0, import_firestore46.getDocs)(q);
13617
14251
  products.push(
13618
14252
  ...snapshot.docs.map(
13619
- (doc32) => ({
13620
- id: doc32.id,
13621
- ...doc32.data()
14253
+ (doc33) => ({
14254
+ id: doc33.id,
14255
+ ...doc33.data()
13622
14256
  })
13623
14257
  )
13624
14258
  );
@@ -13633,8 +14267,8 @@ var ProductService = class extends BaseService {
13633
14267
  ...product,
13634
14268
  updatedAt: /* @__PURE__ */ new Date()
13635
14269
  };
13636
- const docRef = (0, import_firestore45.doc)(this.getProductsRef(technologyId), productId);
13637
- await (0, import_firestore45.updateDoc)(docRef, updateData);
14270
+ const docRef = (0, import_firestore46.doc)(this.getProductsRef(technologyId), productId);
14271
+ await (0, import_firestore46.updateDoc)(docRef, updateData);
13638
14272
  return this.getById(technologyId, productId);
13639
14273
  }
13640
14274
  /**
@@ -13649,8 +14283,8 @@ var ProductService = class extends BaseService {
13649
14283
  * Gets a product by ID
13650
14284
  */
13651
14285
  async getById(technologyId, productId) {
13652
- const docRef = (0, import_firestore45.doc)(this.getProductsRef(technologyId), productId);
13653
- const docSnap = await (0, import_firestore45.getDoc)(docRef);
14286
+ const docRef = (0, import_firestore46.doc)(this.getProductsRef(technologyId), productId);
14287
+ const docSnap = await (0, import_firestore46.getDoc)(docRef);
13654
14288
  if (!docSnap.exists()) return null;
13655
14289
  return {
13656
14290
  id: docSnap.id,
@@ -13679,14 +14313,14 @@ var baseNotificationSchema = import_zod24.z.object({
13679
14313
  userRole: import_zod24.z.nativeEnum(UserRole)
13680
14314
  });
13681
14315
  var preRequirementNotificationSchema = baseNotificationSchema.extend({
13682
- notificationType: import_zod24.z.literal("preRequirement" /* PRE_REQUIREMENT */),
14316
+ notificationType: import_zod24.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
13683
14317
  treatmentId: import_zod24.z.string(),
13684
14318
  requirements: import_zod24.z.array(import_zod24.z.string()),
13685
14319
  deadline: import_zod24.z.any()
13686
14320
  // Timestamp
13687
14321
  });
13688
14322
  var postRequirementNotificationSchema = baseNotificationSchema.extend({
13689
- notificationType: import_zod24.z.literal("postRequirement" /* POST_REQUIREMENT */),
14323
+ notificationType: import_zod24.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
13690
14324
  treatmentId: import_zod24.z.string(),
13691
14325
  requirements: import_zod24.z.array(import_zod24.z.string()),
13692
14326
  deadline: import_zod24.z.any()
@@ -13701,7 +14335,7 @@ var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
13701
14335
  doctorName: import_zod24.z.string()
13702
14336
  });
13703
14337
  var appointmentNotificationSchema = baseNotificationSchema.extend({
13704
- notificationType: import_zod24.z.literal("appointmentNotification" /* APPOINTMENT_NOTIFICATION */),
14338
+ notificationType: import_zod24.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
13705
14339
  appointmentId: import_zod24.z.string(),
13706
14340
  appointmentStatus: import_zod24.z.string(),
13707
14341
  previousStatus: import_zod24.z.string(),
@@ -13798,9 +14432,13 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13798
14432
  PATIENT_LOCATION_INFO_COLLECTION,
13799
14433
  PATIENT_MEDICAL_HISTORY_COLLECTION,
13800
14434
  PATIENT_MEDICAL_INFO_COLLECTION,
14435
+ PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME,
13801
14436
  PATIENT_SENSITIVE_INFO_COLLECTION,
13802
14437
  PRACTITIONERS_COLLECTION,
13803
14438
  PROCEDURES_COLLECTION,
14439
+ PatientInstructionStatus,
14440
+ PatientRequirementOverallStatus,
14441
+ PatientRequirementsService,
13804
14442
  PatientService,
13805
14443
  PaymentStatus,
13806
14444
  PracticeType,
@@ -13865,6 +14503,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13865
14503
  createDefaultClinicGroupSchema,
13866
14504
  createDocumentTemplateSchema,
13867
14505
  createDraftPractitionerSchema,
14506
+ createFilledDocumentDataSchema,
13868
14507
  createPatientLocationInfoSchema,
13869
14508
  createPatientMedicalInfoSchema,
13870
14509
  createPatientProfileSchema,
@@ -13880,6 +14519,8 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13880
14519
  documentTemplateSchema,
13881
14520
  emailSchema,
13882
14521
  emergencyContactSchema,
14522
+ filledDocumentSchema,
14523
+ filledDocumentStatusSchema,
13883
14524
  gamificationSchema,
13884
14525
  getFirebaseApp,
13885
14526
  getFirebaseAuth,
@@ -13929,6 +14570,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13929
14570
  updateClinicSchema,
13930
14571
  updateContraindicationSchema,
13931
14572
  updateDocumentTemplateSchema,
14573
+ updateFilledDocumentDataSchema,
13932
14574
  updateMedicationSchema,
13933
14575
  updatePatientMedicalInfoSchema,
13934
14576
  updateVitalStatsSchema,