Skip to content
Snippets Groups Projects
SubstitutionOverview.vue 4.55 KiB
Newer Older
<script setup>
import SubstitutionDay from "./substitutions/SubstitutionDay.vue";
import CRUDIterator from "aleksis.core/components/generic/CRUDIterator.vue";
import DateField from "aleksis.core/components/generic/forms/DateField.vue";
import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue";

import { DateTime } from "luxon";

import {
  amendedLessonsFromAbsences,
  patchAmendLessonsWithAmends,
  groupsByOwner,
} from "./amendLesson.graphql";
</script>

<template>
  <c-r-u-d-iterator
    :gql-query="gqlQuery"
    :gql-additional-query-args="gqlQueryArgs"
    :gql-patch-mutation="gqlPatchMutation"
    :get-patch-data="gqlGetPatchData"
    i18n-key="chronos.substitutions.overview"
    :enable-search="true"
    :enable-create="false"
    :show-create="false"
    :enable-delete="false"
    :enable-edit="true"
Hangzhi Yu's avatar
Hangzhi Yu committed
    :elevated="false"
    :force-model-item-update="true"
    @lastQuery="lastQuery = $event"
    fixed-header
    disable-pagination
    hide-default-footer
    use-deep-search
    <template #additionalActions="{ attrs, on }">
      <v-autocomplete
        :items="groups"
        item-text="name"
        clearable
        return-object
        filled
        dense
        hide-details
        :placeholder="$t('chronos.substitutions.overview.filter.groups')"
        :loading="$apollo.queries.groups.loading"
        :value="currentObj"
        @input="changeSelection"
        @click:clear="changeSelection"
      />
    </template>

    <template #default="{ items }">
      <substitution-day
        v-for="{ date, substitutions, first, last } in groupSubstitutionsByDay(items)"
        v-intersect="{
            handler: intersectHandler(date, first, last),
            options: {
              rootMargin: '-' + topMargin + 'px 0px 0px 0px',
              threshold: [0, 1],
            },
          }"
        :date="date"
        :substitutions="substitutions"
        :lastQuery="lastQuery"
        :focus-on-mount="initDate && (initDate.toMillis() === date.toMillis())"
        @init="transition"
        :key="'day-' + date"
        ref="days"
        />
    </template>
  </c-r-u-d-iterator>
</template>

<script>
  name: "SubstitutionOverview",
  props: {
    objId: {
      type: [Number, String],
      required: false,
      default: null,
    // Next two in ISODate
    dateStart: {
      type: String,
      required: false,
      default: "",
    },
    dateEnd: {
      type: String,
      required: false,
      default: "",
    /**
    * Margin from substitution list to top of viewport in pixels
    */
    topMargin: {
      type: Number,
      required: false,
      default: 165,
    },
  },
  data() {
    return {
      gqlQuery: amendedLessonsFromAbsences,
      gqlPatchMutation: patchAmendLessonsWithAmends,
      lastQuery: null,
      groups: [],
    groupSubstitutionsByDay(substitutions) {
      // => {dt: {date: dt, substitutions: doc ...} ...}
      const substitutionsByDay = substitutions.reduce((byDay, substitution) => {
        const day = DateTime.fromISO(substitution.datetimeStart).startOf("day");
        byDay[day] ??= {date: day, substitutions: []};
        byDay[day].substitutions.push(substitution);
      // => [{date: dt, substitutions: doc ..., idx: idx, lastIdx: last-idx} ...]
      // sorting is necessary since backend can send substitutions unordered
      return Object.keys(substitutionsByDay)
        .map((key, idx, {length}) => {
          const day = substitutionsByDay[key];
          day.first = idx === 0;
          const lastIdx = length - 1;
          day.last = idx === lastIdx;
          return day;
        });
    },
    intersectHandler(date, first, last) {
      console.log("intersect", date, first, last);
    },
    transition() {
      this.initDate = false
      this.ready = true
    gqlGetPatchData(item) {
      return { id: item.id, teachers: item.teachers };
    },
    changeSelection(selection) {
      this.$router.push({
        name: "chronos.substitutionOvervievByTypeAndDate",
        params: {
          objId: selection.id,
          dateStart: this.dateStart,
          dateEnd: this.dateEnd,
        },
      });
    },
  },
  computed: {
    gqlQueryArgs() {
      return {
        objId: this.objId ? Number(this.objId) : null,
        dateStart: this.dateStart,
        dateEnd: this.dateEnd,
      };
    },
    currentObj() {
      return this.groups.find((o) => o.id === this.objId);
    },
  },
  apollo: {
    groups: groupsByOwner,
  },
};