From b56347c17265c1a1ef71ea1e81148056cad4e1d2 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 19 Jul 2025 11:02:03 +0200 Subject: [PATCH 1/4] base views and store --- .../damageReport/DamageReportListItem.vue | 2 +- .../admin/unit/repair/RepairListItem.vue | 37 ++++++ src/router/index.ts | 76 ++++++++++++ src/router/unit/damageReport.ts | 2 +- src/router/unit/repair.ts | 20 +++ src/stores/admin/navigation.ts | 5 +- .../unit/{damageReport => }/damageReport.ts | 0 .../unit/{maintenance => }/maintenance.ts | 0 src/stores/admin/unit/repair.ts | 106 ++++++++++++++++ src/types/permissionTypes.ts | 3 + .../admin/unit/damageReport.models.ts | 4 +- .../admin/unit/maintenance.models.ts | 3 - src/viewmodels/admin/unit/repair.models.ts | 48 ++++++++ .../admin/unit/damageReport/DamageReport.vue | 2 +- .../unit/damageReport/DamageReportClosed.vue | 2 +- .../unit/damageReport/DamageReportRouting.vue | 4 +- .../admin/unit/damageReport/Overview.vue | 2 +- .../admin/unit/equipment/DamageReport.vue | 2 +- .../admin/unit/equipment/EquipmentRouting.vue | 3 +- .../admin/unit/maintenance/Maintenance.vue | 2 +- src/views/admin/unit/repair/Overview.vue | 116 ++++++++++++++++++ src/views/admin/unit/repair/RepairClosed.vue | 46 +++++++ src/views/admin/unit/repair/RepairOpen.vue | 46 +++++++ src/views/admin/unit/repair/RepairRouting.vue | 82 +++++++++++++ .../admin/unit/repair/RepairStatusRouting.vue | 54 ++++++++ src/views/admin/unit/vehicle/DamageReport.vue | 2 +- .../admin/unit/vehicle/VehicleRouting.vue | 3 +- .../admin/unit/wearable/DamageReport.vue | 2 +- .../admin/unit/wearable/WearableRouting.vue | 3 +- 29 files changed, 655 insertions(+), 22 deletions(-) create mode 100644 src/components/admin/unit/repair/RepairListItem.vue create mode 100644 src/router/unit/repair.ts rename src/stores/admin/unit/{damageReport => }/damageReport.ts (100%) rename src/stores/admin/unit/{maintenance => }/maintenance.ts (100%) create mode 100644 src/stores/admin/unit/repair.ts create mode 100644 src/viewmodels/admin/unit/repair.models.ts create mode 100644 src/views/admin/unit/repair/Overview.vue create mode 100644 src/views/admin/unit/repair/RepairClosed.vue create mode 100644 src/views/admin/unit/repair/RepairOpen.vue create mode 100644 src/views/admin/unit/repair/RepairRouting.vue create mode 100644 src/views/admin/unit/repair/RepairStatusRouting.vue diff --git a/src/components/admin/unit/damageReport/DamageReportListItem.vue b/src/components/admin/unit/damageReport/DamageReportListItem.vue index c22e040..0ece8cb 100644 --- a/src/components/admin/unit/damageReport/DamageReportListItem.vue +++ b/src/components/admin/unit/damageReport/DamageReportListItem.vue @@ -18,7 +18,7 @@
-
+
diff --git a/src/components/admin/unit/repair/RepairListItem.vue b/src/components/admin/unit/repair/RepairListItem.vue new file mode 100644 index 0000000..5b36a28 --- /dev/null +++ b/src/components/admin/unit/repair/RepairListItem.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts index 7fc2f76..68908e5 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -21,6 +21,7 @@ import { setVehicleTypeId } from "./unit/vehicleType"; import { resetInspectionStores, setInspectionId } from "./unit/inspection"; import { setWearableTypeId } from "./unit/wearableType"; import { resetDamageReportStores, setDamageReportId } from "./unit/damageReport"; +import { resetRepairStores, setRepairId } from "./unit/repair"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -374,6 +375,12 @@ const router = createRouter({ component: () => import("@/views/admin/ViewSelect.vue"), props: true, }, + { + path: "repair", + name: "admin-unit-equipment-repair", + component: () => import("@/views/admin/ViewSelect.vue"), + props: true, + }, { path: "inspection", name: "admin-unit-equipment-inspection", @@ -437,6 +444,12 @@ const router = createRouter({ component: () => import("@/views/admin/ViewSelect.vue"), props: true, }, + { + path: "repair", + name: "admin-unit-vehicle-repair", + component: () => import("@/views/admin/ViewSelect.vue"), + props: true, + }, { path: "inspection", name: "admin-unit-vehicle-inspection", @@ -500,6 +513,12 @@ const router = createRouter({ component: () => import("@/views/admin/ViewSelect.vue"), props: true, }, + { + path: "repair", + name: "admin-unit-wearable-repair", + component: () => import("@/views/admin/ViewSelect.vue"), + props: true, + }, { path: "inspection", name: "admin-unit-wearable-inspection", @@ -713,6 +732,11 @@ const router = createRouter({ component: () => import("@/views/admin/unit/damageReport/DamageReportStatusRouting.vue"), beforeEnter: [resetDamageReportStores], children: [ + { + path: "", + name: "admin-unit-damage_report-status", + redirect: { name: "admin-unit-damage_report-open" }, + }, { path: "open", name: "admin-unit-damage_report-open", @@ -742,6 +766,58 @@ const router = createRouter({ }, ], }, + { + path: "repair", + name: "admin-unit-repair-route", + component: () => import("@/views/RouterView.vue"), + meta: { type: "read", section: "unit", module: "repair" }, + beforeEnter: [abilityAndNavUpdate], + children: [ + { + path: "", + name: "admin-unit-repair", + redirect: { name: "admin-unit-repair-open" }, + }, + { + path: "status", + name: "admin-unit-repair-statusrouting", + component: () => import("@/views/admin/unit/repair/RepairStatusRouting.vue"), + beforeEnter: [resetRepairStores], + children: [ + { + path: "", + name: "admin-unit-repair-status", + redirect: { name: "admin-unit-repair-open" }, + }, + { + path: "open", + name: "admin-unit-repair-open", + component: () => import("@/views/admin/unit/repair/RepairOpen.vue"), + }, + { + path: "done", + name: "admin-unit-repair-done", + component: () => import("@/views/admin/unit/repair/RepairClosed.vue"), + }, + ], + }, + { + path: "hi/:repairId", + name: "admin-unit-repair-routing", + component: () => import("@/views/admin/unit/repair/RepairRouting.vue"), + beforeEnter: [setRepairId], + props: true, + children: [ + { + path: "", + name: "admin-unit-repair-overview", + component: () => import("@/views/admin/unit/repair/Overview.vue"), + props: true, + }, + ], + }, + ], + }, { path: "maintenance", name: "admin-unit-maintenance-route", diff --git a/src/router/unit/damageReport.ts b/src/router/unit/damageReport.ts index 86b7f86..4a649bf 100644 --- a/src/router/unit/damageReport.ts +++ b/src/router/unit/damageReport.ts @@ -1,4 +1,4 @@ -import { useDamageReportStore } from "@/stores/admin/unit/damageReport/damageReport"; +import { useDamageReportStore } from "@/stores/admin/unit/damageReport"; export async function setDamageReportId(to: any, from: any, next: any) { const damageReportStore = useDamageReportStore(); diff --git a/src/router/unit/repair.ts b/src/router/unit/repair.ts new file mode 100644 index 0000000..dab9374 --- /dev/null +++ b/src/router/unit/repair.ts @@ -0,0 +1,20 @@ +import { useRepairStore } from "@/stores/admin/unit/repair"; + +export async function setRepairId(to: any, from: any, next: any) { + const repairStore = useRepairStore(); + repairStore.activeRepair = to.params?.repairId ?? null; + + //xystore().$reset(); + + next(); +} + +export async function resetRepairStores(to: any, from: any, next: any) { + const repairStore = useRepairStore(); + repairStore.activeRepair = null; + repairStore.activeRepairObj = null; + + //xystore().$reset(); + + next(); +} diff --git a/src/stores/admin/navigation.ts b/src/stores/admin/navigation.ts index 67aa59c..b6e5461 100644 --- a/src/stores/admin/navigation.ts +++ b/src/stores/admin/navigation.ts @@ -120,12 +120,11 @@ export const useNavigationStore = defineStore("navigation", { ? [{ key: "respiratory_mission", title: "Atemschutz-Einsätze" }] : []), ...(abilityStore.can("create", "unit", "inspection") ? [{ key: "inspection", title: "Prüfungen" }] : []), + ...(abilityStore.can("read", "unit", "maintenance") ? [{ key: "maintenance", title: "Wartungen" }] : []), ...(abilityStore.can("read", "unit", "damage_report") ? [{ key: "damage_report", title: "Schadensmeldungen" }] : []), - ...(abilityStore.can("read", "unit", "maintenance") - ? [{ key: "maintenance", title: "Wartungen / Reparaturen" }] - : []), + ...(abilityStore.can("read", "unit", "repair") ? [{ key: "repair", title: "Reparaturen" }] : []), { key: "divider1", title: "Basisdaten" }, ...(abilityStore.can("read", "unit", "equipment_type") ? [{ key: "equipment_type", title: "Geräte-Typen" }] diff --git a/src/stores/admin/unit/damageReport/damageReport.ts b/src/stores/admin/unit/damageReport.ts similarity index 100% rename from src/stores/admin/unit/damageReport/damageReport.ts rename to src/stores/admin/unit/damageReport.ts diff --git a/src/stores/admin/unit/maintenance/maintenance.ts b/src/stores/admin/unit/maintenance.ts similarity index 100% rename from src/stores/admin/unit/maintenance/maintenance.ts rename to src/stores/admin/unit/maintenance.ts diff --git a/src/stores/admin/unit/repair.ts b/src/stores/admin/unit/repair.ts new file mode 100644 index 0000000..3104db8 --- /dev/null +++ b/src/stores/admin/unit/repair.ts @@ -0,0 +1,106 @@ +import { defineStore } from "pinia"; +import type { RepairViewModel, UpdateRepairViewModel } from "@/viewmodels/admin/unit/repair.models"; +import { http } from "@/serverCom"; +import type { AxiosResponse } from "axios"; + +export const useRepairStore = defineStore("repair", { + state: () => { + return { + repairs: [] as Array, + totalCount: 0 as number, + loading: "loading" as "loading" | "fetched" | "failed", + activeRepair: null as string | null, + activeRepairObj: null as RepairViewModel | null, + loadingActive: "loading" as "loading" | "fetched" | "failed", + }; + }, + actions: { + formatQueryReturnToPagination(result: AxiosResponse, offset: number) { + this.totalCount = result.data.total; + result.data.repairs + .filter((elem: RepairViewModel) => this.repairs.findIndex((m) => m.id == elem.id) == -1) + .map((elem: RepairViewModel, index: number): RepairViewModel & { tab_pos: number } => { + return { + ...elem, + tab_pos: index + offset, + }; + }) + .forEach((elem: RepairViewModel & { tab_pos: number }) => { + this.repairs.push(elem); + }); + }, + fetchOpenRepairs(offset = 0, count = 25, search = "", clear = false) { + if (clear) this.repairs = []; + this.loading = "loading"; + http + .get(`/admin/repair?done=false&offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}`) + .then((result) => { + this.formatQueryReturnToPagination(result, offset); + this.loading = "fetched"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + fetchDoneRepairs(offset = 0, count = 25, search = "", clear = false) { + if (clear) this.repairs = []; + this.loading = "loading"; + http + .get(`/admin/repair?done=true&offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}`) + .then((result) => { + this.formatQueryReturnToPagination(result, offset); + this.loading = "fetched"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + async getAllRepairs(): Promise> { + return await http.get(`/admin/repair?noLimit=true`).then((res) => { + return { ...res, data: res.data.repairs }; + }); + }, + async getRepairsByIds(ids: Array): Promise> { + return await http + .post(`/admin/repair/ids`, { + ids, + }) + .then((res) => { + return { ...res, data: res.data.repairs }; + }); + }, + async searchRepairs(search: string): Promise> { + return await http.get(`/admin/repair?search=${search}&noLimit=true`).then((res) => { + return { ...res, data: res.data.repairs }; + }); + }, + fetchRepairByActiveId() { + this.loadingActive = "loading"; + http + .get(`/admin/repair/${this.activeRepair}`) + .then((res) => { + this.activeRepairObj = res.data; + this.loadingActive = "fetched"; + }) + .catch((err) => { + this.loadingActive = "failed"; + }); + }, + fetchRepairById(id: string) { + return http.get(`/admin/repair/${id}`); + }, + loadRepairImage(url: string) { + return http.get(`/admin/repair/${this.activeRepairObj?.id}/${url}`, { + responseType: "blob", + }); + }, + async updateRepair(repair: UpdateRepairViewModel): Promise> { + const result = await http.patch(`/admin/repair/${repair.id}`, { + status: repair.status, + noteByWorker: repair.noteByWorker, + done: repair.done, + }); + return result; + }, + }, +}); diff --git a/src/types/permissionTypes.ts b/src/types/permissionTypes.ts index 2442d9f..091c0c3 100644 --- a/src/types/permissionTypes.ts +++ b/src/types/permissionTypes.ts @@ -22,6 +22,7 @@ export type PermissionModule = | "respiratory_mission" | "damage_report" | "maintenance" + | "repair" // configuration | "qualification" | "award" @@ -97,6 +98,7 @@ export const permissionModules: Array = [ "respiratory_mission", "damage_report", "maintenance", + "repair", // configuration "qualification", "award", @@ -134,6 +136,7 @@ export const sectionsAndModules: SectionsAndModulesObject = { "respiratory_mission", "damage_report", "maintenance", + "repair", ], configuration: [ "qualification", diff --git a/src/viewmodels/admin/unit/damageReport.models.ts b/src/viewmodels/admin/unit/damageReport.models.ts index d05debe..2c39fe6 100644 --- a/src/viewmodels/admin/unit/damageReport.models.ts +++ b/src/viewmodels/admin/unit/damageReport.models.ts @@ -1,5 +1,5 @@ import type { EquipmentViewModel } from "./equipment/equipment.models"; -import type { MaintenanceViewModel } from "./maintenance.models"; +import type { RepairViewModel } from "./repair.models"; import type { VehicleViewModel } from "./vehicle/vehicle.models"; import type { WearableViewModel } from "./wearable/wearable.models"; @@ -31,7 +31,7 @@ export type DamageReportViewModel = { noteByWorker: string; images: string[]; reportedBy: string; - maintenance?: MaintenanceViewModel; + repair?: RepairViewModel; } & Optional; export interface CreateDamageReportViewModel { diff --git a/src/viewmodels/admin/unit/maintenance.models.ts b/src/viewmodels/admin/unit/maintenance.models.ts index 7ccd66e..bfcf1e2 100644 --- a/src/viewmodels/admin/unit/maintenance.models.ts +++ b/src/viewmodels/admin/unit/maintenance.models.ts @@ -1,4 +1,3 @@ -import type { DamageReportViewModel } from "./damageReport.models"; import type { EquipmentViewModel } from "./equipment/equipment.models"; import type { VehicleViewModel } from "./vehicle/vehicle.models"; import type { WearableViewModel } from "./wearable/wearable.models"; @@ -24,9 +23,7 @@ export type MaintenanceViewModel = { id: string; createdAt: Date; status: string; - done: boolean; description: string; - reports: DamageReportViewModel[]; } & MaintenanceAssigned; export interface CreateMaintenanceViewModel { diff --git a/src/viewmodels/admin/unit/repair.models.ts b/src/viewmodels/admin/unit/repair.models.ts new file mode 100644 index 0000000..b40f157 --- /dev/null +++ b/src/viewmodels/admin/unit/repair.models.ts @@ -0,0 +1,48 @@ +import type { DamageReportViewModel } from "./damageReport.models"; +import type { EquipmentViewModel } from "./equipment/equipment.models"; +import type { MaintenanceViewModel } from "./maintenance.models"; +import type { VehicleViewModel } from "./vehicle/vehicle.models"; +import type { WearableViewModel } from "./wearable/wearable.models"; + +export type RepairAssigned = { + relatedId: string; +} & ( + | { + assigned: "equipment"; + related: EquipmentViewModel; + } + | { + assigned: "vehicle"; + related: VehicleViewModel; + } + | { + assigned: "wearable"; + related: WearableViewModel; + } +); + +export type RepairViewModel = { + id: string; + createdAt: Date; + finishedAt?: Date; + status: string; + responsible: string; + description: string; + images: string[]; + reportDocument: string; + reports: DamageReportViewModel[]; +} & RepairAssigned; + +export interface CreateRepairViewModel { + description: string; + reportedBy: string; + affectedId: string; + affected: "equipment" | "vehicle" | "wearable"; +} + +export interface UpdateRepairViewModel { + id: string; + status: string; + noteByWorker: string; + done: boolean; +} diff --git a/src/views/admin/unit/damageReport/DamageReport.vue b/src/views/admin/unit/damageReport/DamageReport.vue index 4ba8c6a..d33f077 100644 --- a/src/views/admin/unit/damageReport/DamageReport.vue +++ b/src/views/admin/unit/damageReport/DamageReport.vue @@ -19,7 +19,7 @@ import { defineComponent } from "vue"; import { mapActions, mapState } from "pinia"; import MainTemplate from "@/templates/Main.vue"; import { useAbilityStore } from "@/stores/ability"; -import { useDamageReportStore } from "@/stores/admin/unit/damageReport/damageReport"; +import { useDamageReportStore } from "@/stores/admin/unit/damageReport"; import type { DamageReportViewModel } from "@/viewmodels/admin/unit/damageReport.models"; import Pagination from "@/components/Pagination.vue"; import DamageReportListItem from "@/components/admin/unit/damageReport/DamageReportListItem.vue"; diff --git a/src/views/admin/unit/damageReport/DamageReportClosed.vue b/src/views/admin/unit/damageReport/DamageReportClosed.vue index 0766e6d..89d5bc0 100644 --- a/src/views/admin/unit/damageReport/DamageReportClosed.vue +++ b/src/views/admin/unit/damageReport/DamageReportClosed.vue @@ -19,7 +19,7 @@ import { defineComponent } from "vue"; import { mapActions, mapState } from "pinia"; import MainTemplate from "@/templates/Main.vue"; import { useAbilityStore } from "@/stores/ability"; -import { useDamageReportStore } from "@/stores/admin/unit/damageReport/damageReport"; +import { useDamageReportStore } from "@/stores/admin/unit/damageReport"; import type { DamageReportViewModel } from "@/viewmodels/admin/unit/damageReport.models"; import Pagination from "@/components/Pagination.vue"; import DamageReportListItem from "@/components/admin/unit/damageReport/DamageReportListItem.vue"; diff --git a/src/views/admin/unit/damageReport/DamageReportRouting.vue b/src/views/admin/unit/damageReport/DamageReportRouting.vue index 72b2043..a25335c 100644 --- a/src/views/admin/unit/damageReport/DamageReportRouting.vue +++ b/src/views/admin/unit/damageReport/DamageReportRouting.vue @@ -11,7 +11,7 @@ diff --git a/src/views/admin/unit/damageReport/Overview.vue b/src/views/admin/unit/damageReport/Overview.vue index 85c05eb..d72c452 100644 --- a/src/views/admin/unit/damageReport/Overview.vue +++ b/src/views/admin/unit/damageReport/Overview.vue @@ -63,7 +63,7 @@ import { defineComponent } from "vue"; import { mapActions, mapState, mapWritableState } from "pinia"; import { useAbilityStore } from "@/stores/ability"; -import { useDamageReportStore } from "@/stores/admin/unit/damageReport/damageReport"; +import { useDamageReportStore } from "@/stores/admin/unit/damageReport"; import type { DamageReportViewModel, UpdateDamageReportViewModel } from "@/viewmodels/admin/unit/damageReport.models"; diff --git a/src/views/admin/unit/equipment/DamageReport.vue b/src/views/admin/unit/equipment/DamageReport.vue index 857c63d..513277d 100644 --- a/src/views/admin/unit/equipment/DamageReport.vue +++ b/src/views/admin/unit/equipment/DamageReport.vue @@ -25,7 +25,7 @@
-
+
diff --git a/src/views/admin/unit/equipment/EquipmentRouting.vue b/src/views/admin/unit/equipment/EquipmentRouting.vue index 5eb9ced..22f4466 100644 --- a/src/views/admin/unit/equipment/EquipmentRouting.vue +++ b/src/views/admin/unit/equipment/EquipmentRouting.vue @@ -55,9 +55,10 @@ export default defineComponent({ return { tabs: [ { route: "admin-unit-equipment-overview", title: "Übersicht" }, - { route: "admin-unit-equipment-maintenance", title: "Wartungen/Reparaturen" }, { route: "admin-unit-equipment-inspection", title: "Prüfungen" }, + { route: "admin-unit-equipment-maintenance", title: "Wartungen" }, { route: "admin-unit-equipment-damage_report", title: "Schadensmeldungen" }, + { route: "admin-unit-equipment-repair", title: "Reparaturen" }, ], }; }, diff --git a/src/views/admin/unit/maintenance/Maintenance.vue b/src/views/admin/unit/maintenance/Maintenance.vue index 19e0e0c..d54276c 100644 --- a/src/views/admin/unit/maintenance/Maintenance.vue +++ b/src/views/admin/unit/maintenance/Maintenance.vue @@ -19,7 +19,7 @@ import { defineComponent } from "vue"; import { mapActions, mapState } from "pinia"; import MainTemplate from "@/templates/Main.vue"; import { useAbilityStore } from "@/stores/ability"; -import { useMaintenanceStore } from "@/stores/admin/unit/maintenance/maintenance"; +import { useMaintenanceStore } from "@/stores/admin/unit/maintenance"; import type { MaintenanceViewModel } from "@/viewmodels/admin/unit/maintenance.models"; import Pagination from "@/components/Pagination.vue"; import MaintenanceListItem from "@/components/admin/unit/maintenance/MaintenanceListItem.vue"; diff --git a/src/views/admin/unit/repair/Overview.vue b/src/views/admin/unit/repair/Overview.vue new file mode 100644 index 0000000..b401bbe --- /dev/null +++ b/src/views/admin/unit/repair/Overview.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/src/views/admin/unit/repair/RepairClosed.vue b/src/views/admin/unit/repair/RepairClosed.vue new file mode 100644 index 0000000..6a0778b --- /dev/null +++ b/src/views/admin/unit/repair/RepairClosed.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/views/admin/unit/repair/RepairOpen.vue b/src/views/admin/unit/repair/RepairOpen.vue new file mode 100644 index 0000000..1970cc8 --- /dev/null +++ b/src/views/admin/unit/repair/RepairOpen.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/views/admin/unit/repair/RepairRouting.vue b/src/views/admin/unit/repair/RepairRouting.vue new file mode 100644 index 0000000..8d0b8ed --- /dev/null +++ b/src/views/admin/unit/repair/RepairRouting.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/views/admin/unit/repair/RepairStatusRouting.vue b/src/views/admin/unit/repair/RepairStatusRouting.vue new file mode 100644 index 0000000..8d34a29 --- /dev/null +++ b/src/views/admin/unit/repair/RepairStatusRouting.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/src/views/admin/unit/vehicle/DamageReport.vue b/src/views/admin/unit/vehicle/DamageReport.vue index eb2ac38..25938da 100644 --- a/src/views/admin/unit/vehicle/DamageReport.vue +++ b/src/views/admin/unit/vehicle/DamageReport.vue @@ -25,7 +25,7 @@
-
+
diff --git a/src/views/admin/unit/vehicle/VehicleRouting.vue b/src/views/admin/unit/vehicle/VehicleRouting.vue index 4d3b22c..b9c9f32 100644 --- a/src/views/admin/unit/vehicle/VehicleRouting.vue +++ b/src/views/admin/unit/vehicle/VehicleRouting.vue @@ -55,9 +55,10 @@ export default defineComponent({ return { tabs: [ { route: "admin-unit-vehicle-overview", title: "Übersicht" }, - { route: "admin-unit-vehicle-maintenance", title: "Wartungen/Reparaturen" }, { route: "admin-unit-vehicle-inspection", title: "Prüfungen" }, + { route: "admin-unit-vehicle-maintenance", title: "Wartungen" }, { route: "admin-unit-vehicle-damage_report", title: "Schadensmeldungen" }, + { route: "admin-unit-vehicle-repair", title: "Reparaturen" }, ], }; }, diff --git a/src/views/admin/unit/wearable/DamageReport.vue b/src/views/admin/unit/wearable/DamageReport.vue index 847a286..3b40512 100644 --- a/src/views/admin/unit/wearable/DamageReport.vue +++ b/src/views/admin/unit/wearable/DamageReport.vue @@ -25,7 +25,7 @@
-
+
diff --git a/src/views/admin/unit/wearable/WearableRouting.vue b/src/views/admin/unit/wearable/WearableRouting.vue index e1f9f88..a7978dd 100644 --- a/src/views/admin/unit/wearable/WearableRouting.vue +++ b/src/views/admin/unit/wearable/WearableRouting.vue @@ -55,9 +55,10 @@ export default defineComponent({ return { tabs: [ { route: "admin-unit-wearable-overview", title: "Übersicht" }, - { route: "admin-unit-wearable-maintenance", title: "Wartungen/Reparaturen" }, { route: "admin-unit-wearable-inspection", title: "Prüfungen" }, + { route: "admin-unit-wearable-maintenance", title: "Wartungen" }, { route: "admin-unit-wearable-damage_report", title: "Schadensmeldungen" }, + { route: "admin-unit-wearable-repair", title: "Reparaturen" }, ], }; }, -- 2.47.3 From b5a3ff4dc699ba3032ff696b5c6b4b47de496faa Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 21 Jul 2025 11:03:49 +0200 Subject: [PATCH 2/4] extend report by title --- .../unit/damageReport/DamageReportListItem.vue | 1 + src/components/public/damageReport/CheckEntry.vue | 6 ++++++ src/components/public/damageReport/InputData.vue | 15 ++++++++++++++- src/viewmodels/admin/unit/damageReport.models.ts | 2 ++ src/views/admin/unit/equipment/DamageReport.vue | 2 +- src/views/admin/unit/vehicle/DamageReport.vue | 2 +- src/views/admin/unit/wearable/DamageReport.vue | 2 +- src/views/public/damageReport/Report.vue | 13 ++++++++++++- 8 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/components/admin/unit/damageReport/DamageReportListItem.vue b/src/components/admin/unit/damageReport/DamageReportListItem.vue index 0ece8cb..574c584 100644 --- a/src/components/admin/unit/damageReport/DamageReportListItem.vue +++ b/src/components/admin/unit/damageReport/DamageReportListItem.vue @@ -5,6 +5,7 @@ >

+ {{ damageReport.title }} - {{ damageReport?.related?.name ?? "Ohne Zuordnung" }} ({{ damageReport.related.code }})

diff --git a/src/components/public/damageReport/CheckEntry.vue b/src/components/public/damageReport/CheckEntry.vue index 280f43c..a187a32 100644 --- a/src/components/public/damageReport/CheckEntry.vue +++ b/src/components/public/damageReport/CheckEntry.vue @@ -9,6 +9,10 @@

Typ: {{ check.gear.type }}

+
+ + +
@@ -59,6 +63,7 @@ export default defineComponent({ check: { type: Object as PropType<{ gear: undefined | MinifiedEquipmentViewModel | MinifiedVehicleViewModel | MinifiedWearableViewModel; + title: string; description: string; location: string; note: string; @@ -98,6 +103,7 @@ export default defineComponent({ this.message = ""; const formData = new FormData(); if (this.check.gear) formData.append("related", JSON.stringify(this.check.gear)); + formData.append("title", this.check.title); formData.append("description", this.check.description); formData.append("location", this.check.location); formData.append("note", this.check.note); diff --git a/src/components/public/damageReport/InputData.vue b/src/components/public/damageReport/InputData.vue index eb01d9a..20a35ee 100644 --- a/src/components/public/damageReport/InputData.vue +++ b/src/components/public/damageReport/InputData.vue @@ -2,6 +2,10 @@

zurück

+
+ + +
@@ -45,6 +49,7 @@ export default defineComponent({ data: { type: Object as PropType<{ gear: undefined | MinifiedEquipmentViewModel | MinifiedVehicleViewModel | MinifiedWearableViewModel; + title: string; description: string; location: string; note: string; @@ -57,7 +62,14 @@ export default defineComponent({ emits: { nextStep: (s: string) => true, stepBack: () => true, - data: (d: { description: string; location: string; note: string; reportedBy: string; image?: File }) => true, + data: (d: { + title: string; + description: string; + location: string; + note: string; + reportedBy: string; + image?: File; + }) => true, }, mounted() { if (this.data.image) { @@ -68,6 +80,7 @@ export default defineComponent({ setup(e: any) { let formData = e.target.elements; this.$emit("data", { + title: formData.title.value, description: formData.description.value, location: formData.location.value, note: formData.note.value, diff --git a/src/viewmodels/admin/unit/damageReport.models.ts b/src/viewmodels/admin/unit/damageReport.models.ts index 2c39fe6..5544d00 100644 --- a/src/viewmodels/admin/unit/damageReport.models.ts +++ b/src/viewmodels/admin/unit/damageReport.models.ts @@ -22,6 +22,7 @@ export type DamageReportAssigned = { export type DamageReportViewModel = { id: string; + title: string; reportedAt: Date; status: string; done: boolean; @@ -35,6 +36,7 @@ export type DamageReportViewModel = { } & Optional; export interface CreateDamageReportViewModel { + title: string; description: string; reportedBy: string; affectedId: string; diff --git a/src/views/admin/unit/equipment/DamageReport.vue b/src/views/admin/unit/equipment/DamageReport.vue index 513277d..1f04e66 100644 --- a/src/views/admin/unit/equipment/DamageReport.vue +++ b/src/views/admin/unit/equipment/DamageReport.vue @@ -14,7 +14,7 @@ >
-

{{ new Date(row.reportedAt).toLocaleString("de") }} - {{ row.status }}

+

{{ row.title }} - {{ new Date(row.reportedAt).toLocaleString("de") }} - {{ row.status }}

diff --git a/src/views/admin/unit/vehicle/DamageReport.vue b/src/views/admin/unit/vehicle/DamageReport.vue index 25938da..69f41de 100644 --- a/src/views/admin/unit/vehicle/DamageReport.vue +++ b/src/views/admin/unit/vehicle/DamageReport.vue @@ -14,7 +14,7 @@ >
-

{{ new Date(row.reportedAt).toLocaleString("de") }} - {{ row.status }}

+

{{ row.title }} - {{ new Date(row.reportedAt).toLocaleString("de") }} - {{ row.status }}

diff --git a/src/views/admin/unit/wearable/DamageReport.vue b/src/views/admin/unit/wearable/DamageReport.vue index 3b40512..59379ab 100644 --- a/src/views/admin/unit/wearable/DamageReport.vue +++ b/src/views/admin/unit/wearable/DamageReport.vue @@ -14,7 +14,7 @@ >
-

{{ new Date(row.reportedAt).toLocaleString("de") }} - {{ row.status }}

+

{{ row.title }} - {{ new Date(row.reportedAt).toLocaleString("de") }} - {{ row.status }}

diff --git a/src/views/public/damageReport/Report.vue b/src/views/public/damageReport/Report.vue index c36a7be..4fa0026 100644 --- a/src/views/public/damageReport/Report.vue +++ b/src/views/public/damageReport/Report.vue @@ -56,6 +56,7 @@ export default defineComponent({ usingBarcode: false, content: { gear: undefined, + title: "", description: "", location: "", note: "", @@ -63,6 +64,7 @@ export default defineComponent({ image: undefined, } as { gear: undefined | MinifiedEquipmentViewModel | MinifiedVehicleViewModel | MinifiedWearableViewModel; + title: string; description: string; location: string; note: string; @@ -83,7 +85,15 @@ export default defineComponent({ this.step = index; this.successfull = index - 1; }, - updateContent(d: { description: string; location: string; note: string; reportedBy: string; image?: File }) { + updateContent(d: { + title: string; + description: string; + location: string; + note: string; + reportedBy: string; + image?: File; + }) { + this.content.title = d.title; this.content.description = d.description; this.content.location = d.location; this.content.note = d.note; @@ -102,6 +112,7 @@ export default defineComponent({ this.usingBarcode = false; this.content = { gear: undefined, + title: "", description: "", location: "", note: "", -- 2.47.3 From c79d5bb1cd0f917e4f437b768f2d79943d1ef636 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 21 Jul 2025 12:58:32 +0200 Subject: [PATCH 3/4] repair create and view --- .../admin/unit/repair/RepairListItem.vue | 4 +- ...eReportSearchSelectMultipleWithRelated.vue | 230 ++++++++++++++++++ ...ageReportSearchSelectSingleWithRelated.vue | 216 ++++++++++++++++ src/router/index.ts | 15 +- src/stores/admin/unit/damageReport.ts | 17 ++ src/stores/admin/unit/equipment/repair.ts | 43 ++++ src/stores/admin/unit/repair.ts | 17 +- src/stores/admin/unit/vehicle/repair.ts | 43 ++++ src/stores/admin/unit/wearable/repair.ts | 43 ++++ src/viewmodels/admin/unit/repair.models.ts | 9 +- .../unit/damageReport/DamageReportRouting.vue | 34 ++- .../DamageReportStatusRouting.vue | 36 ++- src/views/admin/unit/equipment/Repair.vue | 62 +++++ src/views/admin/unit/repair/RepairCreate.vue | 171 +++++++++++++ src/views/admin/unit/repair/RepairRouting.vue | 2 +- .../admin/unit/repair/RepairStatusRouting.vue | 39 +-- src/views/admin/unit/vehicle/Repair.vue | 62 +++++ src/views/admin/unit/wearable/Repair.vue | 62 +++++ 18 files changed, 1046 insertions(+), 59 deletions(-) create mode 100644 src/components/search/DamageReportSearchSelectMultipleWithRelated.vue create mode 100644 src/components/search/DamageReportSearchSelectSingleWithRelated.vue create mode 100644 src/stores/admin/unit/equipment/repair.ts create mode 100644 src/stores/admin/unit/vehicle/repair.ts create mode 100644 src/stores/admin/unit/wearable/repair.ts create mode 100644 src/views/admin/unit/equipment/Repair.vue create mode 100644 src/views/admin/unit/repair/RepairCreate.vue create mode 100644 src/views/admin/unit/vehicle/Repair.vue create mode 100644 src/views/admin/unit/wearable/Repair.vue diff --git a/src/components/admin/unit/repair/RepairListItem.vue b/src/components/admin/unit/repair/RepairListItem.vue index 5b36a28..69986ee 100644 --- a/src/components/admin/unit/repair/RepairListItem.vue +++ b/src/components/admin/unit/repair/RepairListItem.vue @@ -5,13 +5,15 @@ >

+ {{ repair.title }} - {{ repair?.related?.name ?? "Ohne Zuordnung" }} ({{ repair.related.code }})

-

vera: {{ new Date(repair.createdAt).toLocaleString("de") }}

+

begonnen: {{ new Date(repair.createdAt).toLocaleString("de") }}

Status: {{ repair.status }}

+

Verantwortlich: {{ repair.responsible }}

Beschreibung: {{ repair.description }}

diff --git a/src/components/search/DamageReportSearchSelectMultipleWithRelated.vue b/src/components/search/DamageReportSearchSelectMultipleWithRelated.vue new file mode 100644 index 0000000..bfb45b7 --- /dev/null +++ b/src/components/search/DamageReportSearchSelectMultipleWithRelated.vue @@ -0,0 +1,230 @@ + + + + + diff --git a/src/components/search/DamageReportSearchSelectSingleWithRelated.vue b/src/components/search/DamageReportSearchSelectSingleWithRelated.vue new file mode 100644 index 0000000..101fe78 --- /dev/null +++ b/src/components/search/DamageReportSearchSelectSingleWithRelated.vue @@ -0,0 +1,216 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts index 68908e5..30b6402 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -378,7 +378,7 @@ const router = createRouter({ { path: "repair", name: "admin-unit-equipment-repair", - component: () => import("@/views/admin/ViewSelect.vue"), + component: () => import("@/views/admin/unit/equipment/Repair.vue"), props: true, }, { @@ -447,7 +447,7 @@ const router = createRouter({ { path: "repair", name: "admin-unit-vehicle-repair", - component: () => import("@/views/admin/ViewSelect.vue"), + component: () => import("@/views/admin/unit/vehicle/Repair.vue"), props: true, }, { @@ -516,7 +516,7 @@ const router = createRouter({ { path: "repair", name: "admin-unit-wearable-repair", - component: () => import("@/views/admin/ViewSelect.vue"), + component: () => import("@/views/admin/unit/wearable/Repair.vue"), props: true, }, { @@ -802,7 +802,14 @@ const router = createRouter({ ], }, { - path: "hi/:repairId", + path: "create/:type?/:relatedId?", + name: "admin-unit-repair-create", + component: () => import("@/views/admin/unit/repair/RepairCreate.vue"), + beforeEnter: [], + props: true, + }, + { + path: "execute/:repairId", name: "admin-unit-repair-routing", component: () => import("@/views/admin/unit/repair/RepairRouting.vue"), beforeEnter: [setRepairId], diff --git a/src/stores/admin/unit/damageReport.ts b/src/stores/admin/unit/damageReport.ts index 827086a..d7a458a 100644 --- a/src/stores/admin/unit/damageReport.ts +++ b/src/stores/admin/unit/damageReport.ts @@ -74,6 +74,23 @@ export const useDamageReportStore = defineStore("damageReport", { return { ...res, data: res.data.damageReports }; }); }, + async getAllDamageReportsWithRelated( + related: "vehicle" | "equipment" | "wearable", + relatedId: string + ): Promise> { + return await http.get(`/admin/damageReport/${related}/${relatedId}?noLimit=true`).then((res) => { + return { ...res, data: res.data.damageReports }; + }); + }, + async searchDamageReportsWithRelated( + related: "vehicle" | "equipment" | "wearable", + relatedId: string, + search: string + ): Promise> { + return await http.get(`/admin/damageReport/${related}/${relatedId}?search=${search}&noLimit=true`).then((res) => { + return { ...res, data: res.data.damageReports }; + }); + }, fetchDamageReportByActiveId() { this.loadingActive = "loading"; http diff --git a/src/stores/admin/unit/equipment/repair.ts b/src/stores/admin/unit/equipment/repair.ts new file mode 100644 index 0000000..a3db4ba --- /dev/null +++ b/src/stores/admin/unit/equipment/repair.ts @@ -0,0 +1,43 @@ +import { defineStore } from "pinia"; +import { http } from "@/serverCom"; +import { useEquipmentStore } from "./equipment"; +import type { RepairViewModel } from "@/viewmodels/admin/unit/repair.models"; + +export const useEquipmentRepairStore = defineStore("equipmentRepair", { + state: () => { + return { + repairs: [] as Array, + totalCount: 0 as number, + loading: "loading" as "loading" | "fetched" | "failed", + }; + }, + actions: { + fetchRepairForEquipment(offset = 0, count = 25, search = "", clear = false) { + const equipmentId = useEquipmentStore().activeEquipment; + if (clear) this.repairs = []; + this.loading = "loading"; + http + .get( + `/admin/repair/equipment/${equipmentId}?offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}` + ) + .then((result) => { + this.totalCount = result.data.total; + result.data.repairs + .filter((elem: RepairViewModel) => this.repairs.findIndex((m) => m.id == elem.id) == -1) + .map((elem: RepairViewModel, index: number): RepairViewModel & { tab_pos: number } => { + return { + ...elem, + tab_pos: index + offset, + }; + }) + .forEach((elem: RepairViewModel & { tab_pos: number }) => { + this.repairs.push(elem); + }); + this.loading = "fetched"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + }, +}); diff --git a/src/stores/admin/unit/repair.ts b/src/stores/admin/unit/repair.ts index 3104db8..91e444e 100644 --- a/src/stores/admin/unit/repair.ts +++ b/src/stores/admin/unit/repair.ts @@ -1,5 +1,9 @@ import { defineStore } from "pinia"; -import type { RepairViewModel, UpdateRepairViewModel } from "@/viewmodels/admin/unit/repair.models"; +import type { + CreateRepairViewModel, + RepairViewModel, + UpdateRepairViewModel, +} from "@/viewmodels/admin/unit/repair.models"; import { http } from "@/serverCom"; import type { AxiosResponse } from "axios"; @@ -94,6 +98,17 @@ export const useRepairStore = defineStore("repair", { responseType: "blob", }); }, + async createRepair(repair: CreateRepairViewModel): Promise> { + const result = await http.post(`/admin/repair`, { + affected: repair.affected, + affectedId: repair.affectedId, + title: repair.title, + description: repair.description, + responsible: repair.responsible, + reports: repair.reports, + }); + return result; + }, async updateRepair(repair: UpdateRepairViewModel): Promise> { const result = await http.patch(`/admin/repair/${repair.id}`, { status: repair.status, diff --git a/src/stores/admin/unit/vehicle/repair.ts b/src/stores/admin/unit/vehicle/repair.ts new file mode 100644 index 0000000..beb30a1 --- /dev/null +++ b/src/stores/admin/unit/vehicle/repair.ts @@ -0,0 +1,43 @@ +import { defineStore } from "pinia"; +import { http } from "@/serverCom"; +import { useVehicleStore } from "./vehicle"; +import type { RepairViewModel } from "@/viewmodels/admin/unit/repair.models"; + +export const useVehicleRepairStore = defineStore("vehicleRepair", { + state: () => { + return { + repairs: [] as Array, + totalCount: 0 as number, + loading: "loading" as "loading" | "fetched" | "failed", + }; + }, + actions: { + fetchRepairForVehicle(offset = 0, count = 25, search = "", clear = false) { + const vehicleId = useVehicleStore().activeVehicle; + if (clear) this.repairs = []; + this.loading = "loading"; + http + .get( + `/admin/repair/vehicle/${vehicleId}?offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}` + ) + .then((result) => { + this.totalCount = result.data.total; + result.data.repairs + .filter((elem: RepairViewModel) => this.repairs.findIndex((m) => m.id == elem.id) == -1) + .map((elem: RepairViewModel, index: number): RepairViewModel & { tab_pos: number } => { + return { + ...elem, + tab_pos: index + offset, + }; + }) + .forEach((elem: RepairViewModel & { tab_pos: number }) => { + this.repairs.push(elem); + }); + this.loading = "fetched"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + }, +}); diff --git a/src/stores/admin/unit/wearable/repair.ts b/src/stores/admin/unit/wearable/repair.ts new file mode 100644 index 0000000..95f74e2 --- /dev/null +++ b/src/stores/admin/unit/wearable/repair.ts @@ -0,0 +1,43 @@ +import { defineStore } from "pinia"; +import { http } from "@/serverCom"; +import { useWearableStore } from "./wearable"; +import type { RepairViewModel } from "@/viewmodels/admin/unit/repair.models"; + +export const useWearableRepairStore = defineStore("wearableRepair", { + state: () => { + return { + repairs: [] as Array, + totalCount: 0 as number, + loading: "loading" as "loading" | "fetched" | "failed", + }; + }, + actions: { + fetchRepairForWearable(offset = 0, count = 25, search = "", clear = false) { + const wearableId = useWearableStore().activeWearable; + if (clear) this.repairs = []; + this.loading = "loading"; + http + .get( + `/admin/repair/wearable/${wearableId}?offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}` + ) + .then((result) => { + this.totalCount = result.data.total; + result.data.repairs + .filter((elem: RepairViewModel) => this.repairs.findIndex((m) => m.id == elem.id) == -1) + .map((elem: RepairViewModel, index: number): RepairViewModel & { tab_pos: number } => { + return { + ...elem, + tab_pos: index + offset, + }; + }) + .forEach((elem: RepairViewModel & { tab_pos: number }) => { + this.repairs.push(elem); + }); + this.loading = "fetched"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + }, +}); diff --git a/src/viewmodels/admin/unit/repair.models.ts b/src/viewmodels/admin/unit/repair.models.ts index b40f157..cef3a72 100644 --- a/src/viewmodels/admin/unit/repair.models.ts +++ b/src/viewmodels/admin/unit/repair.models.ts @@ -27,6 +27,7 @@ export type RepairViewModel = { finishedAt?: Date; status: string; responsible: string; + title: string; description: string; images: string[]; reportDocument: string; @@ -34,10 +35,12 @@ export type RepairViewModel = { } & RepairAssigned; export interface CreateRepairViewModel { - description: string; - reportedBy: string; - affectedId: string; affected: "equipment" | "vehicle" | "wearable"; + affectedId: string; + title: string; + description: string; + responsible: string; + reports: string[]; } export interface UpdateRepairViewModel { diff --git a/src/views/admin/unit/damageReport/DamageReportRouting.vue b/src/views/admin/unit/damageReport/DamageReportRouting.vue index a25335c..c876d31 100644 --- a/src/views/admin/unit/damageReport/DamageReportRouting.vue +++ b/src/views/admin/unit/damageReport/DamageReportRouting.vue @@ -5,20 +5,32 @@