fix(all): many changes, see commit details. Add weekly overview data to timesheets
This commit is contained in:
parent
f738a5872a
commit
1e16c8334b
BIN
src/assets/info-pannes.png
Normal file
BIN
src/assets/info-pannes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
|
|
@ -245,6 +245,9 @@ export default {
|
|||
page_header: "Timesheet",
|
||||
week: "week",
|
||||
total_hours: "total hours: ",
|
||||
total_expenses: "total expenses: ",
|
||||
vacation_available: "vacation time available: ",
|
||||
sick_available: "sick time available: ",
|
||||
current_shifts: "shifts worked",
|
||||
apply_preset: "auto-fill",
|
||||
apply_preset_day: "Apply schedule to day",
|
||||
|
|
|
|||
|
|
@ -246,6 +246,9 @@ export default {
|
|||
page_header: "Carte de temps",
|
||||
week: "semaine",
|
||||
total_hours: "heures totales: ",
|
||||
total_expenses: "dépenses totales: ",
|
||||
vacation_available: "vacances disponibles: ",
|
||||
sick_available: "congés maladie disponible: ",
|
||||
current_shifts: "quarts entrées",
|
||||
apply_preset: "auto-remplir",
|
||||
apply_preset_day: "Appliquer horaire pour la journée",
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<template>
|
||||
<q-card
|
||||
class="shortcut-card cursor-pointer"
|
||||
class="shortcut-card cursor-pointer shadow-12"
|
||||
@click="onClickExternalShortcut"
|
||||
>
|
||||
<q-img
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
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: '', value: -1 });
|
||||
options.push({ label: 'Aucun', value: -1 });
|
||||
return options;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -58,21 +58,21 @@
|
|||
name="form"
|
||||
icon="las la-id-card"
|
||||
:label="$q.screen.lt.sm ? '' : $t('employee_management.details_label')"
|
||||
class="rounded-25 q-ma-xs"
|
||||
class="rounded-25 q-ma-xs bg-dark"
|
||||
style="border: 2px solid var(--q-accent);"
|
||||
/>
|
||||
<q-tab
|
||||
name="access"
|
||||
icon="las la-key"
|
||||
:label="$q.screen.lt.sm ? '' : $t('employee_management.access_label')"
|
||||
class="rounded-25 q-ma-xs"
|
||||
class="rounded-25 q-ma-xs bg-dark"
|
||||
style="border: 2px solid var(--q-accent);"
|
||||
/>
|
||||
<q-tab
|
||||
name="schedule"
|
||||
icon="calendar_month"
|
||||
:label="$q.screen.lt.sm ? '' : $t('employee_management.schedule_label')"
|
||||
class="rounded-25 q-ma-xs"
|
||||
class="rounded-25 q-ma-xs bg-dark"
|
||||
style="border: 2px solid var(--q-accent);"
|
||||
/>
|
||||
</q-tabs>
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@
|
|||
:row="props.row"
|
||||
:index="props.rowIndex"
|
||||
:is-management="is_management"
|
||||
@on-profile-click="is_management ? employee_store.openAddModifyDialog : ''"
|
||||
@on-profile-click="email => is_management ? employee_store.openAddModifyDialog(email) : ''"
|
||||
/>
|
||||
</transition>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
v-model="shift.is_remote"
|
||||
dense
|
||||
keep-color
|
||||
size="3em"
|
||||
size="2.5em"
|
||||
color="accent"
|
||||
icon="las la-building"
|
||||
checked-icon="las la-laptop"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
<!-- employee pay period details using chart -->
|
||||
<div
|
||||
v-if="is_dialog_open && !$q.platform.is.mobile"
|
||||
class="col-4 q-px-md no-wrap"
|
||||
class="col-auto q-px-md no-wrap"
|
||||
:class="$q.platform.is.mobile ? 'column' : 'row'"
|
||||
>
|
||||
<DetailsDialogChartHoursWorked class="col" />
|
||||
|
|
@ -50,8 +50,8 @@
|
|||
</div>
|
||||
|
||||
<!-- list of shifts -->
|
||||
<div class="col column no-wrap">
|
||||
<TimesheetWrapper mode="approval" class="col"/>
|
||||
<div class="col-auto column no-wrap">
|
||||
<TimesheetWrapper mode="approval" class="col-auto"/>
|
||||
</div>
|
||||
</div>
|
||||
</q-dialog>
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@
|
|||
</template>
|
||||
|
||||
<template #option="scope">
|
||||
<q-item>
|
||||
<q-item clickable v-bind="scope.itemProps">
|
||||
<q-item-section avatar>
|
||||
<q-icon
|
||||
:name="scope.opt.icon"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
<script
|
||||
setup
|
||||
lang="ts"
|
||||
>
|
||||
import { useAuthStore } from 'src/stores/auth-store';
|
||||
import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-utils';
|
||||
|
||||
const { mode = 'totals', totalHours = 0, vacationHours = 0, sickHours = 0, totalExpenses = 0 } = defineProps<{
|
||||
mode: 'total-hours' | 'off-hours';
|
||||
totalHours?: number;
|
||||
vacationHours?: number;
|
||||
sickHours?: number;
|
||||
totalExpenses?: number;
|
||||
}>();
|
||||
|
||||
const auth_store = useAuthStore();
|
||||
const is_management = auth_store.user?.user_module_access.includes('timesheets_approval');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="column full-width shadow-4 rounded-5 q-pa-sm"
|
||||
style="border: 1px solid var(--q-accent);"
|
||||
>
|
||||
<div
|
||||
v-if="mode === 'total-hours'"
|
||||
class="col column full-width"
|
||||
>
|
||||
<div class="col row full-width">
|
||||
<span class="col-auto text-uppercase text-caption text-bold text-accent">
|
||||
{{ $t('timesheet.total_hours') }}
|
||||
</span>
|
||||
|
||||
<span class="col text-right">{{ getHoursMinutesStringFromHoursFloat(totalHours) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="col row full-width">
|
||||
<span class="col-auto text-uppercase text-caption text-bold text-accent">
|
||||
{{ $t('timesheet.total_expenses') }}
|
||||
</span>
|
||||
|
||||
<span class="col text-right">{{ totalExpenses }}$</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="col column full-width"
|
||||
>
|
||||
<div class="col row full-width">
|
||||
<span class="col-auto text-uppercase text-caption text-bold text-accent">
|
||||
{{ $t('timesheet.vacation_available') }}
|
||||
</span>
|
||||
|
||||
<span class="col text-right">{{ Math.floor(vacationHours / 8) }}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="is_management"
|
||||
class="col row full-width"
|
||||
>
|
||||
<span class="col-auto text-uppercase text-caption text-bold text-accent">
|
||||
{{ $t('timesheet.sick_available') }}
|
||||
</span>
|
||||
|
||||
<span class="col text-right">{{ Math.floor(sickHours / 8) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import { Shift } from 'src/modules/timesheets/models/shift.models';
|
||||
import { useTimesheetApi } from 'src/modules/timesheets/composables/use-timesheet-api';
|
||||
import type { QScrollArea } from 'quasar';
|
||||
import type { QScrollArea, TouchSwipeValue } from 'quasar';
|
||||
import type { TimesheetDay } from 'src/modules/timesheets/models/timesheet.models';
|
||||
|
||||
const CURRENT_DATE_STRING = new Date().toISOString().slice(0, 10);
|
||||
|
|
@ -34,7 +34,9 @@
|
|||
const currentDayComponent = ref<HTMLElement[] | null>(null);
|
||||
const currentDayComponentWatcher = ref(currentDayComponent);
|
||||
|
||||
const scroll_y = computed(() => timesheet_page.value?.getScrollPosition().top ?? 0)
|
||||
const scroll_y = computed(() => timesheet_page.value?.getScrollPosition().top ?? 0);
|
||||
const timesheet_container = ref<HTMLElement | null>(null);
|
||||
const scroll_area_height = ref(0);
|
||||
|
||||
const addNewShift = (day_shifts: Shift[], date: string, timesheet_id: number) => {
|
||||
ui_store.focus_next_component = true;
|
||||
|
|
@ -57,10 +59,10 @@
|
|||
return day.shifts.every(shift => shift.is_approved === true);
|
||||
};
|
||||
|
||||
const handleSwipe = async (direction: 'left' | 'up' | 'down' | 'right' | undefined, distance: { x?: number, y?: number }) => {
|
||||
mobile_animation_direction.value = direction === 'left' ? 'fadeInRight' : 'fadeInLeft';
|
||||
if (distance.x && Math.abs(distance.x) > 10) {
|
||||
await timesheet_api.getTimesheetsBySwiping(direction === 'left' ? 1 : -1)
|
||||
const handleSwipe: TouchSwipeValue = (details) => {
|
||||
mobile_animation_direction.value = details.direction === 'left' ? 'fadeInRight' : 'fadeInLeft';
|
||||
if (details.distance && details.distance.x && Math.abs(details.distance.x) > 10) {
|
||||
timesheet_api.getTimesheetsBySwiping(details.direction === 'left' ? 1 : -1).catch(error => console.error(error));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -74,6 +76,10 @@
|
|||
timesheet_page.value.setScrollPosition('vertical', currentDayComponent.value[0]!.offsetTop, 800);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timesheet_container.value !== null && mode === 'approval') {
|
||||
scroll_area_height.value = timesheet_container.value.offsetHeight
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
@ -81,12 +87,13 @@
|
|||
<div
|
||||
class="column fit relative-position"
|
||||
:style="$q.platform.is.mobile && $q.screen.width < $q.screen.height ? 'margin-bottom: 40px' : ''"
|
||||
v-touch-swipe="value => handleSwipe(value.direction, value.distance ?? { x: 0, y: 0 })"
|
||||
v-touch-swipe="handleSwipe"
|
||||
>
|
||||
<q-scroll-area
|
||||
ref="timesheet_page"
|
||||
:horizontal-offset="[0, 3]"
|
||||
class="absolute-full hide-scrollbar"
|
||||
class="col absolute-full hide-scrollbar"
|
||||
:style="mode === 'approval' ? `height: ${scroll_area_height}px;` : ''"
|
||||
:thumb-style="{ opacity: '0' }"
|
||||
:bar-style="{ opacity: '0' }"
|
||||
>
|
||||
|
|
@ -110,6 +117,7 @@
|
|||
<!-- Else show timesheets if found -->
|
||||
<div
|
||||
v-else
|
||||
ref="timesheet_container"
|
||||
class="col fit"
|
||||
:class="$q.platform.is.mobile ? 'column' : 'row'"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@
|
|||
>
|
||||
/* eslint-disable */
|
||||
import ShiftList from 'src/modules/timesheets/components/shift-list.vue';
|
||||
import LoadingOverlay from 'src/modules/shared/components/loading-overlay.vue';
|
||||
import ExpenseDialog from 'src/modules/timesheets/components/expense-dialog.vue';
|
||||
import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue';
|
||||
import PayPeriodNavigator from 'src/modules/shared/components/pay-period-navigator.vue';
|
||||
import TimesheetErrorWidget from 'src/modules/timesheets/components/timesheet-error-widget.vue';
|
||||
import LoadingOverlay from 'src/modules/shared/components/loading-overlay.vue';
|
||||
import ShiftListWeeklyOverview from 'src/modules/timesheets/components/shift-list-weekly-overview.vue';
|
||||
import ShiftListWeeklyOverviewMobile from 'src/modules/timesheets/components/mobile/shift-list-weekly-overview-mobile.vue';
|
||||
|
||||
import { computed, onMounted } from 'vue';
|
||||
|
|
@ -37,9 +39,41 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="column items-center full-height">
|
||||
<div class="column items-center full-height relative-position no-wrap">
|
||||
<LoadingOverlay v-model="timesheet_store.is_loading" />
|
||||
|
||||
<!-- label for approval mode to delimit that this is the timesheet -->
|
||||
<span
|
||||
v-if="mode === 'approval'"
|
||||
class="col-auto text-uppercase text-bold text-h5"
|
||||
>
|
||||
{{ $t('timesheet.page_header') }}
|
||||
</span>
|
||||
|
||||
|
||||
<!-- weekly overview -->
|
||||
<div class="col-auto row q-px-lg full-width">
|
||||
<!-- supervisor weekly overview -->
|
||||
<div class="col-xs-6 col-md-4 col-xl-3 q-pa-md">
|
||||
<ShiftListWeeklyOverview mode="total-hours" />
|
||||
</div>
|
||||
|
||||
<PageHeaderTemplate
|
||||
v-if="mode === 'normal'"
|
||||
:title="'timesheet.page_header'"
|
||||
:start-date="timesheet_store.pay_period?.period_start ?? ''"
|
||||
:end-date="timesheet_store.pay_period?.period_end ?? ''"
|
||||
class="col"
|
||||
/>
|
||||
|
||||
<q-space v-else />
|
||||
|
||||
<!-- employee weekly overview -->
|
||||
<div class="col-xs-6 col-md-4 col-xl-3 q-pa-md">
|
||||
<ShiftListWeeklyOverview mode="off-hours" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- top menu -->
|
||||
<div
|
||||
class="col-auto row items-center full-width"
|
||||
|
|
@ -66,12 +100,6 @@
|
|||
@click="expenses_store.open"
|
||||
/>
|
||||
|
||||
<!-- label for approval mode to delimit that this is the timesheet -->
|
||||
<span
|
||||
v-if="mode === 'approval'"
|
||||
class="col-auto text-uppercase text-bold text-h5"
|
||||
> {{ $t('timesheet.page_header') }}</span>
|
||||
|
||||
<q-space v-if="$q.screen.width > $q.screen.height" />
|
||||
|
||||
<!-- desktop expenses button -->
|
||||
|
|
@ -107,7 +135,8 @@
|
|||
|
||||
<ShiftList
|
||||
:mode="mode"
|
||||
class="col"
|
||||
:class="mode === 'normal' ? 'col' : 'col-auto'"
|
||||
:style="mode === 'normal' ? '' : 'min-height: 100vh'"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
|
|
|
|||
|
|
@ -49,6 +49,14 @@
|
|||
route="https://map.targointernet.com/infrastructure/map.php"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-3 q-pa-sm">
|
||||
<ShortcutCard
|
||||
image-source="src/assets/info-pannes.png"
|
||||
title="Info Pannes"
|
||||
route="https://infopannes.solutions.hydroquebec.com/info-pannes/pannes/pannes-en-cours"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
const headerComponent = ref<HTMLElement | null>(null);
|
||||
|
||||
const table_max_height = computed(() => {
|
||||
const height = page_height.value - (headerComponent.value?.offsetHeight ?? 0);
|
||||
const height = page_height.value - (headerComponent.value?.clientHeight ?? 0);
|
||||
return height;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@
|
|||
setup
|
||||
lang="ts"
|
||||
>
|
||||
import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue';
|
||||
|
||||
import TimesheetWrapper from 'src/modules/timesheets/components/timesheet-wrapper.vue';
|
||||
|
||||
import { useAuthStore } from 'src/stores/auth-store';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
|
||||
const { user } = useAuthStore();
|
||||
const timesheet_store = useTimesheetStore();
|
||||
</script>
|
||||
|
||||
|
||||
|
|
@ -17,13 +15,6 @@
|
|||
<q-page
|
||||
class="column bg-secondary items-center"
|
||||
>
|
||||
<PageHeaderTemplate
|
||||
:title="'timesheet.page_header'"
|
||||
:start-date="timesheet_store.pay_period?.period_start ?? ''"
|
||||
:end-date="timesheet_store.pay_period?.period_end ?? ''"
|
||||
class="col-auto"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="col column fit"
|
||||
:style="$q.platform.is.mobile && ($q.screen.width < $q.screen.height) ? '' : 'width: 90vw'"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user