feat(timesheet): added comment popup
This commit is contained in:
parent
5c0c9036c4
commit
a2f07ac3fb
|
|
@ -2,6 +2,7 @@ import { useTimesheetStore } from "src/stores/timesheet-store";
|
|||
import { useAuthStore } from "src/stores/auth-store";
|
||||
import type { PayPeriodReportFilters } from "../types/timesheet-approval-pay-period-report-interface";
|
||||
import { default_pay_period_overview_employee, type PayPeriodOverviewEmployee } from "../types/timesheet-approval-pay-period-overview-employee-interface";
|
||||
import { date } from "quasar";
|
||||
|
||||
export const useTimesheetApprovalApi = () => {
|
||||
const timesheet_store = useTimesheetStore();
|
||||
|
|
@ -63,11 +64,29 @@ export const useTimesheetApprovalApi = () => {
|
|||
await timesheet_store.getTimesheetApprovalCSVReport(options);
|
||||
};
|
||||
|
||||
const getCurrentPayPerdioOverview = async (): Promise<void> => {
|
||||
const today = date.formatDate(new Date(), 'YYYY-MM-DD');
|
||||
const success = await timesheet_store.getPayPeriodByDate(today);
|
||||
if(!success) return;
|
||||
|
||||
const { pay_year, pay_period_no } = timesheet_store.current_pay_period;
|
||||
|
||||
await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(
|
||||
pay_year,
|
||||
pay_period_no,
|
||||
auth_store.user.email
|
||||
);
|
||||
|
||||
await timesheet_store.getTimesheetsByPayPeriodAndEmail(auth_store.user.email);
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
getPayPeriodOverviewByDate,
|
||||
getNextPayPeriodOverview,
|
||||
getPayPeriodOverviewByEmployeeEmail,
|
||||
getTimesheetsByPayPeriodAndEmail,
|
||||
getTimesheetApprovalCSVReport
|
||||
getTimesheetApprovalCSVReport,
|
||||
getCurrentPayPerdioOverview
|
||||
}
|
||||
};
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
/* eslint-disable */
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import TimesheetShiftComment from '../shift/timesheet-shift-comment.vue';
|
||||
import TimesheetSavePayload from './timesheet-save-payload.vue';
|
||||
import type { Shift } from '../../types/timesheet-shift-interface';
|
||||
import type{ CreateShiftPayload } from '../../types/timesheet-shifts-payload-interface';
|
||||
|
||||
const timesheet_store = useTimesheetStore();
|
||||
|
||||
const { t, tm, locale } = useI18n();
|
||||
|
||||
const SHIFT_KEY = ['REGULAR', 'EVENING', 'EMERGENCY', 'HOLIDAY', 'VACATION', 'SICK'] as const;
|
||||
const days = computed(()=> {
|
||||
void locale.value;
|
||||
return (tm('timesheet.days') as string[]) ?? [];
|
||||
});
|
||||
|
||||
const shift_options = computed(()=> {
|
||||
void locale.value;
|
||||
return SHIFT_KEY.map(key => ({ value: key, label: t(`timesheet.shift_types.${key}`)}))
|
||||
});
|
||||
|
||||
const empty_row = { date:'', type: '', start_time: '', end_time: '', comment: '', is_approved: false, is_remote: false };
|
||||
//Week dates
|
||||
const week_dates = computed(() => {
|
||||
const start_date = timesheet_store.current_timesheet.start_day;
|
||||
if(!start_date) return [];
|
||||
|
||||
const mm = /^(\d{4})-(\d{2})-(\d{2})$/.exec(start_date);
|
||||
if(!mm) return [];
|
||||
const year = Number(mm[1]), month = Number(mm[2]), day = Number(mm[3])
|
||||
|
||||
const base = new Date(Date.UTC(year, month - 1, day));
|
||||
const yyyymmdd = (date: Date) => {
|
||||
const yyyy = date.getFullYear();
|
||||
const mm = String(date.getUTCMonth() + 1).padStart(2,'0');
|
||||
const dd = String(date.getUTCDate()).padStart(2,'0');
|
||||
return `${yyyy}-${mm}-${dd}`};
|
||||
|
||||
return Array.from({length:7 }, (_, i) => {
|
||||
const date = new Date(base);
|
||||
date.setUTCDate(base.getDate() + i);
|
||||
return yyyymmdd(date);
|
||||
});
|
||||
});
|
||||
|
||||
//filling timesheet with shifts
|
||||
const rows = ref<Shift[]>(
|
||||
days.value.map((_,index) => {
|
||||
const date_ISO = week_dates.value[index];
|
||||
const shift = timesheet_store.current_timesheet.shifts.find(sh => sh.date === date_ISO);
|
||||
return shift ? {
|
||||
date:shift.date || '',
|
||||
type: shift.bank_type || '',
|
||||
start_time: shift.start_time || '',
|
||||
end_time: shift.end_time || '',
|
||||
comment: shift.description || '',
|
||||
is_approved: !!shift.is_approved,
|
||||
is_remote: !!shift.is_remote,
|
||||
}
|
||||
: { ...empty_row };
|
||||
})
|
||||
);
|
||||
const hasData = (row: Shift) => !!(row.type || row.start_time || row.end_time || row.comment);
|
||||
|
||||
const show_comment = ref(false);
|
||||
const selected_index = ref<number | null>(null);
|
||||
const selected_row = computed<Shift | undefined>(()=>
|
||||
selected_index.value != null ? rows.value[selected_index.value] : undefined
|
||||
);
|
||||
|
||||
const setComment = (comment: string) => {
|
||||
if(selected_row.value) selected_row.value.comment = comment;
|
||||
show_comment.value = false;
|
||||
}
|
||||
|
||||
const onClickComment = (index: number)=> {
|
||||
selected_index.value = index;
|
||||
show_comment.value = true;
|
||||
};
|
||||
|
||||
const clearRow = (index: number) => {
|
||||
rows.value[index] = { ...empty_row };
|
||||
}
|
||||
|
||||
|
||||
const emit = defineEmits<{ (e: 'save', payload: CreateShiftPayload[]): void }>();
|
||||
|
||||
//onMounted?
|
||||
watch(
|
||||
() => [timesheet_store.current_timesheet.start_day, timesheet_store.current_timesheet.shifts],
|
||||
() => {
|
||||
const dates = week_dates.value;
|
||||
rows.value = days.value.map((_, idx)=> {
|
||||
const shift = timesheet_store.current_timesheet.shifts.find(sh => sh.date === dates[idx]);
|
||||
return shift
|
||||
? { date: shift.date || '',
|
||||
type: shift.bank_type || '',
|
||||
start_time: shift.start_time || '',
|
||||
end_time: shift.end_time || '',
|
||||
comment: shift.description || '',
|
||||
is_approved: shift.is_approved,
|
||||
is_remote: shift.is_remote,
|
||||
}
|
||||
: { date: '',
|
||||
type: '',
|
||||
start_time: '',
|
||||
end_time: '',
|
||||
comment: '',
|
||||
is_approved: false,
|
||||
is_remote: false
|
||||
};
|
||||
});
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-card class="bg-transparent q-pa-md q-ma-md">
|
||||
<q-dialog
|
||||
v-model="show_comment"
|
||||
transition-show="fade"
|
||||
transition-hide="fade"
|
||||
persistent
|
||||
>
|
||||
<!-- comment popup -->
|
||||
<TimesheetShiftComment
|
||||
:comment-string="selected_row?.comment ?? ''"
|
||||
@click-save="setComment"
|
||||
@click-close="show_comment = false"
|
||||
/>
|
||||
</q-dialog>
|
||||
|
||||
<q-form
|
||||
autofocus
|
||||
class="bg-white q-pa-sm q-pt-lg rounded-10">
|
||||
|
||||
<div
|
||||
v-for="(row, index) in rows"
|
||||
:key="week_dates[index] ?? index"
|
||||
class="q-gutter-sm q-mb-sm"
|
||||
:class="$q.screen.lt.md ? 'column' : 'row'" >
|
||||
<!--Week days-->
|
||||
<span class="text-weight-bold text-primary col-1">{{ days[index] }}</span>
|
||||
<!-- remote work toggle -->
|
||||
<q-toggle
|
||||
v-model="row.is_remote"
|
||||
:disable="row.is_approved"
|
||||
color="primary"
|
||||
checked-icon="home_work"
|
||||
unchecked-icon="business"
|
||||
icon="home_work"
|
||||
class="col-auto q-ml-sm"
|
||||
>
|
||||
<q-tooltip
|
||||
anchor="top middle"
|
||||
self="center middle"
|
||||
class="bg-primary text-uppercase text-weight-bold"
|
||||
>{{ $t('timesheet.remote_button') }}
|
||||
</q-tooltip>
|
||||
</q-toggle>
|
||||
<!-- type selection -->
|
||||
<q-select
|
||||
v-model="row.type"
|
||||
:options="shift_options"
|
||||
:readonly="row.is_approved"
|
||||
class="col-3"
|
||||
:label="$t('timesheet.shift_types_label')"
|
||||
dense
|
||||
filled
|
||||
color="primary"
|
||||
standout="bg-primary text-white"
|
||||
options-dense
|
||||
emit-value
|
||||
map-options
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
hide-dropdown-icon
|
||||
/>
|
||||
<!-- start time input -->
|
||||
<q-input
|
||||
v-model="row.start_time"
|
||||
:readonly="row.is_approved"
|
||||
class="col-auto"
|
||||
:label="$t('timesheet.fields.start')"
|
||||
dense
|
||||
filled
|
||||
color="primary"
|
||||
type="time"
|
||||
step="300"
|
||||
standout="bg-primary text-white"
|
||||
/>
|
||||
<!-- end time input -->
|
||||
<q-input
|
||||
v-model="row.end_time"
|
||||
:readonly="row.is_approved"
|
||||
class="col-auto"
|
||||
:label="$t('timesheet.fields.end')"
|
||||
dense
|
||||
filled
|
||||
color="primary"
|
||||
type="time"
|
||||
step="300"
|
||||
standout="bg-primary text-white"
|
||||
/>
|
||||
<div class="col-3">
|
||||
<!-- comment button -->
|
||||
<q-btn
|
||||
:icon="row.comment.length > 0 ? 'announcement':'chat_bubble_outline'"
|
||||
:color="row.comment.length > 0 ? 'primary' : 'grey-8'"
|
||||
:disable="row.is_approved"
|
||||
flat
|
||||
class="col-auto"
|
||||
@click="onClickComment(index)"
|
||||
/>
|
||||
<!-- expense button -->
|
||||
<q-btn
|
||||
:icon="row.comment.length > 0 ? 'receipt_long':'attach_money'"
|
||||
flat
|
||||
dense
|
||||
class="q-pa-none q-ma-sm col-1"
|
||||
:color="hasData(row) ? 'primary' : 'grey-8'"
|
||||
@click="clearRow(index)"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<!-- reset entries button -->
|
||||
<q-btn
|
||||
icon="cleaning_services"
|
||||
flat
|
||||
dense
|
||||
class="q-pa-none q-ma-sm col-auto"
|
||||
:color="hasData(row) ? 'primary' : 'grey-4'"
|
||||
@click="clearRow(index)"
|
||||
/>
|
||||
<!-- add one more shift buttons -->
|
||||
<q-btn
|
||||
icon="more_time"
|
||||
flat
|
||||
dense
|
||||
class="q-pa-none q-ma-sm col-auto"
|
||||
color="primary"
|
||||
>
|
||||
<q-tooltip
|
||||
anchor="top middle"
|
||||
self="center middle"
|
||||
class="bg-primary text-uppercase text-weight-bold"
|
||||
>{{ $t('timesheet.add_shift') }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
<TimesheetSavePayload
|
||||
:week_dates="week_dates"
|
||||
:rows="rows"
|
||||
@save="(payload) => emit('save', payload)"
|
||||
/>
|
||||
</q-form>
|
||||
|
||||
</q-card>
|
||||
|
||||
</template>
|
||||
|
|
@ -1,10 +1,36 @@
|
|||
<script setup lang="ts">
|
||||
import type { Shift } from 'src/modules/timesheets/types/timesheet-shift-interface';
|
||||
|
||||
import type { Shift } from 'src/modules/timesheets/types/timesheet-shift-interface';
|
||||
import { computed, ref } from 'vue';
|
||||
import ShiftComment from '../shift/shift-comment.vue';
|
||||
/* eslint-disable */
|
||||
const props = defineProps<{
|
||||
shift: Shift;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
'save-comment': [payload: { comment: string; shift_id?: string | number; date?: string }];
|
||||
}>();
|
||||
|
||||
const getComment = computed(()=> (props.shift as any).description || (props.shift as any).comment || '');
|
||||
const show_comment = ref(false);
|
||||
const openComment = ()=> { show_comment.value = true; };
|
||||
const closeComment = ()=> { show_comment.value = false; };
|
||||
const handleSave = (comment: string)=> {
|
||||
emit('save-comment', {
|
||||
comment,
|
||||
shift_id: (props.shift as any).id,
|
||||
date:(props.shift as any).date
|
||||
});
|
||||
show_comment.value = false;
|
||||
}
|
||||
const hasComment = computed(()=> {
|
||||
const comment = (props.shift as any).description ?? (props.shift as any).comment ?? '';
|
||||
return typeof comment === 'string' && comment.trim().length > 0;
|
||||
})
|
||||
const comment_icon = computed(()=> (hasComment.value ? 'announcement' : 'chat_bubble_outline'));
|
||||
const comment_color = computed(()=> (hasComment.value ? 'primary' : 'grey-8'));
|
||||
|
||||
|
||||
const getShiftColor = (type: string): string => {
|
||||
switch(type) {
|
||||
case 'REGULAR': return 'secondary';
|
||||
|
|
@ -85,11 +111,11 @@
|
|||
v-if="props.shift.type !== ''"
|
||||
flat
|
||||
dense
|
||||
color='grey-8'
|
||||
icon="chat_bubble_outline"
|
||||
:color="comment_color"
|
||||
:icon="comment_icon"
|
||||
class="q-pa-none"
|
||||
@click="openComment"
|
||||
/>
|
||||
|
||||
<!-- insert_drive_file or request_quote -->
|
||||
<q-btn
|
||||
v-if="props.shift.type !== ''"
|
||||
|
|
@ -101,4 +127,17 @@
|
|||
/>
|
||||
</q-card-section>
|
||||
</q-card-section>
|
||||
|
||||
<q-dialog
|
||||
v-model="show_comment"
|
||||
transition-show="fade"
|
||||
transition-hide="fade"
|
||||
persistent
|
||||
>
|
||||
<ShiftComment
|
||||
:comment-string="getComment"
|
||||
@click-close="closeComment"
|
||||
@click-save="handleSave"
|
||||
/>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
|
@ -3,7 +3,7 @@ import { default_shift, type Shift } from 'src/modules/timesheets/types/timeshee
|
|||
import TimesheetEmployeeDetailsShiftsRowHeader from './timesheet-details-shifts-row-header.vue';
|
||||
import TimesheetEmployeeDetailsShiftsRow from './timesheet-details-shifts-row.vue';
|
||||
import type { PayPeriod } from 'src/modules/shared/types/pay-period-interface';
|
||||
import type { TimesheetPayPeriodDetailsOverview } from '../types/timesheet-pay-period-details-overview-interface';
|
||||
import type { TimesheetPayPeriodDetailsOverview } from '../../types/timesheet-pay-period-details-overview-interface';
|
||||
|
||||
const props = defineProps<{
|
||||
rawData: TimesheetPayPeriodDetailsOverview;
|
||||
|
|
@ -1,78 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
/* eslint-disable */
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { date as qdate } from 'quasar';
|
||||
import { ref } from 'vue';
|
||||
import { date} from 'quasar';
|
||||
import type { QDateDetails } from 'src/modules/shared/types/q-date-details';
|
||||
|
||||
const is_showing_calendar_picker = ref(false);
|
||||
const calendar_date = ref(date.formatDate( Date.now(), 'YYYY-MM-DD' ));
|
||||
|
||||
const props = defineProps<{
|
||||
isDisabled?: boolean;
|
||||
minPickableDate?: string;
|
||||
currentLabel?: string;
|
||||
isPreviousLimit:boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'navigate-to', targetIso: string, meta?: { reason: 'previous' | 'next' | 'current' | 'picked' }): void;
|
||||
(e: 'date-selected', value: string, reason?: string, details?: QDateDetails): void;
|
||||
(e: 'pressed-previous-button'): void;
|
||||
(e: 'pressed-next-button'): void;
|
||||
(e: 'pressed-current-button'): void;
|
||||
'date-selected': [value: string, reason?: string, details?: QDateDetails]
|
||||
'pressed-previous-button': []
|
||||
'pressed-next-button': []
|
||||
}>();
|
||||
|
||||
const is_showing_calendar_picker = ref(false);
|
||||
|
||||
const currentStartEndDate = computed(()=> {
|
||||
const label = props.currentLabel ?? '';
|
||||
const parts = label.split('.');
|
||||
if(parts.length < 2) return null;
|
||||
return { start_iso: parts[0]!, end_iso: parts[1]! };
|
||||
});
|
||||
|
||||
const to_date = (iso?: string) => (iso ? qdate.extractDate(iso, 'YYYY-MM-DD'): null);
|
||||
const to_iso = (date: Date) => qdate.formatDate(date, 'YYYY-MM-DD');
|
||||
|
||||
const calendar_date = ref(currentStartEndDate.value?.start_iso ?? to_iso(new Date()));
|
||||
|
||||
watch(() => props.currentLabel, () => {
|
||||
if(currentStartEndDate.value?.start_iso) {
|
||||
calendar_date.value = currentStartEndDate.value.start_iso;
|
||||
}
|
||||
});
|
||||
|
||||
const is_previous_limit = computed(() => {
|
||||
const start_end = currentStartEndDate.value;
|
||||
if (!start_end || !props.minPickableDate) return false;
|
||||
const prev_anchor = qdate.addToDate(to_date(start_end.start_iso)!, { days: -1 });
|
||||
return to_iso(prev_anchor) <= props.minPickableDate;
|
||||
});
|
||||
|
||||
|
||||
const onDateSelected = (value: string, reason: string, details: QDateDetails) => {
|
||||
calendar_date.value = value;
|
||||
is_showing_calendar_picker.value = false;
|
||||
emit('date-selected', value, reason, details);
|
||||
emit('navigate-to', value, { reason: 'picked' });
|
||||
};
|
||||
|
||||
const goPrevious = () => {
|
||||
emit('pressed-previous-button');
|
||||
const start_end = currentStartEndDate.value;
|
||||
if (!start_end) return;
|
||||
const prev_anchor = qdate.addToDate(to_date(start_end.start_iso)!, { days: -1 });
|
||||
emit('navigate-to', to_iso(prev_anchor), { reason: 'previous' });
|
||||
};
|
||||
|
||||
const goCurrent = () => {
|
||||
emit('pressed-current-button');
|
||||
emit('navigate-to', to_iso(new Date()), { reason: 'current' });
|
||||
};
|
||||
|
||||
const goNext = () => {
|
||||
emit('pressed-next-button');
|
||||
const start_end = currentStartEndDate.value;
|
||||
if (!start_end) return;
|
||||
const next_anchor = qdate.addToDate(to_date(start_end.end_iso)!, { days: 1 });
|
||||
emit('navigate-to', to_iso(next_anchor), { reason: 'next' });
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -82,8 +32,8 @@
|
|||
push rounded
|
||||
icon="keyboard_arrow_left"
|
||||
color="primary"
|
||||
@click="goPrevious"
|
||||
:disable="is_previous_limit || props.isDisabled"
|
||||
@click="emit('pressed-previous-button')"
|
||||
:disable="props.isPreviousLimit || props.isDisabled"
|
||||
class="q-mr-sm q-px-sm"
|
||||
>
|
||||
<q-tooltip
|
||||
|
|
@ -93,29 +43,13 @@
|
|||
> {{ $t( 'timesheet.nav_button.previous_week' )}}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<!-- navigation to current week -->
|
||||
<q-btn
|
||||
push rounded
|
||||
icon="today"
|
||||
color="primary"
|
||||
@click="goCurrent"
|
||||
:disable="!!props.isDisabled"
|
||||
class="q-mr-sm q-px-lg"
|
||||
>
|
||||
<q-tooltip
|
||||
anchor="top middle"
|
||||
self="center middle"
|
||||
class="bg-primary text-uppercase text-weight-bold"
|
||||
>{{ $t('timesheet.nav_button.current_week') }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<!-- navigation through calendar date picker -->
|
||||
<q-btn
|
||||
push rounded
|
||||
icon="calendar_month"
|
||||
color="primary"
|
||||
@click="is_showing_calendar_picker = true"
|
||||
:disable="!!props.isDisabled"
|
||||
:disable="props.isDisabled"
|
||||
class="q-px-lg"
|
||||
>
|
||||
<q-tooltip
|
||||
|
|
@ -130,8 +64,8 @@
|
|||
push rounded
|
||||
icon="keyboard_arrow_right"
|
||||
color="primary"
|
||||
@click="goNext"
|
||||
:disable="!!props.isDisabled"
|
||||
@click="emit('pressed-next-button')"
|
||||
:disable="props.isDisabled"
|
||||
class="q-ml-sm q-px-sm"
|
||||
>
|
||||
<q-tooltip
|
||||
|
|
@ -155,7 +89,7 @@
|
|||
class="q-mt-xl"
|
||||
today-btn
|
||||
mask="YYYY-MM-DD"
|
||||
:options="date => !props.minPickableDate || date > props.minPickableDate"
|
||||
:options="date => date > '2023/12/16'"
|
||||
@update:model-value="onDateSelected"
|
||||
/>
|
||||
</q-dialog>
|
||||
|
|
|
|||
|
|
@ -1,60 +1,49 @@
|
|||
import { useAuthStore } from "src/stores/auth-store";
|
||||
import { useTimesheetStore } from "src/stores/timesheet-store"
|
||||
import { ref } from "vue";
|
||||
import { timesheetTempService } from "../services/timesheet-services";
|
||||
import type { CreateShiftPayload } from "../types/timesheet-shifts-payload-interface";
|
||||
|
||||
|
||||
export const useTimesheetApi = () => {
|
||||
const timesheet_store = useTimesheetStore();
|
||||
const auth_store = useAuthStore();
|
||||
const week_offset = ref(0);
|
||||
|
||||
const fetchWeek = async (offset = week_offset.value) => {
|
||||
const email = auth_store.user?.email;
|
||||
if(!email) return;
|
||||
try{
|
||||
timesheet_store.is_loading = true;
|
||||
const timesheet = await timesheetTempService.getTimesheetsByEmail(email, offset);
|
||||
timesheet_store.current_timesheet = timesheet;
|
||||
week_offset.value = offset;
|
||||
}catch (err) {
|
||||
console.error('fetch week error', err);
|
||||
timesheet_store.current_timesheet = { ...timesheet_store.current_timesheet, shifts: [], expenses: [] };
|
||||
} finally {
|
||||
timesheet_store.is_loading = false;
|
||||
const getTimesheetsByDate = async (date_string: string) => {
|
||||
const success = await timesheet_store.getPayPeriodByDate(date_string);
|
||||
|
||||
if (success) {
|
||||
await timesheet_store.getTimesheetsByPayPeriodAndEmail(auth_store.user.email)
|
||||
}
|
||||
}
|
||||
|
||||
const fetchPayPeriod = async (direction: number) => {
|
||||
const current_pay_period = timesheet_store.current_pay_period;
|
||||
let new_pay_period_no = current_pay_period.pay_period_no + direction;
|
||||
let new_pay_year = current_pay_period.pay_year;
|
||||
|
||||
if (new_pay_period_no > 26) {
|
||||
new_pay_period_no = 1;
|
||||
new_pay_year += 1;
|
||||
}
|
||||
|
||||
if (new_pay_period_no < 1) {
|
||||
new_pay_period_no = 26;
|
||||
new_pay_year -= 1;
|
||||
}
|
||||
|
||||
const success = await timesheet_store.getPayPeriodByYearAndPeriodNumber(new_pay_year, new_pay_period_no);
|
||||
|
||||
if (success) {
|
||||
await timesheet_store.getTimesheetsByPayPeriodAndEmail(auth_store.user.email);
|
||||
}
|
||||
};
|
||||
|
||||
const this_week = async () => fetchWeek(0);
|
||||
const next_week = async () => fetchWeek(week_offset.value + 1);
|
||||
const previous_week = async () => fetchWeek(week_offset.value - 1);
|
||||
|
||||
const saveTimesheetShifts = async (shifts: CreateShiftPayload[]) => {
|
||||
const email = auth_store.user?.email;
|
||||
if(!email || shifts.length === 0) return;
|
||||
await timesheet_store.createTimesheetShifts(email, shifts, week_offset.value);
|
||||
};
|
||||
|
||||
const weekStart = (date: Date) => {
|
||||
const x = new Date(date);
|
||||
x.setHours(0, 0, 0, 0);
|
||||
x.setDate(x.getDate() - x.getDay());
|
||||
return x;
|
||||
};
|
||||
|
||||
const getCurrentWeekTimesheetOverview = async (when: Date = new Date()) => {
|
||||
const off = Math.trunc((weekStart(when).getTime() - weekStart(new Date()).getTime()) / 604800000);
|
||||
await fetchWeek(off);
|
||||
}
|
||||
const getCurrentPayPeriod = async () => fetchPayPeriod(0);
|
||||
const getNextPayPeriod = async () => fetchPayPeriod(1);
|
||||
const getPreviousPayPeriod = async () => fetchPayPeriod(-1);
|
||||
|
||||
return {
|
||||
week_offset,
|
||||
fetchWeek,
|
||||
this_week,
|
||||
next_week,
|
||||
previous_week,
|
||||
saveTimesheetShifts,
|
||||
getCurrentWeekTimesheetOverview,
|
||||
getTimesheetsByDate,
|
||||
fetchPayPeriod,
|
||||
getCurrentPayPeriod,
|
||||
getNextPayPeriod,
|
||||
getPreviousPayPeriod,
|
||||
};
|
||||
};
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
<script setup lang="ts">
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import { useAuthStore } from 'src/stores/auth-store';
|
||||
import { useTimesheetApi } from '../composables/use-timesheet-api';
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { date } from 'quasar';
|
||||
import TimesheetEmployeeDetailsShifts from '../components/timesheet-details-shifts.vue';
|
||||
import { useAuthStore } from 'src/stores/auth-store';
|
||||
import TimesheetEmployeeDetailsShifts from '../components/timesheet/timesheet-details-shifts.vue';
|
||||
import TimesheetNavigation from '../components/timesheet/timesheet-navigation.vue';
|
||||
import ShiftsLegend from '../components/shift/shifts-legend.vue';
|
||||
|
||||
|
||||
/* eslint-disable */
|
||||
const { locale } = useI18n();
|
||||
const timesheet_store = useTimesheetStore();
|
||||
const auth_store = useAuthStore();
|
||||
const timesheet_api = useTimesheetApi();
|
||||
|
||||
const date_options: Intl.DateTimeFormatOptions = {
|
||||
day: 'numeric',
|
||||
|
|
@ -30,14 +32,22 @@ const pay_period_label = computed(() => {
|
|||
return { start_date, end_date };
|
||||
});
|
||||
|
||||
const is_calendar_limit = computed( () => {
|
||||
return timesheet_store.current_pay_period.pay_year === 2024 &&
|
||||
timesheet_store.current_pay_period.pay_period_no <= 1;
|
||||
});
|
||||
|
||||
|
||||
const onDateSelected = async (date_string: string) => {
|
||||
await timesheet_api.getTimesheetsByDate(date_string);
|
||||
};
|
||||
|
||||
const loadByDate = async (isoDate: string) => {
|
||||
await timesheet_store.getPayPeriodByDate(isoDate);
|
||||
await timesheet_store.getTimesheetsByPayPeriodAndEmail(auth_store.user.email);
|
||||
};
|
||||
|
||||
onMounted( async () => {
|
||||
await timesheet_store.getPayPeriodByDate(date.formatDate(new Date(), 'YYYY-MM-DD'));
|
||||
await timesheet_store.getTimesheetsByPayPeriodAndEmail(auth_store.user.email);
|
||||
await loadByDate(date.formatDate(new Date(), 'YYYY-MM-DD' ));
|
||||
});
|
||||
|
||||
|
|
@ -71,22 +81,23 @@ onMounted( async () => {
|
|||
</div>
|
||||
<div>
|
||||
<q-card flat class="q-mt-md bg-secondary">
|
||||
<TimesheetNavigation
|
||||
:is-disabled="timesheet_store.is_loading"
|
||||
:min-pickable-date="'2023-12-16'"
|
||||
:current-label="timesheet_store.current_pay_period?.label || ''"
|
||||
@navigate-to="(iso) => loadByDate(iso)"
|
||||
/>
|
||||
<ShiftsLegend
|
||||
:is-loading="false"
|
||||
/>
|
||||
<TimesheetNavigation
|
||||
:is-disabled="timesheet_store.is_loading"
|
||||
:is-previous-limit="is_calendar_limit"
|
||||
@date-selected="value => onDateSelected(value)"
|
||||
@pressed-previous-button="timesheet_api.getPreviousPayPeriod()"
|
||||
@pressed-next-button="timesheet_api.getNextPayPeriod()"
|
||||
/>
|
||||
<ShiftsLegend
|
||||
:is-loading="false"
|
||||
/>
|
||||
<q-card-section horizontal>
|
||||
<TimesheetEmployeeDetailsShifts
|
||||
:raw-data="timesheet_store.pay_period_employee_details"
|
||||
:current-pay-period="timesheet_store.current_pay_period"
|
||||
/>
|
||||
<q-inner-loading :showing="timesheet_store.is_loading" color="primary"/>
|
||||
</q-card-section>
|
||||
<q-inner-loading :showing="timesheet_store.is_loading" color="primary"/>
|
||||
</q-card>
|
||||
</div>
|
||||
</q-page>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user