@blackcode_sa/metaestetics-api 1.11.3 → 1.12.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/admin/index.d.mts +329 -318
- package/dist/admin/index.d.ts +329 -318
- package/dist/backoffice/index.d.mts +1166 -430
- package/dist/backoffice/index.d.ts +1166 -430
- package/dist/backoffice/index.js +1128 -245
- package/dist/backoffice/index.mjs +1119 -209
- package/dist/index.d.mts +4428 -4035
- package/dist/index.d.ts +4428 -4035
- package/dist/index.js +1642 -665
- package/dist/index.mjs +1406 -401
- package/package.json +1 -1
- package/src/backoffice/expo-safe/index.ts +3 -0
- package/src/backoffice/services/README.md +40 -0
- package/src/backoffice/services/brand.service.ts +85 -6
- package/src/backoffice/services/category.service.ts +92 -10
- package/src/backoffice/services/constants.service.ts +308 -0
- package/src/backoffice/services/documentation-template.service.ts +56 -2
- package/src/backoffice/services/index.ts +1 -0
- package/src/backoffice/services/product.service.ts +126 -5
- package/src/backoffice/services/requirement.service.ts +13 -0
- package/src/backoffice/services/subcategory.service.ts +184 -13
- package/src/backoffice/services/technology.service.ts +344 -129
- package/src/backoffice/types/admin-constants.types.ts +69 -0
- package/src/backoffice/types/brand.types.ts +1 -0
- package/src/backoffice/types/index.ts +1 -0
- package/src/backoffice/types/product.types.ts +31 -4
- package/src/backoffice/types/static/contraindication.types.ts +1 -0
- package/src/backoffice/types/static/treatment-benefit.types.ts +1 -0
- package/src/backoffice/types/technology.types.ts +113 -4
- package/src/backoffice/validations/schemas.ts +35 -9
- package/src/services/appointment/appointment.service.ts +0 -5
- package/src/services/appointment/utils/appointment.utils.ts +124 -113
- package/src/services/base.service.ts +10 -3
- package/src/services/documentation-templates/documentation-template.service.ts +116 -0
- package/src/services/media/media.service.ts +2 -2
- package/src/services/procedure/procedure.service.ts +436 -234
- package/src/types/appointment/index.ts +2 -3
- package/src/types/clinic/index.ts +1 -6
- package/src/types/patient/medical-info.types.ts +3 -3
- package/src/types/procedure/index.ts +20 -17
- package/src/validations/clinic.schema.ts +1 -6
- package/src/validations/patient/medical-info.schema.ts +7 -2
- package/src/backoffice/services/__tests__/brand.service.test.ts +0 -196
- package/src/backoffice/services/__tests__/category.service.test.ts +0 -201
- package/src/backoffice/services/__tests__/product.service.test.ts +0 -358
- package/src/backoffice/services/__tests__/requirement.service.test.ts +0 -226
- package/src/backoffice/services/__tests__/subcategory.service.test.ts +0 -181
- package/src/backoffice/services/__tests__/technology.service.test.ts +0 -1097
|
@@ -33,7 +33,6 @@ import {
|
|
|
33
33
|
PractitionerProfileInfo,
|
|
34
34
|
} from "../../../types/profile";
|
|
35
35
|
import { BlockingCondition } from "../../../backoffice/types/static/blocking-condition.types";
|
|
36
|
-
import { Contraindication } from "../../../backoffice/types/static/contraindication.types";
|
|
37
36
|
import { Requirement } from "../../../backoffice/types/requirement.types";
|
|
38
37
|
import { PRACTITIONERS_COLLECTION } from "../../../types/practitioner";
|
|
39
38
|
import { CLINICS_COLLECTION } from "../../../types/clinic";
|
|
@@ -43,6 +42,7 @@ import {
|
|
|
43
42
|
Technology,
|
|
44
43
|
TECHNOLOGIES_COLLECTION,
|
|
45
44
|
} from "../../../backoffice/types/technology.types";
|
|
45
|
+
import type { ContraindicationDynamic } from "../../../backoffice";
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Fetches all the necessary information for an appointment by IDs.
|
|
@@ -66,7 +66,7 @@ export async function fetchAggregatedInfoUtil(
|
|
|
66
66
|
patientInfo: PatientProfileInfo;
|
|
67
67
|
procedureInfo: ProcedureSummaryInfo;
|
|
68
68
|
blockingConditions: BlockingCondition[];
|
|
69
|
-
contraindications:
|
|
69
|
+
contraindications: ContraindicationDynamic[];
|
|
70
70
|
preProcedureRequirements: Requirement[];
|
|
71
71
|
postProcedureRequirements: Requirement[];
|
|
72
72
|
}> {
|
|
@@ -162,7 +162,7 @@ export async function fetchAggregatedInfoUtil(
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
let blockingConditions: BlockingCondition[] = [];
|
|
165
|
-
let contraindications:
|
|
165
|
+
let contraindications: ContraindicationDynamic[] = [];
|
|
166
166
|
let preProcedureRequirements: Requirement[] = [];
|
|
167
167
|
let postProcedureRequirements: Requirement[] = [];
|
|
168
168
|
|
|
@@ -213,85 +213,85 @@ export async function fetchAggregatedInfoUtil(
|
|
|
213
213
|
* @param generateId Function to generate a unique ID
|
|
214
214
|
* @returns The created Appointment
|
|
215
215
|
*/
|
|
216
|
-
export async function createAppointmentUtil(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
): Promise<Appointment> {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
216
|
+
// export async function createAppointmentUtil(
|
|
217
|
+
// db: Firestore,
|
|
218
|
+
// data: CreateAppointmentData,
|
|
219
|
+
// aggregatedInfo: {
|
|
220
|
+
// clinicInfo: ClinicInfo;
|
|
221
|
+
// practitionerInfo: PractitionerProfileInfo;
|
|
222
|
+
// patientInfo: PatientProfileInfo;
|
|
223
|
+
// procedureInfo: ProcedureSummaryInfo;
|
|
224
|
+
// blockingConditions: BlockingCondition[];
|
|
225
|
+
// contraindications: ContraindicationDynamic[];
|
|
226
|
+
// preProcedureRequirements: Requirement[];
|
|
227
|
+
// postProcedureRequirements: Requirement[];
|
|
228
|
+
// },
|
|
229
|
+
// generateId: () => string
|
|
230
|
+
// ): Promise<Appointment> {
|
|
231
|
+
// try {
|
|
232
|
+
// const appointmentId = generateId();
|
|
233
|
+
|
|
234
|
+
// // Create appointment object
|
|
235
|
+
// const appointment: Omit<Appointment, "createdAt" | "updatedAt"> & {
|
|
236
|
+
// createdAt: any;
|
|
237
|
+
// updatedAt: any;
|
|
238
|
+
// } = {
|
|
239
|
+
// id: appointmentId,
|
|
240
|
+
// calendarEventId: data.calendarEventId,
|
|
241
|
+
// clinicBranchId: data.clinicBranchId,
|
|
242
|
+
// clinicInfo: aggregatedInfo.clinicInfo,
|
|
243
|
+
// practitionerId: data.practitionerId,
|
|
244
|
+
// practitionerInfo: aggregatedInfo.practitionerInfo,
|
|
245
|
+
// patientId: data.patientId,
|
|
246
|
+
// patientInfo: aggregatedInfo.patientInfo,
|
|
247
|
+
// procedureId: data.procedureId,
|
|
248
|
+
// procedureInfo: aggregatedInfo.procedureInfo,
|
|
249
|
+
// status: data.initialStatus,
|
|
250
|
+
// bookingTime: Timestamp.now(),
|
|
251
|
+
// appointmentStartTime: data.appointmentStartTime,
|
|
252
|
+
// appointmentEndTime: data.appointmentEndTime,
|
|
253
|
+
// patientNotes: data.patientNotes || null,
|
|
254
|
+
// cost: data.cost,
|
|
255
|
+
// currency: data.currency,
|
|
256
|
+
// paymentStatus: data.initialPaymentStatus || PaymentStatus.UNPAID,
|
|
257
|
+
// blockingConditions: aggregatedInfo.blockingConditions,
|
|
258
|
+
// contraindications: aggregatedInfo.contraindications,
|
|
259
|
+
// preProcedureRequirements: aggregatedInfo.preProcedureRequirements,
|
|
260
|
+
// postProcedureRequirements: aggregatedInfo.postProcedureRequirements,
|
|
261
|
+
// completedPreRequirements: [],
|
|
262
|
+
// completedPostRequirements: [],
|
|
263
|
+
// createdAt: serverTimestamp(),
|
|
264
|
+
// updatedAt: serverTimestamp(),
|
|
265
|
+
// };
|
|
266
|
+
|
|
267
|
+
// // Add additional fields for confirmation if appointment is already confirmed
|
|
268
|
+
// if (data.initialStatus === AppointmentStatus.CONFIRMED) {
|
|
269
|
+
// appointment.confirmationTime = Timestamp.now();
|
|
270
|
+
// }
|
|
271
|
+
|
|
272
|
+
// // Save to Firestore
|
|
273
|
+
// await setDoc(doc(db, APPOINTMENTS_COLLECTION, appointmentId), appointment);
|
|
274
|
+
|
|
275
|
+
// // Update the calendar event with the appointment ID
|
|
276
|
+
// const calendarEventRef = doc(db, CALENDAR_COLLECTION, data.calendarEventId);
|
|
277
|
+
// await updateDoc(calendarEventRef, {
|
|
278
|
+
// appointmentId: appointmentId,
|
|
279
|
+
// updatedAt: serverTimestamp(),
|
|
280
|
+
// });
|
|
281
|
+
|
|
282
|
+
// // Return the created appointment
|
|
283
|
+
// // Convert serverTimestamp to regular Timestamp for immediate use
|
|
284
|
+
// const now = Timestamp.now();
|
|
285
|
+
// return {
|
|
286
|
+
// ...appointment,
|
|
287
|
+
// createdAt: now,
|
|
288
|
+
// updatedAt: now,
|
|
289
|
+
// } as Appointment;
|
|
290
|
+
// } catch (error) {
|
|
291
|
+
// console.error("Error creating appointment:", error);
|
|
292
|
+
// throw error;
|
|
293
|
+
// }
|
|
294
|
+
// }
|
|
295
295
|
|
|
296
296
|
/**
|
|
297
297
|
* Updates an existing appointment in Firestore.
|
|
@@ -327,23 +327,27 @@ export async function updateAppointmentUtil(
|
|
|
327
327
|
const validPreReqIds = currentAppointment.preProcedureRequirements.map(
|
|
328
328
|
(req) => req.id
|
|
329
329
|
);
|
|
330
|
-
const invalidPreReqIds = data.completedPreRequirements.filter(
|
|
331
|
-
(id) => !validPreReqIds.includes(id)
|
|
332
|
-
);
|
|
333
330
|
|
|
334
|
-
if
|
|
335
|
-
|
|
336
|
-
|
|
331
|
+
// Only perform validation and merging if the input is an array
|
|
332
|
+
if (Array.isArray(data.completedPreRequirements)) {
|
|
333
|
+
const invalidPreReqIds = data.completedPreRequirements.filter(
|
|
334
|
+
(id) => !validPreReqIds.includes(id)
|
|
337
335
|
);
|
|
338
|
-
}
|
|
339
336
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
337
|
+
if (invalidPreReqIds.length > 0) {
|
|
338
|
+
throw new Error(
|
|
339
|
+
`Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Update the completed pre-requirements
|
|
344
|
+
completedPreRequirements = [
|
|
345
|
+
...new Set([
|
|
346
|
+
...completedPreRequirements,
|
|
347
|
+
...data.completedPreRequirements,
|
|
348
|
+
]),
|
|
349
|
+
];
|
|
350
|
+
}
|
|
347
351
|
}
|
|
348
352
|
|
|
349
353
|
if (data.completedPostRequirements) {
|
|
@@ -351,30 +355,37 @@ export async function updateAppointmentUtil(
|
|
|
351
355
|
const validPostReqIds = currentAppointment.postProcedureRequirements.map(
|
|
352
356
|
(req) => req.id
|
|
353
357
|
);
|
|
354
|
-
const invalidPostReqIds = data.completedPostRequirements.filter(
|
|
355
|
-
(id) => !validPostReqIds.includes(id)
|
|
356
|
-
);
|
|
357
358
|
|
|
358
|
-
if (
|
|
359
|
-
|
|
360
|
-
|
|
359
|
+
if (Array.isArray(data.completedPostRequirements)) {
|
|
360
|
+
const invalidPostReqIds = data.completedPostRequirements.filter(
|
|
361
|
+
(id) => !validPostReqIds.includes(id)
|
|
361
362
|
);
|
|
362
|
-
}
|
|
363
363
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
364
|
+
if (invalidPostReqIds.length > 0) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
`Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Update the completed post-requirements
|
|
371
|
+
completedPostRequirements = [
|
|
372
|
+
...new Set([
|
|
373
|
+
...completedPostRequirements,
|
|
374
|
+
...data.completedPostRequirements,
|
|
375
|
+
]),
|
|
376
|
+
];
|
|
377
|
+
}
|
|
371
378
|
}
|
|
372
379
|
|
|
373
380
|
// Prepare update data
|
|
374
381
|
const updateData: any = {
|
|
375
382
|
...data,
|
|
376
|
-
completedPreRequirements
|
|
377
|
-
|
|
383
|
+
completedPreRequirements: Array.isArray(data.completedPreRequirements)
|
|
384
|
+
? completedPreRequirements
|
|
385
|
+
: data.completedPreRequirements,
|
|
386
|
+
completedPostRequirements: Array.isArray(data.completedPostRequirements)
|
|
387
|
+
? completedPostRequirements
|
|
388
|
+
: data.completedPostRequirements,
|
|
378
389
|
updatedAt: serverTimestamp(),
|
|
379
390
|
};
|
|
380
391
|
|
|
@@ -454,7 +465,7 @@ async function updateCalendarEventStatus(
|
|
|
454
465
|
case AppointmentStatus.CANCELED_CLINIC:
|
|
455
466
|
calendarStatus = "canceled";
|
|
456
467
|
break;
|
|
457
|
-
case AppointmentStatus.
|
|
468
|
+
case AppointmentStatus.RESCHEDULED_BY_CLINIC:
|
|
458
469
|
calendarStatus = "rescheduled";
|
|
459
470
|
break;
|
|
460
471
|
case AppointmentStatus.COMPLETED:
|
|
@@ -7,13 +7,20 @@ export class BaseService {
|
|
|
7
7
|
protected db: Firestore;
|
|
8
8
|
protected auth: Auth;
|
|
9
9
|
protected app: FirebaseApp;
|
|
10
|
-
protected storage
|
|
10
|
+
protected storage!: FirebaseStorage;
|
|
11
11
|
|
|
12
|
-
constructor(
|
|
12
|
+
constructor(
|
|
13
|
+
db: Firestore,
|
|
14
|
+
auth: Auth,
|
|
15
|
+
app: FirebaseApp,
|
|
16
|
+
storage?: FirebaseStorage
|
|
17
|
+
) {
|
|
13
18
|
this.db = db;
|
|
14
19
|
this.auth = auth;
|
|
15
20
|
this.app = app;
|
|
16
|
-
|
|
21
|
+
if (app) {
|
|
22
|
+
this.storage = storage || getStorage(app);
|
|
23
|
+
}
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
/**
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
QueryDocumentSnapshot,
|
|
16
16
|
serverTimestamp,
|
|
17
17
|
Timestamp,
|
|
18
|
+
QueryConstraint,
|
|
18
19
|
} from "firebase/firestore";
|
|
19
20
|
import { BaseService } from "../base.service";
|
|
20
21
|
import {
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
createDocumentTemplateSchema,
|
|
29
30
|
updateDocumentTemplateSchema,
|
|
30
31
|
} from "../../validations/documentation-templates.schema";
|
|
32
|
+
import { getCountFromServer } from "firebase/firestore";
|
|
31
33
|
|
|
32
34
|
/**
|
|
33
35
|
* Service for managing documentation templates
|
|
@@ -38,6 +40,10 @@ export class DocumentationTemplateService extends BaseService {
|
|
|
38
40
|
DOCUMENTATION_TEMPLATES_COLLECTION
|
|
39
41
|
);
|
|
40
42
|
|
|
43
|
+
constructor(...args: ConstructorParameters<typeof BaseService>) {
|
|
44
|
+
super(...args);
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
/**
|
|
42
48
|
* Create a new document template
|
|
43
49
|
* @param data - Template data
|
|
@@ -303,6 +309,116 @@ export class DocumentationTemplateService extends BaseService {
|
|
|
303
309
|
};
|
|
304
310
|
}
|
|
305
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Get all active templates with optional filters and pagination.
|
|
314
|
+
* @param options - Options for filtering and pagination.
|
|
315
|
+
* @returns A promise that resolves to the templates and the last visible document.
|
|
316
|
+
*/
|
|
317
|
+
async getTemplates(options: {
|
|
318
|
+
pageSize?: number;
|
|
319
|
+
lastDoc?: QueryDocumentSnapshot<DocumentTemplate>;
|
|
320
|
+
isUserForm?: boolean;
|
|
321
|
+
isRequired?: boolean;
|
|
322
|
+
sortingOrder?: number;
|
|
323
|
+
}): Promise<{
|
|
324
|
+
templates: DocumentTemplate[];
|
|
325
|
+
lastDoc: QueryDocumentSnapshot<DocumentTemplate> | null;
|
|
326
|
+
}> {
|
|
327
|
+
const {
|
|
328
|
+
pageSize = 20,
|
|
329
|
+
lastDoc,
|
|
330
|
+
isUserForm,
|
|
331
|
+
isRequired,
|
|
332
|
+
sortingOrder,
|
|
333
|
+
} = options;
|
|
334
|
+
const constraints: QueryConstraint[] = [
|
|
335
|
+
where("isActive", "==", true),
|
|
336
|
+
orderBy("sortingOrder", "asc"),
|
|
337
|
+
orderBy("title", "asc"),
|
|
338
|
+
limit(pageSize),
|
|
339
|
+
];
|
|
340
|
+
|
|
341
|
+
if (isUserForm !== undefined) {
|
|
342
|
+
constraints.push(where("isUserForm", "==", isUserForm));
|
|
343
|
+
}
|
|
344
|
+
if (isRequired !== undefined) {
|
|
345
|
+
constraints.push(where("isRequired", "==", isRequired));
|
|
346
|
+
}
|
|
347
|
+
if (sortingOrder !== undefined) {
|
|
348
|
+
constraints.push(where("sortingOrder", "==", sortingOrder));
|
|
349
|
+
}
|
|
350
|
+
if (lastDoc) {
|
|
351
|
+
constraints.push(startAfter(lastDoc));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const q = query(this.collectionRef, ...constraints.filter((c) => c));
|
|
355
|
+
|
|
356
|
+
const querySnapshot = await getDocs(q);
|
|
357
|
+
const templates: DocumentTemplate[] = [];
|
|
358
|
+
let lastVisible: QueryDocumentSnapshot<DocumentTemplate> | null = null;
|
|
359
|
+
|
|
360
|
+
querySnapshot.forEach((doc) => {
|
|
361
|
+
templates.push(doc.data() as DocumentTemplate);
|
|
362
|
+
lastVisible = doc as QueryDocumentSnapshot<DocumentTemplate>;
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
templates,
|
|
367
|
+
lastDoc: lastVisible,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Get the total count of active templates with optional filters.
|
|
373
|
+
* @param options - Options for filtering.
|
|
374
|
+
* @returns A promise that resolves to the total count of templates.
|
|
375
|
+
*/
|
|
376
|
+
async getTemplatesCount(options: {
|
|
377
|
+
isUserForm?: boolean;
|
|
378
|
+
isRequired?: boolean;
|
|
379
|
+
sortingOrder?: number;
|
|
380
|
+
search?: string; // Search will be applied in-memory for now
|
|
381
|
+
}): Promise<number> {
|
|
382
|
+
const { isUserForm, isRequired, sortingOrder } = options;
|
|
383
|
+
const constraints = [where("isActive", "==", true)];
|
|
384
|
+
|
|
385
|
+
if (isUserForm !== undefined) {
|
|
386
|
+
constraints.push(where("isUserForm", "==", isUserForm));
|
|
387
|
+
}
|
|
388
|
+
if (isRequired !== undefined) {
|
|
389
|
+
constraints.push(where("isRequired", "==", isRequired));
|
|
390
|
+
}
|
|
391
|
+
if (sortingOrder !== undefined) {
|
|
392
|
+
constraints.push(where("sortingOrder", "==", sortingOrder));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const q = query(this.collectionRef, ...constraints.filter((c) => c));
|
|
396
|
+
const snapshot = await getCountFromServer(q);
|
|
397
|
+
|
|
398
|
+
return snapshot.data().count;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Get all active templates without pagination for filtering purposes.
|
|
403
|
+
* @returns A promise that resolves to an array of all active templates.
|
|
404
|
+
*/
|
|
405
|
+
async getAllActiveTemplates(): Promise<DocumentTemplate[]> {
|
|
406
|
+
const q = query(
|
|
407
|
+
this.collectionRef,
|
|
408
|
+
where("isActive", "==", true),
|
|
409
|
+
orderBy("title", "asc")
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
const querySnapshot = await getDocs(q);
|
|
413
|
+
const templates: DocumentTemplate[] = [];
|
|
414
|
+
|
|
415
|
+
querySnapshot.forEach((doc) => {
|
|
416
|
+
templates.push(doc.data() as DocumentTemplate);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
return templates;
|
|
420
|
+
}
|
|
421
|
+
|
|
306
422
|
/**
|
|
307
423
|
* Get templates by tags
|
|
308
424
|
* @param tags - Tags to filter by
|
|
@@ -57,8 +57,8 @@ export interface MediaMetadata {
|
|
|
57
57
|
export const MEDIA_METADATA_COLLECTION = "media_metadata";
|
|
58
58
|
|
|
59
59
|
export class MediaService extends BaseService {
|
|
60
|
-
constructor(
|
|
61
|
-
super(
|
|
60
|
+
constructor(...args: ConstructorParameters<typeof BaseService>) {
|
|
61
|
+
super(...args);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/**
|