diff --git a/src/modules/timesheet-approval/components/details-dialog.vue b/src/modules/timesheet-approval/components/details-dialog.vue
index 825eb35..09ee43a 100644
--- a/src/modules/timesheet-approval/components/details-dialog.vue
+++ b/src/modules/timesheet-approval/components/details-dialog.vue
@@ -52,7 +52,11 @@
-
+
diff --git a/src/modules/timesheets/components/expense-dialog-form.vue b/src/modules/timesheets/components/expense-dialog-form.vue
index 6ae8811..0277047 100644
--- a/src/modules/timesheets/components/expense-dialog-form.vue
+++ b/src/modules/timesheets/components/expense-dialog-form.vue
@@ -4,7 +4,7 @@
>
import { date } from 'quasar';
import { useI18n } from 'vue-i18n';
- import { computed, onMounted, ref } from 'vue';
+ import { computed, inject, onMounted, ref } from 'vue';
import { useUiStore } from 'src/stores/ui-store';
import { useExpensesStore } from 'src/stores/expense-store';
import { useTimesheetStore } from 'src/stores/timesheet-store';
@@ -12,35 +12,39 @@
import { getExpenseIcon, useExpenseRules } from 'src/modules/timesheets/utils/expense.util';
import { Expense, type ExpenseType, TYPES_WITH_AMOUNT_ONLY } from 'src/modules/timesheets/models/expense.models';
+ // ================= state ======================
+
interface ExpenseOption {
label: string;
value: ExpenseType;
icon: string;
}
+ const COMMENT_MAX_LENGTH = 280;
+
const { t } = useI18n();
const ui_store = useUiStore();
const timesheet_store = useTimesheetStore();
const expenses_store = useExpensesStore();
const expenses_api = useExpensesApi();
const files = defineModel('files');
-
const is_navigator_open = ref(false);
-
- const COMMENT_MAX_LENGTH = 280;
const rules = useExpenseRules(t);
-
- const period_start_date = computed(() => timesheet_store.pay_period?.period_start.replaceAll('-', '/') ?? '');
- const period_end_date = computed(() => timesheet_store.pay_period?.period_end.replaceAll('-', '/') ?? '');
-
const expense_options: ExpenseOption[] = [
{ label: t('timesheet.expense.types.PER_DIEM'), value: 'PER_DIEM', icon: getExpenseIcon('PER_DIEM') },
{ label: t('timesheet.expense.types.EXPENSES'), value: 'EXPENSES', icon: getExpenseIcon('EXPENSES') },
{ label: t('timesheet.expense.types.MILEAGE'), value: 'MILEAGE', icon: getExpenseIcon('MILEAGE') },
{ label: t('timesheet.expense.types.ON_CALL'), value: 'ON_CALL', icon: getExpenseIcon('ON_CALL') },
]
-
const expense_selected = ref();
+ const employeeEmail = inject('employeeEmail');
+
+ // ================== computed ===================
+
+ const period_start_date = computed(() => timesheet_store.pay_period?.period_start.replaceAll('-', '/') ?? '');
+ const period_end_date = computed(() => timesheet_store.pay_period?.period_end.replaceAll('-', '/') ?? '');
+
+ // ==================== method =======================
const openDatePicker = () => {
is_navigator_open.value = true;
@@ -55,7 +59,7 @@
}
const requestExpenseCreationOrUpdate = async () => {
- await expenses_api.upsertExpense(expenses_store.current_expense);
+ await expenses_api.upsertExpense(expenses_store.current_expense, employeeEmail);
expenses_store.is_showing_create_form = true;
expenses_store.mode = 'create';
diff --git a/src/modules/timesheets/components/expense-dialog-list.vue b/src/modules/timesheets/components/expense-dialog-list.vue
index bc09ce0..57715e2 100644
--- a/src/modules/timesheets/components/expense-dialog-list.vue
+++ b/src/modules/timesheets/components/expense-dialog-list.vue
@@ -2,23 +2,31 @@
setup
lang="ts"
>
- import { computed } from 'vue';
+ import { computed, inject } from 'vue';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import ExpenseDialogListItem from 'src/modules/timesheets/components/expense-dialog-list-item.vue';
import ExpenseDialogListItemMobile from 'src/modules/timesheets/components/mobile/expense-dialog-list-item-mobile.vue';
+ // ================== state =======================
+
const timesheet_store = useTimesheetStore();
const { mode = 'normal' } = defineProps<{
mode?: 'approval' | 'normal';
}>();
+ // ========================== computed ==========================
+
const expenses_list = computed(() => {
if (timesheet_store.timesheets !== undefined) {
return timesheet_store.timesheets.flatMap(week => week.days).flatMap(day => day.expenses);
}
return [];
})
+
+ // ==================== methods ========================
+
+ inject( 'employeeEmail', mode === 'approval' ? timesheet_store.current_pay_period_overview?.email : undefined);
diff --git a/src/modules/timesheets/components/shift-list-day-row.vue b/src/modules/timesheets/components/shift-list-day-row.vue
index f0ed015..b03ca65 100644
--- a/src/modules/timesheets/components/shift-list-day-row.vue
+++ b/src/modules/timesheets/components/shift-list-day-row.vue
@@ -3,24 +3,16 @@
lang="ts"
>
import { useI18n } from 'vue-i18n';
- import { onMounted, ref } from 'vue';
- import { QSelect, QInput, useQuasar } from 'quasar';
+ import { computed, onMounted, ref } from 'vue';
+ import { QSelect, QInput, useQuasar, QSelectProps } from 'quasar';
import { useUiStore } from 'src/stores/ui-store';
import { SHIFT_OPTIONS } from 'src/modules/timesheets/utils/shift.util';
import type { Shift } from 'src/modules/timesheets/models/shift.models';
- const q = useQuasar();
- const { t } = useI18n();
- const ui_store = useUiStore();
+ // ================== State ==================
const COMMENT_LENGTH_MAX = 280;
- const shift = defineModel('shift', { required: true });
- const shift_type_selected = ref(SHIFT_OPTIONS.find(option => option.value == shift.value.type));
- const select_ref = ref(null);
- const error_message = ref();
- const is_showing_delete_confirm = ref(false);
-
const { errorMessage = undefined, isTimesheetApproved = false, holiday = false } = defineProps<{
dense?: boolean;
isTimesheetApproved?: boolean;
@@ -28,7 +20,25 @@
holiday?: boolean | undefined;
}>();
- const time_input_props = {
+ const emit = defineEmits<{
+ 'requestDelete': [void];
+ 'onTimeFieldBlur': [void];
+ }>();
+
+ const shift = defineModel('shift', { required: true });
+
+ const q = useQuasar();
+ const { t } = useI18n();
+ const ui_store = useUiStore();
+
+ const shiftTypeSelected = ref(SHIFT_OPTIONS.find(option => option.value == shift.value.type));
+ const selectRef = ref(null);
+ const shiftErrorMessage = ref();
+ const is_showing_delete_confirm = ref(false);
+
+ // ================== Computed ==================
+
+ const timeInputProps = computed(() => ({
dense: true,
borderless: shift.value.is_approved && isTimesheetApproved,
readonly: shift.value.is_approved && isTimesheetApproved,
@@ -38,32 +48,46 @@
noErrorIcon: true,
hideBottomSpace: true,
error: shift.value.has_error,
- errorMessage: errorMessage ? t(errorMessage) : (error_message.value ? t(error_message.value) : undefined),
+ errorMessage: errorMessage ? t(errorMessage) : (shiftErrorMessage.value ? t(shiftErrorMessage.value) : undefined),
labelColor: shift.value.is_approved ? 'white' : (holiday ? 'purple-5' : 'accent'),
class: `col rounded-5 bg-dark q-mx-xs ${shift.value.id === -2 ? 'bg-negative' : ''} ${shift.value.is_approved || isTimesheetApproved ? 'cursor-not-allowed inset-shadow' : ''}`,
inputClass: `text-weight-medium ${shift.value.id === -2 ? 'text-white ' : ' '} ${shift.value.is_approved ? 'text-white cursor-not-allowed q-px-sm' : ''}`,
style: shift.value.is_approved ? (holiday ? 'background-color: #7b1fa2 !important' : 'background-color: #0a7d32 !important;') : '',
inputStyle: "font-size: 1.2em;"
- }
+ }));
- const emit = defineEmits<{
- 'requestDelete': [void];
- 'onTimeFieldBlur': [void];
- }>();
+ const shiftTypeSelectProps = computed>(() => ({
+ standout: q.dark.isActive ? 'bg-blue-grey-3' : 'bg-blue-grey-9',
+ dense: true,
+ borderless: shift.value.is_approved && isTimesheetApproved,
+ readonly: shift.value.is_approved && isTimesheetApproved,
+ optionsDense: !ui_store.is_mobile_mode,
+ hideDropdownIcon: true,
+ menuOffset: [0, 10],
+ menuAnchor: "bottom middle",
+ menuSelf: "top middle",
+ options: SHIFT_OPTIONS,
+ class: `col rounded-5 q-mx-xs bg-dark ${!shift.value.is_approved && !isTimesheetApproved ? '' : 'inset-shadow'}`,
+ popupContentClass: "text-uppercase text-weight-bold text-center rounded-5",
+ style: shift.value.is_approved ? (holiday ? 'background-color: #7b1fa2 !important' : 'background-color: #0a7d32 !important;') : '',
+ popupContentStyle: "border: 2px solid var(--q-accent)",
+ }));
+
+ // ================== Methods ==================
const onTimeFieldBlur = (time_string: string) => {
if (time_string.length < 1 || !time_string) {
shift.value.has_error = true;
- error_message.value = 'timesheet.errors.SHIFT_TIME_REQUIRED'
+ shiftErrorMessage.value = 'timesheet.errors.SHIFT_TIME_REQUIRED'
} else {
shift.value.has_error = false;
- error_message.value = undefined;
+ shiftErrorMessage.value = undefined;
emit('onTimeFieldBlur');
}
}
const onBlurShiftTypeSelect = () => {
- if (shift_type_selected.value === undefined) {
+ if (shiftTypeSelected.value === undefined) {
shift.value.type = 'REGULAR';
shift.value.id = 0;
emit('requestDelete');
@@ -81,18 +105,22 @@
return 'negative';
};
+ const toggleIsShowingDeleteConfirm = (state: boolean) => {
+ is_showing_delete_confirm.value = state;
+ }
+
onMounted(() => {
if (ui_store.focus_next_component) {
- select_ref.value?.focus();
- select_ref.value?.showPopup();
- shift_type_selected.value = undefined;
+ selectRef.value?.focus();
+ selectRef.value?.showPopup();
+ shiftTypeSelected.value = undefined;
ui_store.focus_next_component = false;
}
});
-
+
shift.type = option.value"
>
@@ -173,6 +187,22 @@
+
+
+
+
+
+
+
+ {{ $t(scope.label) }}
+
+
+
+
+
-
-
-
-
-
-
-
-
- {{ $t(scope.label) }}
-
-
-
@@ -237,7 +252,7 @@
@@ -254,7 +269,7 @@
@@ -267,12 +282,11 @@
-
-
+
!!
+
+
-
+ @click="toggleIsShowingDeleteConfirm(true)"
+ />
+