From 93fd66a95d41a3107dd82d41314d5d3b18dbecd3 Mon Sep 17 00:00:00 2001
From: magicfelix <felix@felix-zauberer.de>
Date: Fri, 18 Aug 2023 00:47:03 +0200
Subject: [PATCH] Add list frontends for absence and reason

---
 .../frontend/components/AbsenceReasons.vue    |  58 +++++++
 .../kolego/frontend/components/Absences.vue   | 153 ++++++++++++++++++
 .../components/absenceReasons.graphql         |  39 +++++
 .../frontend/components/absences.graphql      |  63 ++++++++
 .../frontend/components/persons.graphql       |   6 +
 aleksis/apps/kolego/frontend/index.js         |  19 ++-
 aleksis/apps/kolego/frontend/messages/de.json |  19 +++
 aleksis/apps/kolego/frontend/messages/en.json |  16 +-
 8 files changed, 368 insertions(+), 5 deletions(-)
 create mode 100644 aleksis/apps/kolego/frontend/components/AbsenceReasons.vue
 create mode 100644 aleksis/apps/kolego/frontend/components/Absences.vue
 create mode 100644 aleksis/apps/kolego/frontend/components/absenceReasons.graphql
 create mode 100644 aleksis/apps/kolego/frontend/components/absences.graphql
 create mode 100644 aleksis/apps/kolego/frontend/components/persons.graphql
 create mode 100644 aleksis/apps/kolego/frontend/messages/de.json

