Compare commits
	
		
			2 Commits
		
	
	
		
			ea64568e2b
			...
			5b657f4bf0
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 5b657f4bf0 | |
|  | 13539a675b | 
|  | @ -78,12 +78,7 @@ | |||
|         <q-btn color="primary" label="Schicht hinzufügen" @click="addJob()" /> | ||||
|       </q-card-section> | ||||
|       <q-card-section v-for="(job, index) in event.jobs" :key="index"> | ||||
|         <q-card class="q-my-auto"> | ||||
|           <edit-job-slot | ||||
|             v-model="event.jobs[index]" | ||||
|             @remove-job="removeJob(index)" | ||||
|           /> | ||||
|         </q-card> | ||||
|         <edit-job-slot v-model="event.jobs[index]" @remove-job="removeJob(index)" /> | ||||
|       </q-card-section> | ||||
|       <q-card-actions align="around"> | ||||
|         <q-card-actions align="left"> | ||||
|  | @ -100,11 +95,15 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent, PropType, ref, onBeforeMount } from 'vue'; | ||||
| import { date, ModifyDateOptions } from 'quasar'; | ||||
| import { useEventStore } from '../../store'; | ||||
| import { notEmpty } from '@flaschengeist/api'; | ||||
| import { IsoDateInput } from '@flaschengeist/api/components'; | ||||
| 
 | ||||
| import { useEventStore } from '../../store'; | ||||
| import { emptyEvent, emptyJob, EditableEvent } from '../../store/models'; | ||||
| 
 | ||||
| import { date, ModifyDateOptions } from 'quasar'; | ||||
| import { computed, defineComponent, PropType, ref, onBeforeMount } from 'vue'; | ||||
| 
 | ||||
| import EditJobSlot from './EditJobSlot.vue'; | ||||
| import RecurrenceRule from './RecurrenceRule.vue'; | ||||
| 
 | ||||
