@blackcode_sa/metaestetics-api 1.7.37 → 1.7.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +48 -1
- package/dist/admin/index.d.ts +48 -1
- package/dist/index.d.mts +234 -1
- package/dist/index.d.ts +234 -1
- package/dist/index.js +170 -149
- package/dist/index.mjs +167 -146
- package/package.json +1 -1
- package/src/index.ts +3 -0
- package/src/types/appointment/index.ts +57 -1
- package/src/validations/appointment.schema.ts +38 -0
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/validations/appointment.schema.ts
|
|
2
|
-
import { z as
|
|
2
|
+
import { z as z3 } from "zod";
|
|
3
3
|
|
|
4
4
|
// src/types/appointment/index.ts
|
|
5
5
|
var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
|
|
@@ -267,139 +267,187 @@ var updateFilledDocumentDataSchema = z.object({
|
|
|
267
267
|
status: filledDocumentStatusSchema.optional()
|
|
268
268
|
});
|
|
269
269
|
|
|
270
|
+
// src/backoffice/types/static/pricing.types.ts
|
|
271
|
+
var PricingMeasure = /* @__PURE__ */ ((PricingMeasure3) => {
|
|
272
|
+
PricingMeasure3["PER_ML"] = "per_ml";
|
|
273
|
+
PricingMeasure3["PER_ZONE"] = "per_zone";
|
|
274
|
+
PricingMeasure3["PER_AREA"] = "per_area";
|
|
275
|
+
PricingMeasure3["PER_SESSION"] = "per_session";
|
|
276
|
+
PricingMeasure3["PER_TREATMENT"] = "per_treatment";
|
|
277
|
+
PricingMeasure3["PER_PACKAGE"] = "per_package";
|
|
278
|
+
return PricingMeasure3;
|
|
279
|
+
})(PricingMeasure || {});
|
|
280
|
+
var Currency = /* @__PURE__ */ ((Currency2) => {
|
|
281
|
+
Currency2["EUR"] = "EUR";
|
|
282
|
+
Currency2["USD"] = "USD";
|
|
283
|
+
Currency2["GBP"] = "GBP";
|
|
284
|
+
Currency2["CHF"] = "CHF";
|
|
285
|
+
Currency2["AUD"] = "AUD";
|
|
286
|
+
return Currency2;
|
|
287
|
+
})(Currency || {});
|
|
288
|
+
|
|
289
|
+
// src/validations/media.schema.ts
|
|
290
|
+
import { z as z2 } from "zod";
|
|
291
|
+
var mediaResourceSchema = z2.union([
|
|
292
|
+
z2.string().url(),
|
|
293
|
+
z2.instanceof(File),
|
|
294
|
+
z2.instanceof(Blob)
|
|
295
|
+
]);
|
|
296
|
+
|
|
270
297
|
// src/validations/appointment.schema.ts
|
|
271
298
|
var MIN_STRING_LENGTH = 1;
|
|
272
299
|
var MAX_STRING_LENGTH = 1024;
|
|
273
300
|
var MAX_STRING_LENGTH_LONG = 4096;
|
|
274
301
|
var MAX_ARRAY_LENGTH = 100;
|
|
275
|
-
var appointmentStatusSchema =
|
|
276
|
-
var paymentStatusSchema =
|
|
277
|
-
var mediaTypeSchema =
|
|
278
|
-
var appointmentMediaItemSchema =
|
|
279
|
-
id:
|
|
302
|
+
var appointmentStatusSchema = z3.nativeEnum(AppointmentStatus);
|
|
303
|
+
var paymentStatusSchema = z3.nativeEnum(PaymentStatus);
|
|
304
|
+
var mediaTypeSchema = z3.nativeEnum(MediaType);
|
|
305
|
+
var appointmentMediaItemSchema = z3.object({
|
|
306
|
+
id: z3.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
|
|
280
307
|
type: mediaTypeSchema,
|
|
281
|
-
url:
|
|
282
|
-
fileName:
|
|
283
|
-
uploadedAt:
|
|
308
|
+
url: z3.string().url("Media URL must be a valid URL"),
|
|
309
|
+
fileName: z3.string().optional(),
|
|
310
|
+
uploadedAt: z3.any().refine(
|
|
284
311
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
285
312
|
"uploadedAt must be a valid timestamp or Date object"
|
|
286
313
|
),
|
|
287
|
-
uploadedBy:
|
|
288
|
-
description:
|
|
314
|
+
uploadedBy: z3.string().min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
|
|
315
|
+
description: z3.string().max(MAX_STRING_LENGTH, "Description too long").optional()
|
|
289
316
|
});
|
|
290
|
-
var procedureExtendedInfoSchema =
|
|
291
|
-
id:
|
|
292
|
-
name:
|
|
293
|
-
description:
|
|
294
|
-
cost:
|
|
295
|
-
duration:
|
|
296
|
-
procedureFamily:
|
|
297
|
-
procedureCategoryId:
|
|
298
|
-
procedureCategoryName:
|
|
299
|
-
procedureSubCategoryId:
|
|
300
|
-
procedureSubCategoryName:
|
|
301
|
-
procedureTechnologyId:
|
|
302
|
-
procedureTechnologyName:
|
|
303
|
-
procedureProductBrandId:
|
|
304
|
-
procedureProductBrandName:
|
|
305
|
-
procedureProductId:
|
|
306
|
-
procedureProductName:
|
|
317
|
+
var procedureExtendedInfoSchema = z3.object({
|
|
318
|
+
id: z3.string().min(MIN_STRING_LENGTH),
|
|
319
|
+
name: z3.string().min(MIN_STRING_LENGTH),
|
|
320
|
+
description: z3.string(),
|
|
321
|
+
cost: z3.number().min(0),
|
|
322
|
+
duration: z3.number().min(0),
|
|
323
|
+
procedureFamily: z3.any(),
|
|
324
|
+
procedureCategoryId: z3.string(),
|
|
325
|
+
procedureCategoryName: z3.string(),
|
|
326
|
+
procedureSubCategoryId: z3.string(),
|
|
327
|
+
procedureSubCategoryName: z3.string(),
|
|
328
|
+
procedureTechnologyId: z3.string(),
|
|
329
|
+
procedureTechnologyName: z3.string(),
|
|
330
|
+
procedureProductBrandId: z3.string(),
|
|
331
|
+
procedureProductBrandName: z3.string(),
|
|
332
|
+
procedureProductId: z3.string(),
|
|
333
|
+
procedureProductName: z3.string()
|
|
307
334
|
});
|
|
308
|
-
var linkedFormInfoSchema =
|
|
309
|
-
formId:
|
|
310
|
-
templateId:
|
|
311
|
-
templateVersion:
|
|
312
|
-
title:
|
|
313
|
-
isUserForm:
|
|
314
|
-
isRequired:
|
|
335
|
+
var linkedFormInfoSchema = z3.object({
|
|
336
|
+
formId: z3.string().min(MIN_STRING_LENGTH, "Form ID is required"),
|
|
337
|
+
templateId: z3.string().min(MIN_STRING_LENGTH, "Template ID is required"),
|
|
338
|
+
templateVersion: z3.number().int().positive("Template version must be a positive integer"),
|
|
339
|
+
title: z3.string().min(MIN_STRING_LENGTH, "Form title is required"),
|
|
340
|
+
isUserForm: z3.boolean(),
|
|
341
|
+
isRequired: z3.boolean().optional(),
|
|
315
342
|
status: filledDocumentStatusSchema,
|
|
316
|
-
path:
|
|
317
|
-
submittedAt:
|
|
343
|
+
path: z3.string().min(MIN_STRING_LENGTH, "Form path is required"),
|
|
344
|
+
submittedAt: z3.any().refine(
|
|
318
345
|
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
319
346
|
"submittedAt must be a valid timestamp or Date object"
|
|
320
347
|
).optional(),
|
|
321
|
-
completedAt:
|
|
348
|
+
completedAt: z3.any().refine(
|
|
322
349
|
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
323
350
|
"completedAt must be a valid timestamp or Date object"
|
|
324
351
|
).optional()
|
|
325
352
|
});
|
|
326
|
-
var patientReviewInfoSchema =
|
|
327
|
-
reviewId:
|
|
328
|
-
rating:
|
|
329
|
-
comment:
|
|
330
|
-
reviewedAt:
|
|
353
|
+
var patientReviewInfoSchema = z3.object({
|
|
354
|
+
reviewId: z3.string().min(MIN_STRING_LENGTH, "Review ID is required"),
|
|
355
|
+
rating: z3.number().min(1).max(5, "Rating must be between 1 and 5"),
|
|
356
|
+
comment: z3.string().max(MAX_STRING_LENGTH_LONG, "Comment too long").optional(),
|
|
357
|
+
reviewedAt: z3.any().refine(
|
|
331
358
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
332
359
|
"reviewedAt must be a valid timestamp or Date object"
|
|
333
360
|
)
|
|
334
361
|
});
|
|
335
|
-
var finalizedDetailsSchema =
|
|
336
|
-
by:
|
|
337
|
-
at:
|
|
362
|
+
var finalizedDetailsSchema = z3.object({
|
|
363
|
+
by: z3.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
|
|
364
|
+
at: z3.any().refine(
|
|
338
365
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
339
366
|
"Finalized at must be a valid timestamp or Date object"
|
|
340
367
|
),
|
|
341
|
-
notes:
|
|
368
|
+
notes: z3.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
|
|
369
|
+
});
|
|
370
|
+
var beforeAfterPerZoneSchema = z3.object({
|
|
371
|
+
before: mediaResourceSchema.nullable(),
|
|
372
|
+
after: mediaResourceSchema.nullable(),
|
|
373
|
+
note: z3.string().nullable()
|
|
374
|
+
});
|
|
375
|
+
var billingPerZoneSchema = z3.object({
|
|
376
|
+
Product: z3.string().min(MIN_STRING_LENGTH, "Product name is required"),
|
|
377
|
+
ProductId: z3.string().nullable(),
|
|
378
|
+
Quantity: z3.number().min(0, "Quantity must be non-negative"),
|
|
379
|
+
UnitOfMeasurement: z3.nativeEnum(PricingMeasure),
|
|
380
|
+
UnitPrice: z3.number().min(0, "Unit price must be non-negative"),
|
|
381
|
+
UnitCurency: z3.nativeEnum(Currency),
|
|
382
|
+
Subtotal: z3.number().min(0, "Subtotal must be non-negative"),
|
|
383
|
+
Note: z3.string().nullable()
|
|
342
384
|
});
|
|
343
|
-
var
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
385
|
+
var appointmentMetadataSchema = z3.object({
|
|
386
|
+
selectedZones: z3.array(z3.string()).nullable(),
|
|
387
|
+
zonePhotos: z3.record(z3.string(), beforeAfterPerZoneSchema).nullable(),
|
|
388
|
+
zoneBilling: z3.record(z3.string(), billingPerZoneSchema).nullable()
|
|
389
|
+
});
|
|
390
|
+
var createAppointmentSchema = z3.object({
|
|
391
|
+
clinicBranchId: z3.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
|
|
392
|
+
practitionerId: z3.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
|
|
393
|
+
patientId: z3.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
|
|
394
|
+
procedureId: z3.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
|
|
395
|
+
appointmentStartTime: z3.any().refine(
|
|
349
396
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
350
397
|
"Appointment start time must be a valid timestamp or Date object"
|
|
351
398
|
),
|
|
352
|
-
appointmentEndTime:
|
|
399
|
+
appointmentEndTime: z3.any().refine(
|
|
353
400
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
354
401
|
"Appointment end time must be a valid timestamp or Date object"
|
|
355
402
|
),
|
|
356
|
-
cost:
|
|
357
|
-
currency:
|
|
358
|
-
patientNotes:
|
|
403
|
+
cost: z3.number().min(0, "Cost must be a non-negative number"),
|
|
404
|
+
currency: z3.string().min(1, "Currency is required"),
|
|
405
|
+
patientNotes: z3.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
|
|
359
406
|
initialStatus: appointmentStatusSchema,
|
|
360
407
|
initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */)
|
|
361
408
|
}).refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
|
|
362
409
|
message: "Appointment end time must be after start time",
|
|
363
410
|
path: ["appointmentEndTime"]
|
|
364
411
|
});
|
|
365
|
-
var updateAppointmentSchema =
|
|
412
|
+
var updateAppointmentSchema = z3.object({
|
|
366
413
|
status: appointmentStatusSchema.optional(),
|
|
367
|
-
confirmationTime:
|
|
368
|
-
cancellationTime:
|
|
369
|
-
rescheduleTime:
|
|
370
|
-
procedureActualStartTime:
|
|
371
|
-
actualDurationMinutes:
|
|
372
|
-
cancellationReason:
|
|
373
|
-
canceledBy:
|
|
374
|
-
internalNotes:
|
|
375
|
-
patientNotes:
|
|
414
|
+
confirmationTime: z3.any().optional().nullable(),
|
|
415
|
+
cancellationTime: z3.any().optional().nullable(),
|
|
416
|
+
rescheduleTime: z3.any().optional().nullable(),
|
|
417
|
+
procedureActualStartTime: z3.any().optional().nullable(),
|
|
418
|
+
actualDurationMinutes: z3.number().int().positive("Duration must be a positive integer").optional(),
|
|
419
|
+
cancellationReason: z3.string().max(MAX_STRING_LENGTH, "Cancellation reason too long").nullable().optional(),
|
|
420
|
+
canceledBy: z3.enum(["patient", "clinic", "practitioner", "system"]).optional(),
|
|
421
|
+
internalNotes: z3.string().max(MAX_STRING_LENGTH_LONG, "Internal notes too long").nullable().optional(),
|
|
422
|
+
patientNotes: z3.any().optional().nullable(),
|
|
376
423
|
paymentStatus: paymentStatusSchema.optional(),
|
|
377
|
-
paymentTransactionId:
|
|
378
|
-
completedPreRequirements:
|
|
379
|
-
completedPostRequirements:
|
|
380
|
-
linkedFormIds:
|
|
381
|
-
pendingUserFormsIds:
|
|
382
|
-
appointmentStartTime:
|
|
424
|
+
paymentTransactionId: z3.any().optional().nullable(),
|
|
425
|
+
completedPreRequirements: z3.union([z3.array(z3.string()), z3.any()]).optional(),
|
|
426
|
+
completedPostRequirements: z3.union([z3.array(z3.string()), z3.any()]).optional(),
|
|
427
|
+
linkedFormIds: z3.union([z3.array(z3.string()), z3.any()]).optional(),
|
|
428
|
+
pendingUserFormsIds: z3.union([z3.array(z3.string()), z3.any()]).optional(),
|
|
429
|
+
appointmentStartTime: z3.any().refine(
|
|
383
430
|
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
384
431
|
"Appointment start time must be a valid timestamp or Date object"
|
|
385
432
|
).optional(),
|
|
386
|
-
appointmentEndTime:
|
|
433
|
+
appointmentEndTime: z3.any().refine(
|
|
387
434
|
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
388
435
|
"Appointment end time must be a valid timestamp or Date object"
|
|
389
436
|
).optional(),
|
|
390
|
-
calendarEventId:
|
|
391
|
-
cost:
|
|
392
|
-
clinicBranchId:
|
|
393
|
-
practitionerId:
|
|
394
|
-
linkedForms:
|
|
395
|
-
media:
|
|
396
|
-
|
|
397
|
-
|
|
437
|
+
calendarEventId: z3.string().min(MIN_STRING_LENGTH).optional(),
|
|
438
|
+
cost: z3.number().min(0).optional(),
|
|
439
|
+
clinicBranchId: z3.string().min(MIN_STRING_LENGTH).optional(),
|
|
440
|
+
practitionerId: z3.string().min(MIN_STRING_LENGTH).optional(),
|
|
441
|
+
linkedForms: z3.union([z3.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), z3.any()]).optional(),
|
|
442
|
+
media: z3.union([
|
|
443
|
+
z3.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
|
|
444
|
+
z3.any()
|
|
398
445
|
]).optional(),
|
|
399
|
-
reviewInfo:
|
|
400
|
-
finalizedDetails:
|
|
401
|
-
isArchived:
|
|
402
|
-
updatedAt:
|
|
446
|
+
reviewInfo: z3.union([patientReviewInfoSchema.nullable(), z3.any()]).optional(),
|
|
447
|
+
finalizedDetails: z3.union([finalizedDetailsSchema.nullable(), z3.any()]).optional(),
|
|
448
|
+
isArchived: z3.boolean().optional(),
|
|
449
|
+
updatedAt: z3.any().optional(),
|
|
450
|
+
metadata: appointmentMetadataSchema.optional()
|
|
403
451
|
}).refine(
|
|
404
452
|
(data) => {
|
|
405
453
|
if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */ || data.status === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
|
|
@@ -423,24 +471,24 @@ var updateAppointmentSchema = z2.object({
|
|
|
423
471
|
path: ["appointmentEndTime"]
|
|
424
472
|
}
|
|
425
473
|
);
|
|
426
|
-
var searchAppointmentsSchema =
|
|
427
|
-
patientId:
|
|
428
|
-
practitionerId:
|
|
429
|
-
clinicBranchId:
|
|
430
|
-
startDate:
|
|
474
|
+
var searchAppointmentsSchema = z3.object({
|
|
475
|
+
patientId: z3.string().optional(),
|
|
476
|
+
practitionerId: z3.string().optional(),
|
|
477
|
+
clinicBranchId: z3.string().optional(),
|
|
478
|
+
startDate: z3.any().refine(
|
|
431
479
|
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
432
480
|
"Start date must be a valid timestamp or Date object"
|
|
433
481
|
).optional(),
|
|
434
|
-
endDate:
|
|
482
|
+
endDate: z3.any().refine(
|
|
435
483
|
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
436
484
|
"End date must be a valid timestamp or Date object"
|
|
437
485
|
).optional(),
|
|
438
|
-
status:
|
|
486
|
+
status: z3.union([
|
|
439
487
|
appointmentStatusSchema,
|
|
440
|
-
|
|
488
|
+
z3.array(appointmentStatusSchema).nonempty()
|
|
441
489
|
]).optional(),
|
|
442
|
-
limit:
|
|
443
|
-
startAfter:
|
|
490
|
+
limit: z3.number().positive().int().optional().default(20),
|
|
491
|
+
startAfter: z3.any().optional()
|
|
444
492
|
}).refine(
|
|
445
493
|
(data) => {
|
|
446
494
|
if (!data.startDate && !data.endDate && !data.status) {
|
|
@@ -464,13 +512,13 @@ var searchAppointmentsSchema = z2.object({
|
|
|
464
512
|
path: ["endDate"]
|
|
465
513
|
}
|
|
466
514
|
);
|
|
467
|
-
var rescheduleAppointmentSchema =
|
|
468
|
-
appointmentId:
|
|
469
|
-
newStartTime:
|
|
515
|
+
var rescheduleAppointmentSchema = z3.object({
|
|
516
|
+
appointmentId: z3.string().min(MIN_STRING_LENGTH, "Appointment ID is required"),
|
|
517
|
+
newStartTime: z3.any().refine(
|
|
470
518
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
471
519
|
"New start time must be a valid timestamp, Date object, number, or string"
|
|
472
520
|
),
|
|
473
|
-
newEndTime:
|
|
521
|
+
newEndTime: z3.any().refine(
|
|
474
522
|
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
|
|
475
523
|
"New end time must be a valid timestamp, Date object, number, or string"
|
|
476
524
|
)
|
|
@@ -590,24 +638,24 @@ var USERS_COLLECTION = "users";
|
|
|
590
638
|
import { z as z20 } from "zod";
|
|
591
639
|
|
|
592
640
|
// src/validations/schemas.ts
|
|
593
|
-
import { z as
|
|
594
|
-
var emailSchema =
|
|
595
|
-
var passwordSchema =
|
|
641
|
+
import { z as z4 } from "zod";
|
|
642
|
+
var emailSchema = z4.string().email("Invalid email format").min(5, "Email must be at least 5 characters").max(255, "Email must be less than 255 characters");
|
|
643
|
+
var passwordSchema = z4.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters").regex(
|
|
596
644
|
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d\w\W]{8,}$/,
|
|
597
645
|
"Password must contain at least one uppercase letter, one lowercase letter, and one number"
|
|
598
646
|
);
|
|
599
|
-
var userRoleSchema =
|
|
600
|
-
var userRolesSchema =
|
|
601
|
-
var timestampSchema =
|
|
647
|
+
var userRoleSchema = z4.nativeEnum(UserRole);
|
|
648
|
+
var userRolesSchema = z4.array(userRoleSchema).min(1, "User must have at least one role").max(3, "User cannot have more than 3 roles");
|
|
649
|
+
var timestampSchema = z4.custom((data) => {
|
|
602
650
|
if (data && typeof data === "object" && "isEqual" in data) {
|
|
603
651
|
return true;
|
|
604
652
|
}
|
|
605
653
|
return data && typeof data === "object" && "toDate" in data && "seconds" in data && "nanoseconds" in data;
|
|
606
654
|
}, "Must be a Timestamp object or serverTimestamp");
|
|
607
|
-
var clinicAdminOptionsSchema =
|
|
608
|
-
isGroupOwner:
|
|
609
|
-
groupToken:
|
|
610
|
-
groupId:
|
|
655
|
+
var clinicAdminOptionsSchema = z4.object({
|
|
656
|
+
isGroupOwner: z4.boolean(),
|
|
657
|
+
groupToken: z4.string().optional(),
|
|
658
|
+
groupId: z4.string().optional()
|
|
611
659
|
}).refine(
|
|
612
660
|
(data) => {
|
|
613
661
|
if (!data.isGroupOwner && (!data.groupToken || !data.groupId)) {
|
|
@@ -622,20 +670,20 @@ var clinicAdminOptionsSchema = z3.object({
|
|
|
622
670
|
message: "Invalid clinic admin options configuration"
|
|
623
671
|
}
|
|
624
672
|
);
|
|
625
|
-
var createUserOptionsSchema =
|
|
673
|
+
var createUserOptionsSchema = z4.object({
|
|
626
674
|
clinicAdminData: clinicAdminOptionsSchema.optional()
|
|
627
675
|
});
|
|
628
|
-
var userSchema =
|
|
629
|
-
uid:
|
|
630
|
-
email:
|
|
631
|
-
roles:
|
|
632
|
-
isAnonymous:
|
|
676
|
+
var userSchema = z4.object({
|
|
677
|
+
uid: z4.string(),
|
|
678
|
+
email: z4.string().email().nullable(),
|
|
679
|
+
roles: z4.array(userRoleSchema),
|
|
680
|
+
isAnonymous: z4.boolean(),
|
|
633
681
|
createdAt: timestampSchema,
|
|
634
682
|
updatedAt: timestampSchema,
|
|
635
683
|
lastLoginAt: timestampSchema,
|
|
636
|
-
patientProfile:
|
|
637
|
-
practitionerProfile:
|
|
638
|
-
adminProfile:
|
|
684
|
+
patientProfile: z4.string().optional(),
|
|
685
|
+
practitionerProfile: z4.string().optional(),
|
|
686
|
+
adminProfile: z4.string().optional()
|
|
639
687
|
});
|
|
640
688
|
|
|
641
689
|
// src/errors/auth.errors.ts
|
|
@@ -1371,14 +1419,6 @@ var Gender = /* @__PURE__ */ ((Gender2) => {
|
|
|
1371
1419
|
import { z as z7 } from "zod";
|
|
1372
1420
|
import { Timestamp as Timestamp3 } from "firebase/firestore";
|
|
1373
1421
|
|
|
1374
|
-
// src/validations/media.schema.ts
|
|
1375
|
-
import { z as z4 } from "zod";
|
|
1376
|
-
var mediaResourceSchema = z4.union([
|
|
1377
|
-
z4.string().url(),
|
|
1378
|
-
z4.instanceof(File),
|
|
1379
|
-
z4.instanceof(Blob)
|
|
1380
|
-
]);
|
|
1381
|
-
|
|
1382
1422
|
// src/validations/patient/medical-info.schema.ts
|
|
1383
1423
|
import { z as z6 } from "zod";
|
|
1384
1424
|
|
|
@@ -3633,25 +3673,6 @@ var ProcedureFamily = /* @__PURE__ */ ((ProcedureFamily2) => {
|
|
|
3633
3673
|
return ProcedureFamily2;
|
|
3634
3674
|
})(ProcedureFamily || {});
|
|
3635
3675
|
|
|
3636
|
-
// src/backoffice/types/static/pricing.types.ts
|
|
3637
|
-
var PricingMeasure = /* @__PURE__ */ ((PricingMeasure3) => {
|
|
3638
|
-
PricingMeasure3["PER_ML"] = "per_ml";
|
|
3639
|
-
PricingMeasure3["PER_ZONE"] = "per_zone";
|
|
3640
|
-
PricingMeasure3["PER_AREA"] = "per_area";
|
|
3641
|
-
PricingMeasure3["PER_SESSION"] = "per_session";
|
|
3642
|
-
PricingMeasure3["PER_TREATMENT"] = "per_treatment";
|
|
3643
|
-
PricingMeasure3["PER_PACKAGE"] = "per_package";
|
|
3644
|
-
return PricingMeasure3;
|
|
3645
|
-
})(PricingMeasure || {});
|
|
3646
|
-
var Currency = /* @__PURE__ */ ((Currency2) => {
|
|
3647
|
-
Currency2["EUR"] = "EUR";
|
|
3648
|
-
Currency2["USD"] = "USD";
|
|
3649
|
-
Currency2["GBP"] = "GBP";
|
|
3650
|
-
Currency2["CHF"] = "CHF";
|
|
3651
|
-
Currency2["AUD"] = "AUD";
|
|
3652
|
-
return Currency2;
|
|
3653
|
-
})(Currency || {});
|
|
3654
|
-
|
|
3655
3676
|
// src/validations/shared.schema.ts
|
|
3656
3677
|
var sharedClinicContactInfoSchema = z12.object({
|
|
3657
3678
|
email: z12.string().email(),
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -5,12 +5,16 @@ import {
|
|
|
5
5
|
PatientProfileInfo,
|
|
6
6
|
} from "../profile";
|
|
7
7
|
import { ProcedureSummaryInfo } from "../procedure";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
Currency,
|
|
10
|
+
type PricingMeasure,
|
|
11
|
+
} from "../../backoffice/types/static/pricing.types";
|
|
9
12
|
import { BlockingCondition } from "../../backoffice/types/static/blocking-condition.types";
|
|
10
13
|
import { Contraindication } from "../../backoffice/types/static/contraindication.types";
|
|
11
14
|
import { Requirement } from "../../backoffice/types/requirement.types";
|
|
12
15
|
import { FilledDocumentStatus } from "../documentation-templates";
|
|
13
16
|
import type { ProcedureFamily } from "../../backoffice";
|
|
17
|
+
import type { MediaResource } from "../../services/media/media.service";
|
|
14
18
|
|
|
15
19
|
/**
|
|
16
20
|
* Enum defining the possible statuses of an appointment.
|
|
@@ -111,6 +115,52 @@ export interface PatientReviewInfo {
|
|
|
111
115
|
reviewedAt: Timestamp;
|
|
112
116
|
}
|
|
113
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Interface for before/after photos and notes per zone
|
|
120
|
+
*/
|
|
121
|
+
export interface BeforeAfterPerZone {
|
|
122
|
+
/** URL for before photo or null if not available */
|
|
123
|
+
before: MediaResource | null;
|
|
124
|
+
/** URL for after photo or null if not available */
|
|
125
|
+
after: MediaResource | null;
|
|
126
|
+
/** Optional note for the zone */
|
|
127
|
+
note: string | null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Interface for billing information per zone
|
|
132
|
+
*/
|
|
133
|
+
export interface BillingPerZone {
|
|
134
|
+
/** Product name/description */
|
|
135
|
+
Product: string;
|
|
136
|
+
/** Product ID */
|
|
137
|
+
ProductId: string | null;
|
|
138
|
+
/** Quantity used (can be decimal) */
|
|
139
|
+
Quantity: number;
|
|
140
|
+
/** Unit of measurement */
|
|
141
|
+
UnitOfMeasurement: PricingMeasure;
|
|
142
|
+
/** Unit price for the product */
|
|
143
|
+
UnitPrice: number;
|
|
144
|
+
/** Currency for the unit price */
|
|
145
|
+
UnitCurency: Currency;
|
|
146
|
+
/** Calculated subtotal */
|
|
147
|
+
Subtotal: number;
|
|
148
|
+
/** Optional billing note */
|
|
149
|
+
Note: string | null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Interface for appointment metadata containing zone-specific information
|
|
154
|
+
*/
|
|
155
|
+
export interface AppointmentMetadata {
|
|
156
|
+
/** Array of selected zones for the appointment */
|
|
157
|
+
selectedZones: string[] | null;
|
|
158
|
+
/** Map of zone photos with before/after images and notes */
|
|
159
|
+
zonePhotos: Record<string, BeforeAfterPerZone> | null;
|
|
160
|
+
/** Map of billing information per zone */
|
|
161
|
+
zoneBilling: Record<string, BillingPerZone> | null;
|
|
162
|
+
}
|
|
163
|
+
|
|
114
164
|
/**
|
|
115
165
|
* Represents a booked appointment, aggregating key information and relevant procedure rules.
|
|
116
166
|
*/
|
|
@@ -207,6 +257,9 @@ export interface Appointment {
|
|
|
207
257
|
|
|
208
258
|
/** NEW: Flag for soft deletion or archiving */
|
|
209
259
|
isArchived?: boolean;
|
|
260
|
+
|
|
261
|
+
/** NEW: Metadata for the appointment - used for area selection and photos */
|
|
262
|
+
metadata?: AppointmentMetadata;
|
|
210
263
|
}
|
|
211
264
|
|
|
212
265
|
/**
|
|
@@ -279,6 +332,9 @@ export interface UpdateAppointmentData {
|
|
|
279
332
|
isArchived?: boolean;
|
|
280
333
|
|
|
281
334
|
updatedAt?: FieldValue; // To set server timestamp
|
|
335
|
+
|
|
336
|
+
/** NEW: For updating metadata */
|
|
337
|
+
metadata?: AppointmentMetadata;
|
|
282
338
|
}
|
|
283
339
|
|
|
284
340
|
/**
|
|
@@ -5,6 +5,11 @@ import {
|
|
|
5
5
|
MediaType,
|
|
6
6
|
} from "../types/appointment";
|
|
7
7
|
import { filledDocumentStatusSchema } from "./documentation-templates.schema";
|
|
8
|
+
import {
|
|
9
|
+
Currency,
|
|
10
|
+
PricingMeasure,
|
|
11
|
+
} from "../backoffice/types/static/pricing.types";
|
|
12
|
+
import { mediaResourceSchema } from "./media.schema";
|
|
8
13
|
|
|
9
14
|
// Define common constants locally if not available from common.schema.ts
|
|
10
15
|
const MIN_STRING_LENGTH = 1;
|
|
@@ -147,6 +152,38 @@ export const finalizedDetailsSchema = z.object({
|
|
|
147
152
|
.optional(),
|
|
148
153
|
});
|
|
149
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Schema for before/after photos and notes per zone
|
|
157
|
+
*/
|
|
158
|
+
export const beforeAfterPerZoneSchema = z.object({
|
|
159
|
+
before: mediaResourceSchema.nullable(),
|
|
160
|
+
after: mediaResourceSchema.nullable(),
|
|
161
|
+
note: z.string().nullable(),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Schema for billing information per zone
|
|
166
|
+
*/
|
|
167
|
+
export const billingPerZoneSchema = z.object({
|
|
168
|
+
Product: z.string().min(MIN_STRING_LENGTH, "Product name is required"),
|
|
169
|
+
ProductId: z.string().nullable(),
|
|
170
|
+
Quantity: z.number().min(0, "Quantity must be non-negative"),
|
|
171
|
+
UnitOfMeasurement: z.nativeEnum(PricingMeasure),
|
|
172
|
+
UnitPrice: z.number().min(0, "Unit price must be non-negative"),
|
|
173
|
+
UnitCurency: z.nativeEnum(Currency),
|
|
174
|
+
Subtotal: z.number().min(0, "Subtotal must be non-negative"),
|
|
175
|
+
Note: z.string().nullable(),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Schema for appointment metadata containing zone-specific information
|
|
180
|
+
*/
|
|
181
|
+
export const appointmentMetadataSchema = z.object({
|
|
182
|
+
selectedZones: z.array(z.string()).nullable(),
|
|
183
|
+
zonePhotos: z.record(z.string(), beforeAfterPerZoneSchema).nullable(),
|
|
184
|
+
zoneBilling: z.record(z.string(), billingPerZoneSchema).nullable(),
|
|
185
|
+
});
|
|
186
|
+
|
|
150
187
|
// --- Main Appointment Schemas ---
|
|
151
188
|
|
|
152
189
|
/**
|
|
@@ -291,6 +328,7 @@ export const updateAppointmentSchema = z
|
|
|
291
328
|
.optional(),
|
|
292
329
|
isArchived: z.boolean().optional(),
|
|
293
330
|
updatedAt: z.any().optional(),
|
|
331
|
+
metadata: appointmentMetadataSchema.optional(),
|
|
294
332
|
})
|
|
295
333
|
.refine(
|
|
296
334
|
(data) => {
|