@blackcode_sa/metaestetics-api 1.4.17 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +9633 -7023
- package/dist/index.d.ts +9633 -7023
- package/dist/index.js +2773 -150
- package/dist/index.mjs +2809 -150
- package/package.json +4 -3
- package/src/index.ts +48 -1
- package/src/services/calendar/calendar-refactored.service.ts +1531 -0
- package/src/services/calendar/calendar.service.ts +1077 -0
- package/src/services/calendar/synced-calendars.service.ts +743 -0
- package/src/services/calendar/utils/appointment.utils.ts +314 -0
- package/src/services/calendar/utils/calendar-event.utils.ts +510 -0
- package/src/services/calendar/utils/clinic.utils.ts +237 -0
- package/src/services/calendar/utils/docs.utils.ts +157 -0
- package/src/services/calendar/utils/google-calendar.utils.ts +697 -0
- package/src/services/calendar/utils/index.ts +8 -0
- package/src/services/calendar/utils/patient.utils.ts +198 -0
- package/src/services/calendar/utils/practitioner.utils.ts +221 -0
- package/src/services/calendar/utils/synced-calendar.utils.ts +472 -0
- package/src/services/clinic/clinic.service.ts +2 -2
- package/src/services/clinic/utils/clinic.utils.ts +49 -47
- package/src/services/practitioner/practitioner.service.ts +1 -0
- package/src/types/calendar/index.ts +187 -0
- package/src/types/calendar/synced-calendar.types.ts +66 -0
- package/src/types/clinic/index.ts +4 -15
- package/src/types/index.ts +4 -0
- package/src/types/practitioner/index.ts +21 -0
- package/src/types/profile/index.ts +39 -0
- package/src/validations/calendar.schema.ts +223 -0
- package/src/validations/clinic.schema.ts +3 -3
- package/src/validations/practitioner.schema.ts +21 -0
- package/src/validations/profile-info.schema.ts +41 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Firestore,
|
|
3
|
+
collection,
|
|
4
|
+
doc,
|
|
5
|
+
getDoc,
|
|
6
|
+
getDocs,
|
|
7
|
+
setDoc,
|
|
8
|
+
updateDoc,
|
|
9
|
+
deleteDoc,
|
|
10
|
+
query,
|
|
11
|
+
where,
|
|
12
|
+
orderBy,
|
|
13
|
+
Timestamp,
|
|
14
|
+
serverTimestamp,
|
|
15
|
+
} from "firebase/firestore";
|
|
16
|
+
import {
|
|
17
|
+
SyncedCalendar,
|
|
18
|
+
SyncedCalendarProvider,
|
|
19
|
+
CreateSyncedCalendarData,
|
|
20
|
+
UpdateSyncedCalendarData,
|
|
21
|
+
SYNCED_CALENDARS_COLLECTION,
|
|
22
|
+
} from "../../../types/calendar/synced-calendar.types";
|
|
23
|
+
import {
|
|
24
|
+
getPractitionerSyncedCalendarDocRef,
|
|
25
|
+
getPatientSyncedCalendarDocRef,
|
|
26
|
+
getClinicSyncedCalendarDocRef,
|
|
27
|
+
} from "./docs.utils";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a synced calendar for a practitioner
|
|
31
|
+
* @param db - Firestore instance
|
|
32
|
+
* @param practitionerId - ID of the practitioner
|
|
33
|
+
* @param calendarData - Synced calendar data
|
|
34
|
+
* @param generateId - Function to generate a unique ID
|
|
35
|
+
* @returns Created synced calendar
|
|
36
|
+
*/
|
|
37
|
+
export async function createPractitionerSyncedCalendarUtil(
|
|
38
|
+
db: Firestore,
|
|
39
|
+
practitionerId: string,
|
|
40
|
+
calendarData: Omit<
|
|
41
|
+
CreateSyncedCalendarData,
|
|
42
|
+
"id" | "createdAt" | "updatedAt"
|
|
43
|
+
>,
|
|
44
|
+
generateId: () => string
|
|
45
|
+
): Promise<SyncedCalendar> {
|
|
46
|
+
const calendarId = generateId();
|
|
47
|
+
const calendarRef = getPractitionerSyncedCalendarDocRef(
|
|
48
|
+
db,
|
|
49
|
+
practitionerId,
|
|
50
|
+
calendarId
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const newCalendar: CreateSyncedCalendarData = {
|
|
54
|
+
id: calendarId,
|
|
55
|
+
...calendarData,
|
|
56
|
+
createdAt: serverTimestamp(),
|
|
57
|
+
updatedAt: serverTimestamp(),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
await setDoc(calendarRef, newCalendar);
|
|
61
|
+
|
|
62
|
+
// Convert server timestamp to Timestamp for return value
|
|
63
|
+
return {
|
|
64
|
+
...newCalendar,
|
|
65
|
+
createdAt: Timestamp.now(),
|
|
66
|
+
updatedAt: Timestamp.now(),
|
|
67
|
+
} as SyncedCalendar;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a synced calendar for a patient
|
|
72
|
+
* @param db - Firestore instance
|
|
73
|
+
* @param patientId - ID of the patient
|
|
74
|
+
* @param calendarData - Synced calendar data
|
|
75
|
+
* @param generateId - Function to generate a unique ID
|
|
76
|
+
* @returns Created synced calendar
|
|
77
|
+
*/
|
|
78
|
+
export async function createPatientSyncedCalendarUtil(
|
|
79
|
+
db: Firestore,
|
|
80
|
+
patientId: string,
|
|
81
|
+
calendarData: Omit<
|
|
82
|
+
CreateSyncedCalendarData,
|
|
83
|
+
"id" | "createdAt" | "updatedAt"
|
|
84
|
+
>,
|
|
85
|
+
generateId: () => string
|
|
86
|
+
): Promise<SyncedCalendar> {
|
|
87
|
+
const calendarId = generateId();
|
|
88
|
+
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
89
|
+
|
|
90
|
+
const newCalendar: CreateSyncedCalendarData = {
|
|
91
|
+
id: calendarId,
|
|
92
|
+
...calendarData,
|
|
93
|
+
createdAt: serverTimestamp(),
|
|
94
|
+
updatedAt: serverTimestamp(),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
await setDoc(calendarRef, newCalendar);
|
|
98
|
+
|
|
99
|
+
// Convert server timestamp to Timestamp for return value
|
|
100
|
+
return {
|
|
101
|
+
...newCalendar,
|
|
102
|
+
createdAt: Timestamp.now(),
|
|
103
|
+
updatedAt: Timestamp.now(),
|
|
104
|
+
} as SyncedCalendar;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Creates a synced calendar for a clinic
|
|
109
|
+
* @param db - Firestore instance
|
|
110
|
+
* @param clinicId - ID of the clinic
|
|
111
|
+
* @param calendarData - Synced calendar data
|
|
112
|
+
* @param generateId - Function to generate a unique ID
|
|
113
|
+
* @returns Created synced calendar
|
|
114
|
+
*/
|
|
115
|
+
export async function createClinicSyncedCalendarUtil(
|
|
116
|
+
db: Firestore,
|
|
117
|
+
clinicId: string,
|
|
118
|
+
calendarData: Omit<
|
|
119
|
+
CreateSyncedCalendarData,
|
|
120
|
+
"id" | "createdAt" | "updatedAt"
|
|
121
|
+
>,
|
|
122
|
+
generateId: () => string
|
|
123
|
+
): Promise<SyncedCalendar> {
|
|
124
|
+
const calendarId = generateId();
|
|
125
|
+
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
126
|
+
|
|
127
|
+
const newCalendar: CreateSyncedCalendarData = {
|
|
128
|
+
id: calendarId,
|
|
129
|
+
...calendarData,
|
|
130
|
+
createdAt: serverTimestamp(),
|
|
131
|
+
updatedAt: serverTimestamp(),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
await setDoc(calendarRef, newCalendar);
|
|
135
|
+
|
|
136
|
+
// Convert server timestamp to Timestamp for return value
|
|
137
|
+
return {
|
|
138
|
+
...newCalendar,
|
|
139
|
+
createdAt: Timestamp.now(),
|
|
140
|
+
updatedAt: Timestamp.now(),
|
|
141
|
+
} as SyncedCalendar;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Gets a synced calendar for a practitioner
|
|
146
|
+
* @param db - Firestore instance
|
|
147
|
+
* @param practitionerId - ID of the practitioner
|
|
148
|
+
* @param calendarId - ID of the synced calendar
|
|
149
|
+
* @returns Synced calendar or null if not found
|
|
150
|
+
*/
|
|
151
|
+
export async function getPractitionerSyncedCalendarUtil(
|
|
152
|
+
db: Firestore,
|
|
153
|
+
practitionerId: string,
|
|
154
|
+
calendarId: string
|
|
155
|
+
): Promise<SyncedCalendar | null> {
|
|
156
|
+
const calendarRef = getPractitionerSyncedCalendarDocRef(
|
|
157
|
+
db,
|
|
158
|
+
practitionerId,
|
|
159
|
+
calendarId
|
|
160
|
+
);
|
|
161
|
+
const calendarDoc = await getDoc(calendarRef);
|
|
162
|
+
|
|
163
|
+
if (!calendarDoc.exists()) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return calendarDoc.data() as SyncedCalendar;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Gets all synced calendars for a practitioner
|
|
172
|
+
* @param db - Firestore instance
|
|
173
|
+
* @param practitionerId - ID of the practitioner
|
|
174
|
+
* @returns Array of synced calendars
|
|
175
|
+
*/
|
|
176
|
+
export async function getPractitionerSyncedCalendarsUtil(
|
|
177
|
+
db: Firestore,
|
|
178
|
+
practitionerId: string
|
|
179
|
+
): Promise<SyncedCalendar[]> {
|
|
180
|
+
const calendarsRef = collection(
|
|
181
|
+
db,
|
|
182
|
+
`practitioners/${practitionerId}/${SYNCED_CALENDARS_COLLECTION}`
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const q = query(calendarsRef, orderBy("createdAt", "desc"));
|
|
186
|
+
const querySnapshot = await getDocs(q);
|
|
187
|
+
|
|
188
|
+
return querySnapshot.docs.map((doc) => doc.data() as SyncedCalendar);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Gets a synced calendar for a patient
|
|
193
|
+
* @param db - Firestore instance
|
|
194
|
+
* @param patientId - ID of the patient
|
|
195
|
+
* @param calendarId - ID of the synced calendar
|
|
196
|
+
* @returns Synced calendar or null if not found
|
|
197
|
+
*/
|
|
198
|
+
export async function getPatientSyncedCalendarUtil(
|
|
199
|
+
db: Firestore,
|
|
200
|
+
patientId: string,
|
|
201
|
+
calendarId: string
|
|
202
|
+
): Promise<SyncedCalendar | null> {
|
|
203
|
+
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
204
|
+
const calendarDoc = await getDoc(calendarRef);
|
|
205
|
+
|
|
206
|
+
if (!calendarDoc.exists()) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return calendarDoc.data() as SyncedCalendar;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Gets all synced calendars for a patient
|
|
215
|
+
* @param db - Firestore instance
|
|
216
|
+
* @param patientId - ID of the patient
|
|
217
|
+
* @returns Array of synced calendars
|
|
218
|
+
*/
|
|
219
|
+
export async function getPatientSyncedCalendarsUtil(
|
|
220
|
+
db: Firestore,
|
|
221
|
+
patientId: string
|
|
222
|
+
): Promise<SyncedCalendar[]> {
|
|
223
|
+
const calendarsRef = collection(
|
|
224
|
+
db,
|
|
225
|
+
`patients/${patientId}/${SYNCED_CALENDARS_COLLECTION}`
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const q = query(calendarsRef, orderBy("createdAt", "desc"));
|
|
229
|
+
const querySnapshot = await getDocs(q);
|
|
230
|
+
|
|
231
|
+
return querySnapshot.docs.map((doc) => doc.data() as SyncedCalendar);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Gets a synced calendar for a clinic
|
|
236
|
+
* @param db - Firestore instance
|
|
237
|
+
* @param clinicId - ID of the clinic
|
|
238
|
+
* @param calendarId - ID of the synced calendar
|
|
239
|
+
* @returns Synced calendar or null if not found
|
|
240
|
+
*/
|
|
241
|
+
export async function getClinicSyncedCalendarUtil(
|
|
242
|
+
db: Firestore,
|
|
243
|
+
clinicId: string,
|
|
244
|
+
calendarId: string
|
|
245
|
+
): Promise<SyncedCalendar | null> {
|
|
246
|
+
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
247
|
+
const calendarDoc = await getDoc(calendarRef);
|
|
248
|
+
|
|
249
|
+
if (!calendarDoc.exists()) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return calendarDoc.data() as SyncedCalendar;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Gets all synced calendars for a clinic
|
|
258
|
+
* @param db - Firestore instance
|
|
259
|
+
* @param clinicId - ID of the clinic
|
|
260
|
+
* @returns Array of synced calendars
|
|
261
|
+
*/
|
|
262
|
+
export async function getClinicSyncedCalendarsUtil(
|
|
263
|
+
db: Firestore,
|
|
264
|
+
clinicId: string
|
|
265
|
+
): Promise<SyncedCalendar[]> {
|
|
266
|
+
const calendarsRef = collection(
|
|
267
|
+
db,
|
|
268
|
+
`clinics/${clinicId}/${SYNCED_CALENDARS_COLLECTION}`
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
const q = query(calendarsRef, orderBy("createdAt", "desc"));
|
|
272
|
+
const querySnapshot = await getDocs(q);
|
|
273
|
+
|
|
274
|
+
return querySnapshot.docs.map((doc) => doc.data() as SyncedCalendar);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Updates a synced calendar for a practitioner
|
|
279
|
+
* @param db - Firestore instance
|
|
280
|
+
* @param practitionerId - ID of the practitioner
|
|
281
|
+
* @param calendarId - ID of the synced calendar
|
|
282
|
+
* @param updateData - Data to update
|
|
283
|
+
* @returns Updated synced calendar
|
|
284
|
+
*/
|
|
285
|
+
export async function updatePractitionerSyncedCalendarUtil(
|
|
286
|
+
db: Firestore,
|
|
287
|
+
practitionerId: string,
|
|
288
|
+
calendarId: string,
|
|
289
|
+
updateData: Omit<UpdateSyncedCalendarData, "updatedAt">
|
|
290
|
+
): Promise<SyncedCalendar> {
|
|
291
|
+
const calendarRef = getPractitionerSyncedCalendarDocRef(
|
|
292
|
+
db,
|
|
293
|
+
practitionerId,
|
|
294
|
+
calendarId
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
const updates: UpdateSyncedCalendarData = {
|
|
298
|
+
...updateData,
|
|
299
|
+
updatedAt: serverTimestamp(),
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
await updateDoc(calendarRef, updates as any);
|
|
303
|
+
|
|
304
|
+
// Get the updated document
|
|
305
|
+
const updatedDoc = await getDoc(calendarRef);
|
|
306
|
+
|
|
307
|
+
if (!updatedDoc.exists()) {
|
|
308
|
+
throw new Error("Synced calendar not found after update");
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return updatedDoc.data() as SyncedCalendar;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Updates a synced calendar for a patient
|
|
316
|
+
* @param db - Firestore instance
|
|
317
|
+
* @param patientId - ID of the patient
|
|
318
|
+
* @param calendarId - ID of the synced calendar
|
|
319
|
+
* @param updateData - Data to update
|
|
320
|
+
* @returns Updated synced calendar
|
|
321
|
+
*/
|
|
322
|
+
export async function updatePatientSyncedCalendarUtil(
|
|
323
|
+
db: Firestore,
|
|
324
|
+
patientId: string,
|
|
325
|
+
calendarId: string,
|
|
326
|
+
updateData: Omit<UpdateSyncedCalendarData, "updatedAt">
|
|
327
|
+
): Promise<SyncedCalendar> {
|
|
328
|
+
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
329
|
+
|
|
330
|
+
const updates: UpdateSyncedCalendarData = {
|
|
331
|
+
...updateData,
|
|
332
|
+
updatedAt: serverTimestamp(),
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
await updateDoc(calendarRef, updates as any);
|
|
336
|
+
|
|
337
|
+
// Get the updated document
|
|
338
|
+
const updatedDoc = await getDoc(calendarRef);
|
|
339
|
+
|
|
340
|
+
if (!updatedDoc.exists()) {
|
|
341
|
+
throw new Error("Synced calendar not found after update");
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return updatedDoc.data() as SyncedCalendar;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Updates a synced calendar for a clinic
|
|
349
|
+
* @param db - Firestore instance
|
|
350
|
+
* @param clinicId - ID of the clinic
|
|
351
|
+
* @param calendarId - ID of the synced calendar
|
|
352
|
+
* @param updateData - Data to update
|
|
353
|
+
* @returns Updated synced calendar
|
|
354
|
+
*/
|
|
355
|
+
export async function updateClinicSyncedCalendarUtil(
|
|
356
|
+
db: Firestore,
|
|
357
|
+
clinicId: string,
|
|
358
|
+
calendarId: string,
|
|
359
|
+
updateData: Omit<UpdateSyncedCalendarData, "updatedAt">
|
|
360
|
+
): Promise<SyncedCalendar> {
|
|
361
|
+
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
362
|
+
|
|
363
|
+
const updates: UpdateSyncedCalendarData = {
|
|
364
|
+
...updateData,
|
|
365
|
+
updatedAt: serverTimestamp(),
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
await updateDoc(calendarRef, updates as any);
|
|
369
|
+
|
|
370
|
+
// Get the updated document
|
|
371
|
+
const updatedDoc = await getDoc(calendarRef);
|
|
372
|
+
|
|
373
|
+
if (!updatedDoc.exists()) {
|
|
374
|
+
throw new Error("Synced calendar not found after update");
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return updatedDoc.data() as SyncedCalendar;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Deletes a synced calendar for a practitioner
|
|
382
|
+
* @param db - Firestore instance
|
|
383
|
+
* @param practitionerId - ID of the practitioner
|
|
384
|
+
* @param calendarId - ID of the synced calendar
|
|
385
|
+
*/
|
|
386
|
+
export async function deletePractitionerSyncedCalendarUtil(
|
|
387
|
+
db: Firestore,
|
|
388
|
+
practitionerId: string,
|
|
389
|
+
calendarId: string
|
|
390
|
+
): Promise<void> {
|
|
391
|
+
const calendarRef = getPractitionerSyncedCalendarDocRef(
|
|
392
|
+
db,
|
|
393
|
+
practitionerId,
|
|
394
|
+
calendarId
|
|
395
|
+
);
|
|
396
|
+
await deleteDoc(calendarRef);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Deletes a synced calendar for a patient
|
|
401
|
+
* @param db - Firestore instance
|
|
402
|
+
* @param patientId - ID of the patient
|
|
403
|
+
* @param calendarId - ID of the synced calendar
|
|
404
|
+
*/
|
|
405
|
+
export async function deletePatientSyncedCalendarUtil(
|
|
406
|
+
db: Firestore,
|
|
407
|
+
patientId: string,
|
|
408
|
+
calendarId: string
|
|
409
|
+
): Promise<void> {
|
|
410
|
+
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
411
|
+
await deleteDoc(calendarRef);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Deletes a synced calendar for a clinic
|
|
416
|
+
* @param db - Firestore instance
|
|
417
|
+
* @param clinicId - ID of the clinic
|
|
418
|
+
* @param calendarId - ID of the synced calendar
|
|
419
|
+
*/
|
|
420
|
+
export async function deleteClinicSyncedCalendarUtil(
|
|
421
|
+
db: Firestore,
|
|
422
|
+
clinicId: string,
|
|
423
|
+
calendarId: string
|
|
424
|
+
): Promise<void> {
|
|
425
|
+
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
426
|
+
await deleteDoc(calendarRef);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Updates the last synced timestamp for a synced calendar
|
|
431
|
+
* @param db - Firestore instance
|
|
432
|
+
* @param entityType - Type of entity (practitioner, patient, clinic)
|
|
433
|
+
* @param entityId - ID of the entity
|
|
434
|
+
* @param calendarId - ID of the synced calendar
|
|
435
|
+
* @returns Updated synced calendar
|
|
436
|
+
*/
|
|
437
|
+
export async function updateLastSyncedTimestampUtil(
|
|
438
|
+
db: Firestore,
|
|
439
|
+
entityType: "practitioner" | "patient" | "clinic",
|
|
440
|
+
entityId: string,
|
|
441
|
+
calendarId: string
|
|
442
|
+
): Promise<SyncedCalendar> {
|
|
443
|
+
const updateData: Omit<UpdateSyncedCalendarData, "updatedAt"> = {
|
|
444
|
+
lastSyncedAt: Timestamp.now(),
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
switch (entityType) {
|
|
448
|
+
case "practitioner":
|
|
449
|
+
return updatePractitionerSyncedCalendarUtil(
|
|
450
|
+
db,
|
|
451
|
+
entityId,
|
|
452
|
+
calendarId,
|
|
453
|
+
updateData
|
|
454
|
+
);
|
|
455
|
+
case "patient":
|
|
456
|
+
return updatePatientSyncedCalendarUtil(
|
|
457
|
+
db,
|
|
458
|
+
entityId,
|
|
459
|
+
calendarId,
|
|
460
|
+
updateData
|
|
461
|
+
);
|
|
462
|
+
case "clinic":
|
|
463
|
+
return updateClinicSyncedCalendarUtil(
|
|
464
|
+
db,
|
|
465
|
+
entityId,
|
|
466
|
+
calendarId,
|
|
467
|
+
updateData
|
|
468
|
+
);
|
|
469
|
+
default:
|
|
470
|
+
throw new Error(`Invalid entity type: ${entityType}`);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
@@ -267,7 +267,7 @@ export class ClinicService extends BaseService {
|
|
|
267
267
|
contactInfo: setupData.contactInfo,
|
|
268
268
|
workingHours: setupData.workingHours,
|
|
269
269
|
tags: setupData.tags,
|
|
270
|
-
|
|
270
|
+
coverPhoto: setupData.coverPhoto || null,
|
|
271
271
|
photosWithTags: setupData.photosWithTags || [],
|
|
272
272
|
doctors: [],
|
|
273
273
|
services: [],
|
|
@@ -281,7 +281,7 @@ export class ClinicService extends BaseService {
|
|
|
281
281
|
console.log("[CLINIC_SERVICE] Creating clinic branch with data", {
|
|
282
282
|
name: createClinicData.name,
|
|
283
283
|
hasLogo: !!createClinicData.logo,
|
|
284
|
-
|
|
284
|
+
hasCoverPhoto: !!createClinicData.coverPhoto,
|
|
285
285
|
featuredPhotosCount: createClinicData.featuredPhotos?.length || 0,
|
|
286
286
|
photosWithTagsCount: createClinicData.photosWithTags?.length || 0,
|
|
287
287
|
});
|
|
@@ -153,27 +153,27 @@ export async function createClinic(
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
// Handle
|
|
157
|
-
let
|
|
158
|
-
if (validatedData.
|
|
159
|
-
console.log("[CLINIC] Processing
|
|
156
|
+
// Handle cover photo upload
|
|
157
|
+
let processedCoverPhoto: string | null = null;
|
|
158
|
+
if (validatedData.coverPhoto) {
|
|
159
|
+
console.log("[CLINIC] Processing cover photo");
|
|
160
160
|
try {
|
|
161
|
-
|
|
162
|
-
validatedData.
|
|
161
|
+
processedCoverPhoto = await uploadPhoto(
|
|
162
|
+
validatedData.coverPhoto,
|
|
163
163
|
"clinics",
|
|
164
164
|
clinicId,
|
|
165
|
-
"
|
|
165
|
+
"cover",
|
|
166
166
|
app
|
|
167
167
|
);
|
|
168
|
-
console.log("[CLINIC]
|
|
169
|
-
|
|
168
|
+
console.log("[CLINIC] Cover photo processed", {
|
|
169
|
+
coverPhoto: processedCoverPhoto,
|
|
170
170
|
});
|
|
171
|
-
} catch (
|
|
172
|
-
console.error("[CLINIC] Error processing
|
|
173
|
-
// Continue with clinic creation even if
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
171
|
+
} catch (coverPhotoError) {
|
|
172
|
+
console.error("[CLINIC] Error processing cover photo:", coverPhotoError);
|
|
173
|
+
// Continue with clinic creation even if cover photo upload fails
|
|
174
|
+
processedCoverPhoto = validatedData.coverPhoto.startsWith("data:")
|
|
175
|
+
? null
|
|
176
|
+
: validatedData.coverPhoto;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -269,7 +269,7 @@ export async function createClinic(
|
|
|
269
269
|
logo: logoUrl || "",
|
|
270
270
|
tags: validatedData.tags || [],
|
|
271
271
|
featuredPhotos: processedFeaturedPhotos || [],
|
|
272
|
-
|
|
272
|
+
coverPhoto: processedCoverPhoto,
|
|
273
273
|
photosWithTags: processedPhotosWithTags,
|
|
274
274
|
doctors: [],
|
|
275
275
|
doctorsInfo: [],
|
|
@@ -443,9 +443,8 @@ export async function updateClinic(
|
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
// Check if admin is either:
|
|
446
|
-
// 1. The owner of the clinic group, OR
|
|
447
|
-
// 2. Has this clinic in their managed clinics list
|
|
448
|
-
// 3. Is listed in the clinic's admins array
|
|
446
|
+
// 1. The owner of the clinic group that this clinic belongs to, OR
|
|
447
|
+
// 2. Has this clinic in their managed clinics list AND is listed in the clinic's admins array
|
|
449
448
|
const hasPermission =
|
|
450
449
|
(admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId) ||
|
|
451
450
|
(admin.clinicsManaged.includes(clinicId) &&
|
|
@@ -500,42 +499,42 @@ export async function updateClinic(
|
|
|
500
499
|
}
|
|
501
500
|
}
|
|
502
501
|
|
|
503
|
-
// Handle
|
|
504
|
-
if (data.
|
|
505
|
-
console.log("[CLINIC] Processing
|
|
502
|
+
// Handle cover photo update if provided
|
|
503
|
+
if (data.coverPhoto) {
|
|
504
|
+
console.log("[CLINIC] Processing cover photo update");
|
|
506
505
|
try {
|
|
507
|
-
//
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (dataUrlPhotos.length > 0) {
|
|
516
|
-
const uploadedPhotos = await uploadMultiplePhotos(
|
|
517
|
-
dataUrlPhotos,
|
|
506
|
+
// Check if it's a data URL that needs to be uploaded
|
|
507
|
+
if (
|
|
508
|
+
typeof data.coverPhoto === "string" &&
|
|
509
|
+
data.coverPhoto.startsWith("data:")
|
|
510
|
+
) {
|
|
511
|
+
const uploadedPhoto = await uploadPhoto(
|
|
512
|
+
data.coverPhoto,
|
|
518
513
|
"clinics",
|
|
519
514
|
clinicId,
|
|
520
|
-
"
|
|
515
|
+
"cover",
|
|
521
516
|
app
|
|
522
517
|
);
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
//
|
|
528
|
-
updatedData.
|
|
518
|
+
if (uploadedPhoto) {
|
|
519
|
+
updatedData.coverPhoto = uploadedPhoto;
|
|
520
|
+
}
|
|
521
|
+
} else {
|
|
522
|
+
// Keep existing photo URL
|
|
523
|
+
updatedData.coverPhoto = data.coverPhoto;
|
|
529
524
|
}
|
|
530
|
-
|
|
525
|
+
console.log("[CLINIC] Cover photo update processed");
|
|
526
|
+
} catch (photoError) {
|
|
531
527
|
console.error(
|
|
532
|
-
"[CLINIC] Error processing
|
|
533
|
-
|
|
534
|
-
);
|
|
535
|
-
// Continue with update even if photos upload fails
|
|
536
|
-
updatedData.photos = data.photos.filter(
|
|
537
|
-
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
528
|
+
"[CLINIC] Error processing cover photo update:",
|
|
529
|
+
photoError
|
|
538
530
|
);
|
|
531
|
+
// Keep existing photo if upload fails
|
|
532
|
+
if (
|
|
533
|
+
typeof data.coverPhoto === "string" &&
|
|
534
|
+
!data.coverPhoto.startsWith("data:")
|
|
535
|
+
) {
|
|
536
|
+
updatedData.coverPhoto = data.coverPhoto;
|
|
537
|
+
}
|
|
539
538
|
}
|
|
540
539
|
}
|
|
541
540
|
|
|
@@ -565,6 +564,9 @@ export async function updateClinic(
|
|
|
565
564
|
|
|
566
565
|
// Combine existing photos with newly uploaded ones
|
|
567
566
|
updatedData.featuredPhotos = [...existingPhotos, ...uploadedPhotos];
|
|
567
|
+
} else {
|
|
568
|
+
// If no new photos to upload, just use the existing ones
|
|
569
|
+
updatedData.featuredPhotos = existingPhotos;
|
|
568
570
|
}
|
|
569
571
|
} catch (featuredError) {
|
|
570
572
|
console.error(
|
|
@@ -92,6 +92,7 @@ export class PractitionerService extends BaseService {
|
|
|
92
92
|
basicInfo: validatedData.basicInfo,
|
|
93
93
|
certification: validatedData.certification,
|
|
94
94
|
clinics: validatedData.clinics || [],
|
|
95
|
+
clinicWorkingHours: validatedData.clinicWorkingHours || [],
|
|
95
96
|
isActive: validatedData.isActive,
|
|
96
97
|
isVerified: validatedData.isVerified,
|
|
97
98
|
createdAt: serverTimestamp(),
|