diff --git a/quasar.config.ts b/quasar.config.ts index 47e6b1f..2fc4168 100644 --- a/quasar.config.ts +++ b/quasar.config.ts @@ -29,11 +29,12 @@ export default defineConfig((ctx) => { // 'fontawesome-v6', // 'eva-icons', // 'themify', - // 'line-awesome', + 'line-awesome', + 'material-icons', + 'material-icons-outlined', + + 'roboto-font', // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! - - 'roboto-font', // optional, you are not bound to it - 'material-icons', // optional, you are not bound to it ], // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#build diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index 8f0bc2d..61cd1d9 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -20,7 +20,7 @@ export default { modify_employee: "Modify employee", access_label: "access", details_label: "details", - schedule_label: "schedules", + schedule_label: "schedule", schedule_presets: { preset_list_placeholder: "Select a schedule", preset_name_placeholder: "schedule preset name", diff --git a/src/i18n/fr-ca/index.ts b/src/i18n/fr-ca/index.ts index 7da5978..402646e 100644 --- a/src/i18n/fr-ca/index.ts +++ b/src/i18n/fr-ca/index.ts @@ -20,7 +20,7 @@ export default { modify_employee: "Modifier employé", access_label: "accès", details_label: "détails", - schedule_label: "horaires", + schedule_label: "horaire", schedule_presets: { preset_list_placeholder: "Sélectionner un horaire", preset_name_placeholder: "nom de l'horaire", diff --git a/src/layouts/components/main-layout-left-drawer.vue b/src/layouts/components/main-layout-left-drawer.vue index 2d0a146..01e7ed3 100644 --- a/src/layouts/components/main-layout-left-drawer.vue +++ b/src/layouts/components/main-layout-left-drawer.vue @@ -93,7 +93,7 @@ > diff --git a/src/modules/employee-list/components/add-modify-dialog-access.vue b/src/modules/employee-list/components/add-modify-dialog-access.vue index 8b4ba2f..1dbb15c 100644 --- a/src/modules/employee-list/components/add-modify-dialog-access.vue +++ b/src/modules/employee-list/components/add-modify-dialog-access.vue @@ -5,7 +5,7 @@ import { ref } from 'vue'; import { unwrapAndClone } from 'src/utils/unwrap-and-clone'; import { useEmployeeStore } from 'src/stores/employee-store'; - import { employee_access_options, type ModuleAccessPreset, type ModuleAccessName, employee_access_presets } from 'src/modules/employee-list/models/employee-profile.models'; + import { employee_access_options, type ModuleAccessPreset, type ModuleAccessName, employee_access_presets, getEmployeeAccessOptionIcon } from 'src/modules/employee-list/models/employee-profile.models'; const employee_store = useEmployeeStore(); const preset_preview = ref(); @@ -20,6 +20,7 @@ employee_store.employee.user_module_access = unwrapAndClone(employee_access_presets[preset]); } + const getPreviewBackgroundColor = (name: ModuleAccessName) => { if (employee_access_presets[preset_preview.value!].includes(name)) { if (!employee_store.employee.user_module_access.includes(name)) return 'bg-info text-white'; @@ -141,8 +142,9 @@ class="row full-width cursor-pointer flex-center q-pa-sm rounded-5 no-wrap shadow-5" :class="preset_preview !== undefined ? getPreviewBackgroundColor(option.value) : getBackgroundColor(option.value)" @click="toggleInSelected(option.value)" - > - + > + + {{ $t('employee_management.module_access.' + option.value) }} diff --git a/src/modules/employee-list/components/add-modify-dialog-schedule-preview.vue b/src/modules/employee-list/components/add-modify-dialog-schedule-preview.vue new file mode 100644 index 0000000..65c761a --- /dev/null +++ b/src/modules/employee-list/components/add-modify-dialog-schedule-preview.vue @@ -0,0 +1,59 @@ + + + \ No newline at end of file diff --git a/src/modules/employee-list/components/add-modify-dialog-schedule.vue b/src/modules/employee-list/components/add-modify-dialog-schedule.vue index d1ff64f..5c4514b 100644 --- a/src/modules/employee-list/components/add-modify-dialog-schedule.vue +++ b/src/modules/employee-list/components/add-modify-dialog-schedule.vue @@ -4,19 +4,24 @@ > import HorizontalSlideTransition from 'src/modules/shared/components/horizontal-slide-transition.vue'; import SchedulePresetsDialog from 'src/modules/employee-list/components/schedule_presets_dialog.vue'; + import AddModifyDialogSchedulePreview from './add-modify-dialog-schedule-preview.vue'; import { onMounted, ref } from 'vue'; import { useSchedulePresetsStore } from 'src/stores/schedule-presets.store'; import { useEmployeeStore } from 'src/stores/employee-store'; +import { useEmployeeListApi } from '../composables/use-employee-api'; const schedule_preset_store = useSchedulePresetsStore(); const employee_store = useEmployeeStore(); + const employee_list_api = useEmployeeListApi(); const preset_options = ref<{ label: string, value: number }[]>([]); const current_preset = ref<{ label: string | undefined, value: number }>({ label: undefined, value: -1 }); const getPresetOptions = (): { label: string, value: number }[] => { - return schedule_preset_store.schedule_presets.map(preset => { return { label: preset.name, value: preset.id } }); + const options = schedule_preset_store.schedule_presets.map(preset => { return { label: preset.name, value: preset.id } }); + options.push({ label: '', value: -1 }); + return options; }; onMounted(() => { @@ -35,6 +40,7 @@ v-model="current_preset" standout="bg-accent" dense + options-dense rounded color="accent" :options="getPresetOptions()" @@ -44,11 +50,16 @@ menu-anchor="bottom middle" menu-self="top middle" :menu-offset="[0, 10]" - @update:modelValue="option => schedule_preset_store.setCurrentSchedulePreset(option.value)" + @update:modelValue="option => employee_list_api.setSchedulePreset(option.value)" > @@ -81,6 +92,8 @@ /> + + \ No newline at end of file diff --git a/src/modules/employee-list/components/add-modify-dialog.vue b/src/modules/employee-list/components/add-modify-dialog.vue index 41d69f6..fb3a7e6 100644 --- a/src/modules/employee-list/components/add-modify-dialog.vue +++ b/src/modules/employee-list/components/add-modify-dialog.vue @@ -55,14 +55,14 @@ > + import { ref } from 'vue'; + import { useI18n } from 'vue-i18n'; + import type { ShiftOption } from 'src/modules/timesheets/models/shift.models'; + import type { SchedulePresetShift } from '../models/schedule-presets.models'; + + const { t } = useI18n(); + + const SHIFT_OPTIONS: ShiftOption[] = [ + { label: t('timesheet.shift.types.REGULAR'), value: 'REGULAR', icon: 'wb_sunny', icon_color: 'blue-grey-3' }, + { label: t('timesheet.shift.types.EVENING'), value: 'EVENING', icon: 'bedtime', icon_color: 'indigo-8' }, + { label: t('timesheet.shift.types.EMERGENCY'), value: 'EMERGENCY', icon: 'ring_volume', icon_color: 'red-8' }, + { label: t('timesheet.shift.types.VACATION'), value: 'VACATION', icon: 'beach_access', icon_color: 'yellow-8' }, + { label: t('timesheet.shift.types.HOLIDAY'), value: 'HOLIDAY', icon: 'forest', icon_color: 'green-8' }, + { label: t('timesheet.shift.types.SICK'), value: 'SICK', icon: 'medication_liquid', icon_color: 'light-blue-6' }, + ]; + + const shift = defineModel('shift', { required: true }); + const shift_type_selected = ref(SHIFT_OPTIONS[0]); + + defineEmits<{ + 'click-delete': [void]; + }>(); + + + + + \ No newline at end of file diff --git a/src/modules/employee-list/components/schedule_presets_dialog.vue b/src/modules/employee-list/components/schedule_presets_dialog.vue index 8eab988..0d33281 100644 --- a/src/modules/employee-list/components/schedule_presets_dialog.vue +++ b/src/modules/employee-list/components/schedule_presets_dialog.vue @@ -2,18 +2,29 @@ setup lang="ts" > + import SchedulePresetsDialogRow from './schedule-presets-dialog-row.vue'; + + import { useEmployeeListApi } from '../composables/use-employee-api'; + import { SchedulePresetShift } from '../models/schedule-presets.models'; import { useSchedulePresetsStore } from 'src/stores/schedule-presets.store'; const schedule_preset_store = useSchedulePresetsStore(); + const employee_list_api = useEmployeeListApi(); - - diff --git a/src/modules/employee-list/composables/use-employee-api.ts b/src/modules/employee-list/composables/use-employee-api.ts index a2188cb..75f5bf6 100644 --- a/src/modules/employee-list/composables/use-employee-api.ts +++ b/src/modules/employee-list/composables/use-employee-api.ts @@ -1,25 +1,46 @@ import { useEmployeeStore } from "src/stores/employee-store"; import { useSchedulePresetsStore } from "src/stores/schedule-presets.store"; +import { SchedulePreset } from "../models/schedule-presets.models"; export const useEmployeeListApi = () => { - const employee_list_store = useEmployeeStore(); + const employee_store = useEmployeeStore(); const schedule_preset_store = useSchedulePresetsStore(); const getEmployeeList = async (): Promise => { - employee_list_store.is_loading = true; + employee_store.is_loading = true; - const success = await employee_list_store.getEmployeeList(); + const success = await employee_store.getEmployeeList(); if (success) await schedule_preset_store.findSchedulePresetList(); - employee_list_store.is_loading = false; + employee_store.is_loading = false; }; const getEmployeeDetails = (email: string): Promise => { - return employee_list_store.getEmployeeDetails(email); + return employee_store.getEmployeeDetails(email); + } + + const setSchedulePreset = (preset_id: number) => { + schedule_preset_store.setCurrentSchedulePreset(preset_id); + employee_store.employee.preset_id = preset_id < 0 ? null : preset_id; + } + + const saveSchedulePreset = async() => { + const preset = schedule_preset_store.current_schedule_preset; + const preset_shifts = preset.weekdays.flatMap(weekday => weekday.shifts); + const backend_preset = new SchedulePreset(preset.id, preset.name, preset.is_default, preset_shifts); + + const success = await schedule_preset_store.updateSchedulePreset(backend_preset); + + if (success) { + schedule_preset_store.is_manager_open = false; + await schedule_preset_store.findSchedulePresetList(); + } } return { getEmployeeList, getEmployeeDetails, + setSchedulePreset, + saveSchedulePreset, }; }; \ No newline at end of file diff --git a/src/modules/employee-list/models/employee-profile.models.ts b/src/modules/employee-list/models/employee-profile.models.ts index d801563..ad7520e 100644 --- a/src/modules/employee-list/models/employee-profile.models.ts +++ b/src/modules/employee-list/models/employee-profile.models.ts @@ -19,7 +19,7 @@ export class EmployeeProfile { birth_date: string; is_supervisor: boolean; user_module_access: ModuleAccessName[]; - preset_id?: number; + preset_id?: number | null; constructor() { this.first_name = ''; @@ -115,4 +115,15 @@ export const employee_access_presets: Record { + switch (module) { + case 'dashboard': return 'home'; + case 'employee_list' : return 'groups'; + case 'employee_management': return 'las la-user-edit'; + case 'personal_profile': return 'las la-id-card'; + case 'timesheets': return 'punch_clock'; + case 'timesheets_approval': return 'event_available'; + } } \ No newline at end of file diff --git a/src/modules/employee-list/models/schedule-presets.models.ts b/src/modules/employee-list/models/schedule-presets.models.ts index 0cb1e6f..58696fe 100644 --- a/src/modules/employee-list/models/schedule-presets.models.ts +++ b/src/modules/employee-list/models/schedule-presets.models.ts @@ -1,3 +1,5 @@ +import type { ShiftType } from "src/modules/timesheets/models/shift.models"; + export type Weekday = 'SUN' | 'MON' | 'TUE' | 'WED' | 'THU' | 'FRI' | 'SAT'; export const WEEKDAYS: Weekday[] = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'] @@ -8,18 +10,18 @@ export class SchedulePreset { is_default: boolean; shifts: SchedulePresetShift[]; - constructor() { - this.id = -1; - this.name = 'default'; - this.is_default = true; - this.shifts = []; + constructor(id?: number, name?: string, is_default?: boolean, shifts?: SchedulePresetShift[]) { + this.id = id ?? -1; + this.name = name ?? 'default'; + this.is_default = is_default ?? false; + this.shifts = shifts ?? []; } } -class SchedulePresetShift { +export class SchedulePresetShift { preset_id: number; week_day: Weekday; - type: string; + type: ShiftType; start_time: string; end_time: string; is_remote: boolean; @@ -27,7 +29,7 @@ class SchedulePresetShift { constructor(weekday: Weekday) { this.preset_id = -1; this.week_day = weekday; - this.type = ''; + this.type = 'REGULAR'; this.start_time = '00:00'; this.end_time = '00:00'; this.is_remote = false; diff --git a/src/modules/employee-list/pages/supervisor-crew-add-employee-page.vue b/src/modules/employee-list/pages/supervisor-crew-add-employee-page.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/employee-list/services/schedule-presets-service.ts b/src/modules/employee-list/services/schedule-presets-service.ts index 684f6da..bc000d9 100644 --- a/src/modules/employee-list/services/schedule-presets-service.ts +++ b/src/modules/employee-list/services/schedule-presets-service.ts @@ -3,13 +3,13 @@ import type { SchedulePreset } from "src/modules/employee-list/models/schedule-p import type { BackendResponse } from "src/modules/shared/models/backend-response.models"; export const SchedulePresetsService = { - createSchedulePresets: async (new_schedule: SchedulePreset) => { - const response = await api.post(`/schedule-presets/create/`, new_schedule); + createSchedulePresets: async (preset: SchedulePreset) => { + const response = await api.post(`/schedule-presets/create/`, preset); return response.data; }, - updateSchedulePresets: async (preset_id: number, dto: Partial) => { - const response = await api.patch(`/schedule-presets/update/${preset_id}`, dto); + updateSchedulePresets: async (preset: SchedulePreset): Promise> => { + const response = await api.patch(`/schedule-presets/update`, preset); return response.data; }, diff --git a/src/modules/timesheets/components/shift-list-day-row.vue b/src/modules/timesheets/components/shift-list-day-row.vue index 6d8fd1f..5372805 100644 --- a/src/modules/timesheets/components/shift-list-day-row.vue +++ b/src/modules/timesheets/components/shift-list-day-row.vue @@ -16,6 +16,7 @@ const shift_rules = useShiftRules(t('timesheet.errors.SHIFT_TIME_REQUIRED'),); const COMMENT_LENGTH_MAX = 280; + const SHIFT_OPTIONS: ShiftOption[] = [ { label: t('timesheet.shift.types.REGULAR'), value: 'REGULAR', icon: 'wb_sunny', icon_color: 'blue-grey-3' }, { label: t('timesheet.shift.types.EVENING'), value: 'EVENING', icon: 'bedtime', icon_color: 'indigo-8' }, @@ -24,6 +25,7 @@ { label: t('timesheet.shift.types.HOLIDAY'), value: 'HOLIDAY', icon: 'forest', icon_color: 'green-8' }, { label: t('timesheet.shift.types.SICK'), value: 'SICK', icon: 'medication_liquid', icon_color: 'light-blue-6' }, ]; + const shift = defineModel('shift', { required: true }); const shift_type_selected = ref(SHIFT_OPTIONS.find(option => option.value == shift.value.type)); const select_ref = useTemplateRef('select'); diff --git a/src/stores/schedule-presets.store.ts b/src/stores/schedule-presets.store.ts index bee40f4..1248cd7 100644 --- a/src/stores/schedule-presets.store.ts +++ b/src/stores/schedule-presets.store.ts @@ -11,6 +11,10 @@ export const useSchedulePresetsStore = defineStore('schedule_presets_store', () const is_manager_open = ref(false); const setCurrentSchedulePreset = (preset_id: number) => { + if (preset_id === -1) { + current_schedule_preset.value = new SchedulePresetFrontend; + return; + } current_schedule_preset.value = new SchedulePresetFrontend(schedule_presets.value.find(preset => preset.id === preset_id)!) }; @@ -34,9 +38,10 @@ export const useSchedulePresetsStore = defineStore('schedule_presets_store', () } }; - const updateSchedulePreset = async (): Promise => { + const updateSchedulePreset = async (preset: SchedulePreset): Promise => { try { - return true; + const response = await SchedulePresetsService.updateSchedulePresets(preset); + return response.success; } catch (error) { console.error('DEV ERROR || error while updating schedule preset: ', error); return false;