edit repairs
This commit is contained in:
parent
c79d5bb1cd
commit
789272dc37
9 changed files with 201 additions and 74 deletions
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,38 +1,39 @@
|
|||
<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 w-full">
|
||||
<div v-if="activeRepairObj != null" class="flex flex-col gap-2 h-full w-full overflow-y-auto">
|
||||
<div>
|
||||
<label for="status">Status</label>
|
||||
<input id="status" ref="status" type="text" :readonly="!editStatus" :value="activeRepairObj.status" />
|
||||
</div>
|
||||
<button
|
||||
v-if="!editStatus && !activeRepairObj.finishedAt"
|
||||
primary
|
||||
class="w-fit! self-end"
|
||||
@click="editStatus = true"
|
||||
>
|
||||
Status ändern
|
||||
</button>
|
||||
<div v-else-if="!activeRepairObj.finishedAt" class="flex flex-row gap-2 justify-end">
|
||||
<button primary-outline class="w-fit!" @click="saveStatus(true)">speichern und abschließen</button>
|
||||
<button primary class="w-fit!" @click="saveStatus(false)">Status speichern</button>
|
||||
</div>
|
||||
<br />
|
||||
<form class="flex flex-col gap-2" @submit.prevent="saveData">
|
||||
<div>
|
||||
<label for="status">Status</label>
|
||||
<input id="status" ref="status" type="text" :readonly="!editStatus" :value="activeRepairObj.status" />
|
||||
<label for="title">Kurzbeschreibung</label>
|
||||
<input id="title" type="text" placeholder="---" :value="activeRepairObj.title" />
|
||||
</div>
|
||||
<button
|
||||
v-if="!editStatus && !activeRepairObj.finishedAt"
|
||||
primary
|
||||
class="w-fit! self-end"
|
||||
@click="editStatus = true"
|
||||
>
|
||||
Status ändern
|
||||
</button>
|
||||
<div v-else-if="!activeRepairObj.finishedAt" class="flex flex-row gap-2 justify-end">
|
||||
<button primary-outline class="w-fit!" @click="saveStatus(true)">speichern und abschließen</button>
|
||||
<button primary class="w-fit!" @click="saveStatus(false)">Status speichern</button>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<label for="description">Beschreibung des Schadens</label>
|
||||
<textarea id="description" readonly :value="activeRepairObj.description"></textarea>
|
||||
<label for="description">Beschreibung der Reparatur</label>
|
||||
<textarea id="description" placeholder="---" :value="activeRepairObj.description"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<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>
|
||||
<button primary type="submit" class="w-fit! self-end" :disabled="!!activeRepairObj.finishedAt">
|
||||
Änderungen speichern
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -41,7 +42,7 @@ 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 type { UpdateRepairStatusViewModel, UpdateRepairViewModel } from "@/viewmodels/admin/unit/repair.models";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -49,11 +50,6 @@ export default defineComponent({
|
|||
props: {
|
||||
repairId: String,
|
||||
},
|
||||
watch: {
|
||||
activeRepairObj(val: RepairViewModel, oldVal: RepairViewModel | null) {
|
||||
if (val && oldVal == null) this.loadImages();
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editStatus: false as boolean,
|
||||
|
@ -64,41 +60,47 @@ export default defineComponent({
|
|||
...mapWritableState(useRepairStore, ["activeRepairObj"]),
|
||||
...mapState(useAbilityStore, ["can"]),
|
||||
},
|
||||
mounted() {
|
||||
this.loadImages();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useRepairStore, ["loadRepairImage", "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);
|
||||
});
|
||||
}
|
||||
},
|
||||
...mapActions(useRepairStore, ["loadRepairImage", "updateRepairStatus", "updateRepair"]),
|
||||
saveStatus(finish: boolean) {
|
||||
if (this.activeRepairObj == null) return;
|
||||
this.loading = "loading";
|
||||
let update: UpdateRepairViewModel = {
|
||||
let update: UpdateRepairStatusViewModel = {
|
||||
id: this.activeRepairObj.id,
|
||||
status: (this.$refs.status as HTMLInputElement).value,
|
||||
noteByWorker: (this.$refs.noteByWorker as HTMLInputElement).value,
|
||||
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)
|
||||
.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.editStatus = false;
|
||||
})
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<template #diffMain>
|
||||
<div class="flex flex-col gap-2 grow px-7 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
|
||||
v-for="tab in tabs"
|
||||
:key="tab.route"
|
||||
|
@ -65,7 +65,11 @@ export default defineComponent({
|
|||
},
|
||||
data() {
|
||||
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: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MainTemplate title="Schadensmeldungen">
|
||||
<MainTemplate title="Reparaturen">
|
||||
<template #diffMain>
|
||||
<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">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue