fix(all): Many fixes and adjustements, see full commit comment:
Dashboard: Reworked carousel and added useful links. Help page: made title sections more obvious, minor UI adjustments to spacing, appearance. Timesheets: Make mobile timesheet automaticall scroll to today's date when loading. Layout: Fix UI bugs where menu labels would not appear in mobile and tray would load automatically on mobile.
This commit is contained in:
parent
8989a7d9c0
commit
20fcc0206c
BIN
src/assets/google_thumbnail.png
Normal file
BIN
src/assets/google_thumbnail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 150 KiB |
|
|
@ -4,8 +4,9 @@ export default {
|
||||||
welcome_title: "Welcome to the new Targo Application!",
|
welcome_title: "Welcome to the new Targo Application!",
|
||||||
welcome_message: "Development is complete and the application is live! Things have remained mostly the same, but with a new coat of paint, a more streamlined user experience, and most importantly, drastically improved security and optimization!",
|
welcome_message: "Development is complete and the application is live! Things have remained mostly the same, but with a new coat of paint, a more streamlined user experience, and most importantly, drastically improved security and optimization!",
|
||||||
help_title: "We have a help page!",
|
help_title: "We have a help page!",
|
||||||
help_message: "We did our best to keep the app intuitive with as few clicks and changes as possible, but it's not always perfect! We made this page to explain every part of the app if you any of it ever feels confusing.",
|
help_message: "We've modernized the app while trying to make as few functional changes as possible, but if there's ever any part of the site that leaves you scratching your head, feel free to check out the help page.",
|
||||||
},
|
},
|
||||||
|
useful_links: "useful links",
|
||||||
},
|
},
|
||||||
help: {
|
help: {
|
||||||
label: "Centre d'aide",
|
label: "Centre d'aide",
|
||||||
|
|
@ -207,6 +208,7 @@ export default {
|
||||||
modify: "modify",
|
modify: "modify",
|
||||||
close: "close",
|
close: "close",
|
||||||
download: "download",
|
download: "download",
|
||||||
|
open: "open",
|
||||||
},
|
},
|
||||||
misc: {
|
misc: {
|
||||||
or: "or",
|
or: "or",
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ export default {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
carousel: {
|
carousel: {
|
||||||
welcome_title: "Bienvenue dans la nouvelle application Targo!",
|
welcome_title: "Bienvenue dans la nouvelle application Targo!",
|
||||||
welcome_message: "Le développement est terminé et l'application est officiellement en ligne! Les fonctionnalités demeurent grandement intactes comparé à l'ancienne version, mise à part une nouvelle couche de peinture, une expérience utilisateur plus intuitive et surtout une sécurité et optimization drastiquement amélioriés!",
|
welcome_message: "La nouvelle application est officiellement en ligne ! Plus performante et plus sécuritaire, elle conserve l’essentiel avec un design rafraîchie.",
|
||||||
help_title: "Nous avons une page d'aide!",
|
help_title: "Nous avons une page d'aide!",
|
||||||
help_message: "Nous avons fait notre possible pour rendre l'application plus intuitive et facile d'accès en suivant les tendances modernes, mais il y a toujours place à l'amélioration! La page d'aide est là pour vous si jamais nous avons raté la cible et qu'une partie du site semble nébuleux.",
|
help_message: "L’application a été pensée pour être plus intuitive et moderne. En cas de doute, la page d’aide est à votre disposition.",
|
||||||
},
|
},
|
||||||
|
useful_links: "liens utiles",
|
||||||
},
|
},
|
||||||
help: {
|
help: {
|
||||||
label: "Centre d'aide",
|
label: "Centre d'aide",
|
||||||
|
|
@ -208,6 +209,7 @@ export default {
|
||||||
modify: "modifier",
|
modify: "modifier",
|
||||||
close: "fermer",
|
close: "fermer",
|
||||||
download: "télécharger",
|
download: "télécharger",
|
||||||
|
open: "ouvrir",
|
||||||
},
|
},
|
||||||
misc: {
|
misc: {
|
||||||
or: "ou",
|
or: "ou",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
setup
|
setup
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useAuthStore } from 'src/stores/auth-store';
|
import { useAuthStore } from 'src/stores/auth-store';
|
||||||
import { useUiStore } from 'src/stores/ui-store';
|
import { useUiStore } from 'src/stores/ui-store';
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
{ i18n_key: 'nav_bar.help', icon: "contact_support", route: RouteNames.HELP },
|
{ i18n_key: 'nav_bar.help', icon: "contact_support", route: RouteNames.HELP },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const q = useQuasar();
|
||||||
const auth_store = useAuthStore();
|
const auth_store = useAuthStore();
|
||||||
const ui_store = useUiStore();
|
const ui_store = useUiStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -27,7 +29,7 @@
|
||||||
ui_store.current_page = page_name;
|
ui_store.current_page = page_name;
|
||||||
is_mini.value = true;
|
is_mini.value = true;
|
||||||
|
|
||||||
router.push({ name: page_name }).catch( error => {
|
router.push({ name: page_name }).catch(error => {
|
||||||
console.error('failed to reach page: ', error);
|
console.error('failed to reach page: ', error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -39,6 +41,12 @@
|
||||||
console.error('could not log you out: ', err);
|
console.error('could not log you out: ', err);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if(q.platform.is.mobile) {
|
||||||
|
ui_store.is_left_drawer_open = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -69,7 +77,10 @@
|
||||||
class="col-auto q-pl-sm"
|
class="col-auto q-pl-sm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="col text-uppercase text-weight-bold text-h6 q-mini-drawer-hide q-pl-sm">
|
<div
|
||||||
|
class="col text-uppercase text-weight-bold text-h6 q-pl-sm"
|
||||||
|
:class="$q.platform.is.mobile ? '' : 'q-mini-drawer-hide'"
|
||||||
|
>
|
||||||
{{ $t(button.i18n_key) }}
|
{{ $t(button.i18n_key) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -87,7 +98,10 @@
|
||||||
class="col-auto q-pl-sm"
|
class="col-auto q-pl-sm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="col text-uppercase text-weight-bold text-h6 q-mini-drawer-hide q-pl-sm">
|
<div
|
||||||
|
class="col text-uppercase text-weight-bold text-h6 q-pl-sm"
|
||||||
|
:class="$q.platform.is.mobile ? '' : 'q-mini-drawer-hide'"
|
||||||
|
>
|
||||||
{{ $t('nav_bar.logout') }}
|
{{ $t('nav_bar.logout') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
42
src/modules/dashboard/components/employee/shortcut-card.vue
Normal file
42
src/modules/dashboard/components/employee/shortcut-card.vue
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
<script
|
||||||
|
setup
|
||||||
|
lang="ts"
|
||||||
|
>
|
||||||
|
const { imageSource = "", title = "", description = "", route = "" } = defineProps<{
|
||||||
|
imageSource?: string,
|
||||||
|
title?: string,
|
||||||
|
description?: string,
|
||||||
|
route?: string,
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const onClickExternalShortcut = () => {
|
||||||
|
window.open(route, '_blank')?.focus();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-card
|
||||||
|
class="shortcut-card cursor-pointer"
|
||||||
|
@click="onClickExternalShortcut"
|
||||||
|
>
|
||||||
|
<q-img
|
||||||
|
:src="imageSource"
|
||||||
|
fit="contain"
|
||||||
|
>
|
||||||
|
<div class="absolute-bottom text-uppercase text-weight-bolder text-center">{{ title }}</div>
|
||||||
|
</q-img>
|
||||||
|
|
||||||
|
<q-card-section v-if="description">
|
||||||
|
<span>{{ description }}</span>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style
|
||||||
|
lang="sass"
|
||||||
|
scoped
|
||||||
|
>
|
||||||
|
.shortcut-card
|
||||||
|
width: 100%
|
||||||
|
max-width: 250px
|
||||||
|
</style>
|
||||||
71
src/modules/dashboard/components/main-carousel.vue
Normal file
71
src/modules/dashboard/components/main-carousel.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<script
|
||||||
|
setup
|
||||||
|
lang="ts"
|
||||||
|
>
|
||||||
|
import { RouteNames } from 'src/router/router-constants';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const slide = ref<string>('welcome');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-carousel
|
||||||
|
v-model="slide"
|
||||||
|
transition-prev="jump-right"
|
||||||
|
transition-next="jump-left"
|
||||||
|
swipeable
|
||||||
|
animated
|
||||||
|
infinite
|
||||||
|
arrows
|
||||||
|
:autoplay="9001"
|
||||||
|
control-color="accent"
|
||||||
|
class="bg-dark full-width rounded-15 shadow-18"
|
||||||
|
>
|
||||||
|
<!-- welcome slide -->
|
||||||
|
<q-carousel-slide
|
||||||
|
name="welcome"
|
||||||
|
class="q-pa-none fit"
|
||||||
|
>
|
||||||
|
<div class="column fit">
|
||||||
|
<q-img
|
||||||
|
src="src/assets/targo_building.png"
|
||||||
|
position="50% 25%"
|
||||||
|
fit="cover"
|
||||||
|
class="col-9"
|
||||||
|
>
|
||||||
|
<div class="absolute-bottom text-h6 text-uppercase text-weight-light">
|
||||||
|
{{ $t('dashboard.carousel.welcome_title') }}
|
||||||
|
</div>
|
||||||
|
</q-img>
|
||||||
|
|
||||||
|
<div class="col column flex-center q-px-md">
|
||||||
|
<span class="col-auto text-center">{{ $t('dashboard.carousel.welcome_message') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-carousel-slide>
|
||||||
|
|
||||||
|
<!-- help page slide -->
|
||||||
|
<q-carousel-slide
|
||||||
|
name="tv"
|
||||||
|
class="q-pa-none cursor-pointer"
|
||||||
|
@click="$router.push(RouteNames.HELP)"
|
||||||
|
>
|
||||||
|
<div class="column fit">
|
||||||
|
<q-img
|
||||||
|
src="src/assets/targo_help_banner.png"
|
||||||
|
position="50% 25%"
|
||||||
|
fit="none"
|
||||||
|
class="col-9"
|
||||||
|
>
|
||||||
|
<div class="absolute-bottom text-h6 text-uppercase text-weight-light">
|
||||||
|
{{ $t('dashboard.carousel.help_title') }}
|
||||||
|
</div>
|
||||||
|
</q-img>
|
||||||
|
|
||||||
|
<div class="col column flex-center q-px-md">
|
||||||
|
<span class="col-auto text-center">{{ $t('dashboard.carousel.help_message') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-carousel-slide>
|
||||||
|
</q-carousel>
|
||||||
|
</template>
|
||||||
|
|
@ -1,40 +1,43 @@
|
||||||
<script setup lang="ts">
|
<script
|
||||||
//default images
|
setup
|
||||||
// import default_dashboard from 'src/assets/help-ss/default-dashboard.png';
|
lang="ts"
|
||||||
import default_personal_profile from 'src/assets/help-ss/default-personnal_profile.png';
|
>
|
||||||
import default_timesheet from 'src/assets/help-ss/default-timesheet.png';
|
//default images
|
||||||
import default_employee_list from 'src/assets/help-ss/default-employee-list.png';
|
// import default_dashboard from 'src/assets/help-ss/default-dashboard.png';
|
||||||
import default_employee_management from 'src/assets/help-ss/default-employee-management.png';
|
import default_personal_profile from 'src/assets/help-ss/default-personnal_profile.png';
|
||||||
import default_validation_page from 'src/assets/help-ss/default-validation-page.png';
|
import default_timesheet from 'src/assets/help-ss/default-timesheet.png';
|
||||||
|
import default_employee_list from 'src/assets/help-ss/default-employee-list.png';
|
||||||
|
import default_employee_management from 'src/assets/help-ss/default-employee-management.png';
|
||||||
|
import default_validation_page from 'src/assets/help-ss/default-validation-page.png';
|
||||||
|
|
||||||
const default_images: Record<UserModuleAccess, string> = {
|
const default_images: Record<UserModuleAccess, string> = {
|
||||||
dashboard: '',
|
dashboard: '',
|
||||||
personal_profile: default_personal_profile,
|
personal_profile: default_personal_profile,
|
||||||
timesheets: default_timesheet,
|
timesheets: default_timesheet,
|
||||||
employee_list: default_employee_list,
|
employee_list: default_employee_list,
|
||||||
employee_management: default_employee_management,
|
employee_management: default_employee_management,
|
||||||
timesheets_approval: default_validation_page,
|
timesheets_approval: default_validation_page,
|
||||||
};
|
};
|
||||||
|
|
||||||
import type { HelpModuleOptions } from 'src/modules/help/models/help-module.model';
|
import type { HelpModuleOptions } from 'src/modules/help/models/help-module.model';
|
||||||
import type { UserModuleAccess } from 'src/modules/shared/models/user.models';
|
import type { UserModuleAccess } from 'src/modules/shared/models/user.models';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
help_module: UserModuleAccess;
|
help_module: UserModuleAccess;
|
||||||
options: HelpModuleOptions[];
|
options: HelpModuleOptions[];
|
||||||
moduleIndex: number;
|
moduleIndex: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const help_module = props.help_module;
|
const help_module = props.help_module;
|
||||||
const current_path = ref<string>(default_images[help_module]);
|
const current_path = ref<string>(default_images[help_module]);
|
||||||
|
|
||||||
const switchSide = (index: number) => {
|
const switchSide = (index: number) => {
|
||||||
if (index % 2 !== 0) {
|
if (index % 2 !== 0) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -45,14 +48,15 @@ const switchSide = (index: number) => {
|
||||||
>
|
>
|
||||||
<!-- Card Header -->
|
<!-- Card Header -->
|
||||||
<div
|
<div
|
||||||
class="row col-auto text-h5 q-pa-md text-primary bg-secondary"
|
class="row col-auto text-h4 text-weight-thin q-py-md q-px-xl bg-secondary"
|
||||||
:class="switchSide(moduleIndex) ? 'justify-start' : 'justify-end'"
|
:class="switchSide(moduleIndex) ? 'justify-end' : 'justify-start'"
|
||||||
>
|
>
|
||||||
{{ ($t(`help.tutorial.${help_module}.title`)).toUpperCase() }}
|
{{ ($t(`help.tutorial.${help_module}.title`)).toUpperCase() }}
|
||||||
</div>
|
</div>
|
||||||
<!-- Card Body -->
|
|
||||||
|
<!-- Card Body. The visual support image will alternate left and right -->
|
||||||
<div class="row col full-width q-px-none">
|
<div class="row col full-width q-px-none">
|
||||||
<!-- Object and descriptions zone -->
|
<!-- Left-sided visual support -->
|
||||||
<div
|
<div
|
||||||
class="col flex-center row"
|
class="col flex-center row"
|
||||||
v-if="moduleIndex % 2 !== 0"
|
v-if="moduleIndex % 2 !== 0"
|
||||||
|
|
@ -63,16 +67,17 @@ const switchSide = (index: number) => {
|
||||||
leave-active-class="animated fade-out"
|
leave-active-class="animated fade-out"
|
||||||
>
|
>
|
||||||
<q-img
|
<q-img
|
||||||
class="image-wrapper"
|
|
||||||
:src="current_path"
|
:src="current_path"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
fit="contain"
|
fit="contain"
|
||||||
|
class="rounded-10 image-wrapper"
|
||||||
>
|
>
|
||||||
</q-img>
|
</q-img>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
<div class="col column">
|
|
||||||
|
|
||||||
|
<!-- Area with expandable help items -->
|
||||||
|
<div class="col column q-px-md">
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
v-for="option, index in options"
|
v-for="option, index in options"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|
@ -112,7 +117,8 @@ const switchSide = (index: number) => {
|
||||||
</div>
|
</div>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
</div>
|
</div>
|
||||||
<!-- images of the related selected option -->
|
|
||||||
|
<!-- right-sided visual support -->
|
||||||
<div
|
<div
|
||||||
class="col flex-center row"
|
class="col flex-center row"
|
||||||
v-if="moduleIndex % 2 === 0"
|
v-if="moduleIndex % 2 === 0"
|
||||||
|
|
@ -123,11 +129,10 @@ const switchSide = (index: number) => {
|
||||||
leave-active-class="animated fade-out"
|
leave-active-class="animated fade-out"
|
||||||
>
|
>
|
||||||
<q-img
|
<q-img
|
||||||
class="image-wrapper"
|
|
||||||
:src="current_path"
|
:src="current_path"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
fit="contain"
|
fit="contain"
|
||||||
style="width: 150%;"
|
class="rounded-10 image-wrapper"
|
||||||
>
|
>
|
||||||
</q-img>
|
</q-img>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,13 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="column text-uppercase text-center text-weight-bolder text-h4 q-pt-lg">
|
<div class="column text-uppercase text-center text-weight-bolder text-h4">
|
||||||
<span
|
<span
|
||||||
v-if="!$q.platform.is.mobile"
|
v-if="!$q.platform.is.mobile"
|
||||||
class="col"
|
class="col q-pt-lg"
|
||||||
>{{ $t(title) }}</span>
|
>
|
||||||
|
{{ $t(title) }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<transition
|
<transition
|
||||||
enter-active-class="animated fadeInDown"
|
enter-active-class="animated fadeInDown"
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@
|
||||||
v-model="calendar_date"
|
v-model="calendar_date"
|
||||||
color="primary"
|
color="primary"
|
||||||
today-btn
|
today-btn
|
||||||
|
no-unset
|
||||||
mask="YYYY-MM-DD"
|
mask="YYYY-MM-DD"
|
||||||
:options="date => date >= PAY_PERIOD_DATE_LIMIT"
|
:options="date => date >= PAY_PERIOD_DATE_LIMIT"
|
||||||
@update:model-value="onDateSelected"
|
@update:model-value="onDateSelected"
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,18 @@
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
</q-toggle>
|
</q-toggle>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #option="scope">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-icon :name="scope.opt.icon" />
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
|
<q-item-section class="text-left">
|
||||||
|
{{ $t(scope.label) }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
class="col row flex-center"
|
class="col row flex-center"
|
||||||
>
|
>
|
||||||
<q-badge
|
<q-badge
|
||||||
:color="day.shifts.length > 0 ? (day.shifts.every(shift => shift.is_approved) ? 'accent shadow-2' : 'dark shadow-2') : 'blue-grey-5'"
|
:color="day.shifts.length > 0 ? (day.shifts.every(shift => shift.is_approved) ? 'accent shadow-2' : 'white shadow-2') : 'blue-grey-5'"
|
||||||
:class="day.shifts.length > 0 ? (day.shifts.every(shift => shift.is_approved) ? 'q-px-xs' : 'q-pa-sm') : ''"
|
:class="day.shifts.length > 0 ? (day.shifts.every(shift => shift.is_approved) ? 'q-px-xs' : 'q-pa-sm') : ''"
|
||||||
:style="day.shifts.length > 0 ? '' : 'opacity: 0.5'"
|
:style="day.shifts.length > 0 ? '' : 'opacity: 0.5'"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,20 @@
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
</q-toggle>
|
</q-toggle>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #option="scope">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-icon
|
||||||
|
:name="scope.opt.icon"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
|
<q-item-section class="text-left">
|
||||||
|
{{ $t(scope.label) }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
import ShiftListDateWidget from 'src/modules/timesheets/components/shift-list-date-widget.vue';
|
import ShiftListDateWidget from 'src/modules/timesheets/components/shift-list-date-widget.vue';
|
||||||
|
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { useUiStore } from 'src/stores/ui-store';
|
import { useUiStore } from 'src/stores/ui-store';
|
||||||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||||
import { Shift } from 'src/modules/timesheets/models/shift.models';
|
import { Shift } from 'src/modules/timesheets/models/shift.models';
|
||||||
|
|
@ -14,13 +14,15 @@
|
||||||
import type { QScrollArea } from 'quasar';
|
import type { QScrollArea } from 'quasar';
|
||||||
import type { TimesheetDay } from 'src/modules/timesheets/models/timesheet.models';
|
import type { TimesheetDay } from 'src/modules/timesheets/models/timesheet.models';
|
||||||
|
|
||||||
|
const CURRENT_DATE_STRING = new Date().toISOString().slice(0, 10);
|
||||||
|
|
||||||
const { extractDate } = date;
|
const { extractDate } = date;
|
||||||
|
|
||||||
const ui_store = useUiStore();
|
const ui_store = useUiStore();
|
||||||
const timesheet_store = useTimesheetStore();
|
const timesheet_store = useTimesheetStore();
|
||||||
const timesheet_api = useTimesheetApi();
|
const timesheet_api = useTimesheetApi();
|
||||||
|
|
||||||
const { mode = 'normal'} = defineProps<{
|
const { mode = 'normal' } = defineProps<{
|
||||||
mode: 'normal' | 'approval';
|
mode: 'normal' | 'approval';
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
@ -28,6 +30,9 @@
|
||||||
const animation_style = computed(() => ui_store.is_mobile_mode ? mobile_animation_direction.value : 'fadeInDown');
|
const animation_style = computed(() => ui_store.is_mobile_mode ? mobile_animation_direction.value : 'fadeInDown');
|
||||||
|
|
||||||
const timesheet_page = ref<QScrollArea | null>(null);
|
const timesheet_page = ref<QScrollArea | null>(null);
|
||||||
|
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 addNewShift = (day_shifts: Shift[], date: string, timesheet_id: number) => {
|
const addNewShift = (day_shifts: Shift[], date: string, timesheet_id: number) => {
|
||||||
|
|
@ -44,25 +49,37 @@
|
||||||
const shifts_without_deleted_shift = day.shifts.filter(shift => shift.id !== 0);
|
const shifts_without_deleted_shift = day.shifts.filter(shift => shift.id !== 0);
|
||||||
day.shifts = shifts_without_deleted_shift;
|
day.shifts = shifts_without_deleted_shift;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const getDayApproval = (day: TimesheetDay) => {
|
const getDayApproval = (day: TimesheetDay) => {
|
||||||
if (day.shifts.length < 1) return false;
|
if (day.shifts.length < 1) return false;
|
||||||
return day.shifts.every(shift => shift.is_approved === true);
|
return day.shifts.every(shift => shift.is_approved === true);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleSwipe = async (direction: 'left' | 'up' | 'down' | 'right' | undefined, distance: { x?: number, y?: number }) => {
|
const handleSwipe = async (direction: 'left' | 'up' | 'down' | 'right' | undefined, distance: { x?: number, y?: number }) => {
|
||||||
mobile_animation_direction.value = direction === 'left' ? 'fadeInRight' : 'fadeInLeft';
|
mobile_animation_direction.value = direction === 'left' ? 'fadeInRight' : 'fadeInLeft';
|
||||||
if (distance.x && Math.abs(distance.x) > 10) {
|
if (distance.x && Math.abs(distance.x) > 10) {
|
||||||
await timesheet_api.getTimesheetsBySwiping(direction === 'left' ? 1 : -1)
|
await timesheet_api.getTimesheetsBySwiping(direction === 'left' ? 1 : -1)
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMobileDayRef = (iso_date_string: string): string => {
|
||||||
|
return iso_date_string === CURRENT_DATE_STRING ? 'currentDayComponent' : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(currentDayComponentWatcher, () => {
|
||||||
|
if (currentDayComponent.value && timesheet_page.value) {
|
||||||
|
console.log('setting scroll position to offsetTop of currentDayComponent: ', currentDayComponent.value[0]!.offsetTop);
|
||||||
|
timesheet_page.value.setScrollPosition('vertical', currentDayComponent.value[0]!.offsetTop, 800);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="col column fit relative-position"
|
class="col column fit relative-position"
|
||||||
:style="$q.platform.is.mobile ? 'margin-bottom: 40px' : ''"
|
: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="value => handleSwipe(value.direction, value.distance ?? { x: 0, y: 0 })"
|
||||||
>
|
>
|
||||||
<q-scroll-area
|
<q-scroll-area
|
||||||
|
|
@ -129,9 +146,11 @@
|
||||||
<div
|
<div
|
||||||
v-for="day, day_index in timesheet.days"
|
v-for="day, day_index in timesheet.days"
|
||||||
:key="day.date"
|
:key="day.date"
|
||||||
|
:ref="getMobileDayRef(day.date)"
|
||||||
class="col-auto row q-pa-sm fit"
|
class="col-auto row q-pa-sm fit"
|
||||||
:style="`animation-delay: ${day_index / 15}s;`"
|
:style="`animation-delay: ${day_index / 15}s;`"
|
||||||
>
|
>
|
||||||
|
<!-- mobile version in portrait mode -->
|
||||||
<div
|
<div
|
||||||
v-if="$q.platform.is.mobile && ($q.screen.width < $q.screen.height)"
|
v-if="$q.platform.is.mobile && ($q.screen.width < $q.screen.height)"
|
||||||
class="col column full-width q-px-md q-py-sm"
|
class="col column full-width q-px-md q-py-sm"
|
||||||
|
|
@ -192,6 +211,7 @@
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- desktop version -->
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="col row full-width rounded-10 ellipsis shadow-10"
|
class="col row full-width rounded-10 ellipsis shadow-10"
|
||||||
|
|
@ -274,19 +294,21 @@
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style
|
||||||
|
scoped
|
||||||
|
lang="scss"
|
||||||
|
>
|
||||||
@each $size in (1, 2, 3, 4, 5, 10, 15, 20, 25, 50, 75, 100, 200) {
|
@each $size in (1, 2, 3, 4, 5, 10, 15, 20, 25, 50, 75, 100, 200) {
|
||||||
.mobile-rounded-#{$size} {
|
.mobile-rounded-#{$size} {
|
||||||
border-radius: #{$size}px !important;
|
border-radius: #{$size}px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-rounded-#{$size} > div:first-child {
|
.mobile-rounded-#{$size}>div:first-child {
|
||||||
border-radius: #{$size}px #{$size}px 0 0 !important;
|
border-radius: #{$size}px #{$size}px 0 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-rounded-#{$size} > div:last-child {
|
.mobile-rounded-#{$size}>div:last-child {
|
||||||
border-radius: 0 0 #{$size}px #{$size}px !important;
|
border-radius: 0 0 #{$size}px #{$size}px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
<PayPeriodNavigator
|
<PayPeriodNavigator
|
||||||
v-if="mode === 'normal'"
|
v-if="mode === 'normal'"
|
||||||
class="col-auto"
|
class="col-auto"
|
||||||
@date-selected="date_value => timesheet_api.getTimesheetsByDate(date_value)"
|
@date-selected="timesheet_api.getTimesheetsByDate"
|
||||||
@pressed-previous-button="timesheet_api.getTimesheetsByCurrentPayPeriod"
|
@pressed-previous-button="timesheet_api.getTimesheetsByCurrentPayPeriod"
|
||||||
@pressed-next-button="timesheet_api.getTimesheetsByCurrentPayPeriod"
|
@pressed-next-button="timesheet_api.getTimesheetsByCurrentPayPeriod"
|
||||||
/>
|
/>
|
||||||
|
|
@ -112,7 +112,7 @@
|
||||||
color="accent"
|
color="accent"
|
||||||
icon="upload"
|
icon="upload"
|
||||||
:label="$t('shared.label.save')"
|
:label="$t('shared.label.save')"
|
||||||
class="col-auto absolute-bottom shadow-up-10 z-top"
|
class="col-auto absolute-bottom shadow-up-10"
|
||||||
style="height: 50px;"
|
style="height: 50px;"
|
||||||
@click="shift_api.saveShiftChanges"
|
@click="shift_api.saveShiftChanges"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,14 @@
|
||||||
setup
|
setup
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
import { ref } from 'vue';
|
import MainCarousel from 'src/modules/dashboard/components/main-carousel.vue';
|
||||||
|
import ShortcutCard from 'src/modules/dashboard/components/employee/shortcut-card.vue';
|
||||||
const slide = ref<string>('welcome');
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-page
|
<q-page
|
||||||
padding
|
padding
|
||||||
class="q-pa-md justify-center items-stretch"
|
class="q-pa-md justify-center items-stretch bg-secondary"
|
||||||
:class="$q.platform.is.mobile ? 'column' : 'row'"
|
:class="$q.platform.is.mobile ? 'column' : 'row'"
|
||||||
>
|
>
|
||||||
<!-- left column -->
|
<!-- left column -->
|
||||||
|
|
@ -19,71 +18,37 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- center column -->
|
<!-- center column -->
|
||||||
<div class="column col-xs-12 col-md-8 col-xl-6 flex-center q-pa-md">
|
<div class="column col-xs-12 col-md-8 col-xl-6 items-center q-pa-md">
|
||||||
<q-carousel
|
<div class="col-auto full-width q-py-md">
|
||||||
v-model="slide"
|
<MainCarousel />
|
||||||
transition-prev="jump-right"
|
|
||||||
transition-next="jump-left"
|
|
||||||
swipeable
|
|
||||||
animated
|
|
||||||
navigation
|
|
||||||
infinite
|
|
||||||
:autoplay="9001"
|
|
||||||
control-color="accent"
|
|
||||||
class="col-auto bg-dark rounded-15 shadow-18"
|
|
||||||
:style="$q.platform.is.mobile ? 'height: 60vh;' : 'height: 50vh;'"
|
|
||||||
>
|
|
||||||
<!-- welcome slide -->
|
|
||||||
<q-carousel-slide
|
|
||||||
name="welcome"
|
|
||||||
class="q-pa-none q-pb-xl fit"
|
|
||||||
>
|
|
||||||
<div class="column fit">
|
|
||||||
<q-img
|
|
||||||
src="src/assets/targo_building.png"
|
|
||||||
height="30vh"
|
|
||||||
position="50% 25%"
|
|
||||||
fit="cover"
|
|
||||||
class="col-auto"
|
|
||||||
>
|
|
||||||
<div class="absolute-bottom text-h6 text-uppercase text-weight-light">
|
|
||||||
{{ $t('dashboard.carousel.welcome_title') }}
|
|
||||||
</div>
|
</div>
|
||||||
</q-img>
|
|
||||||
|
|
||||||
<div class="column col q-mt-md q-px-md flex-center">
|
<span class="col-auto text-uppercase text-weight-bold self-start q-pt-md">{{ $t('dashboard.useful_links') }}</span>
|
||||||
<span class="col-auto">{{ $t('dashboard.carousel.welcome_message') }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</q-carousel-slide>
|
|
||||||
|
|
||||||
<!-- help page slide -->
|
<div class="col row full-width justify-evenly items-start q-py-md">
|
||||||
<q-carousel-slide
|
<div class="col-3 q-pa-sm">
|
||||||
name="tv"
|
<ShortcutCard
|
||||||
class="q-pa-none q-pb-xl"
|
image-source="src/assets/google_thumbnail.png"
|
||||||
>
|
title="Google Workspace"
|
||||||
<div class="column fit">
|
route="https://mail.google.com/mail/u/0/#inbox"
|
||||||
<q-img
|
/>
|
||||||
src="src/assets/targo_help_banner.png"
|
|
||||||
height="30vh"
|
|
||||||
position="50% 25%"
|
|
||||||
fit="none"
|
|
||||||
class="col-auto"
|
|
||||||
>
|
|
||||||
<div class="absolute-bottom text-h6 text-uppercase text-weight-light">
|
|
||||||
{{ $t('dashboard.carousel.help_title') }}
|
|
||||||
</div>
|
</div>
|
||||||
</q-img>
|
|
||||||
|
|
||||||
<div class="col column justify-center q-mt-md q-px-md">
|
<div class="col-3 q-pa-sm">
|
||||||
<span class="col-auto">{{ $t('dashboard.carousel.help_message') }}</span>
|
<ShortcutCard
|
||||||
|
image-source="src/assets/facturation_thumbnail.png"
|
||||||
|
title="Facturation"
|
||||||
|
route="https://facturation.targo.ca/facturation/accueil.php?menu=ticket_open"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</q-carousel-slide>
|
|
||||||
</q-carousel>
|
|
||||||
|
|
||||||
<div class="col column">
|
<div class="col-3 q-pa-sm">
|
||||||
<span class="col-auto text-h6 text-uppercase"> </span>
|
<ShortcutCard
|
||||||
|
image-source="src/assets/map_targo_banner.png"
|
||||||
|
title="Map Targo"
|
||||||
|
route="https://map.targointernet.com/infrastructure/map.php"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { RouteNames } from 'src/router/router-constants';
|
||||||
export const useUiStore = defineStore('ui', () => {
|
export const useUiStore = defineStore('ui', () => {
|
||||||
const q = useQuasar();
|
const q = useQuasar();
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
const is_left_drawer_open = ref(false);
|
const is_left_drawer_open = ref(true);
|
||||||
const focus_next_component = ref(false);
|
const focus_next_component = ref(false);
|
||||||
const is_mobile_mode = computed(() => q.screen.lt.md);
|
const is_mobile_mode = computed(() => q.screen.lt.md);
|
||||||
const user_preferences = ref<Preferences>(new Preferences);
|
const user_preferences = ref<Preferences>(new Preferences);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user