flaschengeist-schedule/src/components/overview/slots/JobSlot.vue

166 lines
4.6 KiB
Vue

<template>
<q-card bordered>
<div class="text-weight-medium q-px-xs">
{{ asHour(modelValue.start) }}
<template v-if="modelValue.end">- {{ asHour(modelValue.end) }}</template>
</div>
<div class="q-px-xs">
{{ typeName }}
</div>
<div class="col-auto q-px-xs" style="font-size: 10px">
{{ modelValue.comment }}
</div>
<div>
<q-select
:model-value="modelValue.services"
filled
:option-label="(opt) => userDisplay(opt)"
multiple
disable
use-chips
stack-label
label="Dienste"
class="col-auto q-px-xs"
style="font-size: 6px"
counter
:max-values="modelValue.required_services"
>
</q-select>
<div class="row col-12 justify-end">
<q-btn
v-if="!modelValue.locked && !isEnrolled && !isFull"
flat
color="primary"
label="Eintragen"
@click="assignJob()"
/>
<q-btn v-if="isEnrolled && !modelValue.locked" flat color="secondary" label="Optionen">
<q-menu auto-close>
<q-list style="min-width: 100px">
<q-item v-if="!isFull && canInvite" clickable @click="invite">
<q-item-section>Einladen</q-item-section>
</q-item>
<q-item clickable @click="transfer">
<q-item-section>Tauschen</q-item-section>
</q-item>
<q-separator />
<q-item clickable @click="assignJob(false)">
<q-item-section class="text-negative">Austragen</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</div>
</q-card>
</template>
<script lang="ts">
import { defineComponent, onBeforeMount, computed, PropType } from 'vue';
import { date, useQuasar } from 'quasar';
import { asHour, useMainStore, useUserStore } from '@flaschengeist/api';
import { useEventStore } from '../../../store';
import TransferInviteDialog from './TransferInviteDialog.vue';
export default defineComponent({
name: 'JobSlot',
props: {
modelValue: {
required: true,
type: Object as PropType<FG.Job>,
},
eventId: {
required: true,
type: Number,
},
},
emits: { 'update:modelValue': (v: FG.Job) => !!v },
setup(props, { emit }) {
const store = useEventStore();
const mainStore = useMainStore();
const userStore = useUserStore();
const quasar = useQuasar();
onBeforeMount(async () => userStore.getUsers());
function userDisplay(service: FG.Service) {
return userStore.findUser(service.userid)?.display_name || service.userid;
}
const typeName = computed(() =>
typeof props.modelValue.type === 'object'
? props.modelValue.type.name
: store.jobTypes.find((j) => j.id === props.modelValue.type)?.name || 'Unbekannter Diensttyp'
);
const isEnrolled = computed(
() =>
props.modelValue.services.findIndex(
(service) => service.userid == mainStore.currentUser.userid
) !== -1
);
const isFull = computed(
() =>
props.modelValue.services.map((s) => s.value).reduce((p, c) => p + c, 0) >=
props.modelValue.required_services
);
const canInvite = computed(
() =>
(props.modelValue.end || props.modelValue.start) >
date.subtractFromDate(
date.buildDate({ hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }),
{ days: 1 }
)
);
async function assignJob(assign = true) {
const newService: FG.Service = {
userid: mainStore.currentUser.userid,
is_backup: false,
value: assign ? 1 : -1,
};
try {
const job = await store.assignToJob(props.modelValue.id, newService);
emit('update:modelValue', job);
} catch (error) {
console.warn(error);
quasar.notify({
group: false,
type: 'negative',
message: 'Fehler beim Ein- oder Austragen als Dienst',
timeout: 10000,
progress: true,
actions: [{ icon: 'mdi-close', color: 'white' }],
});
}
}
function invite(isInvite = true) {
quasar.dialog({
component: TransferInviteDialog,
componentProps: {
isInvite: isInvite,
job: props.modelValue,
},
});
}
return {
assignJob,
canInvite,
isEnrolled,
isFull,
invite: () => invite(true),
transfer: () => invite(false),
typeName,
userDisplay,
asHour,
};
},
});
</script>
<style scoped></style>