|  | @ -120,8 +119,8 @@ export default defineComponent({ | |||
|     date: { | ||||
|       required: false, | ||||
|       default: undefined, | ||||
|       type: String as PropType<string|undefined> | ||||
|     } | ||||
|       type: String as PropType<string | undefined>, | ||||
|     }, | ||||
|   }, | ||||
|   emits: { | ||||
|     done: (val: boolean) => typeof val === 'boolean', | ||||
|  | @ -129,33 +128,19 @@ export default defineComponent({ | |||
|   setup(props, { emit }) { | ||||
|     const store = useEventStore(); | ||||
|     const startDate = computed(() => { | ||||
|       const d = date.buildDate({milliseconds: 0, seconds: 0, minutes: 0, hours: 0}) | ||||
|       if (!props.date || !date.isValid(props.date)) return d | ||||
|       const d = date.buildDate({ milliseconds: 0, seconds: 0, minutes: 0, hours: 0 }); | ||||
|       if (!props.date || !date.isValid(props.date)) return d; | ||||
|       const split = props.date.split('-'); | ||||
|       return date.adjustDate(d, {year: parseInt(split[0]), month: parseInt(split[1]), date: parseInt(split[2])}) | ||||
|     }) | ||||
| 
 | ||||
| 
 | ||||
|     const emptyJob = () => ({ | ||||
|       id: NaN, | ||||
|       start: date.adjustDate(startDate.value, {hours: (new Date()).getHours()}, true), | ||||
|       end: date.addToDate(date.adjustDate(startDate.value, {hours: (new Date()).getHours()}, true), {hours: 1}), | ||||
|       services: [], | ||||
|       required_services: 2, | ||||
|       type: store.jobTypes[0], | ||||
|     }); | ||||
| 
 | ||||
|     const emptyEvent = () => ({ | ||||
|       id: NaN, | ||||
|       start: new Date(startDate.value), | ||||
|       jobs: [emptyJob()], | ||||
|       type: store.eventTypes[0], | ||||
|       is_template: false, | ||||
|       return date.adjustDate(d, { | ||||
|         year: parseInt(split[0]), | ||||
|         month: parseInt(split[1]), | ||||
|         date: parseInt(split[2]), | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     const templates = computed(() => store.templates); | ||||
|     const template = ref<FG.Event | undefined>(undefined); | ||||
|     const event = ref<FG.Event>(props.modelValue || emptyEvent()); | ||||
|     const event = ref<EditableEvent>(props.modelValue || emptyEvent(startDate.value)); | ||||
|     const eventtypes = computed(() => store.eventTypes); | ||||
|     const recurrent = ref(false); | ||||
|     const recurrenceRule = ref<FG.RecurrenceRule>({ frequency: 'daily', interval: 1 }); | ||||
|  | @ -184,7 +169,7 @@ export default defineComponent({ | |||
| 
 | ||||
|       event.value.is_template = template; | ||||
|       try { | ||||
|         if (!isNaN(event.value.id)) { | ||||
|         if (event.value?.id !== undefined) { | ||||
|           //fix | ||||
|         } | ||||
|         await store.addEvent(event.value); | ||||
|  | @ -239,7 +224,8 @@ export default defineComponent({ | |||
|       template.value = undefined; | ||||
|     } | ||||
| 
 | ||||
|     const afterStart = (d: Date) => !d || (event.value.start <= d || 'Das Veranstaltungsende muss vor dem Beginn liegen') | ||||
|     const afterStart = (d: Date) => | ||||
|       !d || event.value.start <= d || 'Das Veranstaltungsende muss vor dem Beginn liegen'; | ||||
| 
 | ||||
|     return { | ||||
|       addJob, | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
|   <q-card-section class="fit row justify-start content-center items-center"> | ||||
|   <q-card class="fit row justify-start content-center items-center"> | ||||
|     <q-card-section class="fit row justify-start content-center items-center"> | ||||
|       <IsoDateInput | ||||
|         v-model="job.start" | ||||
|  | @ -45,8 +45,10 @@ | |||
|         filled | ||||
|       /> | ||||
|     </q-card-section> | ||||
|     <q-btn label="Schicht löschen" color="negative" :disabled="jobCanDelete" @click="removeJob" /> | ||||
|   </q-card-section> | ||||
|     <q-card-actions> | ||||
|       <q-btn label="Schicht löschen" color="negative" :disabled="canDelete" @click="removeJob" /> | ||||
|     </q-card-actions> | ||||
|   </q-card> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
|  | @ -63,10 +65,10 @@ export default defineComponent({ | |||
|       required: true, | ||||
|       type: Object as PropType<FG.Job>, | ||||
|     }, | ||||
|     jobCanDelete: { | ||||
|     canDelete: { | ||||
|       type: Boolean, | ||||
|       default: false, | ||||
|     } | ||||
|     }, | ||||
|   }, | ||||
|   emits: { | ||||
|     'remove-job': () => true, | ||||
|  | @ -82,7 +84,7 @@ export default defineComponent({ | |||
|     const job = new Proxy(props.modelValue, { | ||||
|       get(target, prop) { | ||||
|         if (typeof prop === 'string') { | ||||
|           return ((props.modelValue as unknown) as Record<string, unknown>)[prop]; | ||||
|           return (props.modelValue as unknown as Record<string, unknown>)[prop]; | ||||
|         } | ||||
|       }, | ||||
|       set(obj, prop, value) { | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
|   <div> | ||||
|   <q-page padding class="fit row justify-center content-start items-start q-gutter-sm"> | ||||
|     <q-tabs v-if="$q.screen.gt.sm" v-model="tab"> | ||||
|       <q-tab | ||||
|         v-for="(tabindex, index) in tabs" | ||||
|  | @ -24,25 +24,23 @@ | |||
|         </q-item> | ||||
|       </q-list> | ||||
|     </q-drawer> | ||||
|     <q-page padding class="fit row justify-center content-start items-start q-gutter-sm"> | ||||
|       <q-tab-panels | ||||
|         v-model="tab" | ||||
|         style="background-color: transparent" | ||||
|         class="q-ma-none q-pa-none fit row justify-center content-start items-start" | ||||
|         animated | ||||
|       > | ||||
|         <q-tab-panel name="create"> | ||||
|           <EditEvent :date="date" /> | ||||
|         </q-tab-panel> | ||||
|         <q-tab-panel name="eventtypes"> | ||||
|           <ManageTypes title="Veranstaltungstyp" type="EventType" /> | ||||
|         </q-tab-panel> | ||||
|         <q-tab-panel name="jobtypes"> | ||||
|           <ManageTypes title="Dienstart" type="JobType" /> | ||||
|         </q-tab-panel> | ||||
|       </q-tab-panels> | ||||
|     </q-page> | ||||
|   </div> | ||||
|     <q-tab-panels | ||||
|       v-model="tab" | ||||
|       style="background-color: transparent" | ||||
|       class="q-ma-none q-pa-none fit row justify-center content-start items-start" | ||||
|       animated | ||||
|     > | ||||
|       <q-tab-panel name="create"> | ||||
|         <EditEvent :date="date" /> | ||||
|       </q-tab-panel> | ||||
|       <q-tab-panel name="eventtypes"> | ||||
|         <ManageTypes title="Veranstaltungstyp" type="EventType" /> | ||||
|       </q-tab-panel> | ||||
|       <q-tab-panel name="jobtypes"> | ||||
|         <ManageTypes title="Dienstart" type="JobType" /> | ||||
|       </q-tab-panel> | ||||
|     </q-tab-panels> | ||||
|   </q-page> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
|  | @ -60,14 +58,16 @@ export default defineComponent({ | |||
|     date: { | ||||
|       type: String, | ||||
|       required: false, | ||||
|       default: undefined | ||||
|     } | ||||
|       default: undefined, | ||||
|     }, | ||||
|   }, | ||||
|   setup() { | ||||
|     const tabs = computed(() => [ | ||||
|       { name: 'create', label: 'Veranstaltungen' }, | ||||
|       ...(hasPermission(PERMISSIONS.JOB_TYPE) ? [{ name: 'jobtypes', label: 'Dienstarten' }] : []), | ||||
|       ...(hasPermission(PERMISSIONS.EVENT_TYPE) ? [{ name: 'eventtypes', label: 'Veranstaltungsarten' }] : []) | ||||
|       ...(hasPermission(PERMISSIONS.EVENT_TYPE) | ||||
|         ? [{ name: 'eventtypes', label: 'Veranstaltungsarten' }] | ||||
|         : []), | ||||
|     ]); | ||||
| 
 | ||||
|     const drawer = ref<boolean>(false); | ||||
|  | @ -82,7 +82,6 @@ export default defineComponent({ | |||
|       }, | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
|     return { | ||||
|       showDrawer, | ||||
|       tab, | ||||
|  | @ -19,7 +19,7 @@ export const innerRoutes: FG_Plugin.MenuRoute[] = [ | |||
|         route: { | ||||
|           path: 'schedule-overview', | ||||
|           name: 'schedule-overview', | ||||
|           component: () => import('../pages/Overview.vue'), | ||||
|           component: () => import('../pages/EventOverview.vue'), | ||||
|         }, | ||||
|       }, | ||||
|       { | ||||
|  | @ -30,7 +30,7 @@ export const innerRoutes: FG_Plugin.MenuRoute[] = [ | |||
|         route: { | ||||
|           path: 'schedule-management', | ||||
|           name: 'schedule-management', | ||||
|           component: () => import('../pages/Management.vue'), | ||||
|           component: () => import('../pages/EventManagement.vue'), | ||||
|           props: (route) => ({date: route.query.date}), | ||||
|         }, | ||||
|       }, | ||||
|  | @ -41,7 +41,7 @@ export const innerRoutes: FG_Plugin.MenuRoute[] = [ | |||
|         route: { | ||||
|           path: 'schedule-requests', | ||||
|           name: 'schedule-requests', | ||||
|           component: () => import('../pages/Requests.vue'), | ||||
|           component: () => import('../pages/EventRequests.vue'), | ||||
|         }, | ||||
|       }, | ||||
|     ], | ||||
|  | @ -57,6 +57,6 @@ export const privateRoutes: FG_Plugin.NamedRouteRecordRaw[] = [ | |||
|   { | ||||
|     name: 'events-edit', | ||||
|     path: 'schedule/:id/edit', | ||||
|     component: () => import('../pages/Event.vue'), | ||||
|     component: () => import('../pages/EventPage.vue'), | ||||
|   }, | ||||
| ]; | ||||
|  |  | |||
|  | @ -1,9 +1,6 @@ | |||
| import { api, isAxiosError } from '@flaschengeist/api'; | ||||
| import { defineStore } from 'pinia'; | ||||
| 
 | ||||
| interface UserService { | ||||
|   user: FG.Service; | ||||
| } | ||||
| import { EditableEvent } from './models'; | ||||
| 
 | ||||
| function fixJob(job: FG.Job) { | ||||
|   job.start = new Date(job.start); | ||||
|  | @ -142,8 +139,8 @@ export const useEventStore = defineStore({ | |||
|       return api.post<FG.Job>(`/events/jobs/${jobId}/assign`, service);   | ||||
|     }, | ||||
| 
 | ||||
|     async addEvent(event: FG.Event) { | ||||
|       if (isNaN(event.id)) { | ||||
|     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); | ||||
|         return data; | ||||
|  | @ -156,10 +153,12 @@ export const useEventStore = defineStore({ | |||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     async sendInvite(job: FG.Job, invitees: FG.User[], transfer = false) { | ||||
|       await Promise.resolve() | ||||
|       console.log(job, invitees, transfer) | ||||
|       return Promise.resolve() | ||||
|     async sendInvite(job: FG.Job, invitees: FG.User[], isInvite = true) { | ||||
|       return api.post<FG.Event>('/events/transfer', { | ||||
|         job: job.id, | ||||
|         receiver: invitees, | ||||
|         is_invite: isInvite | ||||
|       }); | ||||
|     } | ||||
|   }, | ||||
| }); | ||||
|  | @ -0,0 +1,38 @@ | |||
| import { date } from 'quasar'; | ||||
| 
 | ||||
| /** An new event does not contain an id and the type might be unset */ | ||||
| export type EditableEvent = Omit<Omit<Omit<FG.Event, 'jobs'>, 'type'>, 'id'> & { | ||||
|   type?: FG.EventType | number; | ||||
|   id?: number; | ||||
|   jobs: EditableJob[]; | ||||
| }; | ||||
| 
 | ||||
| /** A new job does not have an id or type assigned */ | ||||
| export type EditableJob = Omit<Omit<FG.Job, 'type'>, 'id'> & { | ||||
|   type?: FG.EventType | number; | ||||
|   id?: number; | ||||
| }; | ||||
| 
 | ||||
| export function emptyJob(startDate = new Date()): EditableJob { | ||||
|   const start = date.adjustDate(startDate, { | ||||
|     hours: new Date().getHours(), | ||||
|     minutes: 0, | ||||
|     seconds: 0, | ||||
|     milliseconds: 0, | ||||
|   }); | ||||
|   return { | ||||
|     start: start, | ||||
|     end: date.addToDate(start, { hours: 1 }), | ||||
|     services: [], | ||||
|     locked: false, | ||||
|     required_services: 2, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export function emptyEvent(startDate?: Date): EditableEvent { | ||||
|   return { | ||||
|     start: startDate === undefined ? new Date() : new Date(startDate), | ||||
|     jobs: [emptyJob(startDate)], | ||||
|     is_template: false, | ||||
|   }; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue