@blackcode_sa/metaestetics-api 1.13.5 → 1.13.6
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 +20 -1
- package/dist/admin/index.d.ts +20 -1
- package/dist/admin/index.js +217 -1
- package/dist/admin/index.mjs +217 -1
- package/package.json +121 -121
- package/src/__mocks__/firstore.ts +10 -10
- package/src/admin/aggregation/README.md +79 -79
- package/src/admin/aggregation/appointment/README.md +128 -128
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
- package/src/admin/aggregation/appointment/index.ts +1 -1
- package/src/admin/aggregation/clinic/README.md +52 -52
- package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +966 -703
- package/src/admin/aggregation/clinic/index.ts +1 -1
- package/src/admin/aggregation/forms/README.md +13 -13
- package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
- package/src/admin/aggregation/forms/index.ts +1 -1
- package/src/admin/aggregation/index.ts +8 -8
- package/src/admin/aggregation/patient/README.md +27 -27
- package/src/admin/aggregation/patient/index.ts +1 -1
- package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
- package/src/admin/aggregation/practitioner/README.md +42 -42
- package/src/admin/aggregation/practitioner/index.ts +1 -1
- package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
- package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
- package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
- package/src/admin/aggregation/procedure/README.md +43 -43
- package/src/admin/aggregation/procedure/index.ts +1 -1
- package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
- package/src/admin/aggregation/reviews/index.ts +1 -1
- package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
- package/src/admin/analytics/analytics.admin.service.ts +278 -278
- package/src/admin/analytics/index.ts +2 -2
- package/src/admin/booking/README.md +125 -125
- package/src/admin/booking/booking.admin.ts +1037 -1037
- package/src/admin/booking/booking.calculator.ts +712 -712
- package/src/admin/booking/booking.types.ts +59 -59
- package/src/admin/booking/index.ts +3 -3
- package/src/admin/booking/timezones-problem.md +185 -185
- package/src/admin/calendar/README.md +7 -7
- package/src/admin/calendar/calendar.admin.service.ts +345 -345
- package/src/admin/calendar/index.ts +1 -1
- package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
- package/src/admin/documentation-templates/index.ts +1 -1
- package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
- package/src/admin/free-consultation/index.ts +1 -1
- package/src/admin/index.ts +81 -81
- package/src/admin/logger/index.ts +78 -78
- package/src/admin/mailing/README.md +95 -95
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
- package/src/admin/mailing/appointment/index.ts +1 -1
- package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
- package/src/admin/mailing/base.mailing.service.ts +208 -208
- package/src/admin/mailing/index.ts +3 -3
- package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
- package/src/admin/mailing/practitionerInvite/index.ts +2 -2
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
- package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
- package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
- package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
- package/src/admin/notifications/index.ts +1 -1
- package/src/admin/notifications/notifications.admin.ts +710 -710
- package/src/admin/requirements/README.md +128 -128
- package/src/admin/requirements/index.ts +1 -1
- package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
- package/src/admin/users/index.ts +1 -1
- package/src/admin/users/user-profile.admin.ts +405 -405
- package/src/backoffice/constants/certification.constants.ts +13 -13
- package/src/backoffice/constants/index.ts +1 -1
- package/src/backoffice/errors/backoffice.errors.ts +181 -181
- package/src/backoffice/errors/index.ts +1 -1
- package/src/backoffice/expo-safe/README.md +26 -26
- package/src/backoffice/expo-safe/index.ts +41 -41
- package/src/backoffice/index.ts +5 -5
- package/src/backoffice/services/FIXES_README.md +102 -102
- package/src/backoffice/services/README.md +57 -57
- package/src/backoffice/services/analytics.service.proposal.md +863 -863
- package/src/backoffice/services/analytics.service.summary.md +143 -143
- package/src/backoffice/services/brand.service.ts +256 -256
- package/src/backoffice/services/category.service.ts +384 -384
- package/src/backoffice/services/constants.service.ts +385 -385
- package/src/backoffice/services/documentation-template.service.ts +202 -202
- package/src/backoffice/services/index.ts +10 -10
- package/src/backoffice/services/migrate-products.ts +116 -116
- package/src/backoffice/services/product.service.ts +553 -553
- package/src/backoffice/services/requirement.service.ts +235 -235
- package/src/backoffice/services/subcategory.service.ts +461 -461
- package/src/backoffice/services/technology.service.ts +1151 -1151
- package/src/backoffice/types/README.md +12 -12
- package/src/backoffice/types/admin-constants.types.ts +69 -69
- package/src/backoffice/types/brand.types.ts +29 -29
- package/src/backoffice/types/category.types.ts +67 -67
- package/src/backoffice/types/documentation-templates.types.ts +28 -28
- package/src/backoffice/types/index.ts +10 -10
- package/src/backoffice/types/procedure-product.types.ts +38 -38
- package/src/backoffice/types/product.types.ts +240 -240
- package/src/backoffice/types/requirement.types.ts +63 -63
- package/src/backoffice/types/static/README.md +18 -18
- package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
- package/src/backoffice/types/static/certification.types.ts +37 -37
- package/src/backoffice/types/static/contraindication.types.ts +19 -19
- package/src/backoffice/types/static/index.ts +6 -6
- package/src/backoffice/types/static/pricing.types.ts +16 -16
- package/src/backoffice/types/static/procedure-family.types.ts +14 -14
- package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
- package/src/backoffice/types/subcategory.types.ts +34 -34
- package/src/backoffice/types/technology.types.ts +168 -168
- package/src/backoffice/validations/index.ts +1 -1
- package/src/backoffice/validations/schemas.ts +164 -164
- package/src/config/__mocks__/firebase.ts +99 -99
- package/src/config/firebase.ts +78 -78
- package/src/config/index.ts +9 -9
- package/src/errors/auth.error.ts +6 -6
- package/src/errors/auth.errors.ts +200 -200
- package/src/errors/clinic.errors.ts +32 -32
- package/src/errors/firebase.errors.ts +47 -47
- package/src/errors/user.errors.ts +99 -99
- package/src/index.backup.ts +407 -407
- package/src/index.ts +6 -6
- package/src/locales/en.ts +31 -31
- package/src/recommender/admin/index.ts +1 -1
- package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
- package/src/recommender/front/index.ts +1 -1
- package/src/recommender/front/services/onboarding.service.ts +5 -5
- package/src/recommender/front/services/recommender.service.ts +3 -3
- package/src/recommender/index.ts +1 -1
- package/src/services/PATIENTAUTH.MD +197 -197
- package/src/services/README.md +106 -106
- package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
- package/src/services/__tests__/auth/auth.setup.ts +293 -293
- package/src/services/__tests__/auth.service.test.ts +346 -346
- package/src/services/__tests__/base.service.test.ts +77 -77
- package/src/services/__tests__/user.service.test.ts +528 -528
- package/src/services/analytics/ARCHITECTURE.md +199 -199
- package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
- package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
- package/src/services/analytics/QUICK_START.md +393 -393
- package/src/services/analytics/README.md +304 -304
- package/src/services/analytics/SUMMARY.md +141 -141
- package/src/services/analytics/TRENDS.md +380 -380
- package/src/services/analytics/USAGE_GUIDE.md +518 -518
- package/src/services/analytics/analytics-cloud.service.ts +222 -222
- package/src/services/analytics/analytics.service.ts +2142 -2142
- package/src/services/analytics/index.ts +4 -4
- package/src/services/analytics/review-analytics.service.ts +941 -941
- package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
- package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
- package/src/services/analytics/utils/grouping.utils.ts +434 -434
- package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
- package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
- package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
- package/src/services/appointment/README.md +17 -17
- package/src/services/appointment/appointment.service.ts +2558 -2558
- package/src/services/appointment/index.ts +1 -1
- package/src/services/appointment/utils/appointment.utils.ts +552 -552
- package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
- package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
- package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
- package/src/services/appointment/utils/zone-management.utils.ts +353 -353
- package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
- package/src/services/auth/auth.service.ts +989 -989
- package/src/services/auth/auth.v2.service.ts +961 -961
- package/src/services/auth/index.ts +7 -7
- package/src/services/auth/utils/error.utils.ts +90 -90
- package/src/services/auth/utils/firebase.utils.ts +49 -49
- package/src/services/auth/utils/index.ts +21 -21
- package/src/services/auth/utils/practitioner.utils.ts +125 -125
- package/src/services/base.service.ts +41 -41
- package/src/services/calendar/calendar.service.ts +1077 -1077
- package/src/services/calendar/calendar.v2.service.ts +1683 -1683
- package/src/services/calendar/calendar.v3.service.ts +313 -313
- package/src/services/calendar/externalCalendar.service.ts +178 -178
- package/src/services/calendar/index.ts +5 -5
- package/src/services/calendar/synced-calendars.service.ts +743 -743
- package/src/services/calendar/utils/appointment.utils.ts +265 -265
- package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
- package/src/services/calendar/utils/clinic.utils.ts +237 -237
- package/src/services/calendar/utils/docs.utils.ts +157 -157
- package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
- package/src/services/calendar/utils/index.ts +8 -8
- package/src/services/calendar/utils/patient.utils.ts +198 -198
- package/src/services/calendar/utils/practitioner.utils.ts +221 -221
- package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
- package/src/services/clinic/README.md +204 -204
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
- package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
- package/src/services/clinic/billing-transactions.service.ts +217 -217
- package/src/services/clinic/clinic-admin.service.ts +202 -202
- package/src/services/clinic/clinic-group.service.ts +310 -310
- package/src/services/clinic/clinic.service.ts +708 -708
- package/src/services/clinic/index.ts +5 -5
- package/src/services/clinic/practitioner-invite.service.ts +519 -519
- package/src/services/clinic/utils/admin.utils.ts +551 -551
- package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
- package/src/services/clinic/utils/clinic.utils.ts +949 -949
- package/src/services/clinic/utils/filter.utils.d.ts +23 -23
- package/src/services/clinic/utils/filter.utils.ts +446 -446
- package/src/services/clinic/utils/index.ts +11 -11
- package/src/services/clinic/utils/photos.utils.ts +188 -188
- package/src/services/clinic/utils/search.utils.ts +84 -84
- package/src/services/clinic/utils/tag.utils.ts +124 -124
- package/src/services/documentation-templates/documentation-template.service.ts +537 -537
- package/src/services/documentation-templates/filled-document.service.ts +587 -587
- package/src/services/documentation-templates/index.ts +2 -2
- package/src/services/index.ts +14 -14
- package/src/services/media/index.ts +1 -1
- package/src/services/media/media.service.ts +418 -418
- package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
- package/src/services/notifications/index.ts +1 -1
- package/src/services/notifications/notification.service.ts +215 -215
- package/src/services/patient/README.md +48 -48
- package/src/services/patient/To-Do.md +43 -43
- package/src/services/patient/__tests__/patient.service.test.ts +294 -294
- package/src/services/patient/index.ts +2 -2
- package/src/services/patient/patient.service.ts +883 -883
- package/src/services/patient/patientRequirements.service.ts +285 -285
- package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
- package/src/services/patient/utils/clinic.utils.ts +80 -80
- package/src/services/patient/utils/docs.utils.ts +142 -142
- package/src/services/patient/utils/index.ts +9 -9
- package/src/services/patient/utils/location.utils.ts +126 -126
- package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
- package/src/services/patient/utils/medical.utils.ts +458 -458
- package/src/services/patient/utils/practitioner.utils.ts +260 -260
- package/src/services/patient/utils/profile.utils.ts +510 -510
- package/src/services/patient/utils/sensitive.utils.ts +260 -260
- package/src/services/patient/utils/token.utils.ts +211 -211
- package/src/services/practitioner/README.md +145 -145
- package/src/services/practitioner/index.ts +1 -1
- package/src/services/practitioner/practitioner.service.ts +1742 -1742
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +2200 -2200
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +734 -734
- package/src/services/user/index.ts +1 -1
- package/src/services/user/user.service.ts +489 -489
- package/src/services/user/user.v2.service.ts +466 -466
- package/src/types/analytics/analytics.types.ts +597 -597
- package/src/types/analytics/grouped-analytics.types.ts +173 -173
- package/src/types/analytics/index.ts +4 -4
- package/src/types/analytics/stored-analytics.types.ts +137 -137
- package/src/types/appointment/index.ts +480 -480
- package/src/types/calendar/index.ts +258 -258
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +498 -498
- package/src/types/clinic/practitioner-invite.types.ts +91 -91
- package/src/types/clinic/preferences.types.ts +159 -159
- package/src/types/clinic/to-do +3 -3
- package/src/types/documentation-templates/index.ts +308 -308
- package/src/types/index.ts +47 -47
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +286 -286
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/index.ts +275 -275
- package/src/types/patient/medical-info.types.ts +152 -152
- package/src/types/patient/patient-requirements.ts +92 -92
- package/src/types/patient/token.types.ts +61 -61
- package/src/types/practitioner/index.ts +206 -206
- package/src/types/procedure/index.ts +181 -181
- package/src/types/profile/index.ts +39 -39
- package/src/types/reviews/index.ts +132 -132
- package/src/types/tz-lookup.d.ts +4 -4
- package/src/types/user/index.ts +38 -38
- package/src/utils/TIMESTAMPS.md +176 -176
- package/src/utils/TimestampUtils.ts +241 -241
- package/src/utils/index.ts +1 -1
- package/src/validations/appointment.schema.ts +574 -574
- package/src/validations/calendar.schema.ts +225 -225
- package/src/validations/clinic.schema.ts +494 -494
- package/src/validations/common.schema.ts +25 -25
- package/src/validations/documentation-templates/index.ts +1 -1
- package/src/validations/documentation-templates/template.schema.ts +220 -220
- package/src/validations/documentation-templates.schema.ts +10 -10
- package/src/validations/index.ts +20 -20
- package/src/validations/media.schema.ts +10 -10
- package/src/validations/notification.schema.ts +90 -90
- package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
- package/src/validations/patient/medical-info.schema.ts +125 -125
- package/src/validations/patient/patient-requirements.schema.ts +84 -84
- package/src/validations/patient/token.schema.ts +29 -29
- package/src/validations/patient.schema.ts +217 -217
- package/src/validations/practitioner.schema.ts +222 -222
- package/src/validations/procedure-product.schema.ts +41 -41
- package/src/validations/procedure.schema.ts +124 -124
- package/src/validations/profile-info.schema.ts +41 -41
- package/src/validations/reviews.schema.ts +195 -195
- package/src/validations/schemas.ts +104 -104
- package/src/validations/shared.schema.ts +78 -78
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { ProcedureFamily } from "../types/static/procedure-family.types";
|
|
3
|
-
import { BlockingCondition } from "../types/static/blocking-condition.types";
|
|
4
|
-
import { TimeUnit, RequirementType } from "../types/requirement.types";
|
|
5
|
-
import {
|
|
6
|
-
CertificationLevel,
|
|
7
|
-
CertificationSpecialty,
|
|
8
|
-
} from "../types/static/certification.types";
|
|
9
|
-
|
|
10
|
-
import { documentTemplateSchema } from "../../validations/documentation-templates.schema";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Zod validation schema for a single dynamic contraindication.
|
|
14
|
-
* @see ContraindicationDynamic in admin-constants.types.ts
|
|
15
|
-
*/
|
|
16
|
-
export const contraindicationDynamicSchema = z.object({
|
|
17
|
-
id: z
|
|
18
|
-
.string()
|
|
19
|
-
.min(1, "Contraindication ID is required")
|
|
20
|
-
.regex(
|
|
21
|
-
/^[a-z0-9_]+$/,
|
|
22
|
-
"ID must be in snake_case (lowercase, numbers, and underscores only)"
|
|
23
|
-
),
|
|
24
|
-
name: z.string().min(1, "Contraindication name is required"),
|
|
25
|
-
description: z.string().optional(),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Zod validation schema for a single dynamic treatment benefit.
|
|
30
|
-
* @see TreatmentBenefitDynamic in admin-constants.types.ts
|
|
31
|
-
*/
|
|
32
|
-
export const treatmentBenefitDynamicSchema = z.object({
|
|
33
|
-
id: z
|
|
34
|
-
.string()
|
|
35
|
-
.min(1, "Benefit ID is required")
|
|
36
|
-
.regex(
|
|
37
|
-
/^[a-z0-9_]+$/,
|
|
38
|
-
"ID must be in snake_case (lowercase, numbers, and underscores only)"
|
|
39
|
-
),
|
|
40
|
-
name: z.string().min(1, "Benefit name is required"),
|
|
41
|
-
description: z.string().optional(),
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Base validation schemas for enums
|
|
46
|
-
*/
|
|
47
|
-
export const blockingConditionSchemaBackoffice =
|
|
48
|
-
z.nativeEnum(BlockingCondition);
|
|
49
|
-
export const contraindicationSchemaBackoffice = contraindicationDynamicSchema;
|
|
50
|
-
export const treatmentBenefitSchemaBackoffice = treatmentBenefitDynamicSchema;
|
|
51
|
-
export const procedureFamilySchemaBackoffice = z.nativeEnum(ProcedureFamily);
|
|
52
|
-
export const timeUnitSchemaBackoffice = z.nativeEnum(TimeUnit);
|
|
53
|
-
export const requirementTypeSchema = z.nativeEnum(RequirementType);
|
|
54
|
-
export const certificationLevelSchema = z.nativeEnum(CertificationLevel);
|
|
55
|
-
export const certificationSpecialtySchema = z.nativeEnum(
|
|
56
|
-
CertificationSpecialty
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Certification requirement validation schema
|
|
61
|
-
*/
|
|
62
|
-
export const certificationRequirementSchema = z.object({
|
|
63
|
-
minimumLevel: certificationLevelSchema,
|
|
64
|
-
requiredSpecialties: z
|
|
65
|
-
.array(certificationSpecialtySchema)
|
|
66
|
-
.max(5, "Maximum 5 specialties allowed")
|
|
67
|
-
.optional(),
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Timeframe validation schema
|
|
72
|
-
*/
|
|
73
|
-
export const timeframeSchema = z.object({
|
|
74
|
-
duration: z.number().min(1, "Duration must be positive"),
|
|
75
|
-
unit: timeUnitSchemaBackoffice,
|
|
76
|
-
notifyAt: z
|
|
77
|
-
.array(z.number())
|
|
78
|
-
.min(1, "At least one notification point is required"),
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Requirement validation schema
|
|
83
|
-
*/
|
|
84
|
-
export const requirementSchema = z.object({
|
|
85
|
-
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
86
|
-
description: z.string().min(1, "Description is required"),
|
|
87
|
-
type: requirementTypeSchema,
|
|
88
|
-
timeframe: timeframeSchema,
|
|
89
|
-
importance: z.enum(["low", "medium", "high"]),
|
|
90
|
-
isActive: z.boolean().default(true),
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Technology requirements validation schema
|
|
95
|
-
*/
|
|
96
|
-
export const technologyRequirementsSchema = z.object({
|
|
97
|
-
pre: z.array(requirementSchema),
|
|
98
|
-
post: z.array(requirementSchema),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Technology validation schema
|
|
103
|
-
*/
|
|
104
|
-
export const technologySchema = z.object({
|
|
105
|
-
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
106
|
-
description: z.string().max(1000, "Description is too long").optional(),
|
|
107
|
-
technicalDetails: z
|
|
108
|
-
.string()
|
|
109
|
-
.max(2000, "Technical details are too long")
|
|
110
|
-
.optional(),
|
|
111
|
-
family: procedureFamilySchemaBackoffice,
|
|
112
|
-
categoryId: z.string().min(1, "Category ID is required"),
|
|
113
|
-
subcategoryId: z.string().min(1, "Subcategory ID is required"),
|
|
114
|
-
requirements: technologyRequirementsSchema.default({
|
|
115
|
-
pre: [],
|
|
116
|
-
post: [],
|
|
117
|
-
}),
|
|
118
|
-
blockingConditions: z.array(blockingConditionSchemaBackoffice),
|
|
119
|
-
contraindications: z.array(contraindicationSchemaBackoffice),
|
|
120
|
-
documentationTemplates: z.array(documentTemplateSchema),
|
|
121
|
-
benefits: z.array(treatmentBenefitSchemaBackoffice),
|
|
122
|
-
certificationRequirement: certificationRequirementSchema,
|
|
123
|
-
photoTemplate: z.string().url("Photo template must be a valid URL").optional(),
|
|
124
|
-
isActive: z.boolean().default(true),
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Category validation schema
|
|
129
|
-
*/
|
|
130
|
-
export const categorySchema = z.object({
|
|
131
|
-
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
132
|
-
description: z.string().optional(),
|
|
133
|
-
family: procedureFamilySchemaBackoffice,
|
|
134
|
-
isActive: z.boolean().default(true),
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Subcategory validation schema
|
|
139
|
-
*/
|
|
140
|
-
export const subcategorySchema = z.object({
|
|
141
|
-
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
142
|
-
description: z.string().optional(),
|
|
143
|
-
categoryId: z.string().min(1, "Category ID is required"),
|
|
144
|
-
isActive: z.boolean().default(true),
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Partial schemas for updates
|
|
149
|
-
*/
|
|
150
|
-
export const categoryUpdateSchema = categorySchema.partial();
|
|
151
|
-
export const subcategoryUpdateSchema = subcategorySchema.partial();
|
|
152
|
-
export const technologyUpdateSchema = technologySchema.partial();
|
|
153
|
-
export const requirementUpdateSchema = requirementSchema.partial();
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Documentation Templates schemas
|
|
157
|
-
*/
|
|
158
|
-
export {
|
|
159
|
-
createDocumentTemplateSchema,
|
|
160
|
-
updateDocumentTemplateSchema,
|
|
161
|
-
documentTemplateSchema,
|
|
162
|
-
documentElementSchema,
|
|
163
|
-
documentElementWithoutIdSchema,
|
|
164
|
-
} from "../../validations/documentation-templates.schema";
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ProcedureFamily } from "../types/static/procedure-family.types";
|
|
3
|
+
import { BlockingCondition } from "../types/static/blocking-condition.types";
|
|
4
|
+
import { TimeUnit, RequirementType } from "../types/requirement.types";
|
|
5
|
+
import {
|
|
6
|
+
CertificationLevel,
|
|
7
|
+
CertificationSpecialty,
|
|
8
|
+
} from "../types/static/certification.types";
|
|
9
|
+
|
|
10
|
+
import { documentTemplateSchema } from "../../validations/documentation-templates.schema";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Zod validation schema for a single dynamic contraindication.
|
|
14
|
+
* @see ContraindicationDynamic in admin-constants.types.ts
|
|
15
|
+
*/
|
|
16
|
+
export const contraindicationDynamicSchema = z.object({
|
|
17
|
+
id: z
|
|
18
|
+
.string()
|
|
19
|
+
.min(1, "Contraindication ID is required")
|
|
20
|
+
.regex(
|
|
21
|
+
/^[a-z0-9_]+$/,
|
|
22
|
+
"ID must be in snake_case (lowercase, numbers, and underscores only)"
|
|
23
|
+
),
|
|
24
|
+
name: z.string().min(1, "Contraindication name is required"),
|
|
25
|
+
description: z.string().optional(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Zod validation schema for a single dynamic treatment benefit.
|
|
30
|
+
* @see TreatmentBenefitDynamic in admin-constants.types.ts
|
|
31
|
+
*/
|
|
32
|
+
export const treatmentBenefitDynamicSchema = z.object({
|
|
33
|
+
id: z
|
|
34
|
+
.string()
|
|
35
|
+
.min(1, "Benefit ID is required")
|
|
36
|
+
.regex(
|
|
37
|
+
/^[a-z0-9_]+$/,
|
|
38
|
+
"ID must be in snake_case (lowercase, numbers, and underscores only)"
|
|
39
|
+
),
|
|
40
|
+
name: z.string().min(1, "Benefit name is required"),
|
|
41
|
+
description: z.string().optional(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Base validation schemas for enums
|
|
46
|
+
*/
|
|
47
|
+
export const blockingConditionSchemaBackoffice =
|
|
48
|
+
z.nativeEnum(BlockingCondition);
|
|
49
|
+
export const contraindicationSchemaBackoffice = contraindicationDynamicSchema;
|
|
50
|
+
export const treatmentBenefitSchemaBackoffice = treatmentBenefitDynamicSchema;
|
|
51
|
+
export const procedureFamilySchemaBackoffice = z.nativeEnum(ProcedureFamily);
|
|
52
|
+
export const timeUnitSchemaBackoffice = z.nativeEnum(TimeUnit);
|
|
53
|
+
export const requirementTypeSchema = z.nativeEnum(RequirementType);
|
|
54
|
+
export const certificationLevelSchema = z.nativeEnum(CertificationLevel);
|
|
55
|
+
export const certificationSpecialtySchema = z.nativeEnum(
|
|
56
|
+
CertificationSpecialty
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Certification requirement validation schema
|
|
61
|
+
*/
|
|
62
|
+
export const certificationRequirementSchema = z.object({
|
|
63
|
+
minimumLevel: certificationLevelSchema,
|
|
64
|
+
requiredSpecialties: z
|
|
65
|
+
.array(certificationSpecialtySchema)
|
|
66
|
+
.max(5, "Maximum 5 specialties allowed")
|
|
67
|
+
.optional(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Timeframe validation schema
|
|
72
|
+
*/
|
|
73
|
+
export const timeframeSchema = z.object({
|
|
74
|
+
duration: z.number().min(1, "Duration must be positive"),
|
|
75
|
+
unit: timeUnitSchemaBackoffice,
|
|
76
|
+
notifyAt: z
|
|
77
|
+
.array(z.number())
|
|
78
|
+
.min(1, "At least one notification point is required"),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Requirement validation schema
|
|
83
|
+
*/
|
|
84
|
+
export const requirementSchema = z.object({
|
|
85
|
+
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
86
|
+
description: z.string().min(1, "Description is required"),
|
|
87
|
+
type: requirementTypeSchema,
|
|
88
|
+
timeframe: timeframeSchema,
|
|
89
|
+
importance: z.enum(["low", "medium", "high"]),
|
|
90
|
+
isActive: z.boolean().default(true),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Technology requirements validation schema
|
|
95
|
+
*/
|
|
96
|
+
export const technologyRequirementsSchema = z.object({
|
|
97
|
+
pre: z.array(requirementSchema),
|
|
98
|
+
post: z.array(requirementSchema),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Technology validation schema
|
|
103
|
+
*/
|
|
104
|
+
export const technologySchema = z.object({
|
|
105
|
+
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
106
|
+
description: z.string().max(1000, "Description is too long").optional(),
|
|
107
|
+
technicalDetails: z
|
|
108
|
+
.string()
|
|
109
|
+
.max(2000, "Technical details are too long")
|
|
110
|
+
.optional(),
|
|
111
|
+
family: procedureFamilySchemaBackoffice,
|
|
112
|
+
categoryId: z.string().min(1, "Category ID is required"),
|
|
113
|
+
subcategoryId: z.string().min(1, "Subcategory ID is required"),
|
|
114
|
+
requirements: technologyRequirementsSchema.default({
|
|
115
|
+
pre: [],
|
|
116
|
+
post: [],
|
|
117
|
+
}),
|
|
118
|
+
blockingConditions: z.array(blockingConditionSchemaBackoffice),
|
|
119
|
+
contraindications: z.array(contraindicationSchemaBackoffice),
|
|
120
|
+
documentationTemplates: z.array(documentTemplateSchema),
|
|
121
|
+
benefits: z.array(treatmentBenefitSchemaBackoffice),
|
|
122
|
+
certificationRequirement: certificationRequirementSchema,
|
|
123
|
+
photoTemplate: z.string().url("Photo template must be a valid URL").optional(),
|
|
124
|
+
isActive: z.boolean().default(true),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Category validation schema
|
|
129
|
+
*/
|
|
130
|
+
export const categorySchema = z.object({
|
|
131
|
+
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
132
|
+
description: z.string().optional(),
|
|
133
|
+
family: procedureFamilySchemaBackoffice,
|
|
134
|
+
isActive: z.boolean().default(true),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Subcategory validation schema
|
|
139
|
+
*/
|
|
140
|
+
export const subcategorySchema = z.object({
|
|
141
|
+
name: z.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
142
|
+
description: z.string().optional(),
|
|
143
|
+
categoryId: z.string().min(1, "Category ID is required"),
|
|
144
|
+
isActive: z.boolean().default(true),
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Partial schemas for updates
|
|
149
|
+
*/
|
|
150
|
+
export const categoryUpdateSchema = categorySchema.partial();
|
|
151
|
+
export const subcategoryUpdateSchema = subcategorySchema.partial();
|
|
152
|
+
export const technologyUpdateSchema = technologySchema.partial();
|
|
153
|
+
export const requirementUpdateSchema = requirementSchema.partial();
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Documentation Templates schemas
|
|
157
|
+
*/
|
|
158
|
+
export {
|
|
159
|
+
createDocumentTemplateSchema,
|
|
160
|
+
updateDocumentTemplateSchema,
|
|
161
|
+
documentTemplateSchema,
|
|
162
|
+
documentElementSchema,
|
|
163
|
+
documentElementWithoutIdSchema,
|
|
164
|
+
} from "../../validations/documentation-templates.schema";
|
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
import { FirebaseApp } from "firebase/app";
|
|
2
|
-
import { Firestore, Timestamp } from "firebase/firestore";
|
|
3
|
-
import { Auth } from "firebase/auth";
|
|
4
|
-
import { Analytics } from "firebase/analytics";
|
|
5
|
-
|
|
6
|
-
interface FirebaseInstance {
|
|
7
|
-
app: FirebaseApp;
|
|
8
|
-
db: Firestore;
|
|
9
|
-
auth: Auth;
|
|
10
|
-
analytics: Analytics | null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let initializationAttempts = 0;
|
|
14
|
-
const MAX_ATTEMPTS = 3;
|
|
15
|
-
const RETRY_DELAY = 1000;
|
|
16
|
-
|
|
17
|
-
export const mockDb = {
|
|
18
|
-
collection: jest.fn((db, collectionPath, ...pathSegments) => {
|
|
19
|
-
const fullPath = [collectionPath, ...pathSegments].join("/");
|
|
20
|
-
return {
|
|
21
|
-
doc: jest.fn().mockReturnValue({
|
|
22
|
-
collection: jest.fn(),
|
|
23
|
-
get: jest.fn().mockResolvedValue({ exists: true, data: () => ({}) }),
|
|
24
|
-
set: jest.fn().mockResolvedValue(undefined),
|
|
25
|
-
update: jest.fn().mockResolvedValue(undefined),
|
|
26
|
-
delete: jest.fn().mockResolvedValue(undefined),
|
|
27
|
-
}),
|
|
28
|
-
where: jest.fn().mockReturnThis(),
|
|
29
|
-
orderBy: jest.fn().mockReturnThis(),
|
|
30
|
-
limit: jest.fn().mockReturnThis(),
|
|
31
|
-
get: jest.fn().mockResolvedValue({
|
|
32
|
-
docs: [],
|
|
33
|
-
forEach: jest.fn(),
|
|
34
|
-
}),
|
|
35
|
-
};
|
|
36
|
-
}),
|
|
37
|
-
doc: jest.fn((db, collectionPath, docPath, ...pathSegments) => {
|
|
38
|
-
const fullPath = [collectionPath, docPath, ...pathSegments].join("/");
|
|
39
|
-
return {
|
|
40
|
-
collection: jest.fn(),
|
|
41
|
-
get: jest.fn().mockResolvedValue({ exists: true, data: () => ({}) }),
|
|
42
|
-
set: jest.fn().mockResolvedValue(undefined),
|
|
43
|
-
update: jest.fn().mockResolvedValue(undefined),
|
|
44
|
-
delete: jest.fn().mockResolvedValue(undefined),
|
|
45
|
-
};
|
|
46
|
-
}),
|
|
47
|
-
} as unknown as Firestore & {
|
|
48
|
-
collection: jest.Mock;
|
|
49
|
-
doc: jest.Mock;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export const mockAuth = {
|
|
53
|
-
currentUser: {
|
|
54
|
-
uid: "test-uid",
|
|
55
|
-
email: "test@example.com",
|
|
56
|
-
isAnonymous: false,
|
|
57
|
-
},
|
|
58
|
-
signInWithEmailAndPassword: jest.fn(),
|
|
59
|
-
createUserWithEmailAndPassword: jest.fn(),
|
|
60
|
-
signOut: jest.fn(),
|
|
61
|
-
} as unknown as Auth;
|
|
62
|
-
|
|
63
|
-
export const mockTimestamp = {
|
|
64
|
-
now: jest.fn().mockReturnValue({
|
|
65
|
-
toDate: jest.fn().mockReturnValue(new Date()),
|
|
66
|
-
}),
|
|
67
|
-
fromDate: jest.fn().mockReturnValue({
|
|
68
|
-
toDate: jest.fn().mockReturnValue(new Date()),
|
|
69
|
-
}),
|
|
70
|
-
} as unknown as typeof Timestamp;
|
|
71
|
-
|
|
72
|
-
export const mockFirebaseInstance: FirebaseInstance = {
|
|
73
|
-
app: {} as FirebaseApp,
|
|
74
|
-
db: mockDb,
|
|
75
|
-
auth: mockAuth,
|
|
76
|
-
analytics: null,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export const getFirebaseInstance = jest.fn().mockImplementation(() => {
|
|
80
|
-
if (initializationAttempts >= MAX_ATTEMPTS) {
|
|
81
|
-
initializationAttempts = 0;
|
|
82
|
-
return Promise.reject(
|
|
83
|
-
new Error("Firebase inicijalizacija nije uspela nakon više pokušaja")
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
initializationAttempts++;
|
|
88
|
-
return Promise.resolve(mockFirebaseInstance);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
export const getFirebaseAuth = jest.fn().mockResolvedValue(mockAuth);
|
|
92
|
-
export const getFirebaseDB = jest.fn().mockResolvedValue(mockDb);
|
|
93
|
-
export const getFirebaseApp = jest.fn().mockResolvedValue({} as FirebaseApp);
|
|
94
|
-
|
|
95
|
-
// Reset mock state before each test
|
|
96
|
-
beforeEach(() => {
|
|
97
|
-
initializationAttempts = 0;
|
|
98
|
-
jest.clearAllMocks();
|
|
99
|
-
});
|
|
1
|
+
import { FirebaseApp } from "firebase/app";
|
|
2
|
+
import { Firestore, Timestamp } from "firebase/firestore";
|
|
3
|
+
import { Auth } from "firebase/auth";
|
|
4
|
+
import { Analytics } from "firebase/analytics";
|
|
5
|
+
|
|
6
|
+
interface FirebaseInstance {
|
|
7
|
+
app: FirebaseApp;
|
|
8
|
+
db: Firestore;
|
|
9
|
+
auth: Auth;
|
|
10
|
+
analytics: Analytics | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let initializationAttempts = 0;
|
|
14
|
+
const MAX_ATTEMPTS = 3;
|
|
15
|
+
const RETRY_DELAY = 1000;
|
|
16
|
+
|
|
17
|
+
export const mockDb = {
|
|
18
|
+
collection: jest.fn((db, collectionPath, ...pathSegments) => {
|
|
19
|
+
const fullPath = [collectionPath, ...pathSegments].join("/");
|
|
20
|
+
return {
|
|
21
|
+
doc: jest.fn().mockReturnValue({
|
|
22
|
+
collection: jest.fn(),
|
|
23
|
+
get: jest.fn().mockResolvedValue({ exists: true, data: () => ({}) }),
|
|
24
|
+
set: jest.fn().mockResolvedValue(undefined),
|
|
25
|
+
update: jest.fn().mockResolvedValue(undefined),
|
|
26
|
+
delete: jest.fn().mockResolvedValue(undefined),
|
|
27
|
+
}),
|
|
28
|
+
where: jest.fn().mockReturnThis(),
|
|
29
|
+
orderBy: jest.fn().mockReturnThis(),
|
|
30
|
+
limit: jest.fn().mockReturnThis(),
|
|
31
|
+
get: jest.fn().mockResolvedValue({
|
|
32
|
+
docs: [],
|
|
33
|
+
forEach: jest.fn(),
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
}),
|
|
37
|
+
doc: jest.fn((db, collectionPath, docPath, ...pathSegments) => {
|
|
38
|
+
const fullPath = [collectionPath, docPath, ...pathSegments].join("/");
|
|
39
|
+
return {
|
|
40
|
+
collection: jest.fn(),
|
|
41
|
+
get: jest.fn().mockResolvedValue({ exists: true, data: () => ({}) }),
|
|
42
|
+
set: jest.fn().mockResolvedValue(undefined),
|
|
43
|
+
update: jest.fn().mockResolvedValue(undefined),
|
|
44
|
+
delete: jest.fn().mockResolvedValue(undefined),
|
|
45
|
+
};
|
|
46
|
+
}),
|
|
47
|
+
} as unknown as Firestore & {
|
|
48
|
+
collection: jest.Mock;
|
|
49
|
+
doc: jest.Mock;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const mockAuth = {
|
|
53
|
+
currentUser: {
|
|
54
|
+
uid: "test-uid",
|
|
55
|
+
email: "test@example.com",
|
|
56
|
+
isAnonymous: false,
|
|
57
|
+
},
|
|
58
|
+
signInWithEmailAndPassword: jest.fn(),
|
|
59
|
+
createUserWithEmailAndPassword: jest.fn(),
|
|
60
|
+
signOut: jest.fn(),
|
|
61
|
+
} as unknown as Auth;
|
|
62
|
+
|
|
63
|
+
export const mockTimestamp = {
|
|
64
|
+
now: jest.fn().mockReturnValue({
|
|
65
|
+
toDate: jest.fn().mockReturnValue(new Date()),
|
|
66
|
+
}),
|
|
67
|
+
fromDate: jest.fn().mockReturnValue({
|
|
68
|
+
toDate: jest.fn().mockReturnValue(new Date()),
|
|
69
|
+
}),
|
|
70
|
+
} as unknown as typeof Timestamp;
|
|
71
|
+
|
|
72
|
+
export const mockFirebaseInstance: FirebaseInstance = {
|
|
73
|
+
app: {} as FirebaseApp,
|
|
74
|
+
db: mockDb,
|
|
75
|
+
auth: mockAuth,
|
|
76
|
+
analytics: null,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const getFirebaseInstance = jest.fn().mockImplementation(() => {
|
|
80
|
+
if (initializationAttempts >= MAX_ATTEMPTS) {
|
|
81
|
+
initializationAttempts = 0;
|
|
82
|
+
return Promise.reject(
|
|
83
|
+
new Error("Firebase inicijalizacija nije uspela nakon više pokušaja")
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
initializationAttempts++;
|
|
88
|
+
return Promise.resolve(mockFirebaseInstance);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export const getFirebaseAuth = jest.fn().mockResolvedValue(mockAuth);
|
|
92
|
+
export const getFirebaseDB = jest.fn().mockResolvedValue(mockDb);
|
|
93
|
+
export const getFirebaseApp = jest.fn().mockResolvedValue({} as FirebaseApp);
|
|
94
|
+
|
|
95
|
+
// Reset mock state before each test
|
|
96
|
+
beforeEach(() => {
|
|
97
|
+
initializationAttempts = 0;
|
|
98
|
+
jest.clearAllMocks();
|
|
99
|
+
});
|