diff --git a/src/components/admin/unit/equipment/CreateEquipmentModal.vue b/src/components/admin/unit/equipment/CreateEquipmentModal.vue new file mode 100644 index 0000000..4f934d7 --- /dev/null +++ b/src/components/admin/unit/equipment/CreateEquipmentModal.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/src/components/admin/unit/equipment/EquipmentListItem.vue b/src/components/admin/unit/equipment/EquipmentListItem.vue new file mode 100644 index 0000000..8eed147 --- /dev/null +++ b/src/components/admin/unit/equipment/EquipmentListItem.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/components/admin/unit/vehicle/CreateVehicleModal.vue b/src/components/admin/unit/vehicle/CreateVehicleModal.vue new file mode 100644 index 0000000..19fe092 --- /dev/null +++ b/src/components/admin/unit/vehicle/CreateVehicleModal.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/src/components/admin/unit/vehicle/VehicleListItem.vue b/src/components/admin/unit/vehicle/VehicleListItem.vue new file mode 100644 index 0000000..5ac56f5 --- /dev/null +++ b/src/components/admin/unit/vehicle/VehicleListItem.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts index 503ce7f..65d07b0 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -310,6 +310,43 @@ const router = createRouter({ component: () => import("@/views/RouterView.vue"), meta: { type: "read", section: "unit" }, beforeEnter: [abilityAndNavUpdate], + children: [ + { + path: "", + name: "admin-unit-default", + component: () => import("@/views/admin/ViewSelect.vue"), + meta: { type: "read", section: "unit" }, + beforeEnter: [abilityAndNavUpdate], + }, + { + path: "equipment", + name: "admin-unit-equipment-route", + component: () => import("@/views/RouterView.vue"), + meta: { type: "read", section: "unit", module: "equipment" }, + beforeEnter: [abilityAndNavUpdate], + children: [ + { + path: "", + name: "admin-unit-equipment", + component: () => import("@/views/admin/unit/equipment/Equipment.vue"), + }, + ], + }, + { + path: "vehicle", + name: "admin-unit-vehicle-route", + component: () => import("@/views/RouterView.vue"), + meta: { type: "read", section: "unit", module: "vehicle" }, + beforeEnter: [abilityAndNavUpdate], + children: [ + { + path: "", + name: "admin-unit-vehicle", + component: () => import("@/views/admin/unit/vehicle/Vehicle.vue"), + }, + ], + }, + ], }, { path: "configuration", diff --git a/src/stores/admin/navigation.ts b/src/stores/admin/navigation.ts index a17bba9..f11acbf 100644 --- a/src/stores/admin/navigation.ts +++ b/src/stores/admin/navigation.ts @@ -62,7 +62,7 @@ export const useNavigationStore = defineStore("navigation", { { key: "unit", title: "Wehr", - levelDefault: "", + levelDefault: "equipment", } as topLevelNavigationModel, ] : []), @@ -104,6 +104,13 @@ export const useNavigationStore = defineStore("navigation", { ...(abilityStore.can("read", "club", "listprint") ? [{ key: "listprint", title: "Liste Drucken" }] : []), ], }, + unit: { + mainTitle: "Wehr", + main: [ + ...(abilityStore.can("read", "unit", "equipment") ? [{ key: "equipment", title: "Gerätschaften" }] : []), + ...(abilityStore.can("read", "unit", "vehicle") ? [{ key: "vehicle", title: "Fahrzeuge" }] : []), + ], + }, configuration: { mainTitle: "Einstellungen", main: [ diff --git a/src/stores/admin/unit/equipment/equipment.ts b/src/stores/admin/unit/equipment/equipment.ts new file mode 100644 index 0000000..b0611ae --- /dev/null +++ b/src/stores/admin/unit/equipment/equipment.ts @@ -0,0 +1,128 @@ +import { defineStore } from "pinia"; +import type { + EquipmentViewModel, + CreateEquipmentViewModel, + EquipmentStatisticsViewModel, + UpdateEquipmentViewModel, +} from "@/viewmodels/admin/unit/equipment/equipment.models"; +import { http } from "@/serverCom"; +import type { AxiosResponse } from "axios"; + +export const useEquipmentStore = defineStore("equipment", { + state: () => { + return { + equipments: [] as Array, + totalCount: 0 as number, + loading: "loading" as "loading" | "fetched" | "failed", + activeEquipment: null as string | null, + activeEquipmentObj: null as EquipmentViewModel | null, + activeEquipmentStatistics: null as EquipmentStatisticsViewModel | null, + loadingActive: "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> { + return await http.get(`/admin/equipment?noLimit=true`).then((res) => { + return { ...res, data: res.data.equipments }; + }); + }, + async getEquipmentsByIds(ids: Array): Promise> { + return await http + .post(`/admin/equipment/ids`, { + ids, + }) + .then((res) => { + return { ...res, data: res.data.equipments }; + }); + }, + async searchEquipments(search: string): Promise> { + return await http.get(`/admin/equipment?search=${search}&noLimit=true`).then((res) => { + return { ...res, data: res.data.equipments }; + }); + }, + fetchEquipmentByActiveId() { + this.loadingActive = "loading"; + http + .get(`/admin/equipment/${this.activeEquipment}`) + .then((res) => { + this.activeEquipmentObj = res.data; + this.loadingActive = "fetched"; + }) + .catch((err) => { + this.loadingActive = "failed"; + }); + }, + fetchEquipmentById(id: string) { + return http.get(`/admin/equipment/${id}`); + }, + fetchEquipmentStatisticsByActiveId() { + http + .get(`/admin/equipment/${this.activeEquipment}/statistics`) + .then((res) => { + this.activeEquipmentStatistics = res.data; + }) + .catch((err) => {}); + }, + async printEquipmentByActiveId() { + return http.get(`/admin/equipment/${this.activeEquipment}/print`, { + responseType: "blob", + }); + }, + fetchEquipmentStatisticsById(id: string) { + return http.get(`/admin/equipment/${id}/statistics`); + }, + async createEquipment(equipment: CreateEquipmentViewModel): Promise> { + const result = await http.post(`/admin/equipment`, { + salutationId: equipment.salutationId, + firstname: equipment.firstname, + lastname: equipment.lastname, + nameaffix: equipment.nameaffix, + birthdate: equipment.birthdate, + internalId: equipment.internalId, + }); + this.fetchEquipments(); + return result; + }, + async updateActiveEquipment(equipment: UpdateEquipmentViewModel): Promise> { + const result = await http.patch(`/admin/equipment/${equipment.id}`, { + salutationId: equipment.salutationId, + firstname: equipment.firstname, + lastname: equipment.lastname, + nameaffix: equipment.nameaffix, + birthdate: equipment.birthdate, + internalId: equipment.internalId, + }); + this.fetchEquipments(); + return result; + }, + async deleteEquipment(equipment: number): Promise> { + const result = await http.delete(`/admin/equipment/${equipment}`); + this.fetchEquipments(); + return result; + }, + }, +}); diff --git a/src/stores/admin/unit/vehicle/vehicle.ts b/src/stores/admin/unit/vehicle/vehicle.ts new file mode 100644 index 0000000..5b3e669 --- /dev/null +++ b/src/stores/admin/unit/vehicle/vehicle.ts @@ -0,0 +1,128 @@ +import { defineStore } from "pinia"; +import type { + VehicleViewModel, + CreateVehicleViewModel, + VehicleStatisticsViewModel, + UpdateVehicleViewModel, +} from "@/viewmodels/admin/unit/vehicle/vehicle.models"; +import { http } from "@/serverCom"; +import type { AxiosResponse } from "axios"; + +export const useVehicleStore = defineStore("vehicle", { + state: () => { + return { + vehicles: [] as Array, + totalCount: 0 as number, + loading: "loading" as "loading" | "fetched" | "failed", + activeVehicle: null as string | null, + activeVehicleObj: null as VehicleViewModel | null, + activeVehicleStatistics: null as VehicleStatisticsViewModel | null, + loadingActive: "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> { + return await http.get(`/admin/vehicle?noLimit=true`).then((res) => { + return { ...res, data: res.data.vehicles }; + }); + }, + async getVehiclesByIds(ids: Array): Promise> { + return await http + .post(`/admin/vehicle/ids`, { + ids, + }) + .then((res) => { + return { ...res, data: res.data.vehicles }; + }); + }, + async searchVehicles(search: string): Promise> { + return await http.get(`/admin/vehicle?search=${search}&noLimit=true`).then((res) => { + return { ...res, data: res.data.vehicles }; + }); + }, + fetchVehicleByActiveId() { + this.loadingActive = "loading"; + http + .get(`/admin/vehicle/${this.activeVehicle}`) + .then((res) => { + this.activeVehicleObj = res.data; + this.loadingActive = "fetched"; + }) + .catch((err) => { + this.loadingActive = "failed"; + }); + }, + fetchVehicleById(id: string) { + return http.get(`/admin/vehicle/${id}`); + }, + fetchVehicleStatisticsByActiveId() { + http + .get(`/admin/vehicle/${this.activeVehicle}/statistics`) + .then((res) => { + this.activeVehicleStatistics = res.data; + }) + .catch((err) => {}); + }, + async printVehicleByActiveId() { + return http.get(`/admin/vehicle/${this.activeVehicle}/print`, { + responseType: "blob", + }); + }, + fetchVehicleStatisticsById(id: string) { + return http.get(`/admin/vehicle/${id}/statistics`); + }, + async createVehicle(vehicle: CreateVehicleViewModel): Promise> { + const result = await http.post(`/admin/vehicle`, { + salutationId: vehicle.salutationId, + firstname: vehicle.firstname, + lastname: vehicle.lastname, + nameaffix: vehicle.nameaffix, + birthdate: vehicle.birthdate, + internalId: vehicle.internalId, + }); + this.fetchVehicles(); + return result; + }, + async updateActiveVehicle(vehicle: UpdateVehicleViewModel): Promise> { + const result = await http.patch(`/admin/vehicle/${vehicle.id}`, { + salutationId: vehicle.salutationId, + firstname: vehicle.firstname, + lastname: vehicle.lastname, + nameaffix: vehicle.nameaffix, + birthdate: vehicle.birthdate, + internalId: vehicle.internalId, + }); + this.fetchVehicles(); + return result; + }, + async deleteVehicle(vehicle: number): Promise> { + const result = await http.delete(`/admin/vehicle/${vehicle}`); + this.fetchVehicles(); + return result; + }, + }, +}); diff --git a/src/types/permissionTypes.ts b/src/types/permissionTypes.ts index 8dae3d3..8a686a9 100644 --- a/src/types/permissionTypes.ts +++ b/src/types/permissionTypes.ts @@ -1,27 +1,33 @@ export type PermissionSection = "club" | "unit" | "configuration" | "management"; export type PermissionModule = + // club | "member" | "calendar" | "newsletter" - | "newsletter_config" | "protocol" + | "query" | "listprint" + // unit + | "equipment" + | "vehicle" + // configuration | "qualification" | "award" | "executive_position" | "communication_type" | "membership_status" + | "newsletter_config" | "salutation" | "calendar_type" - | "user" - | "role" - | "webapi" - | "query" | "query_store" | "template" | "template_usage" - | "backup"; + | "backup" + // management + | "user" + | "role" + | "webapi"; export type PermissionType = "read" | "create" | "update" | "delete"; @@ -52,6 +58,8 @@ export const permissionModules: Array = [ "newsletter_config", "protocol", "listprint", + "equipment", + "vehicle", "qualification", "award", "executive_position", @@ -71,7 +79,7 @@ export const permissionModules: Array = [ export const permissionTypes: Array = ["read", "create", "update", "delete"]; export const sectionsAndModules: SectionsAndModulesObject = { club: ["member", "calendar", "newsletter", "protocol", "query", "listprint"], - unit: [], + unit: ["equipment", "vehicle"], configuration: [ "qualification", "award", diff --git a/src/viewmodels/admin/unit/equipment/equipment.models.ts b/src/viewmodels/admin/unit/equipment/equipment.models.ts new file mode 100644 index 0000000..4ea40a5 --- /dev/null +++ b/src/viewmodels/admin/unit/equipment/equipment.models.ts @@ -0,0 +1,39 @@ +export interface EquipmentViewModel { + id: string; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + internalId?: string; +} + +export interface EquipmentStatisticsViewModel { + id: string; + salutation: string; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + todayAge: number; + ageThisYear: number; + exactAge: string; +} + +export interface CreateEquipmentViewModel { + salutationId: number; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + internalId?: string; +} + +export interface UpdateEquipmentViewModel { + id: string; + salutationId: number; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + internalId?: string; +} diff --git a/src/viewmodels/admin/unit/vehicle/vehicle.models.ts b/src/viewmodels/admin/unit/vehicle/vehicle.models.ts new file mode 100644 index 0000000..d35fe94 --- /dev/null +++ b/src/viewmodels/admin/unit/vehicle/vehicle.models.ts @@ -0,0 +1,39 @@ +export interface VehicleViewModel { + id: string; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + internalId?: string; +} + +export interface VehicleStatisticsViewModel { + id: string; + salutation: string; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + todayAge: number; + ageThisYear: number; + exactAge: string; +} + +export interface CreateVehicleViewModel { + salutationId: number; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + internalId?: string; +} + +export interface UpdateVehicleViewModel { + id: string; + salutationId: number; + firstname: string; + lastname: string; + nameaffix: string; + birthdate: Date; + internalId?: string; +} diff --git a/src/views/admin/unit/equipment/Equipment.vue b/src/views/admin/unit/equipment/Equipment.vue new file mode 100644 index 0000000..4348010 --- /dev/null +++ b/src/views/admin/unit/equipment/Equipment.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/src/views/admin/unit/vehicle/Vehicle.vue b/src/views/admin/unit/vehicle/Vehicle.vue new file mode 100644 index 0000000..6b16546 --- /dev/null +++ b/src/views/admin/unit/vehicle/Vehicle.vue @@ -0,0 +1,70 @@ + + + + +