feat(filters): add possibility of hiding inactive users, filter structure set up for future filters
This commit is contained in:
parent
e665cf87ab
commit
9a70875f78
|
|
@ -284,6 +284,7 @@ export default {
|
|||
mileage: "mileage",
|
||||
verified: "approved",
|
||||
unverified: "pending",
|
||||
inactive: "inactive",
|
||||
},
|
||||
tooltip: {
|
||||
button_detailed_view: "detailed view",
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ export default {
|
|||
mileage: "kilométrage",
|
||||
verified: "approuvé",
|
||||
unverified: "à vérifier",
|
||||
inactive: "inactif",
|
||||
},
|
||||
tooltip: {
|
||||
button_detailed_view: "vue détaillée",
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
dense
|
||||
rounded
|
||||
debounce="300"
|
||||
class="right-rounded"
|
||||
:label="$t('shared.label.search')"
|
||||
label-color="accent"
|
||||
bg-color="white"
|
||||
color="accent"
|
||||
bg-color="white"
|
||||
label-color="accent"
|
||||
class="text-primary"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
setup
|
||||
lang="ts"
|
||||
>
|
||||
import { ref } from 'vue';
|
||||
import type { PayPeriodOverviewFilters } from 'src/modules/timesheet-approval/models/timesheet-overview.models';
|
||||
|
||||
const boolean_filters = ref([])
|
||||
const filters = defineModel<PayPeriodOverviewFilters>('filters', { required: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -17,15 +17,14 @@ import { ref } from 'vue';
|
|||
|
||||
<div class="col row">
|
||||
<q-checkbox
|
||||
v-model="boolean_filters"
|
||||
v-model="filters.is_showing_inactive"
|
||||
size="lg"
|
||||
val="inactive"
|
||||
color="accent"
|
||||
label="show inactive"
|
||||
class="col"
|
||||
/>
|
||||
<q-checkbox
|
||||
v-model="boolean_filters"
|
||||
v-model="filters.is_showing_team_only"
|
||||
size="lg"
|
||||
val="team"
|
||||
color="accent"
|
||||
|
|
|
|||
|
|
@ -24,16 +24,20 @@
|
|||
>
|
||||
<q-card
|
||||
class="rounded-10 shadow-5"
|
||||
:style="`animation-delay: ${index / 15}s;`"
|
||||
:style="`animation-delay: ${index / 15}s; opacity: ${row.is_active ? '1' : '0.5'}; transform: scale(${row.is_active ? '1' : '0.9'})`"
|
||||
>
|
||||
<!-- Card header with employee name and details button-->
|
||||
<q-card-section
|
||||
horizontal
|
||||
class="q-py-none q-px-sm q-ma-none justify-between items-center bg-primary text-white"
|
||||
class="q-py-xs q-px-sm q-ma-none justify-between items-center bg-primary text-white"
|
||||
>
|
||||
<div>
|
||||
<span class="text-h5 text-uppercase text-weight-medium text-accent q-mr-xs">{{ row.employee_name.split(' ')[0]
|
||||
}}</span>
|
||||
<span
|
||||
class="text-h5 text-uppercase text-weight-medium q-mr-xs"
|
||||
:class="row.is_active ? 'text-accent' : 'text-negative'"
|
||||
>
|
||||
{{ row.employee_name.split(' ')[0] }}
|
||||
</span>
|
||||
<span class="text-uppercase text-weight-light">{{ row.employee_name.split(' ')[1] }}</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -45,7 +49,7 @@
|
|||
unelevated
|
||||
class="col-auto q-pa-none q-ma-none"
|
||||
color="accent"
|
||||
icon="work_history"
|
||||
icon="las la-chart-pie"
|
||||
@click="emit('clickDetails', row)"
|
||||
>
|
||||
<q-tooltip
|
||||
|
|
@ -55,6 +59,8 @@
|
|||
>
|
||||
{{ $t('timesheet_approvals.tooltip.button_detailed_view') }}
|
||||
</q-tooltip>
|
||||
|
||||
<q-icon name="las la-chart-bar" color="accent"/>
|
||||
</q-btn>
|
||||
</q-card-section>
|
||||
|
||||
|
|
@ -67,12 +73,12 @@
|
|||
<div class="col column">
|
||||
<span
|
||||
class="text-weight-bold text-uppercase q-pa-none q-my-none"
|
||||
:class="row.regular_hours > 80 ? 'text-negative' : 'text-accent'"
|
||||
:class="row.regular_hours > 80 || !row.is_active ? 'text-negative' : 'text-accent'"
|
||||
> {{
|
||||
$t('shared.shift_type.regular') }} </span>
|
||||
<span
|
||||
class="text-weight-bolder text-h3 q-py-none"
|
||||
:class="row.regular_hours > 80 ? 'text-negative' : ''"
|
||||
:class="row.regular_hours > 80 || !row.is_active ? 'text-negative' : ''"
|
||||
> {{ row.regular_hours }} </span>
|
||||
<q-separator class="q-mr-sm" />
|
||||
</div>
|
||||
|
|
@ -133,16 +139,20 @@
|
|||
<q-card-section
|
||||
horizontal
|
||||
class="justify-between items-center text-weight-bold q-pa-none"
|
||||
:class="row.is_approved ? 'text-white bg-accent' : 'bg-dark text-accent'"
|
||||
:class="row.is_active ? (row.is_approved ? 'text-white bg-accent' : 'bg-dark text-accent') : 'bg-transparent'"
|
||||
>
|
||||
<div class="col-auto">
|
||||
<span class="text-uppercase text-h6 q-ml-sm text-weight-bolder"> {{ row.total_hours }} </span>
|
||||
<div
|
||||
v-if="row.is_active"
|
||||
class="col row full-width"
|
||||
>
|
||||
<div class="col">
|
||||
<span class="text-uppercase text-h6 q-ml-sm text-weight-bolder"> {{ row.total_hours }}
|
||||
</span>
|
||||
<span class="text-uppercase text-weight-bold text-caption q-ml-xs"> total </span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-auto q-py-xs q-px-md"
|
||||
style="border: 1px solid var(--q-accent);"
|
||||
>
|
||||
<q-checkbox
|
||||
v-model="modelApproval"
|
||||
|
|
@ -158,6 +168,21 @@
|
|||
:class="row.is_approved ? '' : 'text-accent'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="col row flex-center q-px-sm full-width"
|
||||
>
|
||||
<q-icon
|
||||
name="block"
|
||||
color="negative"
|
||||
class="col-auto"
|
||||
size="lg"
|
||||
/>
|
||||
<span class="col q-pl-sm text-uppercase text-weight-bold text-h5">{{
|
||||
$t('timesheet_approvals.table.inactive') }}</span>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</transition>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,24 @@
|
|||
<script setup lang="ts">
|
||||
/* eslint-disable */
|
||||
import { computed, ref } from 'vue';
|
||||
import OverviewListItem from 'src/modules/timesheet-approval/components/overview-list-item.vue';
|
||||
import LoadingOverlay from 'src/modules/shared/components/loading-overlay.vue';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import { overview_column_names, pay_period_overview_columns, type TimesheetOverview } from 'src/modules/timesheet-approval/models/timesheet-overview.models';
|
||||
<script
|
||||
setup
|
||||
lang="ts"
|
||||
>
|
||||
/* eslint-disable */
|
||||
import OverviewListItem from 'src/modules/timesheet-approval/components/overview-list-item.vue';
|
||||
import LoadingOverlay from 'src/modules/shared/components/loading-overlay.vue';
|
||||
import QTableFilters from 'src/modules/shared/components/q-table-filters.vue';
|
||||
import PayPeriodNavigator from 'src/modules/shared/components/pay-period-navigator.vue';
|
||||
import OverviewListFilters from 'src/modules/timesheet-approval/components/overview-list-filters.vue';
|
||||
|
||||
const timesheet_store = useTimesheetStore();
|
||||
import { computed, ref } from 'vue';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api';
|
||||
import { overview_column_names, pay_period_overview_columns, PayPeriodOverviewFilters, type TimesheetOverview } from 'src/modules/timesheet-approval/models/timesheet-overview.models';
|
||||
|
||||
const visible_columns = ref<string[]>([
|
||||
|
||||
const timesheet_store = useTimesheetStore();
|
||||
const timesheet_approval_api = useTimesheetApprovalApi();
|
||||
|
||||
const visible_columns = ref<string[]>([
|
||||
overview_column_names.REGULAR,
|
||||
overview_column_names.EVENING,
|
||||
overview_column_names.EMERGENCY,
|
||||
|
|
@ -17,17 +27,38 @@ const visible_columns = ref<string[]>([
|
|||
overview_column_names.HOLIDAY,
|
||||
overview_column_names.OVERTIME,
|
||||
overview_column_names.IS_APPROVED,
|
||||
]);
|
||||
]);
|
||||
const is_showing_filters = ref(false);
|
||||
const search_string = ref('');
|
||||
|
||||
const onClickedDetails = async (row: TimesheetOverview) => {
|
||||
const overview_rows = computed(() => timesheet_store.pay_period_overviews.filter(overview => overview));
|
||||
const overview_filters = ref<PayPeriodOverviewFilters>({
|
||||
is_showing_inactive: false,
|
||||
is_showing_team_only: false,
|
||||
supervisors: [],
|
||||
name_search_string: search_string.value,
|
||||
});
|
||||
|
||||
const onClickedDetails = async (row: TimesheetOverview) => {
|
||||
timesheet_store.current_pay_period_overview = row;
|
||||
await timesheet_store.getTimesheetsByOptionalEmployeeEmail(row.email);
|
||||
|
||||
timesheet_store.is_details_dialog_open = true;
|
||||
};
|
||||
};
|
||||
|
||||
const overview_rows = computed(() => timesheet_store.pay_period_overviews.filter(overview => overview))
|
||||
const filterEmployeeRows = (rows: readonly TimesheetOverview[], terms: PayPeriodOverviewFilters): TimesheetOverview[] => {
|
||||
let result = [...rows];
|
||||
|
||||
if (!terms.is_showing_inactive) {
|
||||
result = result.filter(row => row.is_active);
|
||||
}
|
||||
|
||||
// if (terms.name_search_string) {
|
||||
// result = result.filter(row => row.employee_name.includes(terms.name_search_string ?? ''));
|
||||
// }
|
||||
|
||||
return result;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -45,10 +76,12 @@ const onClickedDetails = async (row: TimesheetOverview) => {
|
|||
:rows="overview_rows"
|
||||
:columns="pay_period_overview_columns"
|
||||
row-key="email"
|
||||
:filter="timesheet_store.search_filter"
|
||||
:grid="timesheet_store.is_approval_grid_mode"
|
||||
:dense="timesheet_store.is_approval_grid_mode"
|
||||
hide-pagination
|
||||
:pagination="{ sortBy: 'is_active' }"
|
||||
:filter="overview_filters"
|
||||
:filter-method="filterEmployeeRows"
|
||||
color="accent"
|
||||
:rows-per-page-options="[0]"
|
||||
card-container-class="justify-center"
|
||||
|
|
@ -59,6 +92,87 @@ const onClickedDetails = async (row: TimesheetOverview) => {
|
|||
:no-results-label="$t('shared.error.no_search_results')"
|
||||
:loading-label="$t('shared.label.loading')"
|
||||
>
|
||||
<template #top>
|
||||
<div class="column full-width">
|
||||
|
||||
<div
|
||||
class="col-auto row items-start full-width q-px-lg"
|
||||
:class="($q.platform.is.mobile ? 'column flex-center' : 'row q-mt-md') + (timesheet_store.is_approval_grid_mode ? '' : ' q-mb-md')"
|
||||
>
|
||||
<PayPeriodNavigator
|
||||
@date-selected="timesheet_approval_api.getTimesheetOverviews"
|
||||
@pressed-next-button="timesheet_approval_api.getTimesheetOverviews"
|
||||
@pressed-previous-button="timesheet_approval_api.getTimesheetOverviews"
|
||||
:class="$q.platform.is.mobile ? 'q-mb-sm' : ''"
|
||||
style="height: 40px;"
|
||||
/>
|
||||
|
||||
<q-space />
|
||||
|
||||
<div
|
||||
class="col-auto row no-wrap items-start"
|
||||
:class="$q.platform.is.mobile ? 'q-mb-md' : ''"
|
||||
>
|
||||
<q-btn-toggle
|
||||
v-model="timesheet_store.is_approval_grid_mode"
|
||||
push
|
||||
rounded
|
||||
color="white"
|
||||
text-color="accent"
|
||||
toggle-color="accent"
|
||||
class="col-auto"
|
||||
:class="$q.platform.is.mobile ? 'q-mb-sm' : 'q-mr-sm'"
|
||||
:options="[
|
||||
{ icon: 'grid_view', value: true },
|
||||
{ icon: 'view_list', value: false },
|
||||
]"
|
||||
style="height: 40px;"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
push
|
||||
rounded
|
||||
icon="download"
|
||||
color="accent"
|
||||
:label="$q.screen.lt.md ? '' : $t('shared.label.download')"
|
||||
class="col-auto q-mr-sm"
|
||||
style="height: 40px;"
|
||||
@click="timesheet_store.is_report_dialog_open = true"
|
||||
/>
|
||||
|
||||
<QTableFilters
|
||||
v-model:search="search_string"
|
||||
class="col-auto q-mb-xs"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
flat
|
||||
icon="filter_alt"
|
||||
color="white"
|
||||
:label="$q.platform.is.mobile ? '' : $t('shared.label.filter')"
|
||||
class="col q-ml-sm self-stretch bg-accent"
|
||||
style="border-radius: 5px 5px 0 0;"
|
||||
@click="is_showing_filters = !is_showing_filters"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<q-slide-transition>
|
||||
<OverviewListFilters
|
||||
v-if="is_showing_filters"
|
||||
v-model:filters="overview_filters"
|
||||
class="q-mx-lg col-auto"
|
||||
/>
|
||||
</q-slide-transition>
|
||||
|
||||
<q-separator
|
||||
color="accent"
|
||||
size="5px"
|
||||
class="q-mx-lg"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #header="props">
|
||||
<q-tr
|
||||
:props="props"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import type { QTableColumn } from "quasar";
|
||||
|
||||
export interface TimesheetOverview {
|
||||
export class TimesheetOverview {
|
||||
email: string;
|
||||
employee_name: string;
|
||||
is_active: boolean;
|
||||
regular_hours: number;
|
||||
other_hours: {
|
||||
evening_hours: number;
|
||||
|
|
@ -16,6 +17,25 @@ export interface TimesheetOverview {
|
|||
expenses: number;
|
||||
mileage: number;
|
||||
is_approved: boolean;
|
||||
|
||||
constructor() {
|
||||
this.email = '';
|
||||
this.employee_name = 'John Doe';
|
||||
this.is_active = true;
|
||||
this.regular_hours = 0;
|
||||
this.other_hours = {
|
||||
evening_hours: 0,
|
||||
emergency_hours: 0,
|
||||
overtime_hours: 0,
|
||||
sick_hours: 0,
|
||||
holiday_hours: 0,
|
||||
vacation_hours: 0,
|
||||
}
|
||||
this.total_hours = 0;
|
||||
this.expenses = 0;
|
||||
this.mileage = 0;
|
||||
this.is_approved = false;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PayPeriodOverviewResponse {
|
||||
|
|
@ -28,22 +48,11 @@ export interface PayPeriodOverviewResponse {
|
|||
employees_overview: TimesheetOverview[];
|
||||
}
|
||||
|
||||
export const default_pay_period_overview: TimesheetOverview = {
|
||||
email: '',
|
||||
employee_name: '',
|
||||
regular_hours: -1,
|
||||
other_hours: {
|
||||
evening_hours: -1,
|
||||
emergency_hours: -1,
|
||||
overtime_hours: -1,
|
||||
sick_hours: -1,
|
||||
holiday_hours: -1,
|
||||
vacation_hours: -1,
|
||||
},
|
||||
total_hours: -1,
|
||||
expenses: -1,
|
||||
mileage: -1,
|
||||
is_approved: false
|
||||
export interface PayPeriodOverviewFilters {
|
||||
is_showing_inactive: boolean;
|
||||
is_showing_team_only: boolean;
|
||||
supervisors: string[];
|
||||
name_search_string: string | number | null;
|
||||
}
|
||||
|
||||
export const overview_column_names = {
|
||||
|
|
@ -59,6 +68,7 @@ export const overview_column_names = {
|
|||
EXPENSES: 'expenses',
|
||||
MILEAGE: 'mileage',
|
||||
IS_APPROVED: 'is_approved',
|
||||
IS_ACTIVE: 'is_active',
|
||||
}
|
||||
|
||||
export const pay_period_overview_columns: QTableColumn[] = [
|
||||
|
|
@ -145,5 +155,11 @@ export const pay_period_overview_columns: QTableColumn[] = [
|
|||
label: 'timesheet_approvals.table.is_approved',
|
||||
field: 'is_approved',
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: overview_column_names.IS_ACTIVE,
|
||||
label: 'timesheet_approvals.table.is_active',
|
||||
field: 'is_active',
|
||||
sortable: true,
|
||||
}
|
||||
]
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
}>();
|
||||
|
||||
onMounted(async () => {
|
||||
if (mode === 'normal')
|
||||
await timesheet_api.getTimesheetsByDate(date.formatDate(new Date(), 'YYYY-MM-DD'));
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -6,21 +6,16 @@
|
|||
import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue';
|
||||
import OverviewList from 'src/modules/timesheet-approval/components/overview-list.vue';
|
||||
import DetailsDialog from 'src/modules/timesheet-approval/components/details-dialog.vue';
|
||||
import QTableFilters from 'src/modules/shared/components/q-table-filters.vue';
|
||||
import PayPeriodNavigator from 'src/modules/shared/components/pay-period-navigator.vue';
|
||||
import OverviewListFilters from 'src/modules/timesheet-approval/components/overview-list-filters.vue';
|
||||
import OverviewReport from 'src/modules/timesheet-approval/components/overview-report.vue';
|
||||
|
||||
import { date } from 'quasar';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { onMounted } from 'vue';
|
||||
import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api';
|
||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
|
||||
const timesheet_approval_api = useTimesheetApprovalApi();
|
||||
const timesheet_store = useTimesheetStore();
|
||||
|
||||
const is_showing_filters = ref(false);
|
||||
|
||||
onMounted(async () => {
|
||||
await timesheet_approval_api.getTimesheetOverviewsByDate(date.formatDate(new Date(), 'YYYY-MM-DD'));
|
||||
});
|
||||
|
|
@ -44,80 +39,6 @@
|
|||
:timesheets="timesheet_store.timesheets"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="col-auto row items-start full-width q-px-lg"
|
||||
:class="($q.platform.is.mobile ? 'column flex-center' : 'row q-mt-md') + (timesheet_store.is_approval_grid_mode ? '' : ' q-mb-md')"
|
||||
>
|
||||
<PayPeriodNavigator
|
||||
@date-selected="timesheet_approval_api.getTimesheetOverviews"
|
||||
@pressed-next-button="timesheet_approval_api.getTimesheetOverviews"
|
||||
@pressed-previous-button="timesheet_approval_api.getTimesheetOverviews"
|
||||
:class="$q.platform.is.mobile ? 'q-mb-sm' : ''"
|
||||
style="height: 40px;"
|
||||
/>
|
||||
|
||||
<q-space />
|
||||
|
||||
<div
|
||||
class="col-auto row no-wrap items-start"
|
||||
:class="$q.platform.is.mobile ? 'q-mb-md' : ''"
|
||||
>
|
||||
<q-btn-toggle
|
||||
v-model="timesheet_store.is_approval_grid_mode"
|
||||
push
|
||||
rounded
|
||||
color="white"
|
||||
text-color="accent"
|
||||
toggle-color="accent"
|
||||
class="col-auto"
|
||||
:class="$q.platform.is.mobile ? 'q-mb-sm' : 'q-mr-sm'"
|
||||
:options="[
|
||||
{ icon: 'grid_view', value: true },
|
||||
{ icon: 'view_list', value: false },
|
||||
]"
|
||||
style="height: 40px;"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
push
|
||||
rounded
|
||||
icon="download"
|
||||
color="accent"
|
||||
:label="$q.screen.lt.md ? '' : $t('shared.label.download')"
|
||||
class="col-auto q-mr-sm"
|
||||
style="height: 40px;"
|
||||
@click="timesheet_store.is_report_dialog_open = true"
|
||||
/>
|
||||
|
||||
<QTableFilters
|
||||
v-model:search="timesheet_store.search_filter"
|
||||
class="col-auto q-mb-xs"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
flat
|
||||
icon="filter_alt"
|
||||
color="white"
|
||||
:label="$q.platform.is.mobile ? '' : $t('shared.label.filter')"
|
||||
class="col q-ml-sm self-stretch bg-accent"
|
||||
style="border-radius: 5px 5px 0 0;"
|
||||
@click="is_showing_filters = !is_showing_filters"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<q-slide-transition class="col-auto">
|
||||
<OverviewListFilters
|
||||
v-if="is_showing_filters"
|
||||
class="q-mx-lg col-auto"
|
||||
/>
|
||||
</q-slide-transition>
|
||||
|
||||
<q-separator
|
||||
color="accent"
|
||||
size="5px"
|
||||
class="q-mx-lg"
|
||||
/>
|
||||
<OverviewReport />
|
||||
|
||||
<OverviewList class="col" />
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
|||
const is_details_dialog_open = ref(false);
|
||||
const selected_employee_name = ref<string>();
|
||||
const current_pay_period_overview = ref<TimesheetOverview>();
|
||||
const search_filter = ref<string | number | null>('');
|
||||
const is_approval_grid_mode = ref<boolean>(true);
|
||||
const pay_period_report = ref();
|
||||
|
||||
|
|
@ -147,7 +146,6 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
|||
is_report_dialog_open,
|
||||
is_approval_grid_mode,
|
||||
is_details_dialog_open,
|
||||
search_filter,
|
||||
pay_period,
|
||||
pay_period_overviews,
|
||||
current_pay_period_overview,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user