diff --git a/aleksis/apps/kolego/frontend/components/AbsenceReasons.vue b/aleksis/apps/kolego/frontend/components/AbsenceReasons.vue
new file mode 100644
index 0000000..2a44295
--- /dev/null
+++ b/aleksis/apps/kolego/frontend/components/AbsenceReasons.vue
@@ -0,0 +1,58 @@
+<script setup>
+import InlineCRUDList from "aleksis.core/components/generic/InlineCRUDList.vue";
+</script>
+
+<template>
+  <v-container>
+  <inline-c-r-u-d-list
+    :headers="headers"
+    :i18n-key="i18nKey"
+    create-item-i18n-key="kolego.absence_reason.create"
+    :gql-query="gqlQuery"
+    :gql-create-mutation="gqlCreateMutation"
+    :gql-patch-mutation="gqlPatchMutation"
+    :gql-delete-mutation="gqlDeleteMutation"
+    :default-item="defaultItem"
+  >
+  </inline-c-r-u-d-list>
+  </v-container>
+</template>
+
+<script>
+import {
+  gqlAbsenceReasons,
+  createAbsenceReason,
+  deleteAbsenceReason,
+  updateAbsenceReasons,
+} from "./absenceReasons.graphql";
+
+export default {
+  name: "AbsenceReasons",
+  data() {
+    return {
+      headers: [
+        {
+          text: this.$t("kolego.absence_reason.short_name"),
+          value: "shortName",
+        },
+        {
+          text: this.$t("kolego.absence_reason.name"),
+          value: "name",
+        },
+      ],
+      i18nKey: "kolego.absence_reason",
+      gqlQuery: gqlAbsenceReasons,
+      gqlCreateMutation: createAbsenceReason,
+      gqlPatchMutation: updateAbsenceReasons,
+      gqlDeleteMutation: deleteAbsenceReason,
+      defaultItem: {
+        shortName: "",
+        name: "",
+      },
+      required: [(value) => !!value || this.$t("forms.errors.required")],
+    };
+  },
+};
+</script>
+
+<style scoped></style>
diff --git a/aleksis/apps/kolego/frontend/components/Absences.vue b/aleksis/apps/kolego/frontend/components/Absences.vue
new file mode 100644
index 0000000..bec3233
--- /dev/null
+++ b/aleksis/apps/kolego/frontend/components/Absences.vue
@@ -0,0 +1,153 @@
+<script setup>
+import InlineCRUDList from "aleksis.core/components/generic/InlineCRUDList.vue";
+import DateTimeField from "aleksis.core/components/generic/forms/DateTimeField.vue";
+</script>
+
+<template>
+  <v-container>
+  <inline-c-r-u-d-list
+    :headers="headers"
+    :i18n-key="i18nKey"
+    create-item-i18n-key="kolego.absence.create"
+    :gql-query="gqlQuery"
+    :gql-create-mutation="gqlCreateMutation"
+    :gql-patch-mutation="gqlPatchMutation"
+    :gql-delete-mutation="gqlDeleteMutation"
+    :default-item="defaultItem"
+  >
+    <template #datetimeStart="{ item }">
+      {{ $d(new Date(item.datetimeStart), "short") }}
+    </template>
+    <!-- eslint-disable-next-line vue/valid-v-slot -->
+    <template #datetimeStart.field="{ attrs, on, item }">
+      <div aria-required="true">
+        <date-time-field
+          v-bind="attrs"
+          v-on="on"
+          :rules="required"
+          :max="item ? item.datetimeEnd : undefined"
+          required
+        ></date-time-field>
+      </div>
+    </template>
+
+    <template #datetimeEnd="{ item }">
+      {{ $d(new Date(item.datetimeEnd), "short") }}
+    </template>
+    <!-- eslint-disable-next-line vue/valid-v-slot -->
+    <template #datetimeEnd.field="{ attrs, on, item }">
+      <div aria-required="true">
+        <date-time-field
+          v-bind="attrs"
+          v-on="on"
+          required
+          :rules="required"
+          :min="item ? item.datetimeStart : undefined"
+        ></date-time-field>
+      </div>
+    </template>
+
+    <template #person="{ item }">
+      <v-chip>{{
+        item.person.fullName
+      }}</v-chip
+      >&nbsp;
+    </template>
+    <!-- eslint-disable-next-line vue/valid-v-slot -->
+    <template #person.field="{ attrs, on }">
+      <div aria-required="true">
+        <v-autocomplete
+          :items="persons"
+          item-text="fullName"
+          item-value="id"
+          v-bind="attrs"
+          v-on="on"
+          return-object
+          required
+          :rules="required"
+        />
+      </div>
+    </template>
+
+    <template #reason="{ item }">
+      <v-chip>{{
+        item.shortName
+      }}</v-chip
+      >&nbsp;
+    </template>
+    <!-- eslint-disable-next-line vue/valid-v-slot -->
+    <template #reason.field="{ attrs, on }">
+      <div aria-required="true">
+        <v-autocomplete
+          :items="absenceReasons"
+          item-text="shortName"
+          item-value="id"
+          v-bind="attrs"
+          v-on="on"
+          return-object
+        />
+      </div>
+    </template>
+  </inline-c-r-u-d-list>
+  </v-container>
+</template>
+
+<script>
+import {
+  absences,
+  createAbsence,
+  deleteAbsence,
+  updateAbsences,
+} from "./absences.graphql";
+import gqlPersons from "./persons.graphql";
+import gqlAbsenceReasons from "./absenceReasons.graphql";
+
+export default {
+  name: "Absences",
+  data() {
+    return {
+      headers: [
+        {
+          text: this.$t("school_term.date_start"),
+          value: "datetimeStart",
+        },
+        {
+          text: this.$t("school_term.date_end"),
+          value: "datetimeEnd",
+        },
+        {
+          text: this.$t("person.title"),
+          value: "person",
+        },
+        {
+          text: this.$t("kolego.absence.reason"),
+          value: "reason",
+        },
+        {
+          text: this.$t("kolego.absence.comment"),
+          value: "comment",
+        },
+      ],
+      i18nKey: "kolego.absence",
+      gqlQuery: absences,
+      gqlCreateMutation: createAbsence,
+      gqlPatchMutation: updateAbsences,
+      gqlDeleteMutation: deleteAbsence,
+      defaultItem: {
+        datetimeStart: new Date().toISOString(),
+        datetimeEnd: new Date().toISOString(),
+        person: "",
+        reason: "",
+        comment: "",
+      },
+      required: [(value) => !!value || this.$t("forms.errors.required")],
+    };
+  },
+  apollo: {
+    persons: gqlPersons,
+    absenceReasons: gqlAbsenceReasons,
+  },
+};
+</script>
+
+<style scoped></style>
diff --git a/aleksis/apps/kolego/frontend/components/absenceReasons.graphql b/aleksis/apps/kolego/frontend/components/absenceReasons.graphql
new file mode 100644
index 0000000..996e514
--- /dev/null
+++ b/aleksis/apps/kolego/frontend/components/absenceReasons.graphql
@@ -0,0 +1,39 @@
+query gqlAbsenceReasons($orderBy: [String], $filters: JSONString) {
+  items: absenceReasons(orderBy: $orderBy, filters: $filters) {
+    id
+    shortName
+    name
+    canEdit
+    canDelete
+  }
+}
+
+mutation createAbsenceReason($input: CreateAbsenceReasonInput!) {
+  createAbsenceReason(input: $input) {
+    absenceReason {
+      id
+      shortName
+      name
+      canEdit
+      canDelete
+    }
+  }
+}
+
+mutation deleteAbsenceReason($id: ID!) {
+  deleteAbsenceReason(id: $id) {
+    ok
+  }
+}
+
+mutation updateAbsenceReasons($input: [BatchPatchAbsenceReasonInput]!) {
+  batchMutation: updateAbsenceReasons(input: $input) {
+    items: absenceReasons {
+      id
+      shortName
+      name
+      canEdit
+      canDelete
+    }
+  }
+}
diff --git a/aleksis/apps/kolego/frontend/components/absences.graphql b/aleksis/apps/kolego/frontend/components/absences.graphql
new file mode 100644
index 0000000..e3b07d1
--- /dev/null
+++ b/aleksis/apps/kolego/frontend/components/absences.graphql
@@ -0,0 +1,63 @@
+query absences($orderBy: [String], $filters: JSONString) {
+  items: absences(orderBy: $orderBy, filters: $filters) {
+    id
+    person {
+      fullName
+    }
+    reason {
+      shortName
+      name
+    }
+    comment
+    dateStart
+    dateEnd
+    canEdit
+    canDelete
+  }
+}
+
+mutation createAbsence($input: CreateAbsenceInput!) {
+  createAbsence(input: $input) {
+    absence {
+      id
+      person {
+        fullName
+      }
+      reason {
+        shortName
+        name
+      }
+      comment
+      dateStart
+      dateEnd
+      canEdit
+      canDelete
+    }
+  }
+}
+
+mutation deleteAbsence($id: ID!) {
+  deleteAbsence(id: $id) {
+    ok
+  }
+}
+
+mutation updateAbsences($input: [BatchPatchAbsenceInput]!) {
+  batchMutation: updateAbsences(input: $input) {
+    items: absences {
+      id
+      person {
+        fullName
+      }
+      reason {
+        shortName
+        name
+      }
+      comment
+      dateStart
+      dateEnd
+      canEdit
+      canDelete
+    }
+  }
+}
diff --git a/aleksis/apps/kolego/frontend/components/persons.graphql b/aleksis/apps/kolego/frontend/components/persons.graphql
new file mode 100644
index 0000000..42405e5
--- /dev/null
+++ b/aleksis/apps/kolego/frontend/components/persons.graphql
@@ -0,0 +1,6 @@
+query gqlPersons {
+  persons {
+    id
+    fullName
+  }
+}
diff --git a/aleksis/apps/kolego/frontend/index.js b/aleksis/apps/kolego/frontend/index.js
index d40cace..9110cd7 100644
--- a/aleksis/apps/kolego/frontend/index.js
+++ b/aleksis/apps/kolego/frontend/index.js
@@ -11,12 +11,23 @@ export default {
   },
   children: [
     {
-      path: "empty",
-      component: () => import("./components/Empty.vue"),
-      name: "kolego.empty",
+      path: "absences",
+      component: () => import("./components/Absences.vue"),
+      name: "kolego.absences",
       meta: {
         inMenu: true,
-        titleKey: "kolego.menu_title",
+        titleKey: "kolego.absence.menu_title",
+        icon: "",
+        permission: "",
+      },
+    },
+    {
+      path: "absence_reasons",
+      component: () => import("./components/AbsenceReasons.vue"),
+      name: "kolego.absence_reasons",
+      meta: {
+        inMenu: true,
+        titleKey: "kolego.absence_reason.menu_title",
         icon: "",
         permission: "",
       },
diff --git a/aleksis/apps/kolego/frontend/messages/de.json b/aleksis/apps/kolego/frontend/messages/de.json
new file mode 100644
index 0000000..098717b
--- /dev/null
+++ b/aleksis/apps/kolego/frontend/messages/de.json
@@ -0,0 +1,19 @@
+{
+  "kolego": {
+    "menu_title": "Kolego",
+    "absence": {
+      "menu_title": "Abwesenheiten",
+      "title_plural": "Abwesenheiten",
+      "create": "Abwesenheit anlegen",
+      "reason": "Grund",
+      "comment": "Kommentar"
+    },
+    "absence_reason": {
+      "menu_title": "Abwesenheitsgründe",
+      "title_plural": "Abwesenheitsgründe",
+      "create": "Abwesenheitsgrund erstellen",
+      "short_name": "Kurzname",
+      "name": "Name"
+    }
+  }
+}
diff --git a/aleksis/apps/kolego/frontend/messages/en.json b/aleksis/apps/kolego/frontend/messages/en.json
index accecb3..bae3de6 100644
--- a/aleksis/apps/kolego/frontend/messages/en.json
+++ b/aleksis/apps/kolego/frontend/messages/en.json
@@ -1,5 +1,19 @@
 {
   "kolego": {
-    "menu_title": "Kolego"
+    "menu_title": "Kolego",
+    "absence": {
+      "menu_title": "Absences",
+      "title_plural": "Absences",
+      "create": "Create absence",
+      "reason": "Reason",
+      "comment": "Comment"
+    },
+    "absence_reason": {
+      "menu_title": "Absence Reasons",
+      "title_plural": "Absence Reasons",
+      "create": "Create absence reason",
+      "short_name": "Short name",
+      "name": "Name"
+    }
   }
 }
-- 
GitLab