2025-03-09 22:21:13 +01:00
|
|
|
<template>
|
2025-06-11 21:05:17 +02:00
|
|
|
<main v-if="schedule.deleted">
|
|
|
|
<h1>Error</h1>
|
|
|
|
<p>
|
|
|
|
Schedule has been deleted.
|
|
|
|
</p>
|
|
|
|
</main>
|
|
|
|
<main v-else>
|
2025-03-09 22:21:13 +01:00
|
|
|
<h1>Edit</h1>
|
2025-03-15 22:47:32 +01:00
|
|
|
<label>
|
|
|
|
Crew Filter:
|
|
|
|
<select
|
|
|
|
v-model="crewFilter"
|
|
|
|
>
|
|
|
|
<option
|
|
|
|
:value="undefined"
|
|
|
|
:selected="crewFilter === undefined"
|
|
|
|
><All Crew></option>
|
|
|
|
<option
|
|
|
|
v-for="account in accounts?.filter(a => a.type === 'crew' || a.type === 'admin')"
|
|
|
|
:key="account.id"
|
|
|
|
:value="String(account.id)"
|
|
|
|
:selected="crewFilter === String(account.id)"
|
|
|
|
>{{ account.name }}</option>
|
|
|
|
</select>
|
|
|
|
</label>
|
2025-03-11 14:12:33 +01:00
|
|
|
<h2>Locations</h2>
|
2025-05-24 20:01:23 +02:00
|
|
|
<LocationsTable :edit="accountStore.canEditPublic" />
|
2025-03-14 18:19:58 +01:00
|
|
|
<h2>Schedule</h2>
|
|
|
|
<label>
|
|
|
|
Location Filter:
|
|
|
|
<select
|
|
|
|
v-model="locationFilter"
|
|
|
|
>
|
|
|
|
<option
|
|
|
|
:value="undefined"
|
|
|
|
:selected="locationFilter === undefined"
|
|
|
|
><All locations></option>
|
|
|
|
<option
|
2025-06-11 21:05:17 +02:00
|
|
|
v-for="location in schedule.locations?.filter(l => !l.deleted)"
|
2025-03-14 18:19:58 +01:00
|
|
|
:key="location.id"
|
|
|
|
:value="location.id"
|
|
|
|
:selected="locationFilter === location.id"
|
|
|
|
>{{ location.name }}</option>
|
|
|
|
</select>
|
|
|
|
</label>
|
2025-03-15 22:47:32 +01:00
|
|
|
<ScheduleTable :edit="true" :location="locationFilter" :eventSlotFilter :shiftSlotFilter />
|
2025-03-15 14:20:38 +01:00
|
|
|
<h2>Events</h2>
|
|
|
|
<EventsTable :edit="true" />
|
2025-03-15 15:10:42 +01:00
|
|
|
<h2>Roles</h2>
|
|
|
|
<RolesTable :edit="true" />
|
2025-03-15 16:45:02 +01:00
|
|
|
<h2>Shift Schedule</h2>
|
|
|
|
<label>
|
|
|
|
Role Filter:
|
|
|
|
<select
|
|
|
|
v-model="roleFilter"
|
|
|
|
>
|
|
|
|
<option
|
|
|
|
:value="undefined"
|
|
|
|
:selected="roleFilter === undefined"
|
|
|
|
><All roles></option>
|
|
|
|
<option
|
2025-06-11 21:05:17 +02:00
|
|
|
v-for="role in schedule.roles?.filter(r => !r.deleted)"
|
2025-03-15 16:45:02 +01:00
|
|
|
:key="role.id"
|
|
|
|
:value="role.id"
|
|
|
|
:selected="roleFilter === role.id"
|
|
|
|
>{{ role.name }}</option>
|
|
|
|
</select>
|
|
|
|
</label>
|
2025-06-11 21:05:17 +02:00
|
|
|
<ShiftScheduleTable :edit="true" :roleId="roleFilter" :eventSlotFilter :shiftSlotFilter />
|
2025-03-15 17:06:23 +01:00
|
|
|
<h2>Shifts</h2>
|
2025-06-11 21:05:17 +02:00
|
|
|
<ShiftsTable :edit="true" :roleId="roleFilter" />
|
2025-03-09 22:21:13 +01:00
|
|
|
</main>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-06-11 21:05:17 +02:00
|
|
|
import type { ApiScheduleEventSlot, ApiScheduleShiftSlot } from '~/shared/types/api';
|
2025-03-14 18:19:58 +01:00
|
|
|
|
2025-03-09 22:21:13 +01:00
|
|
|
definePageMeta({
|
|
|
|
middleware: ["authenticated"],
|
|
|
|
allowedAccountTypes: ["crew", "admin"],
|
2025-03-11 14:12:33 +01:00
|
|
|
});
|
|
|
|
|
2025-03-14 18:19:58 +01:00
|
|
|
const schedule = await useSchedule();
|
2025-03-15 22:47:32 +01:00
|
|
|
const { data: accounts } = await useAccounts();
|
2025-05-24 20:01:23 +02:00
|
|
|
const accountStore = useAccountStore();
|
2025-03-14 18:19:58 +01:00
|
|
|
|
|
|
|
const route = useRoute();
|
2025-03-15 22:47:32 +01:00
|
|
|
const crewFilter = computed({
|
|
|
|
get: () => queryToString(route.query.crew),
|
|
|
|
set: (value: string | undefined) => navigateTo({
|
|
|
|
path: route.path,
|
|
|
|
query: {
|
|
|
|
...route.query,
|
|
|
|
crew: value,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
const eventSlotFilter = computed(() => {
|
2025-05-24 20:01:23 +02:00
|
|
|
if (crewFilter.value === undefined || !accountStore.valid) {
|
2025-03-15 22:47:32 +01:00
|
|
|
return () => true;
|
|
|
|
}
|
|
|
|
const cid = parseInt(crewFilter.value);
|
2025-06-11 21:05:17 +02:00
|
|
|
return (slot: ApiScheduleEventSlot) => slot.assigned?.some(id => id === cid) || false;
|
2025-03-15 22:47:32 +01:00
|
|
|
});
|
|
|
|
const shiftSlotFilter = computed(() => {
|
2025-05-24 20:01:23 +02:00
|
|
|
if (crewFilter.value === undefined || !accountStore.valid) {
|
2025-03-15 22:47:32 +01:00
|
|
|
return () => true;
|
|
|
|
}
|
|
|
|
const cid = parseInt(crewFilter.value);
|
2025-06-11 21:05:17 +02:00
|
|
|
return (slot: ApiScheduleShiftSlot) => slot.assigned?.some(id => id === cid) || false;
|
2025-03-15 22:47:32 +01:00
|
|
|
});
|
|
|
|
|
2025-03-14 18:19:58 +01:00
|
|
|
const locationFilter = computed({
|
2025-06-11 21:05:17 +02:00
|
|
|
get: () => queryToNumber(route.query.location),
|
|
|
|
set: (value: number | undefined) => navigateTo({
|
2025-03-14 18:19:58 +01:00
|
|
|
path: route.path,
|
|
|
|
query: {
|
|
|
|
...route.query,
|
2025-06-11 21:05:17 +02:00
|
|
|
location: value !== undefined ? String(value) : undefined,
|
2025-03-14 18:19:58 +01:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
|
2025-03-15 16:45:02 +01:00
|
|
|
const roleFilter = computed({
|
2025-06-11 21:05:17 +02:00
|
|
|
get: () => queryToNumber(route.query.role),
|
2025-03-15 16:45:02 +01:00
|
|
|
set: (value: string | undefined) => navigateTo({
|
|
|
|
path: route.path,
|
|
|
|
query: {
|
|
|
|
...route.query,
|
|
|
|
role: value,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
});
|
2025-03-09 22:21:13 +01:00
|
|
|
</script>
|