From 242449766dd06189d6757022da3ab53a7be001fe Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Fri, 12 Apr 2024 21:50:41 +0200
Subject: [PATCH] Introduce view for regular timetables

---
 .../components/timetables/GroupTimeTable.vue  |  39 +++++++
 .../components/timetables/Timetable.vue       | 102 ++++++++++++++++++
 aleksis/apps/lesrooster/frontend/index.js     |  36 ++++++-
 .../apps/lesrooster/frontend/messages/en.json |   3 +
 4 files changed, 179 insertions(+), 1 deletion(-)
 create mode 100644 aleksis/apps/lesrooster/frontend/components/timetables/GroupTimeTable.vue
 create mode 100644 aleksis/apps/lesrooster/frontend/components/timetables/Timetable.vue

diff --git a/aleksis/apps/lesrooster/frontend/components/timetables/GroupTimeTable.vue b/aleksis/apps/lesrooster/frontend/components/timetables/GroupTimeTable.vue
new file mode 100644
index 00000000..1705dcb3
--- /dev/null
+++ b/aleksis/apps/lesrooster/frontend/components/timetables/GroupTimeTable.vue
@@ -0,0 +1,39 @@
+<script>
+import { defineComponent } from "vue";
+import { lessonsGroup } from "./timetables.graphql";
+import MiniTimeTable from "./MiniTimeTable.vue";
+
+export default defineComponent({
+  name: "GroupTimeTable",
+  extends: MiniTimeTable,
+  props: {
+    id: {
+      type: String,
+      required: true,
+    },
+  },
+  computed: {
+    lessons() {
+      return this.lessonsGroup;
+    },
+    loading() {
+      return this.$apollo.queries.lessonsGroup.loading;
+    },
+  },
+  apollo: {
+    lessonsGroup: {
+      query: lessonsGroup,
+      variables() {
+        console.log(this.timeGrid, "TIMEGRID");
+        return {
+          timeGrid: this.timeGrid.id,
+          group: this.id,
+        };
+      },
+      skip() {
+        return this.timeGrid === null;
+      },
+    },
+  },
+});
+</script>
diff --git a/aleksis/apps/lesrooster/frontend/components/timetables/Timetable.vue b/aleksis/apps/lesrooster/frontend/components/timetables/Timetable.vue
new file mode 100644
index 00000000..6694e29f
--- /dev/null
+++ b/aleksis/apps/lesrooster/frontend/components/timetables/Timetable.vue
@@ -0,0 +1,102 @@
+<script setup>
+import TimetableWrapper from "aleksis.apps.chronos/components/TimetableWrapper.vue";
+import TimeGridField from "../validity_range/TimeGridField.vue";
+import RoomTimeTable from "./RoomTimeTable.vue";
+import GroupTimeTable from "./GroupTimeTable.vue";
+import TeacherTimeTable from "./TeacherTimeTable.vue";
+</script>
+<script>
+export default {
+  name: "Timetable",
+  data() {
+    return {
+      timeGrid: null,
+      selected: null,
+    };
+  },
+  watch: {
+    timeGrid(newTimeGrid) {
+      this.onSelected(this.selected);
+    },
+  },
+  computed: {
+    timetableAttrs() {
+      return {
+        id: this.$route.params.id,
+        timeGrid: this.timeGrid,
+      };
+    },
+  },
+  methods: {
+    onSelected(selected) {
+      this.selected = selected;
+      if (!selected && this.timeGrid) {
+        this.$router.push({
+          name: "lesrooster.timetableWithTimeGrid",
+          params: { timeGrid: this.timeGrid.id },
+        });
+      } else if (!selected && !this.timeGrid) {
+        this.$router.push({ name: "lesrooster.timetable" });
+      } else if (
+        selected.objId !== this.$route.params.id ||
+        selected.type.toLowerCase() !== this.$route.params.type ||
+        this.timeGrid.id !== this.$route.params.timeGrid
+      ) {
+        this.$router.push({
+          name: "lesrooster.timetableWithId",
+          params: {
+            timeGrid: this.timeGrid.id,
+            type: selected.type.toLowerCase(),
+            id: selected.objId,
+          },
+        });
+      }
+    },
+    setInitialTimeGrid(timeGrids) {
+      if (!this.timeGrid) {
+        this.timeGrid = timeGrids.find(
+          this.$route.params.timeGrid
+            ? (timeGrid) => timeGrid.id === this.$route.params.timeGrid
+            : (timeGrid) => timeGrid.validityRange.isCurrent && !timeGrid.group,
+        );
+      }
+    },
+  },
+};
+</script>
+
+<template>
+  <timetable-wrapper :on-selected="onSelected">
+    <template #additionalSelect="{ selected }">
+      <v-card class="mb-2">
+        <v-card-text>
+          <time-grid-field
+            outlined
+            filled
+            label="Select Validity Range"
+            hide-details
+            with-dates
+            :enable-create="false"
+            v-model="timeGrid"
+            @items="setInitialTimeGrid"
+          >
+          </time-grid-field>
+        </v-card-text>
+      </v-card>
+    </template>
+    <template #default="{ selected }">
+      <group-time-table
+        v-if="$route.params.type === 'group'"
+        v-bind="timetableAttrs"
+      />
+      <teacher-time-table
+        v-else-if="$route.params.type === 'teacher'"
+        v-bind="timetableAttrs"
+      />
+      <room-time-table
+        v-else-if="$route.params.type === 'room'"
+        v-bind="timetableAttrs"
+      />
+    </template>
+  </timetable-wrapper>
+</template>
diff --git a/aleksis/apps/lesrooster/frontend/index.js b/aleksis/apps/lesrooster/frontend/index.js
index e9aa58e8..0484a740 100644
--- a/aleksis/apps/lesrooster/frontend/index.js
+++ b/aleksis/apps/lesrooster/frontend/index.js
@@ -10,6 +10,40 @@ export default {
     permission: "lesrooster.view_lesrooster_menu_rule",
   },
   children: [
+    {
+      path: "timetable/",
+      component: () => import("./components/timetables/Timetable.vue"),
+      name: "lesrooster.timetable",
+      meta: {
+        inMenu: true,
+        titleKey: "lesrooster.timetable.menu_title",
+        toolbarTitle: "lesrooster.timetable.menu_title",
+        icon: "mdi-grid",
+        permission: "chronos.view_timetable_overview_rule",
+        fullWidth: true,
+      },
+      children: [
+        {
+          path: ":timeGrid(\\d+)/",
+          component: () => import("./components/timetables/Timetable.vue"),
+          name: "lesrooster.timetableWithTimeGrid",
+          meta: {
+            permission: "chronos.view_timetable_overview_rule",
+            fullWidth: true,
+          },
+        },
+        {
+          path: ":timeGrid(\\d+)/:type(\\w+)/:id(\\d+)/",
+          component: () => import("./components/timetables/Timetable.vue"),
+          name: "lesrooster.timetableWithId",
+          meta: {
+            permission: "chronos.view_timetable_overview_rule",
+            fullWidth: true,
+          },
+        },
+      ],
+    },
+
     {
       path: "validity_ranges/",
       component: () => import("./components/validity_range/ValidityRange.vue"),
@@ -49,7 +83,7 @@ export default {
       },
     },
     {
-      path: "timetable/",
+      path: "timetable_management/",
       component: () =>
         import("./components/timetable_management/TimetableManagement.vue"),
       name: "lesrooster.timetable_management_select",
diff --git a/aleksis/apps/lesrooster/frontend/messages/en.json b/aleksis/apps/lesrooster/frontend/messages/en.json
index 1789802d..336f8d26 100644
--- a/aleksis/apps/lesrooster/frontend/messages/en.json
+++ b/aleksis/apps/lesrooster/frontend/messages/en.json
@@ -127,6 +127,9 @@
         }
       }
     },
+    "timetable": {
+      "menu_title": "Timetables"
+    },
     "supervision": {
       "menu_title": "Supervisions",
       "title": "Supervision",
-- 
GitLab