ManageStudentsDialog.vue 6.48 KiB
<script>
import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue";
import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue";
import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue";
import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.vue";
import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue";
import mutateMixin from "aleksis.core/mixins/mutateMixin.js";
import documentationPartMixin from "../documentation/documentationPartMixin";
import LessonInformation from "../documentation/LessonInformation.vue";
import { updateParticipationStatuses } from "./participationStatus.graphql";
import SlideIterator from "aleksis.core/components/generic/SlideIterator.vue";
export default {
name: "ManageStudentsDialog",
extends: MobileFullscreenDialog,
components: {
AbsenceReasonChip,
AbsenceReasonGroupSelect,
AbsenceReasonButtons,
CancelButton,
LessonInformation,
MobileFullscreenDialog,
SlideIterator,
},
mixins: [documentationPartMixin, mutateMixin],
data() {
return {
dialog: false,
search: "",
loadSelected: false,
selected: [],
isExpanded: false,
};
},
props: {
loadingIndicator: {
type: Boolean,
default: false,
required: false,
},
},
computed: {
items() {
return this.documentation.participations;
},
},
methods: {
sendToServer(participations, field, value) {
if (field !== "absenceReason") return;
this.mutate(
updateParticipationStatuses,
{
input: participations.map((participation) => ({
id: participation.id,
absenceReason: value === "present" ? null : value,
})),
},
(storedDocumentations, incomingStatuses) => {
const documentation = storedDocumentations.find(
(doc) => doc.id === this.documentation.id,
);
incomingStatuses.forEach((newStatus) => {
const participationStatus = documentation.participations.find(
(part) => part.id === newStatus.id,
);
participationStatus.absenceReason = newStatus.absenceReason;
participationStatus.isOptimistic = newStatus.isOptimistic;
});
return storedDocumentations;
},
// {
// optimisticResponse: {
// updateParticipationStatuses: {
// items: [
// {
// id: participation.id,
// isOptimistic: true,
// relatedDocumentation: {
// id: this.documentation.id,
// __typename: "DocumentationType",
// },
// absenceReason: value === "present" ? null : {
// id: value,
// name: "",
// shortName: "",
// __typename: "AbsenceReasonType",
// },
// __typename: "ParticipationStatusType",
// },
// ],
// __typename: "ParticipationStatusBatchPatchMutation",
// },
// },
// },
);
},
handleMultipleAction(absenceReasonId) {
this.loadSelected = true;
this.sendToServer(this.selected, "absenceReason", absenceReasonId);
this.$once("save", this.resetMultipleAction);
},
resetMultipleAction() {
this.loadSelected = false;
this.$set(this.selected, []);
this.$refs.iterator.selected = [];
},
},
};
</script>
<template>
<mobile-fullscreen-dialog
scrollable
v-bind="$attrs"
v-on="$listeners"
v-model="dialog"
>
<template #activator="activator">
<slot name="activator" v-bind="activator" />
</template>
<template #title>
<lesson-information v-bind="documentationPartProps" />
<v-scroll-x-transition leave-absolute>
<v-text-field
v-show="!isExpanded"
type="search"
v-model="search"
clearable
rounded
hide-details
single-line
prepend-inner-icon="$search"
dense
outlined
:placeholder="$t('actions.search')"
class="pt-4 full-width"
/>
</v-scroll-x-transition>
<v-scroll-x-transition>
<div v-show="selected.length > 0" class="full-width mt-4">
<absence-reason-buttons
allow-empty
empty-value="present"
@input="handleMultipleAction"
/>
</div>
</v-scroll-x-transition>
</template>
<template #content>
<slide-iterator
ref="iterator"
v-model="selected"
:items="items"
:search="search"
:item-key-getter="
(item) => 'documentation-' + documentation.id + '-student-' + item.id
"
:is-expanded.sync="isExpanded"
:loading="loadingIndicator || loadSelected"
:load-only-selected="loadSelected"
:disabled="loading"
>
<template #listItemContent="{ item }">
<v-list-item-title>
{{ item.person.fullName }}
</v-list-item-title>
<v-list-item-subtitle v-if="item.absenceReason">
<absence-reason-chip small :absence-reason="item.absenceReason" />
</v-list-item-subtitle>
</template>
<template #expandedItem="{ item, close }">
<v-card-title>
<v-tooltip bottom>
<template #activator="{ on, attrs }">
<v-btn v-bind="attrs" v-on="on" icon @click="close">
<v-icon>$prev</v-icon>
</v-btn>
</template>
<span v-t="'actions.back_to_overview'" />
</v-tooltip>
{{ item.person.fullName }}
</v-card-title>
<v-card-text>
<absence-reason-group-select
allow-empty
empty-value="present"
:loadSelectedChip="loading"
:value="item.absenceReason?.id || 'present'"
@input="sendToServer([item], 'absenceReason', $event)"
/>
</v-card-text>
</template>
</slide-iterator>
</template>
<template #actions>
<cancel-button
@click="dialog = false"
i18n-key="actions.close"
v-show="$vuetify.breakpoint.mobile"
/>
</template>
</mobile-fullscreen-dialog>
</template>
<style scoped></style>