Skip to content
Snippets Groups Projects
SubstitutionCard.vue 6.24 KiB
Newer Older
<script setup>
import DeleteButton from "aleksis.core/components/generic/buttons/DeleteButton.vue";
Hangzhi Yu's avatar
Hangzhi Yu committed
import SubstitutionInformation from "./SubstitutionInformation.vue";
import LessonRelatedObjectChip from "../LessonRelatedObjectChip.vue";
import { gqlPersons } from "../amendLesson.graphql";

import createOrPatchMixin from "aleksis.core/mixins/createOrPatchMixin.js";
</script>

<template>
  <v-card class="my-1 full-width" :loading="loading">
    <!-- flex-md-row zeile ab medium -->
    <!-- align-stretch - stretch full-width -->
Hangzhi Yu's avatar
Hangzhi Yu committed
    <v-card-text
      class="full-width main-body pa-2"
      :class="{
Hangzhi Yu's avatar
Hangzhi Yu committed
        vertical: $vuetify.breakpoint.mobile,
Hangzhi Yu's avatar
Hangzhi Yu committed
      }"
Hangzhi Yu's avatar
Hangzhi Yu committed
      <substitution-information :substitution="substitution" />
Hangzhi Yu's avatar
Hangzhi Yu committed
      <v-spacer />

Hangzhi Yu's avatar
Hangzhi Yu committed
      <v-text-field dense outlined hide-details v-model="comment" :label="$t('chronos.substitutions.overview.comment')" @change="saveComment" />

      <v-autocomplete
        v-model="teachers"
        multiple
        chips
        deletable-chips
        dense
        hide-details
        :items="amendableTeachers"
        item-text="fullName"
        item-value="id"
        @input="saveTeachers"
      >
        <template #prepend-inner>
            v-for="teacher in teachersWithStatus.filter(
Hangzhi Yu's avatar
Hangzhi Yu committed
              (t) => t.status === 'removed',
            )"
            outlined
            color="error"
            class="mb-2"
Hangzhi Yu's avatar
Hangzhi Yu committed
            <v-icon left>mdi-account-off-outline</v-icon>
Hangzhi Yu's avatar
Hangzhi Yu committed
            <div class="text-decoration-line-through">
              {{ teacher.fullName }}
            </div>
          </v-chip>
        </template>
        <template #selection="data">
          <v-chip
            v-bind="data.attrs"
            :input-value="data.selected"
            close
            class="mb-2"
            :outlined="getTeacherStatus(data.item) === 'new'"
            :color="getTeacherStatus(data.item) === 'new' ? 'success' : ''"
            @click:close="removeTeacher(data.item)"
          >
            <v-icon left v-if="getTeacherStatus(data.item) === 'new'">
Hangzhi Yu's avatar
Hangzhi Yu committed
              mdi-account-plus-outline
            </v-icon>
            {{ data.item.fullName }}
          </v-chip>
        </template>
      </v-autocomplete>
      <v-chip-group
        v-model="cancelled"
        column
        mandatory
        :disabled="loading"
        class="justify-self-end"
        @change="changeCancel"
      >
        <v-chip
          filter
          outlined
          color="success"
          :value="false"
        >
          {{ $t("chronos.substitutions.overview.cancel.not_cancelled") }}
        </v-chip>
        <v-chip
          filter
          outlined
          color="error"
          :value="true"
        >
          {{ $t("chronos.substitutions.overview.cancel.cancelled") }}
        </v-chip>
      </v-chip-group>
Hangzhi Yu's avatar
Hangzhi Yu committed
    </v-card-text>
  </v-card>
</template>

<script>
export default {
  name: "SubstitutionCard",
  emits: ["open", "close"],
  mixins: [createOrPatchMixin],
  data() {
    return {
      loading: false,
      teachers: [],
Hangzhi Yu's avatar
Hangzhi Yu committed
      comment: "",
      cancelled: false,
      ready: false,
      type: Object,
      required: true,
    },
  },
    handleUpdateAfterCreateOrPatch(itemId) {
      return (cached, incoming) => {
        for (const object of incoming) {
          console.log("summary: handleUpdateAfterCreateOrPatch", object);
          // Replace the current substitution
          const index = cached.findIndex(
            (o) => o[itemId] === this.substitution.id,
          );
          // merged with the incoming partial substitution
          // if creation of proper substitution from dummy one, set ID of substitution currently being edited as oldID so that key in overview doesn't change
          cached[index] = {
            ...this.substitution,
            ...object,
            oldId:
              this.substitution.id !== object.id
                ? this.substitution.id
                : this.substitution.oldId,
          };
        }
        return cached;
      };
    },
    getTeacherStatus(teacher) {
      return this.teachersWithStatus.find((t) => t.id === teacher.id)?.status;
    },
    addTeacher(teacher) {
      this.teachers.push(teacher.id);
      this.saveTeachers();
    removeTeacher(teacher) {
      const index = this.teachers.indexOf(teacher.id);
      if (index >= 0) {
        this.teachers.splice(index, 1);
        this.saveTeachers();
      }
    },
    saveTeachers() {
      this.createOrPatch([
        {
          teachers: this.teachers,
        },
      ]);
Hangzhi Yu's avatar
Hangzhi Yu committed
    saveComment() {
      this.createOrPatch([
        {
          id: this.substitution.id,
          comment: this.comment,
        },
      ]);
    },
    changeCancel() {
      if (this.ready) {
        this.createOrPatch([
          {
            id: this.substitution.id,
            cancelled: this.cancelled,
          },
        ]);
      }
  computed: {
    teachersWithStatus() {
Hangzhi Yu's avatar
Hangzhi Yu committed
      const oldIds = this.substitution.amends.teachers.map(
        (teacher) => teacher.id,
      );
      const newIds = this.substitution.teachers.map((teacher) => teacher.id);
Hangzhi Yu's avatar
Hangzhi Yu committed
      const allTeachers = new Set(
        this.substitution.amends.teachers.concat(this.substitution.teachers),
      );
      let teachersWithStatus = Array.from(allTeachers).map((teacher) => {
        let status = "regular";
        if (newIds.includes(teacher.id) && !oldIds.includes(teacher.id)) {
          status = "new";
        } else if (
          !newIds.includes(teacher.id) &&
          oldIds.includes(teacher.id)
        ) {
          status = "removed";
        }
        return { ...teacher, status: status };
      });
      return teachersWithStatus;
    },
  },
  apollo: {
    amendableTeachers: gqlPersons,
  },
  mounted() {
Hangzhi Yu's avatar
Hangzhi Yu committed
    this.teachers = this.substitution.teachers.map((teacher) => teacher.id);
Hangzhi Yu's avatar
Hangzhi Yu committed
    this.comment = this.substitution.comment;
    this.cancelled = this.substitution.cancelled;
    this.ready = true;
Hangzhi Yu's avatar
Hangzhi Yu committed

<style scoped>
.main-body {
  display: grid;
  align-items: center;
Hangzhi Yu's avatar
Hangzhi Yu committed
  grid-template-columns: 2fr 1fr 2fr 2fr 2fr;
Hangzhi Yu's avatar
Hangzhi Yu committed
  gap: 1em;
}
.vertical {
  grid-template-columns: 1fr;
}
.justify-self-end {
  justify-self: end;
}
Hangzhi Yu's avatar
Hangzhi Yu committed
</style>