diff --git a/components/AssignedCrew.vue b/components/AssignedCrew.vue
new file mode 100644
index 0000000..3d7fc0d
--- /dev/null
+++ b/components/AssignedCrew.vue
@@ -0,0 +1,62 @@
+
+
+
+ {{ account.name }}
+
+ {{ " " }}
+
+
+
+
+
+
+
+
diff --git a/components/ScheduleTable.vue b/components/ScheduleTable.vue
index ed1bae1..256a8e6 100644
--- a/components/ScheduleTable.vue
+++ b/components/ScheduleTable.vue
@@ -10,6 +10,7 @@
event |
s |
location |
+ assigned |
|
@@ -53,6 +54,7 @@
>{{ location.name }}
+ |
Add at
|
+
+
+ |
|
+ |
+ |
|
{{ status(es) }} |
{{ es.location }} |
+ |
@@ -225,6 +237,7 @@ interface EventSlot {
origLocation: string,
name: string,
location: string,
+ assigned: number[],
start: DateTime,
end: DateTime,
}
@@ -332,6 +345,7 @@ function mergeSlot(event: ScheduleEvent, eventSlot: EventSlot): ScheduleEvent {
return {
...s,
locations: [...locations],
+ assigned: eventSlot.assigned.length ? eventSlot.assigned : undefined,
start,
end,
};
@@ -349,6 +363,7 @@ function mergeSlot(event: ScheduleEvent, eventSlot: EventSlot): ScheduleEvent {
slots: [...event.slots, {
id: oldSlot ? oldSlot.id : `${event.id}-${nextId}`,
locations: [eventSlot.location],
+ assigned: eventSlot.assigned.length ? eventSlot.assigned : undefined,
start,
end,
}],
@@ -487,6 +502,7 @@ function editEventSlot(
duration?: string,
name?: string,
location?: string,
+ assigned?: number[],
}
) {
if (edits.start) {
@@ -522,6 +538,12 @@ function editEventSlot(
location: edits.location,
};
}
+ if (edits.assigned !== undefined) {
+ eventSlot = {
+ ...eventSlot,
+ assigned: edits.assigned,
+ };
+ }
const change = { op: "set" as const, data: eventSlot };
changes.value = replaceChange(change, changes.value);
}
@@ -568,6 +590,7 @@ function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) {
name,
origLocation: location,
location,
+ assigned: [],
start,
end,
},
@@ -612,6 +635,7 @@ const eventSlots = computed(() => {
slot,
name: event.name,
location,
+ assigned: slot.assigned ?? [],
origLocation: location,
start: DateTime.fromISO(slot.start, { zone: timezone.value }),
end: DateTime.fromISO(slot.end, { zone: timezone.value }),
diff --git a/components/ShiftScheduleTable.vue b/components/ShiftScheduleTable.vue
index 60cf7b2..90c264e 100644
--- a/components/ShiftScheduleTable.vue
+++ b/components/ShiftScheduleTable.vue
@@ -10,6 +10,7 @@
shift |
s |
role |
+ assigned |
|
@@ -53,6 +54,7 @@
>{{ role.name }}
+ |
Add at
|
+
+
+ |
|
-
+ |
|
{{ status(ss) }} |
{{ ss.role }} |
+ |
@@ -225,6 +235,7 @@ interface ShiftSlot {
origRole: string,
name: string,
role: string,
+ assigned: number[],
start: DateTime,
end: DateTime,
}
@@ -299,6 +310,7 @@ function mergeSlot(shift: Shift, shiftSlot: ShiftSlot): Shift {
})) + 1;
const start = shiftSlot.start.toUTC().toISO({ suppressSeconds: true })!;
const end = shiftSlot.end.toUTC().toISO({ suppressSeconds: true })!;
+ const assigned = shiftSlot.assigned.length ? shiftSlot.assigned : undefined;
if (shift.role !== shiftSlot.role) {
console.warn(`Attempt to add slot id=${shiftSlot.id} role=${shiftSlot.role} to shift id=${shift.id} role=${shift.role}`);
@@ -308,7 +320,7 @@ function mergeSlot(shift: Shift, shiftSlot: ShiftSlot): Shift {
if (oldSlot && oldSlot.id === shiftSlot.id) {
return {
...shift,
- slots: shift.slots.map(s => s.id !== oldSlot.id ? s : { ...s, start, end, }),
+ slots: shift.slots.map(s => s.id !== oldSlot.id ? s : { ...s, assigned, start, end, }),
};
}
@@ -317,6 +329,7 @@ function mergeSlot(shift: Shift, shiftSlot: ShiftSlot): Shift {
...shift,
slots: [...(oldSlot ? shift.slots.filter(s => s.id !== oldSlot.id) : shift.slots), {
id: oldSlot ? oldSlot.id : `${shift.id}-${nextId}`,
+ assigned,
start,
end,
}],
@@ -459,6 +472,7 @@ function editShiftSlot(
duration?: string,
name?: string,
role?: string,
+ assigned?: number[],
}
) {
if (edits.start) {
@@ -505,6 +519,12 @@ function editShiftSlot(
changes.value = changesCopy;
return;
}
+ if (edits.assigned !== undefined) {
+ shiftSlot = {
+ ...shiftSlot,
+ assigned: edits.assigned,
+ };
+ }
const change = { op: "set" as const, data: shiftSlot };
changes.value = replaceChange(change, changes.value);
}
@@ -551,6 +571,7 @@ function newShiftSlot(options: { start?: DateTime, end?: DateTime } = {}) {
name,
origRole: role,
role,
+ assigned: [],
start,
end,
},
@@ -594,6 +615,7 @@ const shiftSlots = computed(() => {
slot,
name: shift.name,
role: shift.role,
+ assigned: slot.assigned ?? [],
origRole: shift.role,
start: DateTime.fromISO(slot.start, { zone: timezone.value }),
end: DateTime.fromISO(slot.end, { zone: timezone.value }),
diff --git a/composables/accounts.ts b/composables/accounts.ts
new file mode 100644
index 0000000..ffc4a55
--- /dev/null
+++ b/composables/accounts.ts
@@ -0,0 +1,9 @@
+export const useAccounts = () => useFetch(
+ "/api/accounts",
+ {
+ transform: (input) => input === undefined ? false as any as null: input,
+ getCachedData(key, nuxtApp) {
+ return nuxtApp.payload.data[key];
+ },
+ }
+);
diff --git a/server/api/accounts/index.get.ts b/server/api/accounts/index.get.ts
new file mode 100644
index 0000000..4713a62
--- /dev/null
+++ b/server/api/accounts/index.get.ts
@@ -0,0 +1,23 @@
+import { readAccounts } from "~/server/database"
+import { requireAccountSession } from "~/server/utils/session";
+
+export default defineEventHandler(async (event) => {
+ const session = await requireAccountSession(event);
+ const accounts = await readAccounts();
+ const account = accounts.find(a => a.id === session.accountId);
+ if (!account) {
+ throw new Error("Account does not exist");
+ }
+
+ if (account.type === "admin") {
+ return accounts;
+ }
+ if (account.type === "crew") {
+ return accounts.filter(a => a.type === "crew" || a.type === "admin");
+ }
+ throw createError({
+ status: 403,
+ statusText: "Forbidden",
+ message: "You do not have permission to list accounts",
+ });
+})
diff --git a/server/utils/schedule.ts b/server/utils/schedule.ts
index cfc78e7..12eed15 100644
--- a/server/utils/schedule.ts
+++ b/server/utils/schedule.ts
@@ -29,6 +29,14 @@ export function canSeeCrew(accountType: string | undefined) {
export function filterSchedule(schedule: Schedule): Schedule {
return {
locations: schedule.locations,
- events: schedule.events.filter(event => !event.crew),
+ events: schedule.events
+ .filter(event => !event.crew)
+ .map(event => ({
+ ...event,
+ slots: event.slots.map(slot => ({
+ ...slot,
+ assigned: undefined,
+ }),
+ }),
}
}
diff --git a/shared/types/schedule.d.ts b/shared/types/schedule.d.ts
index ad8736b..cdad137 100644
--- a/shared/types/schedule.d.ts
+++ b/shared/types/schedule.d.ts
@@ -20,6 +20,7 @@ export interface TimeSlot {
start: string,
end: string,
locations: string[],
+ assigned?: number[],
interested?: number,
}
@@ -41,6 +42,7 @@ export interface ShiftSlot {
id: string,
start: string,
end: string,
+ assigned?: number[],
}
export interface Schedule {