2025-06-30 18:58:24 +02:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
*/
|
2025-06-23 12:48:09 +02:00
|
|
|
import { readSchedule, type ServerUser, writeSchedule } from '~/server/database';
|
2025-06-11 21:05:17 +02:00
|
|
|
import { broadcastEvent } from '~/server/streams';
|
2025-06-24 15:19:11 +02:00
|
|
|
import type { ApiSchedule, ApiTombstone } from '~/shared/types/api';
|
2025-03-07 22:28:55 +01:00
|
|
|
|
2025-06-23 00:17:22 +02:00
|
|
|
export async function updateScheduleInterestedCounts(users: ServerUser[]) {
|
2025-06-11 21:05:17 +02:00
|
|
|
const eventCounts = new Map<number, number>();
|
|
|
|
const eventSlotCounts = new Map<number, number>();
|
2025-06-23 00:17:22 +02:00
|
|
|
for (const user of users) {
|
|
|
|
if (user.deleted)
|
|
|
|
continue;
|
|
|
|
if (user.interestedEventIds)
|
|
|
|
for (const id of user.interestedEventIds)
|
2025-06-11 21:05:17 +02:00
|
|
|
eventCounts.set(id, (eventCounts.get(id) ?? 0) + 1);
|
2025-06-23 00:17:22 +02:00
|
|
|
if (user.interestedEventSlotIds)
|
|
|
|
for (const id of user.interestedEventSlotIds)
|
2025-06-11 21:05:17 +02:00
|
|
|
eventSlotCounts.set(id, (eventSlotCounts.get(id) ?? 0) + 1);
|
|
|
|
}
|
2025-03-07 22:28:55 +01:00
|
|
|
|
|
|
|
const schedule = await readSchedule();
|
2025-06-11 21:05:17 +02:00
|
|
|
if (schedule.deleted) {
|
|
|
|
throw new Error("Deleted schedule not implemented");
|
|
|
|
}
|
|
|
|
const update: ApiSchedule = {
|
|
|
|
id: schedule.id,
|
|
|
|
updatedAt: new Date().toISOString(),
|
|
|
|
events: [],
|
|
|
|
};
|
|
|
|
const updatedFrom = schedule.updatedAt;
|
|
|
|
for (const event of schedule.events ?? []) {
|
|
|
|
let modified = false;
|
|
|
|
if (event.deleted)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
let count = eventCounts.get(event.id);
|
|
|
|
if (count !== event.interested) {
|
|
|
|
event.interested = eventCounts.get(event.id);
|
|
|
|
modified = true;
|
|
|
|
}
|
2025-03-07 22:28:55 +01:00
|
|
|
for (const slot of event.slots) {
|
2025-06-11 21:05:17 +02:00
|
|
|
let slotCount = eventSlotCounts.get(slot.id);
|
|
|
|
if (slotCount !== slot.interested) {
|
|
|
|
slot.interested = slotCount;
|
|
|
|
modified = true;
|
|
|
|
}
|
2025-03-07 22:28:55 +01:00
|
|
|
}
|
2025-06-11 21:05:17 +02:00
|
|
|
if (modified) {
|
|
|
|
event.updatedAt = update.updatedAt;
|
|
|
|
update.events!.push(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!update.events!.length) {
|
|
|
|
return; // No changes
|
2025-03-07 22:28:55 +01:00
|
|
|
}
|
2025-06-11 21:05:17 +02:00
|
|
|
schedule.updatedAt = updatedFrom;
|
2025-03-07 22:28:55 +01:00
|
|
|
await writeSchedule(schedule);
|
2025-06-11 21:05:17 +02:00
|
|
|
await broadcastEvent({
|
|
|
|
type: "schedule-update",
|
|
|
|
updatedFrom,
|
|
|
|
data: update,
|
|
|
|
});
|
2025-03-10 16:26:52 +01:00
|
|
|
}
|
|
|
|
|
2025-06-23 00:17:22 +02:00
|
|
|
export function canSeeAnonymous(userType: string | undefined) {
|
|
|
|
return userType === "admin";
|
|
|
|
}
|
|
|
|
|
|
|
|
export function canSeeCrew(userType: string | undefined) {
|
|
|
|
return userType === "crew" || userType === "admin";
|
2025-03-10 16:26:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Filters out crew visible only parts of schedule */
|
2025-06-24 15:19:11 +02:00
|
|
|
export function filterSchedule(schedule: ApiSchedule | ApiTombstone): ApiSchedule | ApiTombstone {
|
2025-06-11 21:05:17 +02:00
|
|
|
if (schedule.deleted) {
|
|
|
|
return schedule;
|
|
|
|
}
|
2025-03-10 16:26:52 +01:00
|
|
|
return {
|
2025-06-11 21:05:17 +02:00
|
|
|
id: schedule.id,
|
|
|
|
updatedAt: schedule.updatedAt,
|
2025-03-10 16:26:52 +01:00
|
|
|
locations: schedule.locations,
|
2025-06-11 21:05:17 +02:00
|
|
|
events: (schedule.events ?? [])
|
|
|
|
.map(event => (
|
|
|
|
event.deleted
|
|
|
|
? event
|
|
|
|
: event.crew
|
|
|
|
// Pretend crew events are deleted.
|
|
|
|
? { id: event.id, deleted: true, updatedAt: event.updatedAt }
|
|
|
|
: {
|
|
|
|
...event,
|
|
|
|
slots: event.slots.map(slot => ({
|
|
|
|
...slot,
|
|
|
|
assigned: undefined,
|
|
|
|
}
|
|
|
|
)),
|
2025-03-15 18:30:22 +01:00
|
|
|
})),
|
2025-03-10 16:26:52 +01:00
|
|
|
}
|
2025-03-07 22:28:55 +01:00
|
|
|
}
|