Merge branch 'develop' into milestone/ff-admin-unit

# Conflicts:
#	package-lock.json
#	package.json
#	src/views/admin/club/newsletter/NewsletterRecipients.vue
This commit is contained in:
Julian Krauser 2025-06-08 08:02:16 +02:00
commit b7f22357ec
53 changed files with 1757 additions and 950 deletions

View file

@ -106,6 +106,7 @@ export const useMemberStore = defineStore("member", {
nameaffix: member.nameaffix,
birthdate: member.birthdate,
internalId: member.internalId,
note: member.note,
});
this.fetchMembers();
return result;
@ -118,6 +119,7 @@ export const useMemberStore = defineStore("member", {
nameaffix: member.nameaffix,
birthdate: member.birthdate,
internalId: member.internalId,
note: member.note,
});
this.fetchMembers();
return result;

View file

@ -0,0 +1,67 @@
import { defineStore } from "pinia";
import { http } from "@/serverCom";
import type { AxiosResponse } from "axios";
import { useMemberStore } from "./member";
import type {
CreateMemberEducationViewModel,
MemberEducationViewModel,
UpdateMemberEducationViewModel,
} from "@/viewmodels/admin/club/member/memberEducation.models";
export const useMemberEducationStore = defineStore("memberEducation", {
state: () => {
return {
memberEducations: [] as Array<MemberEducationViewModel>,
loading: "loading" as "loading" | "fetched" | "failed",
};
},
actions: {
fetchMemberEducationsForMember() {
const memberId = useMemberStore().activeMember;
this.loading = "loading";
http
.get(`/admin/member/${memberId}/educations`)
.then((result) => {
this.memberEducations = result.data;
this.loading = "fetched";
})
.catch((err) => {
this.loading = "failed";
});
},
fetchMemberEducationById(id: number) {
const memberId = useMemberStore().activeMember;
return http.get(`/admin/member/${memberId}/education/${id}`);
},
async createMemberEducation(memberEducation: CreateMemberEducationViewModel): Promise<AxiosResponse<any, any>> {
const memberId = useMemberStore().activeMember;
const result = await http.post(`/admin/member/${memberId}/education`, {
start: memberEducation.start,
end: memberEducation.end,
place: memberEducation.place,
note: memberEducation.note,
educationId: memberEducation.educationId,
});
this.fetchMemberEducationsForMember();
return result;
},
async updateMemberEducation(memberEducation: UpdateMemberEducationViewModel): Promise<AxiosResponse<any, any>> {
const memberId = useMemberStore().activeMember;
const result = await http.patch(`/admin/member/${memberId}/education/${memberEducation.id}`, {
start: memberEducation.start,
end: memberEducation.end,
place: memberEducation.place,
note: memberEducation.note,
educationId: memberEducation.educationId,
});
this.fetchMemberEducationsForMember();
return result;
},
async deleteMemberEducation(memberEducation: number): Promise<AxiosResponse<any, any>> {
const memberId = useMemberStore().activeMember;
const result = await http.delete(`/admin/member/${memberId}/education/${memberEducation}`);
this.fetchMemberEducationsForMember();
return result;
},
},
});

View file

@ -7,6 +7,7 @@ import { useMemberStore } from "./member";
import type {
CreateMembershipViewModel,
MembershipStatisticsViewModel,
MembershipTotalStatisticsViewModel,
MembershipViewModel,
UpdateMembershipViewModel,
} from "@/viewmodels/admin/club/member/membership.models";
@ -16,6 +17,7 @@ export const useMembershipStore = defineStore("membership", {
return {
memberships: [] as Array<MembershipViewModel>,
membershipStatistics: [] as Array<MembershipStatisticsViewModel>,
totalMembershipStatistics: undefined as undefined | MembershipTotalStatisticsViewModel,
loading: "loading" as "loading" | "fetched" | "failed",
};
},
@ -42,6 +44,15 @@ export const useMembershipStore = defineStore("membership", {
})
.catch((err) => {});
},
fetchMembershipTotalStatisticsForMember() {
const memberId = useMemberStore().activeMember;
http
.get(`/admin/member/${memberId}/memberships/totalstatistics`)
.then((result) => {
this.totalMembershipStatistics = result.data;
})
.catch((err) => {});
},
fetchMembershipById(id: number) {
const memberId = useMemberStore().activeMember;
return http.get(`/admin/member/${memberId}/membership/${id}`);

View file

@ -1,11 +1,10 @@
import { defineStore } from "pinia";
import type { CreateNewsletterViewModel, SyncNewsletterViewModel } from "@/viewmodels/admin/club/newsletter/newsletter.models";
import type { CreateNewsletterViewModel } from "@/viewmodels/admin/club/newsletter/newsletter.models";
import { http } from "@/serverCom";
import type { AxiosResponse } from "axios";
import type { NewsletterViewModel } from "@/viewmodels/admin/club/newsletter/newsletter.models";
import cloneDeep from "lodash.clonedeep";
import isEqual from "lodash.isequal";
import difference from "lodash.difference";
export const useNewsletterStore = defineStore("newsletter", {
state: () => {
@ -72,7 +71,6 @@ export const useNewsletterStore = defineStore("newsletter", {
const result = await http.post(`/admin/newsletter`, {
title: newsletter.title,
});
this.fetchNewsletters();
return result;
},
async synchronizeActiveNewsletter(): Promise<void> {

View file

@ -1,11 +1,10 @@
import { defineStore } from "pinia";
import type { CreateProtocolViewModel, SyncProtocolViewModel } from "@/viewmodels/admin/club/protocol/protocol.models";
import type { CreateProtocolViewModel } from "@/viewmodels/admin/club/protocol/protocol.models";
import { http } from "@/serverCom";
import type { AxiosResponse } from "axios";
import type { ProtocolViewModel } from "@/viewmodels/admin/club/protocol/protocol.models";
import cloneDeep from "lodash.clonedeep";
import isEqual from "lodash.isequal";
import difference from "lodash.difference";
export const useProtocolStore = defineStore("protocol", {
state: () => {
@ -73,7 +72,6 @@ export const useProtocolStore = defineStore("protocol", {
title: protocol.title,
date: protocol.date,
});
this.fetchProtocols();
return result;
},
async synchronizeActiveProtocol(): Promise<void> {

View file

@ -71,7 +71,7 @@ export const useProtocolAgendaStore = defineStore("protocolAgenda", {
await http
.patch(`/admin/protocol/${protocolId}/synchronize/agenda`, {
agenda: differenceWith(this.agenda, this.origin, isEqual),
agenda: this.agenda,
})
.then((res) => {
this.syncingProtocolAgenda = "synced";

View file

@ -72,7 +72,7 @@ export const useProtocolDecisionStore = defineStore("protocolDecision", {
await http
.patch(`/admin/protocol/${protocolId}/synchronize/decisions`, {
decisions: differenceWith(this.decision, this.origin, isEqual),
decisions: this.decision,
})
.then((res) => {
this.syncingProtocolDecision = "synced";

View file

@ -75,7 +75,7 @@ export const useProtocolVotingStore = defineStore("protocolVoting", {
await http
.patch(`/admin/protocol/${protocolId}/synchronize/votings`, {
votings: differenceWith(this.voting, this.origin, isEqual),
votings: this.voting,
})
.then((res) => {
this.syncingProtocolVoting = "synced";

View file

@ -0,0 +1,55 @@
import { defineStore } from "pinia";
import type {
CreateEducationViewModel,
UpdateEducationViewModel,
EducationViewModel,
} from "@/viewmodels/admin/configuration/education.models";
import { http } from "@/serverCom";
import type { AxiosResponse } from "axios";
export const useEducationStore = defineStore("education", {
state: () => {
return {
educations: [] as Array<EducationViewModel>,
loading: "loading" as "loading" | "fetched" | "failed",
};
},
actions: {
fetchEducations() {
this.loading = "loading";
http
.get("/admin/education")
.then((result) => {
this.educations = result.data;
this.loading = "fetched";
})
.catch((err) => {
this.loading = "failed";
});
},
fetchEducationById(id: number): Promise<AxiosResponse<any, any>> {
return http.get(`/admin/education/${id}`);
},
async createEducation(education: CreateEducationViewModel): Promise<AxiosResponse<any, any>> {
const result = await http.post(`/admin/education`, {
education: education.education,
description: education.description,
});
this.fetchEducations();
return result;
},
async updateActiveEducation(education: UpdateEducationViewModel): Promise<AxiosResponse<any, any>> {
const result = await http.patch(`/admin/education/${education.id}`, {
education: education.education,
description: education.description,
});
this.fetchEducations();
return result;
},
async deleteEducation(education: number): Promise<AxiosResponse<any, any>> {
const result = await http.delete(`/admin/education/${education}`);
this.fetchEducations();
return result;
},
},
});

View file

@ -155,6 +155,9 @@ export const useNavigationStore = defineStore("navigation", {
...(abilityStore.can("read", "configuration", "qualification")
? [{ key: "qualification", title: "Qualifikationen" }]
: []),
...(abilityStore.can("read", "configuration", "education")
? [{ key: "education", title: "Aus-/Fortbildungen" }]
: []),
...(abilityStore.can("read", "configuration", "executive_position")
? [{ key: "executive_position", title: "Vereinsämter" }]
: []),