Use a single mutable location, event, slot, etc, for each unique resource that keeps track of the local editable client copy and the server copy of the data contained in it. This makes it much simpler to update these data structures as I can take advantage of the v-model bindings in Vue.js and work with the system instead of against it.
175 lines
3.7 KiB
Vue
175 lines
3.7 KiB
Vue
<template>
|
|
<div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>id</th>
|
|
<th>name</th>
|
|
<th>description</th>
|
|
<th>p</th>
|
|
<th>s</th>
|
|
<th v-if="edit"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<template v-if="edit">
|
|
<tr
|
|
v-for="event in schedule.events.values()"
|
|
:key="event.id"
|
|
:class="{ removed: event.deleted }"
|
|
>
|
|
<td>{{ event.id }}</td>
|
|
<td>
|
|
<input
|
|
type="text"
|
|
:disabled="!canEdit(event)"
|
|
v-model="event.name"
|
|
>
|
|
</td>
|
|
<td>
|
|
<input
|
|
type="text"
|
|
:disabled="!canEdit(event)"
|
|
v-model="event.description"
|
|
>
|
|
</td>
|
|
<td>
|
|
<input
|
|
type="checkbox"
|
|
:disabled="!accountStore.canEditPublic"
|
|
:value="!event.crew"
|
|
:checked="!event.crew"
|
|
@change="event.crew = !($event.target as HTMLInputElement).value"
|
|
>
|
|
</td>
|
|
<td>{{ event.slots.size ? event.slots.size : "" }}</td>
|
|
<td>
|
|
<button
|
|
type="button"
|
|
:disabled="!canEdit(event) || event.deleted"
|
|
@click="event.deleted = true"
|
|
>Delete</button>
|
|
<button
|
|
v-if="event.isModified()"
|
|
type="button"
|
|
@click="schedule.events.discardId(event.id)"
|
|
>Revert</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>{{ schedule.nextClientId }}</td>
|
|
<td>
|
|
<input
|
|
type="text"
|
|
v-model="newEventName"
|
|
>
|
|
</td>
|
|
<td>
|
|
<input
|
|
type="text"
|
|
v-model="newEventDescription"
|
|
>
|
|
</td>
|
|
<td>
|
|
<input
|
|
type="checkbox"
|
|
:disabled="!accountStore.canEditPublic"
|
|
v-model="newEventPublic"
|
|
>
|
|
</td>
|
|
<td></td>
|
|
<td>
|
|
<button
|
|
v-if="eventExists(newEventName)"
|
|
disabled
|
|
>Event already exists</button>
|
|
<button
|
|
v-else
|
|
type="button"
|
|
@click="newEvent"
|
|
>Add Event</button>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
<template v-else>
|
|
<tr
|
|
v-for="event in schedule.events.values()"
|
|
:key="event.id"
|
|
>
|
|
<td>{{ event.id }}</td>
|
|
<td>{{ event.name }}</td>
|
|
<td>{{ event.description }}</td>
|
|
<td>{{ event.crew ? "" : "Yes"}}</td>
|
|
<td>{{ event.slots.size ? event.slots.size : "" }}</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { Info } from '~/shared/utils/luxon';
|
|
import { toId } from '~/shared/utils/functions';
|
|
|
|
defineProps<{
|
|
edit?: boolean,
|
|
}>();
|
|
|
|
const schedule = await useSchedule();
|
|
const accountStore = useAccountStore();
|
|
|
|
function canEdit(event: ClientScheduleEvent) {
|
|
return event.crew || accountStore.canEditPublic;
|
|
}
|
|
|
|
const newEventName = ref("");
|
|
const newEventDescription = ref("");
|
|
const newEventPublic = ref(false);
|
|
function eventExists(name: string) {
|
|
name = toId(name);
|
|
return (
|
|
[...schedule.value.events.values()].some(e => !e.deleted && toId(e.name) === name)
|
|
);
|
|
}
|
|
function newEvent() {
|
|
if (eventExists(newEventName.value)) {
|
|
alert(`Event ${newEventName.value} already exists`);
|
|
return;
|
|
}
|
|
const zone = Info.normalizeZone(accountStore.activeTimezone);
|
|
const locale = accountStore.activeLocale;
|
|
const event = ClientScheduleEvent.create(
|
|
schedule.value,
|
|
schedule.value.nextClientId--,
|
|
newEventName.value,
|
|
!newEventPublic.value,
|
|
"",
|
|
false,
|
|
newEventDescription.value,
|
|
0,
|
|
new Set(),
|
|
{ zone, locale },
|
|
);
|
|
schedule.value.events.add(event);
|
|
newEventName.value = "";
|
|
newEventDescription.value = "";
|
|
newEventPublic.value = false;
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
table {
|
|
border-spacing: 0;
|
|
}
|
|
table th {
|
|
text-align: left;
|
|
border-bottom: 1px solid var(--foreground);
|
|
}
|
|
table :is(th, td) + :is(th, td) {
|
|
padding-inline-start: 0.4em;
|
|
}
|
|
.removed :is(td, input) {
|
|
text-decoration: line-through;
|
|
}
|
|
</style>
|