250 lines
7.1 KiB
TypeScript
250 lines
7.1 KiB
TypeScript
import { api, isAxiosError } from '@flaschengeist/api';
|
|
import { defineStore } from 'pinia';
|
|
import { EditableEvent } from './models';
|
|
import { Notify } from 'quasar';
|
|
|
|
/**
|
|
* Convert JSON decoded Job to real job (fix Date object)
|
|
*/
|
|
function fixJob(job: FG.Job) {
|
|
job.start = new Date(job.start);
|
|
if (job.end) job.end = new Date(job.end);
|
|
return job;
|
|
}
|
|
|
|
/**
|
|
* Convert JSON decoded Event to real Event object (fix Date object)
|
|
*/
|
|
function fixEvent(event: FG.Event) {
|
|
event.start = new Date(event.start);
|
|
if (event.end) event.end = new Date(event.end);
|
|
|
|
event.jobs.forEach((job) => fixJob(job));
|
|
}
|
|
|
|
export const useEventStore = defineStore({
|
|
id: 'events',
|
|
|
|
state: () => ({
|
|
jobTypes: [] as FG.JobType[],
|
|
eventTypes: [] as FG.EventType[],
|
|
templates: [] as FG.Event[],
|
|
invitations: [] as FG.Invitation[],
|
|
}),
|
|
|
|
getters: {},
|
|
|
|
actions: {
|
|
async getJobTypes(force = false) {
|
|
if (force || this.jobTypes.length == 0)
|
|
try {
|
|
const { data } = await api.get<FG.JobType[]>('/events/job-types');
|
|
this.jobTypes = data;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
return this.jobTypes;
|
|
},
|
|
|
|
addJobType(name: string) {
|
|
return api
|
|
.post<FG.JobType>('/events/job-types', { name: name })
|
|
.then(({ data }) => this.jobTypes.push(data));
|
|
},
|
|
|
|
removeJobType(id: number) {
|
|
return api
|
|
.delete(`/events/job-types/${id}`)
|
|
.then(() => (this.jobTypes = this.jobTypes.filter((v) => v.id !== id)));
|
|
},
|
|
|
|
renameJobType(id: number, newName: string) {
|
|
return api.put(`/events/job-types/${id}`, { name: newName }).then(() => {
|
|
const idx = this.jobTypes.findIndex((v) => v.id === id);
|
|
if (idx >= 0) this.jobTypes[idx].name = newName;
|
|
});
|
|
},
|
|
|
|
async getEventTypes(force = false) {
|
|
if (force || this.eventTypes.length == 0)
|
|
try {
|
|
const { data } = await api.get<FG.EventType[]>('/events/event-types');
|
|
this.eventTypes = data;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
return this.eventTypes;
|
|
},
|
|
|
|
/** Add new EventType
|
|
*
|
|
* @param name Name of new EventType
|
|
*/
|
|
addEventType(name: string) {
|
|
return api
|
|
.post<FG.EventType>('/events/event-types', { name: name })
|
|
.then(({ data }) => this.eventTypes.push(data));
|
|
},
|
|
|
|
removeEventType(id: number) {
|
|
return api
|
|
.delete(`/events/event-types/${id}`)
|
|
.then(() => (this.eventTypes = this.eventTypes.filter((v) => v.id !== id)));
|
|
},
|
|
|
|
renameEventType(id: number, newName: string) {
|
|
return api.put(`/events/event-types/${id}`, { name: newName }).then(() => {
|
|
const idx = this.eventTypes.findIndex((v) => v.id === id);
|
|
if (idx >= 0) this.eventTypes[idx].name = newName;
|
|
});
|
|
},
|
|
|
|
async getTemplates(force = false) {
|
|
if (force || this.templates.length == 0) {
|
|
const { data } = await api.get<FG.Event[]>('/events/templates');
|
|
data.forEach((element) => fixEvent(element));
|
|
this.templates = data;
|
|
}
|
|
return this.templates;
|
|
},
|
|
|
|
async getEvents(
|
|
filter?: FG.PaginationFilter & {
|
|
user?: string;
|
|
}
|
|
) {
|
|
try {
|
|
const { data } = await api.get<FG.PaginationResponse<FG.Event>>('/events', {
|
|
params: <unknown>filter,
|
|
});
|
|
data.result.forEach((element) => fixEvent(element));
|
|
return data;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
async getEvent(id: number) {
|
|
try {
|
|
const { data } = await api.get<FG.Event>(`/events/${id}`);
|
|
fixEvent(data);
|
|
return data;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
async removeEvent(id: number) {
|
|
try {
|
|
await api.delete(`/events/${id}`);
|
|
const idx = this.templates.findIndex((v) => v.id === id);
|
|
if (idx !== -1) this.templates.splice(idx, 1);
|
|
} catch (e) {
|
|
if (isAxiosError(e, 404)) return false;
|
|
throw e;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
async addEvent(event: EditableEvent) {
|
|
if (event?.id === undefined) {
|
|
const { data } = await api.post<FG.Event>('/events', event);
|
|
if (data.is_template) this.templates.push(data);
|
|
fixEvent(data);
|
|
return data;
|
|
} else {
|
|
if (typeof event.type === 'object') event.type = event.type.id;
|
|
const { data } = await api.put<FG.Event>(`/events/${event.id}`, event);
|
|
if (data.is_template) this.templates.push(data);
|
|
fixEvent(data);
|
|
return data;
|
|
}
|
|
},
|
|
|
|
async assignToJob(jobId: number, service: FG.Service) {
|
|
return api
|
|
.post<FG.Job>(`/events/jobs/${jobId}/assign`, service)
|
|
.then(({ data }) => fixJob(data));
|
|
},
|
|
|
|
async getJob(id: number) {
|
|
return api.get<FG.Job>(`/events/jobs/${id}`).then(({ data }) => fixJob(data));
|
|
},
|
|
|
|
async getJobs(filter?: FG.PaginationFilter) {
|
|
return api
|
|
.get<FG.PaginationResponse<FG.Job>>('/events/jobs', { params: <unknown>filter })
|
|
.then(({ data }) => {
|
|
data.result.forEach((j) => fixJob(j));
|
|
return data;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Send invite to job or transfer to other user
|
|
* @param job Job to invite to
|
|
* @param invitees Users to invite
|
|
* @param isTransfer set to True to transfer service instead of invite
|
|
*/
|
|
async invite(job: FG.Job, invitees: FG.User[], transferee: FG.User | undefined = undefined) {
|
|
return api.post<FG.Invitation[]>('/events/invitations', {
|
|
job: job.id,
|
|
invitees: invitees.map((v) => v.userid),
|
|
transferee: transferee?.userid,
|
|
});
|
|
},
|
|
|
|
async getInvitations(force = false) {
|
|
if (this.invitations.length == 0 || force) {
|
|
const { data } = await api.get<FG.Invitation[]>('/events/invitations');
|
|
this.invitations = data;
|
|
}
|
|
return this.invitations;
|
|
},
|
|
|
|
async rejectInvitation(invite: FG.Invitation | number) {
|
|
try {
|
|
await api.delete(`/events/invitations/${typeof invite === 'number' ? invite : invite.id}`);
|
|
const idx = this.invitations.findIndex((v) => v.id === (invite.id || invite));
|
|
if (idx >= 0) this.invitations.splice(idx, 1);
|
|
notify_success('Einladung für erfolgreich abgelehnt');
|
|
} catch (e) {
|
|
notify_failure();
|
|
}
|
|
},
|
|
|
|
async acceptInvitation(invite: FG.Invitation | number) {
|
|
try {
|
|
await api.put(`/events/invitations/${typeof invite === 'number' ? invite : invite.id}`, {
|
|
accept: true,
|
|
});
|
|
const idx = this.invitations.findIndex((v) => v.id === (invite.id || invite));
|
|
if (idx >= 0) this.invitations.splice(idx, 1);
|
|
notify_success('Einladung für erfolgreich angenommen');
|
|
} catch (e) {
|
|
notify_failure();
|
|
}
|
|
},
|
|
},
|
|
});
|
|
|
|
function notify_failure() {
|
|
Notify.create({
|
|
message: 'Es ist ein Fehler aufgetreten.',
|
|
color: 'negative',
|
|
group: false,
|
|
timeout: 10000,
|
|
actions: [{ icon: 'mdi-close', color: 'white' }],
|
|
});
|
|
}
|
|
|
|
function notify_success(msg: string) {
|
|
Notify.create({
|
|
message: msg,
|
|
color: 'positive',
|
|
group: false,
|
|
timeout: 5000,
|
|
actions: [{ icon: 'mdi-close', color: 'white' }],
|
|
});
|
|
}
|