edit repairs
This commit is contained in:
parent
c79d5bb1cd
commit
789272dc37
9 changed files with 201 additions and 74 deletions
|
@ -111,7 +111,7 @@ export default defineComponent({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ["update:model-value", "add:difference", "remove:difference", "add:damageReport", "add:damageReportByArray"],
|
emits: ["update:model-value", "add:difference", "remove:difference", "add:damageReport"],
|
||||||
watch: {
|
watch: {
|
||||||
modelValue() {
|
modelValue() {
|
||||||
// if (this.initialLoaded) return;
|
// if (this.initialLoaded) return;
|
||||||
|
@ -215,15 +215,18 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getDamageReportFromSearch(id: string) {
|
getDamageReportFromSearch(id: string) {
|
||||||
return this.filtered.find((f) => f.id == id);
|
return this.available.find((f) => f.id == id);
|
||||||
},
|
},
|
||||||
loadDamageReportsInitial() {
|
loadDamageReportsInitial() {
|
||||||
if (this.modelValue.length == 0) return;
|
if (this.modelValue.length == 0) {
|
||||||
|
this.chosen = [];
|
||||||
|
} else {
|
||||||
this.getDamageReportsByIds(this.modelValue)
|
this.getDamageReportsByIds(this.modelValue)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.chosen = res.data;
|
this.chosen = res.data;
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -201,7 +201,7 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getDamageReportFromSearch(id: string) {
|
getDamageReportFromSearch(id: string) {
|
||||||
return this.filtered.find((f) => f.id == id);
|
return this.available.find((f) => f.id == id);
|
||||||
},
|
},
|
||||||
loadDamageReportInitial() {
|
loadDamageReportInitial() {
|
||||||
if (this.modelValue == "" || this.modelValue == null) return;
|
if (this.modelValue == "" || this.modelValue == null) return;
|
||||||
|
|
|
@ -821,6 +821,12 @@ const router = createRouter({
|
||||||
component: () => import("@/views/admin/unit/repair/Overview.vue"),
|
component: () => import("@/views/admin/unit/repair/Overview.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "reports",
|
||||||
|
name: "admin-unit-repair-reports",
|
||||||
|
component: () => import("@/views/admin/unit/repair/DamageReports.vue"),
|
||||||
|
props: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { defineStore } from "pinia";
|
||||||
import type {
|
import type {
|
||||||
CreateRepairViewModel,
|
CreateRepairViewModel,
|
||||||
RepairViewModel,
|
RepairViewModel,
|
||||||
|
UpdateRepairStatusViewModel,
|
||||||
UpdateRepairViewModel,
|
UpdateRepairViewModel,
|
||||||
} from "@/viewmodels/admin/unit/repair.models";
|
} from "@/viewmodels/admin/unit/repair.models";
|
||||||
import { http } from "@/serverCom";
|
import { http } from "@/serverCom";
|
||||||
|
@ -110,9 +111,22 @@ export const useRepairStore = defineStore("repair", {
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
async updateRepair(repair: UpdateRepairViewModel): Promise<AxiosResponse<any, any>> {
|
async updateRepair(repair: UpdateRepairViewModel): Promise<AxiosResponse<any, any>> {
|
||||||
const result = await http.patch(`/admin/repair/${repair.id}`, {
|
const result = await http.patch(`/admin/repair/${this.activeRepairObj?.id}`, {
|
||||||
|
title: repair.title,
|
||||||
|
description: repair.description,
|
||||||
|
responsible: repair.responsible,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
async updateRepairReports(reports: Array<string>): Promise<AxiosResponse<any, any>> {
|
||||||
|
const result = await http.patch(`/admin/repair/${this.activeRepairObj?.id}/reports`, {
|
||||||
|
reports,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
async updateRepairStatus(repair: UpdateRepairStatusViewModel): Promise<AxiosResponse<any, any>> {
|
||||||
|
const result = await http.patch(`/admin/repair/${this.activeRepairObj?.id}/status`, {
|
||||||
status: repair.status,
|
status: repair.status,
|
||||||
noteByWorker: repair.noteByWorker,
|
|
||||||
done: repair.done,
|
done: repair.done,
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -43,9 +43,15 @@ export interface CreateRepairViewModel {
|
||||||
reports: string[];
|
reports: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateRepairViewModel {
|
export interface UpdateRepairStatusViewModel {
|
||||||
id: string;
|
id: string;
|
||||||
status: string;
|
status: string;
|
||||||
noteByWorker: string;
|
|
||||||
done: boolean;
|
done: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateRepairViewModel {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
responsible: string;
|
||||||
|
}
|
||||||
|
|
92
src/views/admin/unit/repair/DamageReports.vue
Normal file
92
src/views/admin/unit/repair/DamageReports.vue
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="activeRepairObj != null" class="flex flex-col gap-2 h-full w-full">
|
||||||
|
<DamageReportSearchSelectMultipleWithRelated
|
||||||
|
title="verbundene Schadensmeldungen"
|
||||||
|
:related="activeRepairObj.assigned"
|
||||||
|
:relatedId="activeRepairObj.relatedId"
|
||||||
|
:model-value="activeRepairObj.reports.map((r) => r.id)"
|
||||||
|
:disabled="!!activeRepairObj.finishedAt"
|
||||||
|
@add:damage-report="handleReportAdd"
|
||||||
|
@remove:difference="handleReportRemove"
|
||||||
|
/>
|
||||||
|
<div class="flex flex-col gap-2 overflow-y-scroll h-full">
|
||||||
|
<div
|
||||||
|
v-for="damageReport in activeRepairObj.reports"
|
||||||
|
:key="damageReport.id"
|
||||||
|
class="flex flex-col h-fit w-full border border-primary rounded-md"
|
||||||
|
>
|
||||||
|
<div class="bg-primary p-2 text-white flex flex-row justify-between items-center">
|
||||||
|
<p>{{ damageReport.title }}</p>
|
||||||
|
<TrashIcon
|
||||||
|
v-if="!activeRepairObj.finishedAt"
|
||||||
|
class="w-5 h-5 cursor-pointer"
|
||||||
|
@click="handleReportRemove(damageReport.id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p v-if="damageReport.description">Beschreibung: {{ damageReport.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button primary class="w-fit! self-end" :disabled="!!activeRepairObj.finishedAt" @click="saveReports">
|
||||||
|
Änderungen speichern
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import { mapActions, mapState, mapWritableState } from "pinia";
|
||||||
|
import { useAbilityStore } from "@/stores/ability";
|
||||||
|
import { useRepairStore } from "@/stores/admin/unit/repair";
|
||||||
|
import type { RepairViewModel, UpdateRepairViewModel } from "@/viewmodels/admin/unit/repair.models";
|
||||||
|
import DamageReportSearchSelectMultipleWithRelated from "@/components/search/DamageReportSearchSelectMultipleWithRelated.vue";
|
||||||
|
import { aC } from "node_modules/@fullcalendar/core/internal-common";
|
||||||
|
import type { DamageReportViewModel } from "@/viewmodels/admin/unit/damageReport.models";
|
||||||
|
import { TrashIcon } from "@heroicons/vue/24/outline";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
repairId: String,
|
||||||
|
},
|
||||||
|
watch: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: undefined as undefined | "loading" | "success" | "failed",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapWritableState(useRepairStore, ["activeRepairObj"]),
|
||||||
|
...mapState(useAbilityStore, ["can"]),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useRepairStore, ["loadRepairImage", "updateRepairReports"]),
|
||||||
|
handleReportAdd(report: DamageReportViewModel) {
|
||||||
|
if (!this.activeRepairObj) return;
|
||||||
|
this.activeRepairObj.reports.push(report);
|
||||||
|
},
|
||||||
|
handleReportRemove(reportId: string) {
|
||||||
|
if (!this.activeRepairObj) return;
|
||||||
|
this.activeRepairObj.reports = this.activeRepairObj.reports.filter((r) => r.id != reportId);
|
||||||
|
},
|
||||||
|
saveReports() {
|
||||||
|
if (this.activeRepairObj == null) return;
|
||||||
|
this.loading = "loading";
|
||||||
|
this.updateRepairReports(this.activeRepairObj.reports.map((r) => r.id))
|
||||||
|
.then((res) => {
|
||||||
|
this.loading = "success";
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.loading = "failed";
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loading = undefined;
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
<div v-if="activeRepairObj != null" class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||||
<div v-if="activeRepairObj != null" class="flex flex-col gap-2 w-full">
|
|
||||||
<div>
|
<div>
|
||||||
<label for="status">Status</label>
|
<label for="status">Status</label>
|
||||||
<input id="status" ref="status" type="text" :readonly="!editStatus" :value="activeRepairObj.status" />
|
<input id="status" ref="status" type="text" :readonly="!editStatus" :value="activeRepairObj.status" />
|
||||||
|
@ -18,21 +17,23 @@
|
||||||
<button primary class="w-fit!" @click="saveStatus(false)">Status speichern</button>
|
<button primary class="w-fit!" @click="saveStatus(false)">Status speichern</button>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
<form class="flex flex-col gap-2" @submit.prevent="saveData">
|
||||||
<div>
|
<div>
|
||||||
<label for="description">Beschreibung des Schadens</label>
|
<label for="title">Kurzbeschreibung</label>
|
||||||
<textarea id="description" readonly :value="activeRepairObj.description"></textarea>
|
<input id="title" type="text" placeholder="---" :value="activeRepairObj.title" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="description">Beschreibung der Reparatur</label>
|
||||||
|
<textarea id="description" placeholder="---" :value="activeRepairObj.description"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="responsible">Verantwortlich</label>
|
<label for="responsible">Verantwortlich</label>
|
||||||
<input id="responsible" type="text" readonly placeholder="---" :value="activeRepairObj.responsible" />
|
<input id="responsible" type="text" placeholder="---" :value="activeRepairObj.responsible" />
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Bild</label>
|
|
||||||
<div ref="imgs">
|
|
||||||
<small v-if="activeRepairObj.images.length == 0">Keine Bilder hochgeladen</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<button primary type="submit" class="w-fit! self-end" :disabled="!!activeRepairObj.finishedAt">
|
||||||
|
Änderungen speichern
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ import { defineComponent } from "vue";
|
||||||
import { mapActions, mapState, mapWritableState } from "pinia";
|
import { mapActions, mapState, mapWritableState } from "pinia";
|
||||||
import { useAbilityStore } from "@/stores/ability";
|
import { useAbilityStore } from "@/stores/ability";
|
||||||
import { useRepairStore } from "@/stores/admin/unit/repair";
|
import { useRepairStore } from "@/stores/admin/unit/repair";
|
||||||
import type { RepairViewModel, UpdateRepairViewModel } from "@/viewmodels/admin/unit/repair.models";
|
import type { UpdateRepairStatusViewModel, UpdateRepairViewModel } from "@/viewmodels/admin/unit/repair.models";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -49,11 +50,6 @@ export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
repairId: String,
|
repairId: String,
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
activeRepairObj(val: RepairViewModel, oldVal: RepairViewModel | null) {
|
|
||||||
if (val && oldVal == null) this.loadImages();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editStatus: false as boolean,
|
editStatus: false as boolean,
|
||||||
|
@ -64,41 +60,47 @@ export default defineComponent({
|
||||||
...mapWritableState(useRepairStore, ["activeRepairObj"]),
|
...mapWritableState(useRepairStore, ["activeRepairObj"]),
|
||||||
...mapState(useAbilityStore, ["can"]),
|
...mapState(useAbilityStore, ["can"]),
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.loadImages();
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useRepairStore, ["loadRepairImage", "updateRepair"]),
|
...mapActions(useRepairStore, ["loadRepairImage", "updateRepairStatus", "updateRepair"]),
|
||||||
loadImages() {
|
|
||||||
for (const i of this.activeRepairObj?.images ?? []) {
|
|
||||||
this.loadRepairImage(i)
|
|
||||||
.then((response) => {
|
|
||||||
const contentType =
|
|
||||||
response.headers && response.headers["content-type"] ? response.headers["content-type"] : "image/*";
|
|
||||||
const blob = new Blob([response.data], { type: contentType });
|
|
||||||
const img = document.createElement("img");
|
|
||||||
img.src = window.URL.createObjectURL(blob);
|
|
||||||
img.alt = "Schadensbild";
|
|
||||||
img.classList = "h-35 w-auto";
|
|
||||||
(this.$refs.imgs as HTMLElement).appendChild(img);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saveStatus(finish: boolean) {
|
saveStatus(finish: boolean) {
|
||||||
if (this.activeRepairObj == null) return;
|
if (this.activeRepairObj == null) return;
|
||||||
this.loading = "loading";
|
this.loading = "loading";
|
||||||
let update: UpdateRepairViewModel = {
|
let update: UpdateRepairStatusViewModel = {
|
||||||
id: this.activeRepairObj.id,
|
id: this.activeRepairObj.id,
|
||||||
status: (this.$refs.status as HTMLInputElement).value,
|
status: (this.$refs.status as HTMLInputElement).value,
|
||||||
noteByWorker: (this.$refs.noteByWorker as HTMLInputElement).value,
|
|
||||||
done: finish,
|
done: finish,
|
||||||
};
|
};
|
||||||
|
this.updateRepairStatus(update)
|
||||||
|
.then((res) => {
|
||||||
|
this.activeRepairObj!.status = update.status;
|
||||||
|
this.activeRepairObj!.finishedAt = update.done ? new Date() : undefined;
|
||||||
|
this.loading = "success";
|
||||||
|
this.editStatus = false;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.loading = "failed";
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loading = undefined;
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
saveData(e: any) {
|
||||||
|
if (this.activeRepairObj == null) return;
|
||||||
|
this.loading = "loading";
|
||||||
|
const formData = e.target.elements;
|
||||||
|
let update: UpdateRepairViewModel = {
|
||||||
|
id: this.activeRepairObj.id,
|
||||||
|
title: formData.title.value,
|
||||||
|
description: formData.description.value,
|
||||||
|
responsible: formData.responsible.value,
|
||||||
|
};
|
||||||
this.updateRepair(update)
|
this.updateRepair(update)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.activeRepairObj!.status = update.status;
|
this.activeRepairObj!.title = update.title;
|
||||||
|
this.activeRepairObj!.description = update.description;
|
||||||
|
this.activeRepairObj!.responsible = update.responsible;
|
||||||
this.loading = "success";
|
this.loading = "success";
|
||||||
this.editStatus = false;
|
this.editStatus = false;
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<template #diffMain>
|
<template #diffMain>
|
||||||
<div class="flex flex-col gap-2 grow px-7 overflow-hidden">
|
<div class="flex flex-col gap-2 grow px-7 overflow-hidden">
|
||||||
<div class="flex flex-col grow gap-2 overflow-hidden">
|
<div class="flex flex-col grow gap-2 overflow-hidden">
|
||||||
<div hidden class="w-full flex flex-row max-lg:flex-wrap justify-center">
|
<div class="w-full flex flex-row max-lg:flex-wrap justify-center">
|
||||||
<RouterLink
|
<RouterLink
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
:key="tab.route"
|
:key="tab.route"
|
||||||
|
@ -65,7 +65,11 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tabs: [{ route: "admin-unit-repair-overview", title: "Übersicht" }],
|
tabs: [
|
||||||
|
{ route: "admin-unit-repair-overview", title: "Übersicht" },
|
||||||
|
// { route: "admin-unit-repair-overview", title: "Bilder & Bericht" },
|
||||||
|
{ route: "admin-unit-repair-reports", title: "Schadensmeldungen" },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<MainTemplate title="Schadensmeldungen">
|
<MainTemplate title="Reparaturen">
|
||||||
<template #diffMain>
|
<template #diffMain>
|
||||||
<div class="flex flex-col gap-2 grow px-7 overflow-hidden">
|
<div class="flex flex-col gap-2 grow px-7 overflow-hidden">
|
||||||
<div class="w-full flex flex-row max-lg:flex-wrap justify-center">
|
<div class="w-full flex flex-row max-lg:flex-wrap justify-center">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue