diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index 1041d09..2697fe5 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -160,10 +160,12 @@ export default { }, }, expense: { - add_expense:"Add Expense", - amount:"Amount", - date:"Date", - empty_list:"No registered expenses", + add_expense:'Add Expense', + amount:'Amount', + date:'Date', + empty_list:'No registered expenses', + employee_comment:'Comment', + supervisor_comment:'Supervisor note', errors: { date_required_or_invalid:"the date is missing or invalid", comment_required:"A comment required", diff --git a/src/i18n/fr-ca/index.ts b/src/i18n/fr-ca/index.ts index c39cff3..4a5a9ba 100644 --- a/src/i18n/fr-ca/index.ts +++ b/src/i18n/fr-ca/index.ts @@ -160,10 +160,12 @@ export default { }, }, expense: { - add_expense:"Ajouter une dépense", - amount:"Montant", - date:"Date", - empty_list:"Aucun dépense enregistrée", + add_expense:'Ajouter une dépense', + amount:'Montant', + date:'Date', + empty_list:'Aucun dépense enregistrée', + employee_comment:'Commentaire', + supervisor_comment:'Note du Superviseur', errors: { date_required_or_invalid:"La date est manquante ou invalide", comment_required:"un commentaire est requis", diff --git a/src/modules/timesheets/components/expenses/timesheet-details-expenses.vue b/src/modules/timesheets/components/expenses/timesheet-details-expenses.vue index cda1de1..f2c7690 100644 --- a/src/modules/timesheets/components/expenses/timesheet-details-expenses.vue +++ b/src/modules/timesheets/components/expenses/timesheet-details-expenses.vue @@ -3,11 +3,10 @@ import { computed, ref } from 'vue'; import { EXPENSE_TYPE, type ExpenseType, type TimesheetExpense } from '../../types/timesheet-expenses-interface'; import { compute_expense_totals, ExpensesValidationError, normalize_expense, validate_expense_UI } from '../../utils/timesheet-expenses-validators'; -import { useI18n } from 'vue-i18n'; +// import { date } from 'quasar'; import { COMMENT_MAX_LENGTH } from '../../composables/use-shift-api'; /* eslint-disable */ -const { t } = useI18n(); //props const props = defineProps<{ @@ -31,27 +30,28 @@ const emit = defineEmits<{ }>(); //q-select mapper -const type_options = computed(()=> EXPENSE_TYPE.map((val)=> ({ - label: t(`timesheet.expense.types.${val}`, val), - value: val, -}))); +const type_options = computed(()=> EXPENSE_TYPE.map( val => ({ label: val, value: val }))); //refs & states const items = ref(Array.isArray(props.initial_expenses) ? props.initial_expenses.map(normalize_expense): []); +const formRef = ref | null>(null); +const triedSubmit = ref(false); + +const DEFAULT_TYPE: ExpenseType = 'EXPENSES' + const draft = ref>({ date:'', - type: 'EXPENSES', + type: DEFAULT_TYPE, comment:'', }); // computeds -const totals = computed(()=> compute_expense_totals(items.value)); -const remaining_comment_chars = computed(()=> { - const comment = String(draft.value.comment ?? ''); - return COMMENT_MAX_LENGTH - comment.length; -}); +const totals = computed(()=> compute_expense_totals(items.value)); +const is_readonly = computed(()=> !!props.is_approved); +const showMileage = computed(()=> (draft.value.type as string) === 'MILEAGE'); +const showAmount = computed(()=> !showMileage.value); -//actions +//helpers const reset_draft = () => { draft.value.date = ''; draft.value.type = 'EXPENSES'; @@ -60,10 +60,20 @@ const reset_draft = () => { draft.value.comment = ''; }; +const set_draft_type = (value: ExpenseType) => { + draft.value.type = value; + if (value === 'MILEAGE') { + delete draft.value.amount; + } else { + delete draft.value.mileage; + } +}; + +//actions const add_draft_as_item = () => { const candidate: TimesheetExpense = normalize_expense({ - date: String(draft.value.date ?? '').trim(), - type: String(draft.value.type ?? '').trim(), + date: draft.value.date, + type: normType(draft.value.type), ...(typeof draft.value.amount === 'number' ? { amount: draft.value.amount }: {}), ...(typeof draft.value.mileage === 'number' ? { mileage: draft.value.mileage }: {}), comment: String(draft.value.comment ?? '').trim(), @@ -117,217 +127,270 @@ const on_save = () => { } }; +const on_form_submit = async () => { + triedSubmit.value = true; + const ok = await formRef.value?.validate(true); + if(!ok) return; + add_draft_as_item(); +}; + const on_close = () => emit('close'); - -//read-only guard for supervisor comment and approved expenses -const is_readonly = computed(()=> !!props.is_approved); - - -const set_draft_type = (value: ExpenseType) => (draft.value.type = value); -const set_draft_amount = (value: number | null) => { - if(value === null || value === undefined || Number.isNaN(Number(value))) { - delete draft.value.amount; - } else { - draft.value.amount = Number(value); - } -}; -const set_draft_mileage = (value: number | null) => { - if(value === null || value === undefined || Number.isNaN(Number(value))) { - delete draft.value.mileage; - } else { - draft.value.mileage = Number(value); - } +//icons managament +type ExpensesType = 'MILEAGE' | 'EXPENSES' | 'PER_DIEM' | 'PRIME_GARDE' | string; +const normType = (type: unknown) => String(type ?? '').trim().toUpperCase(); +const expenseTypeIcon = (type: ExpensesType) => { + const t = normType(type); + const map: Record = { + MILEAGE: 'time_to_leave', + EXPENSES: 'receipt_long', + PER_DIEM: 'hotel', + PRIME_GARDE: 'admin_panel_settings', + }; + return map[String(t)] ?? 'help_outline'; }; \ No newline at end of file diff --git a/src/modules/timesheets/pages/timesheet-details-overview.vue b/src/modules/timesheets/pages/timesheet-details-overview.vue index 08bb5cc..d183998 100644 --- a/src/modules/timesheets/pages/timesheet-details-overview.vue +++ b/src/modules/timesheets/pages/timesheet-details-overview.vue @@ -261,19 +261,19 @@ const on_request_delete = async ({ date, shift }: { date: string; shift: any }) persistent > - {{ expenses_error }} - + --> = ['MILEAGE']; -export const TYPES_WITH_AMOUNT_ONLY: Readonly = ['PER_DIEM', 'EXPENSES', 'PRIME_DISPO'] \ No newline at end of file +export const TYPES_WITH_AMOUNT_ONLY: Readonly = ['PER_DIEM', 'EXPENSES', 'PRIME_GARDE'] \ No newline at end of file