diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index f256e88..db4d786 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -109,10 +109,11 @@ export default { banked_hours: "available banked hours", sick_hours: "available PTO hours", vacation_hours: "available vacation hours", + save_changes_notification: "save changes to employee profile?", schedule_presets: { preset_list_placeholder: "Select a schedule", preset_name_placeholder: "schedule preset name", - delete_warning: "", + delete_warning: "Are you certain you wish to delete this schedule?", delete_warning_employee_1: "This schedule is used by", delete_warning_employee_2: "Deleting this preset will not affect previous timesheets, but they will no longer be able to apply this preset to their timesheets going forward.", }, @@ -237,10 +238,13 @@ export default { cancel: "cancel", update: "update", modify: "modify", + copy: "copy", close: "close", download: "download", open: "open", day: "day", + empty: "empty", + name: "name", }, misc: { or: "or", @@ -327,6 +331,9 @@ export default { empty_list: 'No registered expenses', employee_comment: 'Comment', supervisor_comment: 'Supervisor note', + actions: { + delete_confirm: "Delete this expense?", + }, hints: { amount_or_mileage: "Either amount or mileage, not both", comment_required: "A comment required", diff --git a/src/i18n/fr-ca/index.ts b/src/i18n/fr-ca/index.ts index 8ab3e7c..935cdb4 100644 --- a/src/i18n/fr-ca/index.ts +++ b/src/i18n/fr-ca/index.ts @@ -109,6 +109,7 @@ export default { banked_hours: "heures en banque disponibles", sick_hours: "heures d'absence payées disponibles", vacation_hours: "heures de vacances disponibles", + save_changes_notification: "Sauvegarder les modifications du profil?", schedule_presets: { preset_list_placeholder: "Sélectionner un horaire", preset_name_placeholder: "nom de l'horaire", @@ -237,10 +238,13 @@ export default { cancel: "annuler", update: "mettre à jour", modify: "modifier", + copy: "copier", close: "fermer", download: "télécharger", open: "ouvrir", day: "jour", + empty: "vide", + name: "nom", }, misc: { or: "ou", @@ -327,6 +331,9 @@ export default { empty_list: 'Aucun dépense enregistrée', employee_comment: 'Commentaire', supervisor_comment: 'Note du Superviseur', + actions: { + delete_confirm: "Supprimer cette dépense?", + }, hints: { amount_or_mileage: "Soit dépense ou kilométrage, pas les deux", comment_required: "un commentaire est requis", diff --git a/src/modules/chatbot/components/chatbot-drawer.vue b/src/modules/chatbot/components/chatbot-drawer.vue index 380c991..ca1ce8f 100644 --- a/src/modules/chatbot/components/chatbot-drawer.vue +++ b/src/modules/chatbot/components/chatbot-drawer.vue @@ -45,7 +45,7 @@
@@ -92,6 +92,7 @@ color="accent" size="2em" class="shadow-5" + style="pointer-events: auto;" @click="chatbot_store.is_showing_chatbot = true" />
@@ -103,5 +104,6 @@ :deep(.q-drawer) { background: rgba(0, 0, 0, 0); overflow: hidden; + pointer-events: none; } \ 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 4f73c10..c82edcc 100644 --- a/src/modules/employee-list/components/add-modify-dialog-schedule.vue +++ b/src/modules/employee-list/components/add-modify-dialog-schedule.vue @@ -2,43 +2,58 @@ setup lang="ts" > - 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 { useI18n } from 'vue-i18n'; 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'; import type { PresetManagerMode } from 'src/modules/employee-list/models/schedule-presets.models'; + import type { QSelectOption } from 'quasar'; - // ================= state ====================== + // ========== state ======================================== + const { t } = useI18n(); 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 preset_options = ref[]>([]); + const selected_preset = ref>({ label: '', value: -1 }); - // ====================== methods ======================== + // ========== methods ======================================== + + const getPresetOptions = (): QSelectOption[] => { + const options: QSelectOption[] = [{ label: t('shared.label.empty'), value: -1 }]; + schedule_preset_store.schedule_presets.forEach(preset => { + options.push({ label: preset.name, value: preset.id }) + }); + options.push({ label: '', value: 0 }); - const getPresetOptions = (): { label: string, value: number }[] => { - const options = schedule_preset_store.schedule_presets.map(preset => { return { label: preset.name, value: preset.id } }); - options.push({ label: 'Aucun', value: -1 }); return options; }; const onClickSchedulePresetManager = (mode: PresetManagerMode, preset_id?: number) => { schedule_preset_store.schedule_preset_dialog_mode = mode; - schedule_preset_store.openSchedulePresetManager(preset_id ?? current_preset.value.value); + schedule_preset_store.openSchedulePresetManager(preset_id ?? selected_preset.value.value); } const loadSelectedPresetOption = () => { preset_options.value = getPresetOptions(); - const current_option = preset_options.value.find(option => option.value === employee_store.employee.preset_id); - current_preset.value = current_option ?? { label: undefined, value: -1 }; - schedule_preset_store.setCurrentSchedulePreset(current_preset.value.value); + const employee = employee_store.employee; + + if (!employee.preset_id) + selected_preset.value = preset_options.value[0]!; + + else + selected_preset.value = preset_options.value.find(opt => + opt.value === employee.preset_id + )!; + + schedule_preset_store.setCurrentSchedulePreset(selected_preset.value.value); + schedule_preset_store.schedule_preset_dialog_mode = undefined; }; onMounted(() => { @@ -48,76 +63,111 @@ \ 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 df83a8d..307f4c0 100644 --- a/src/modules/employee-list/components/add-modify-dialog.vue +++ b/src/modules/employee-list/components/add-modify-dialog.vue @@ -8,21 +8,52 @@ import { ref } from 'vue'; import { useEmployeeStore } from 'src/stores/employee-store'; - import { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models'; + + // ========== state ======================================== const employee_store = useEmployeeStore(); const current_step = ref<'form' | 'access' | 'schedule'>('form'); - const initial_employee_profile = ref(new EmployeeProfile) + const initial_employee_details = ref(''); + const is_showing_close_confirm = ref(false); + + // ========== methods ======================================== + + const onBeforeHide = () => { + const current_employee_details = JSON.stringify(employee_store.employee); + + if (initial_employee_details.value !== current_employee_details) + is_showing_close_confirm.value = true; + else + employee_store.is_add_modify_dialog_open = false; + }; + + const onBeforeShow = () => { + current_step.value = 'form'; + initial_employee_details.value = JSON.stringify(employee_store.employee); + }; + + const onClickSaveChanges = async () => { + const success = await employee_store.createOrUpdateEmployee(employee_store.employee); + + if (success) + closeAllDialogs(); + } + + const closeAllDialogs = () => { + is_showing_close_confirm.value = false; + employee_store.is_add_modify_dialog_open = false; + } \ No newline at end of file diff --git a/src/modules/employee-list/components/employee-list-table.vue b/src/modules/employee-list/components/employee-list-table.vue index 0b06c64..b41d05d 100644 --- a/src/modules/employee-list/components/employee-list-table.vue +++ b/src/modules/employee-list/components/employee-list-table.vue @@ -147,7 +147,6 @@ color="accent" bg-color="white" label-color="accent" - class="text-primary" debounce="300" :label="$t('shared.label.search')" > @@ -298,4 +297,8 @@ tbody { :deep(.q-table__grid-content) { overflow: auto } + +:deep(.q-field__native) { + color: var(--q-primary); +} \ No newline at end of file diff --git a/src/modules/employee-list/components/schedule-presets-dialog-delete.vue b/src/modules/employee-list/components/schedule-presets-dialog-delete.vue index 23e82b7..f005bb4 100644 --- a/src/modules/employee-list/components/schedule-presets-dialog-delete.vue +++ b/src/modules/employee-list/components/schedule-presets-dialog-delete.vue @@ -6,17 +6,37 @@ import { useEmployeeStore } from 'src/stores/employee-store'; import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-employee-api'; - const employee_store = useEmployeeStore(); - const employee_list_api = useEmployeeListApi(); + // ========== state =================================== const { presetId } = defineProps<{ presetId: number; }>(); + const emit = defineEmits<{ + 'onConfirmDelete': [void]; + }>(); + + const employee_store = useEmployeeStore(); + const employee_list_api = useEmployeeListApi(); + const employee_amount_using_preset = ref(0); const delete_input_string = ref(''); + + // ========== computed ================================== + const is_approve_deletion = computed(() => ['SUPPRIMER', 'DELETE'].includes(delete_input_string.value)); + // ========== methods =================================== + + const onClickDeleteConfirm = async () => { + const success = await employee_list_api.deleteSchedulePreset(presetId); + + if (success && employee_store.employee.preset_id === presetId) + employee_store.employee.preset_id = null; + + emit('onConfirmDelete'); + }; + onMounted(() => { const employees_with_preset = employee_store.employee_list.filter(employee => employee.preset_id === presetId); employee_amount_using_preset.value = employees_with_preset.length; @@ -68,7 +88,7 @@ :color="is_approve_deletion ? 'negative' : 'grey-6'" :label="$t('shared.label.remove')" class="q-px-md" - @click="employee_list_api.deleteSchedulePreset(presetId)" + @click="onClickDeleteConfirm" /> diff --git a/src/modules/employee-list/components/schedule-presets-dialog.vue b/src/modules/employee-list/components/schedule-presets-dialog.vue index d4f1585..8eac059 100644 --- a/src/modules/employee-list/components/schedule-presets-dialog.vue +++ b/src/modules/employee-list/components/schedule-presets-dialog.vue @@ -10,18 +10,35 @@ import { useSchedulePresetsStore } from 'src/stores/schedule-presets.store'; import { isShiftOverlap } from 'src/modules/timesheets/utils/shift.util'; - const schedule_preset_store = useSchedulePresetsStore(); + const emit = defineEmits<{ + 'onClose': [void]; + }>(); + + const schedulePresetStore = useSchedulePresetsStore(); const employee_list_api = useEmployeeListApi(); + + const onClickSaveSchedulePreset = async () => { + const success = await employee_list_api.saveSchedulePreset(); + + if (success) + closePresetManager(); + } + + const closePresetManager = () => { + emit('onClose'); + schedulePresetStore.isManagerOpen = false; + }