force management
This commit is contained in:
parent
f50dff99f3
commit
8353eca4a2
14 changed files with 453 additions and 30 deletions
|
@ -5,6 +5,10 @@
|
|||
</div>
|
||||
<br />
|
||||
<form class="flex flex-col gap-4 py-2" @submit.prevent="triggerCreate">
|
||||
<div>
|
||||
<label for="internalId">Interne Id (optional)</label>
|
||||
<input type="text" id="internalId" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="firstname">Vorname</label>
|
||||
<input type="text" id="firstname" required />
|
||||
|
@ -17,6 +21,14 @@
|
|||
<label for="nameaffix">Nameaffix (optional)</label>
|
||||
<input type="text" id="nameaffix" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="commissioned">verfügbar ab (optional)</label>
|
||||
<input type="date" id="commissioned" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="decommissioned">verfügbar bis (optional)</label>
|
||||
<input type="date" id="decommissioned" />
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<button primary type="submit" :disabled="status == 'loading' || status?.status == 'success'">erstellen</button>
|
||||
<Spinner v-if="status == 'loading'" class="my-auto" />
|
||||
|
@ -67,9 +79,12 @@ export default defineComponent({
|
|||
triggerCreate(e: any) {
|
||||
let formData = e.target.elements;
|
||||
let createForce: CreateForceViewModel = {
|
||||
internalId: formData.internalId.value,
|
||||
firstname: formData.firstname.value,
|
||||
lastname: formData.lastname.value,
|
||||
nameaffix: formData.nameaffix.value,
|
||||
commissioned: formData.commissioned.value,
|
||||
decommissioned: formData.decommissioned.value,
|
||||
};
|
||||
this.status = "loading";
|
||||
this.createForce(createForce)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<template>
|
||||
<div class="w-full md:max-w-md">
|
||||
<div class="flex flex-col items-center">
|
||||
<p class="text-xl font-medium">Mitglied löschen</p>
|
||||
<p class="text-xl font-medium">Kraft löschen</p>
|
||||
</div>
|
||||
<br />
|
||||
<p class="text-center">
|
||||
Mitglied {{ force?.lastname }}, {{ force?.firstname }}
|
||||
{{ force?.nameaffix ? `- ${force.nameaffix}` : "" }} löschen?
|
||||
Kraft {{ force?.lastname }}, {{ force?.firstname }} {{ force?.nameaffix ? `- ${force.nameaffix}` : "" }} löschen?
|
||||
</p>
|
||||
<br />
|
||||
|
||||
|
@ -74,7 +73,7 @@ export default defineComponent({
|
|||
.then(() => {
|
||||
this.status = { status: "success" };
|
||||
this.timeout = setTimeout(() => {
|
||||
this.$router.push({ name: "admin-club-force" });
|
||||
this.$router.push({ name: "admin-configuration-force" });
|
||||
this.closeModal();
|
||||
}, 1500);
|
||||
})
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
<template>
|
||||
<RouterLink
|
||||
:to="{ name: 'admin-club-force-overview', params: { forceId: force.id } }"
|
||||
class="flex flex-col h-fit w-full border border-primary rounded-md"
|
||||
>
|
||||
<div 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>{{ force.lastname }}, {{ force.firstname }} {{ force.nameaffix ? `- ${force.nameaffix}` : "" }}</p>
|
||||
<div class="flex flex-row">
|
||||
<div v-if="can('update', 'configuration', 'force')" @click="openUpdateModal">
|
||||
<PencilIcon class="w-5 h-5 p-1 box-content cursor-pointer" />
|
||||
</div>
|
||||
<div v-if="can('delete', 'configuration', 'force')" @click="openDeleteModal">
|
||||
<TrashIcon class="w-5 h-5 p-1 box-content cursor-pointer" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-2">
|
||||
<p>Daten</p>
|
||||
<p>verfügbar ab: {{ force.commissioned }}</p>
|
||||
<p>verfügbar bis: {{ force?.decommissioned ?? "---" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
import { defineAsyncComponent, defineComponent, markRaw, type PropType } from "vue";
|
||||
import { mapState, mapActions } from "pinia";
|
||||
import { useAbilityStore } from "@/stores/ability";
|
||||
import type { ForceViewModel } from "@/viewmodels/admin/configuration/force.models";
|
||||
import { useModalStore } from "../../../../stores/modal";
|
||||
import { PencilIcon, TrashIcon } from "@heroicons/vue/24/outline";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -27,5 +35,20 @@ export default defineComponent({
|
|||
computed: {
|
||||
...mapState(useAbilityStore, ["can"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useModalStore, ["openModal"]),
|
||||
openUpdateModal() {
|
||||
this.openModal(
|
||||
markRaw(defineAsyncComponent(() => import("@/components/admin/configuration/force/UpdateForceModal.vue"))),
|
||||
this.force.id
|
||||
);
|
||||
},
|
||||
openDeleteModal() {
|
||||
this.openModal(
|
||||
markRaw(defineAsyncComponent(() => import("@/components/admin/configuration/force/DeleteForceModal.vue"))),
|
||||
this.force.id
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
145
src/components/admin/configuration/force/UpdateForceModal.vue
Normal file
145
src/components/admin/configuration/force/UpdateForceModal.vue
Normal file
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<div class="w-full md:max-w-md">
|
||||
<div class="flex flex-col items-center">
|
||||
<p class="text-xl font-medium">Kraft aktualisieren</p>
|
||||
</div>
|
||||
<br />
|
||||
<Spinner v-if="loading == 'loading' && force == null" class="mx-auto" />
|
||||
<p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">↺ laden fehlgeschlagen</p>
|
||||
<form v-if="force" class="flex flex-col gap-4 py-2" @submit.prevent="triggerUpdate">
|
||||
<div>
|
||||
<label for="internalId">Interne Id (optional)</label>
|
||||
<input type="text" id="internalId" v-model="force.internalId" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="firstname">Vorname</label>
|
||||
<input type="text" id="firstname" required v-model="force.firstname" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="lastname">Nachname</label>
|
||||
<input type="text" id="lastname" required v-model="force.lastname" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="nameaffix">Nameaffix (optional)</label>
|
||||
<input type="text" id="nameaffix" v-model="force.nameaffix" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="commissioned">verfügbar ab (optional)</label>
|
||||
<input type="date" id="commissioned" v-model="force.commissioned" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="decommissioned">verfügbar bis (optional)</label>
|
||||
<input type="date" id="decommissioned" v-model="force.decommissioned" />
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<button primary-outline type="reset" :disabled="canSaveOrReset" @click="resetForm">verwerfen</button>
|
||||
<button primary type="submit" :disabled="status == 'loading' || canSaveOrReset">speichern</button>
|
||||
<Spinner v-if="status == 'loading'" class="my-auto" />
|
||||
<SuccessCheckmark v-else-if="status?.status == 'success'" />
|
||||
<FailureXMark v-else-if="status?.status == 'failed'" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="flex flex-row justify-end">
|
||||
<div class="flex flex-row gap-4 py-2">
|
||||
<button primary-outline @click="closeModal" :disabled="status == 'loading' || status?.status == 'success'">
|
||||
schließen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { mapState, mapActions } from "pinia";
|
||||
import { useModalStore } from "@/stores/modal";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import SuccessCheckmark from "@/components/SuccessCheckmark.vue";
|
||||
import FailureXMark from "@/components/FailureXMark.vue";
|
||||
import { Listbox, ListboxButton, ListboxOptions, ListboxOption, ListboxLabel } from "@headlessui/vue";
|
||||
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid";
|
||||
import { useForceStore } from "@/stores/admin/configuration/forces";
|
||||
import type {
|
||||
CreateForceViewModel,
|
||||
ForceViewModel,
|
||||
UpdateForceViewModel,
|
||||
} from "@/viewmodels/admin/configuration/force.models";
|
||||
import isEqual from "lodash.isequal";
|
||||
import cloneDeep from "lodash.clonedeep";
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
props: {
|
||||
data: { type: String, default: "" },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: "loading" as "loading" | "fetched" | "failed",
|
||||
status: null as null | "loading" | { status: "success" | "failed"; reason?: string },
|
||||
force: null as null | ForceViewModel,
|
||||
origin: null as null | ForceViewModel,
|
||||
timeout: null as any,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canSaveOrReset(): boolean {
|
||||
return isEqual(this.origin, this.force);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchItem();
|
||||
},
|
||||
beforeUnmount() {
|
||||
try {
|
||||
clearTimeout(this.timeout);
|
||||
} catch (error) {}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useModalStore, ["closeModal"]),
|
||||
...mapActions(useForceStore, ["updateForce", "fetchForceById"]),
|
||||
resetForm() {
|
||||
this.force = cloneDeep(this.origin);
|
||||
},
|
||||
fetchItem() {
|
||||
this.loading = "loading";
|
||||
this.fetchForceById(this.data)
|
||||
.then((res) => {
|
||||
this.loading = "fetched";
|
||||
this.origin = res.data;
|
||||
this.force = cloneDeep(this.origin);
|
||||
})
|
||||
.catch((err) => {
|
||||
this.loading = "failed";
|
||||
});
|
||||
},
|
||||
triggerUpdate(e: any) {
|
||||
let formData = e.target.elements;
|
||||
let updateForce: UpdateForceViewModel = {
|
||||
id: this.data,
|
||||
internalId: formData.internalId.value,
|
||||
firstname: formData.firstname.value,
|
||||
lastname: formData.lastname.value,
|
||||
nameaffix: formData.nameaffix.value,
|
||||
commissioned: formData.commissioned.value,
|
||||
decommissioned: formData.decommissioned.value,
|
||||
};
|
||||
this.status = "loading";
|
||||
this.updateForce(updateForce)
|
||||
.then(() => {
|
||||
this.fetchItem();
|
||||
this.status = { status: "success" };
|
||||
})
|
||||
.catch(() => {
|
||||
this.status = { status: "failed" };
|
||||
})
|
||||
.finally(() => {
|
||||
this.timeout = setTimeout(() => {
|
||||
this.status = null;
|
||||
}, 2000);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
|
@ -119,10 +119,24 @@ const router = createRouter({
|
|||
{
|
||||
path: "force",
|
||||
name: "admin-configuration-force",
|
||||
component: () => import("@/views/admin/ViewSelect.vue"),
|
||||
component: () => import("@/views/admin/configuration/force/Force.vue"),
|
||||
meta: { type: "read", section: "configuration", module: "force" },
|
||||
beforeEnter: [abilityAndNavUpdate],
|
||||
},
|
||||
{
|
||||
path: "equipment",
|
||||
name: "admin-configuration-equipment",
|
||||
component: () => import("@/views/admin/configuration/force/Force.vue"),
|
||||
meta: { type: "read", section: "configuration", module: "equipment" },
|
||||
beforeEnter: [abilityAndNavUpdate],
|
||||
},
|
||||
{
|
||||
path: "vehicle",
|
||||
name: "admin-configuration-vehicle",
|
||||
component: () => import("@/views/admin/configuration/force/Force.vue"),
|
||||
meta: { type: "read", section: "configuration", module: "vehicle" },
|
||||
beforeEnter: [abilityAndNavUpdate],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
81
src/stores/admin/configuration/equipment.ts
Normal file
81
src/stores/admin/configuration/equipment.ts
Normal file
|
@ -0,0 +1,81 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { http } from "@/serverCom";
|
||||
import type { AxiosResponse } from "axios";
|
||||
import type {
|
||||
EquipmentViewModel,
|
||||
CreateEquipmentViewModel,
|
||||
UpdateEquipmentViewModel,
|
||||
} from "../../../viewmodels/admin/configuration/equipment.models";
|
||||
|
||||
export const useEquipmentStore = defineStore("equipment", {
|
||||
state: () => {
|
||||
return {
|
||||
equipments: [] as Array<EquipmentViewModel & { tab_pos: number }>,
|
||||
totalCount: 0 as number,
|
||||
loading: "loading" as "loading" | "fetched" | "failed",
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
fetchEquipments(offset = 0, count = 25, search = "", clear = false) {
|
||||
if (clear) this.equipments = [];
|
||||
this.loading = "loading";
|
||||
http
|
||||
.get(`/admin/equipment?offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}`)
|
||||
.then((result) => {
|
||||
this.totalCount = result.data.total;
|
||||
result.data.equipments
|
||||
.filter((elem: EquipmentViewModel) => this.equipments.findIndex((m) => m.id == elem.id) == -1)
|
||||
.map((elem: EquipmentViewModel, index: number): EquipmentViewModel & { tab_pos: number } => {
|
||||
return {
|
||||
...elem,
|
||||
tab_pos: index + offset,
|
||||
};
|
||||
})
|
||||
.forEach((elem: EquipmentViewModel & { tab_pos: number }) => {
|
||||
this.equipments.push(elem);
|
||||
});
|
||||
this.loading = "fetched";
|
||||
})
|
||||
.catch((err) => {
|
||||
this.loading = "failed";
|
||||
});
|
||||
},
|
||||
async getAllEquipments(): Promise<AxiosResponse<any, any>> {
|
||||
return await http.get(`/admin/equipment?noLimit=true`).then((res) => {
|
||||
return { ...res, data: res.data.equipments };
|
||||
});
|
||||
},
|
||||
async getEquipmentsByIds(ids: Array<string>): Promise<AxiosResponse<any, any>> {
|
||||
return await http
|
||||
.post(`/admin/equipment/ids`, {
|
||||
ids,
|
||||
})
|
||||
.then((res) => {
|
||||
return { ...res, data: res.data.equipments };
|
||||
});
|
||||
},
|
||||
async searchEquipments(search: string): Promise<AxiosResponse<any, any>> {
|
||||
return await http.get(`/admin/equipment?search=${search}&noLimit=true`).then((res) => {
|
||||
return { ...res, data: res.data.equipments };
|
||||
});
|
||||
},
|
||||
fetchEquipmentById(id: string) {
|
||||
return http.get(`/admin/equipment/${id}`);
|
||||
},
|
||||
async createEquipment(equipment: CreateEquipmentViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.post(`/admin/equipment`, equipment);
|
||||
this.fetchEquipments();
|
||||
return result;
|
||||
},
|
||||
async updateActiveEquipment(equipment: UpdateEquipmentViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.patch(`/admin/equipment/${equipment.id}`, equipment);
|
||||
this.fetchEquipments();
|
||||
return result;
|
||||
},
|
||||
async deleteEquipment(equipment: number): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.delete(`/admin/equipment/${equipment}`);
|
||||
this.fetchEquipments();
|
||||
return result;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -63,20 +63,12 @@ export const useForceStore = defineStore("force", {
|
|||
return http.get(`/admin/force/${id}`);
|
||||
},
|
||||
async createForce(force: CreateForceViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.post(`/admin/force`, {
|
||||
firstname: force.firstname,
|
||||
lastname: force.lastname,
|
||||
nameaffix: force.nameaffix,
|
||||
});
|
||||
const result = await http.post(`/admin/force`, force);
|
||||
this.fetchForces();
|
||||
return result;
|
||||
},
|
||||
async updateActiveForce(force: UpdateForceViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.patch(`/admin/force/${force.id}`, {
|
||||
firstname: force.firstname,
|
||||
lastname: force.lastname,
|
||||
nameaffix: force.nameaffix,
|
||||
});
|
||||
async updateForce(force: UpdateForceViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.patch(`/admin/force/${force.id}`, force);
|
||||
this.fetchForces();
|
||||
return result;
|
||||
},
|
||||
|
|
81
src/stores/admin/configuration/vehicle.ts
Normal file
81
src/stores/admin/configuration/vehicle.ts
Normal file
|
@ -0,0 +1,81 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { http } from "@/serverCom";
|
||||
import type { AxiosResponse } from "axios";
|
||||
import type {
|
||||
VehicleViewModel,
|
||||
CreateVehicleViewModel,
|
||||
UpdateVehicleViewModel,
|
||||
} from "../../../viewmodels/admin/configuration/vehicle.models";
|
||||
|
||||
export const useVehicleStore = defineStore("vehicle", {
|
||||
state: () => {
|
||||
return {
|
||||
vehicles: [] as Array<VehicleViewModel & { tab_pos: number }>,
|
||||
totalCount: 0 as number,
|
||||
loading: "loading" as "loading" | "fetched" | "failed",
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
fetchVehicles(offset = 0, count = 25, search = "", clear = false) {
|
||||
if (clear) this.vehicles = [];
|
||||
this.loading = "loading";
|
||||
http
|
||||
.get(`/admin/vehicle?offset=${offset}&count=${count}${search != "" ? "&search=" + search : ""}`)
|
||||
.then((result) => {
|
||||
this.totalCount = result.data.total;
|
||||
result.data.vehicles
|
||||
.filter((elem: VehicleViewModel) => this.vehicles.findIndex((m) => m.id == elem.id) == -1)
|
||||
.map((elem: VehicleViewModel, index: number): VehicleViewModel & { tab_pos: number } => {
|
||||
return {
|
||||
...elem,
|
||||
tab_pos: index + offset,
|
||||
};
|
||||
})
|
||||
.forEach((elem: VehicleViewModel & { tab_pos: number }) => {
|
||||
this.vehicles.push(elem);
|
||||
});
|
||||
this.loading = "fetched";
|
||||
})
|
||||
.catch((err) => {
|
||||
this.loading = "failed";
|
||||
});
|
||||
},
|
||||
async getAllVehicles(): Promise<AxiosResponse<any, any>> {
|
||||
return await http.get(`/admin/vehicle?noLimit=true`).then((res) => {
|
||||
return { ...res, data: res.data.vehicles };
|
||||
});
|
||||
},
|
||||
async getVehiclesByIds(ids: Array<string>): Promise<AxiosResponse<any, any>> {
|
||||
return await http
|
||||
.post(`/admin/vehicle/ids`, {
|
||||
ids,
|
||||
})
|
||||
.then((res) => {
|
||||
return { ...res, data: res.data.vehicles };
|
||||
});
|
||||
},
|
||||
async searchVehicles(search: string): Promise<AxiosResponse<any, any>> {
|
||||
return await http.get(`/admin/vehicle?search=${search}&noLimit=true`).then((res) => {
|
||||
return { ...res, data: res.data.vehicles };
|
||||
});
|
||||
},
|
||||
fetchVehicleById(id: string) {
|
||||
return http.get(`/admin/vehicle/${id}`);
|
||||
},
|
||||
async createVehicle(vehicle: CreateVehicleViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.post(`/admin/vehicle`, vehicle);
|
||||
this.fetchVehicles();
|
||||
return result;
|
||||
},
|
||||
async updateActiveVehicle(vehicle: UpdateVehicleViewModel): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.patch(`/admin/vehicle/${vehicle.id}`, vehicle);
|
||||
this.fetchVehicles();
|
||||
return result;
|
||||
},
|
||||
async deleteVehicle(vehicle: number): Promise<AxiosResponse<any, any>> {
|
||||
const result = await http.delete(`/admin/vehicle/${vehicle}`);
|
||||
this.fetchVehicles();
|
||||
return result;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -94,7 +94,11 @@ export const useNavigationStore = defineStore("navigation", {
|
|||
},
|
||||
configuration: {
|
||||
mainTitle: "Konfiguration",
|
||||
main: [...(abilityStore.can("read", "configuration", "force") ? [{ key: "force", title: "Kräfte" }] : [])],
|
||||
main: [
|
||||
...(abilityStore.can("read", "configuration", "force") ? [{ key: "force", title: "Kräfte" }] : []),
|
||||
...(abilityStore.can("read", "configuration", "equipment") ? [{ key: "equipment", title: "Geräte" }] : []),
|
||||
...(abilityStore.can("read", "configuration", "vehicle") ? [{ key: "vehicle", title: "Fahrzeuge" }] : []),
|
||||
],
|
||||
},
|
||||
management: {
|
||||
mainTitle: "Verwaltung",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export type PermissionSection = "operation" | "configuration" | "management";
|
||||
|
||||
export type PermissionModule = "mission" | "force" | "user" | "role" | "backup";
|
||||
export type PermissionModule = "mission" | "force" | "vehicle" | "equipment" | "user" | "role" | "backup";
|
||||
|
||||
export type PermissionType = "read" | "create" | "update" | "delete";
|
||||
|
||||
|
@ -24,10 +24,18 @@ export type SectionsAndModulesObject = {
|
|||
};
|
||||
|
||||
export const permissionSections: Array<PermissionSection> = ["operation", "configuration", "management"];
|
||||
export const permissionModules: Array<PermissionModule> = ["mission", "force", "user", "role", "backup"];
|
||||
export const permissionModules: Array<PermissionModule> = [
|
||||
"mission",
|
||||
"force",
|
||||
"vehicle",
|
||||
"equipment",
|
||||
"user",
|
||||
"role",
|
||||
"backup",
|
||||
];
|
||||
export const permissionTypes: Array<PermissionType> = ["read", "create", "update", "delete"];
|
||||
export const sectionsAndModules: SectionsAndModulesObject = {
|
||||
operation: ["mission"],
|
||||
configuration: ["force"],
|
||||
configuration: ["force", "vehicle", "equipment"],
|
||||
management: ["user", "role", "backup"],
|
||||
};
|
||||
|
|
25
src/viewmodels/admin/configuration/equipment.models.ts
Normal file
25
src/viewmodels/admin/configuration/equipment.models.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
export interface EquipmentViewModel {
|
||||
id: string;
|
||||
code?: string;
|
||||
type?: string;
|
||||
name: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
||||
export interface CreateEquipmentViewModel {
|
||||
code?: string;
|
||||
type?: string;
|
||||
name: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
||||
export interface UpdateEquipmentViewModel {
|
||||
id: string;
|
||||
code?: string;
|
||||
type?: string;
|
||||
name: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
|
@ -1,19 +1,28 @@
|
|||
export interface ForceViewModel {
|
||||
id: string;
|
||||
internalId?: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
||||
export interface CreateForceViewModel {
|
||||
internalId?: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
||||
export interface UpdateForceViewModel {
|
||||
id: string;
|
||||
internalId?: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
|
25
src/viewmodels/admin/configuration/vehicle.models.ts
Normal file
25
src/viewmodels/admin/configuration/vehicle.models.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
export interface VehicleViewModel {
|
||||
id: string;
|
||||
code?: string;
|
||||
type?: string;
|
||||
name: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
||||
export interface CreateVehicleViewModel {
|
||||
code?: string;
|
||||
type?: string;
|
||||
name: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
||||
|
||||
export interface UpdateVehicleViewModel {
|
||||
id: string;
|
||||
code?: string;
|
||||
type?: string;
|
||||
name: string;
|
||||
commissioned: Date;
|
||||
decommissioned?: Date;
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<div class="flex flex-row gap-4">
|
||||
<button v-if="can('create', 'operation', 'force')" primary class="!w-fit" @click="openCreateModal">
|
||||
Mitglied erstellen
|
||||
Kraft erstellen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@ import { defineAsyncComponent, defineComponent, markRaw } from "vue";
|
|||
import { mapActions, mapState } from "pinia";
|
||||
import MainTemplate from "@/templates/Main.vue";
|
||||
import { useForceStore } from "@/stores/admin/configuration/forces";
|
||||
import ForceListItem from "@/components/admin/club/force/ForceListItem.vue";
|
||||
import ForceListItem from "@/components/admin/configuration/force/ForceListItem.vue";
|
||||
import { useModalStore } from "@/stores/modal";
|
||||
import Pagination from "@/components/Pagination.vue";
|
||||
import type { ForceViewModel } from "@/viewmodels/admin/configuration/force.models";
|
||||
|
@ -62,7 +62,9 @@ export default defineComponent({
|
|||
...mapActions(useForceStore, ["fetchForces"]),
|
||||
...mapActions(useModalStore, ["openModal"]),
|
||||
openCreateModal() {
|
||||
this.openModal(markRaw(defineAsyncComponent(() => import("@/components/admin/club/force/CreateForceModal.vue"))));
|
||||
this.openModal(
|
||||
markRaw(defineAsyncComponent(() => import("@/components/admin/configuration/force/CreateForceModal.vue")))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue