feat(api)!: add calendar pagination and sorting
This commit is contained in:
@ -31,6 +31,13 @@ type ScheduleExceptionPayload = {
|
||||
overrideEndAt?: string | null;
|
||||
};
|
||||
|
||||
type CalendarQueryOptions = {
|
||||
limit?: number;
|
||||
page?: number;
|
||||
order_field?: "startAt" | "endAt" | "title" | "seriesId" | "status";
|
||||
order_direction?: "asc" | "desc";
|
||||
};
|
||||
|
||||
export class ScheduleModel {
|
||||
static async listSeries(filterObj = {}): Promise<SelectQueryBuilder<any>> {
|
||||
const repo = OrmHelper.DB.getRepository(ScheduleSeries);
|
||||
@ -52,7 +59,7 @@ export class ScheduleModel {
|
||||
return query;
|
||||
}
|
||||
|
||||
static async getScheduleCalendarRange(start: string, end: string, filterObj = {}): Promise<any> {
|
||||
static async getScheduleCalendarRange(start: string, end: string, filterObj = {}, options: CalendarQueryOptions = {}): Promise<any> {
|
||||
const startDate = new Date(start);
|
||||
const endDate = new Date(end);
|
||||
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
|
||||
@ -96,8 +103,7 @@ export class ScheduleModel {
|
||||
exceptionMap.set(key, ex);
|
||||
}
|
||||
|
||||
const resourceMap = new Map<string, any>();
|
||||
const events: any[] = [];
|
||||
const allEvents: any[] = [];
|
||||
|
||||
for (const series of seriesList) {
|
||||
const occurrenceDates = ScheduleModel.expandSeriesOccurrences(series, rangeStart, rangeEnd);
|
||||
@ -121,15 +127,7 @@ export class ScheduleModel {
|
||||
const roomName = (room as any)?.room || (room as any)?.name || (room as any)?.code || "";
|
||||
const doctorName = (doctor as any)?.name || (doctor as any)?.fullname || (doctor as any)?.username || "";
|
||||
|
||||
resourceMap.set(resourceId, {
|
||||
id: resourceId,
|
||||
roomId,
|
||||
roomName,
|
||||
doctorId,
|
||||
doctorName,
|
||||
});
|
||||
|
||||
events.push({
|
||||
allEvents.push({
|
||||
id: `occ:${series.id}:${occurrenceYmd}`,
|
||||
seriesId: series.id,
|
||||
resourceId,
|
||||
@ -139,11 +137,52 @@ export class ScheduleModel {
|
||||
isRecurring: !!series.recurrence_rule,
|
||||
isException: !!exception,
|
||||
status: "confirmed",
|
||||
_resource: {
|
||||
id: resourceId,
|
||||
roomId,
|
||||
roomName,
|
||||
doctorId,
|
||||
doctorName,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { resources: [...resourceMap.values()], events };
|
||||
const orderField = options.order_field || "startAt";
|
||||
const orderDirection = (options.order_direction || "asc").toUpperCase() as "ASC" | "DESC";
|
||||
const sortFactor = orderDirection === "ASC" ? 1 : -1;
|
||||
|
||||
allEvents.sort((a, b) => {
|
||||
const av = a[orderField];
|
||||
const bv = b[orderField];
|
||||
if (av === bv) return 0;
|
||||
return av > bv ? sortFactor : -sortFactor;
|
||||
});
|
||||
|
||||
const totalCount = allEvents.length;
|
||||
const page = options.page ?? 1;
|
||||
const limit = options.limit ?? totalCount;
|
||||
const offset = (page - 1) * limit;
|
||||
const pagedEventsRaw = allEvents.slice(offset, offset + limit);
|
||||
|
||||
const resourceMap = new Map<string, any>();
|
||||
const pagedEvents = pagedEventsRaw.map((event) => {
|
||||
resourceMap.set(event._resource.id, event._resource);
|
||||
const { _resource, ...cleanEvent } = event;
|
||||
return cleanEvent;
|
||||
});
|
||||
|
||||
return {
|
||||
resources: [...resourceMap.values()],
|
||||
events: pagedEvents,
|
||||
meta: {
|
||||
total_count: totalCount,
|
||||
page,
|
||||
limit,
|
||||
order_field: orderField,
|
||||
order_direction: orderDirection,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static async getScheduleOptions(filterObj = {}): Promise<any> {
|
||||
|
||||
Reference in New Issue
Block a user