refactor(profile): finalize appearance and functionality
This commit is contained in:
parent
8368702490
commit
af6cdbe890
BIN
src/assets/en-CA.png
Normal file
BIN
src/assets/en-CA.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
BIN
src/assets/fr-FR.png
Normal file
BIN
src/assets/fr-FR.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 880 B |
|
|
@ -93,6 +93,7 @@ export default {
|
||||||
'en-CA': "English",
|
'en-CA': "English",
|
||||||
dark_mode: "dark",
|
dark_mode: "dark",
|
||||||
light_mode: "light",
|
light_mode: "light",
|
||||||
|
auto_mode: "auto",
|
||||||
update_successful: "Preferences saved",
|
update_successful: "Preferences saved",
|
||||||
update_failed: "Failed to save preferences",
|
update_failed: "Failed to save preferences",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ export default {
|
||||||
'en-CA': "Anglais",
|
'en-CA': "Anglais",
|
||||||
dark_mode: "sombre",
|
dark_mode: "sombre",
|
||||||
light_mode: "clair",
|
light_mode: "clair",
|
||||||
|
auto_mode: "automatique",
|
||||||
update_successful: "Préférences enregistrées",
|
update_successful: "Préférences enregistrées",
|
||||||
update_failed: "Échec de sauvegarde",
|
update_failed: "Échec de sauvegarde",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import { useUiStore } from 'src/stores/ui-store';
|
import { useUiStore } from 'src/stores/ui-store';
|
||||||
import { useEmployeeStore } from 'src/stores/employee-store';
|
import { useEmployeeStore } from 'src/stores/employee-store';
|
||||||
import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-employee-api';
|
import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-employee-api';
|
||||||
import { employee_list_columns, getCompanyName } from 'src/modules/employee-list/models/employee-profile.models';
|
import { employee_list_columns } from 'src/modules/employee-list/models/employee-profile.models';
|
||||||
|
|
||||||
const employee_list_api = useEmployeeListApi();
|
const employee_list_api = useEmployeeListApi();
|
||||||
const employee_store = useEmployeeStore();
|
const employee_store = useEmployeeStore();
|
||||||
|
|
@ -126,8 +126,7 @@
|
||||||
:props="scope"
|
:props="scope"
|
||||||
class="text-weight-medium"
|
class="text-weight-medium"
|
||||||
>
|
>
|
||||||
<span v-if="scope.col.name === 'company_name'"> {{ getCompanyName(scope.value) }}</span>
|
<span >{{ scope.value }}</span>
|
||||||
<span v-else>{{ scope.value }}</span>
|
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,22 +26,24 @@
|
||||||
full-width
|
full-width
|
||||||
@beforeShow="current_step = 'form'"
|
@beforeShow="current_step = 'form'"
|
||||||
>
|
>
|
||||||
<q-card
|
<div
|
||||||
class="bg-secondary rounded-10"
|
class="column bg-secondary rounded-10"
|
||||||
:class="$q.dark.isActive ? 'shadow-24' : 'shadow-10'"
|
:class="$q.dark.isActive ? 'shadow-24' : 'shadow-10'"
|
||||||
:style="($q.screen.lt.md ? ' ' : 'max-width: 70vw !important; height: 50vh') +
|
:style="($q.screen.lt.md ? ' ' : 'max-width: 60vw !important; height: 60vh') +
|
||||||
($q.dark.isActive ? 'border: 2px solid var(--q-accent)' : '')"
|
($q.dark.isActive ? 'border: 2px solid var(--q-accent)' : '')"
|
||||||
>
|
>
|
||||||
<q-card-section class="row text-weight-bolder text-white text-h5 bg-primary flex-center shadow-5 q-pa-none">
|
<div class="row col-auto text-white bg-primary flex-center shadow-5">
|
||||||
<div class="q-py-sm text-uppercase">
|
<div class="q-py-sm text-uppercase text-weight-bolder text-h5 ">
|
||||||
{{ $t('employee_management.' + employee_store.management_mode) }}
|
{{ $t('employee_management.' + employee_store.management_mode) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="employee_store.employee.first_name.length > 0"
|
v-if="employee_store.employee.first_name.length > 0"
|
||||||
class="text-uppercase text-weight-light text-h6 q-ml-sm"
|
class="text-uppercase text-weight-light text-h6 q-ml-sm"
|
||||||
>
|
>
|
||||||
{{ `${employee_store.employee.first_name} ${employee_store.employee.last_name}` }}
|
{{ `${employee_store.employee.first_name} ${employee_store.employee.last_name}` }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-slide-transition>
|
<q-slide-transition>
|
||||||
<div
|
<div
|
||||||
v-if="current_step === 'access'"
|
v-if="current_step === 'access'"
|
||||||
|
|
@ -60,10 +62,10 @@
|
||||||
>{{ $t('employee_management.module_access.usage_description') }}</q-item-label>
|
>{{ $t('employee_management.module_access.usage_description') }}</q-item-label>
|
||||||
</div>
|
</div>
|
||||||
</q-slide-transition>
|
</q-slide-transition>
|
||||||
</q-card-section>
|
</div>
|
||||||
|
|
||||||
<q-card-section class="q-pt-sm">
|
|
||||||
<div class="full-height column">
|
<div class="col column q-pa-md">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<transition
|
<transition
|
||||||
:enter-active-class="'animated ' + transition_in_animation"
|
:enter-active-class="'animated ' + transition_in_animation"
|
||||||
|
|
@ -83,7 +85,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row col-auto">
|
<div class="row col-auto q-py-sm">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="current_step === 'access'"
|
v-if="current_step === 'access'"
|
||||||
flat
|
flat
|
||||||
|
|
@ -107,9 +109,23 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
|
||||||
|
|
||||||
|
<!-- <div class="col-auto self-center q-pa-xs">
|
||||||
|
<q-btn
|
||||||
|
push
|
||||||
|
color="accent"
|
||||||
|
:label="$t('shared.label.save')"
|
||||||
|
class="q-py-xs"
|
||||||
|
/>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<q-btn
|
||||||
|
square
|
||||||
|
color="accent"
|
||||||
|
:label="employee_store.management_mode === 'add_employee' ? $t('shared.label.save') : $t('shared.label.update')"
|
||||||
|
class="col-auto q-py-sm shadow-up-5"
|
||||||
|
/>
|
||||||
<q-inner-loading :showing="employee_store.is_loading" />
|
<q-inner-loading :showing="employee_store.is_loading" />
|
||||||
</q-card>
|
</div>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import type { QSelectOption, QTableColumn } from "quasar";
|
import type { QSelectOption, QTableColumn } from "quasar";
|
||||||
|
|
||||||
export type ModuleAccessName = 'dashboard' | 'employee_list' | 'employee_management' | 'personal_profile' | 'timesheets' | 'timesheets_approval';
|
export type ModuleAccessName = 'dashboard' | 'employee_list' | 'employee_management' | 'personal_profile' | 'timesheets' | 'timesheets_approval';
|
||||||
export type ModuleAccessPreset = 'admin' | 'employee' | 'none';
|
export type ModuleAccessPreset = 'admin' | 'supervisor' | 'employee' | 'none';
|
||||||
|
export type CompanyNames = 'Targo' | 'Solucom';
|
||||||
|
|
||||||
export class EmployeeProfile {
|
export class EmployeeProfile {
|
||||||
first_name: string;
|
first_name: string;
|
||||||
last_name: string;
|
last_name: string;
|
||||||
supervisor_full_name: string;
|
supervisor_full_name: string;
|
||||||
company_name: number;
|
company_name: CompanyNames;
|
||||||
job_title: string;
|
job_title: string;
|
||||||
email: string;
|
email: string;
|
||||||
phone_number: string;
|
phone_number: string;
|
||||||
|
|
@ -22,7 +23,7 @@ export class EmployeeProfile {
|
||||||
this.first_name = '';
|
this.first_name = '';
|
||||||
this.last_name = '';
|
this.last_name = '';
|
||||||
this.supervisor_full_name = '';
|
this.supervisor_full_name = '';
|
||||||
this.company_name = 271583;
|
this.company_name = 'Targo';
|
||||||
this.job_title = '';
|
this.job_title = '';
|
||||||
this.email = '';
|
this.email = '';
|
||||||
this.phone_number = '';
|
this.phone_number = '';
|
||||||
|
|
@ -85,14 +86,7 @@ export const employee_access_options: QSelectOption<ModuleAccessName>[] = [
|
||||||
|
|
||||||
export const employee_access_presets: Record<ModuleAccessPreset, ModuleAccessName[]> = {
|
export const employee_access_presets: Record<ModuleAccessPreset, ModuleAccessName[]> = {
|
||||||
'admin' : ['dashboard', 'employee_list', 'employee_management', 'personal_profile', 'timesheets', 'timesheets_approval'],
|
'admin' : ['dashboard', 'employee_list', 'employee_management', 'personal_profile', 'timesheets', 'timesheets_approval'],
|
||||||
|
'supervisor' : ['dashboard', 'employee_list', 'personal_profile', 'timesheets', 'timesheets_approval'],
|
||||||
'employee' : ['dashboard', 'timesheets', 'personal_profile', 'employee_list'],
|
'employee' : ['dashboard', 'timesheets', 'personal_profile', 'employee_list'],
|
||||||
'none' : [],
|
'none' : [],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCompanyName = (company_code: number) => {
|
|
||||||
switch (company_code) {
|
|
||||||
case 271583: return 'Targo';
|
|
||||||
case 271585: return 'Solucom';
|
|
||||||
default: return 'N / A';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
import MenuPanelPersonal from 'src/modules/profile/components/employee/menu-panel-personal.vue';
|
import MenuPanelPersonal from 'src/modules/profile/components/employee/menu-panel-personal.vue';
|
||||||
import MenuPanelEmployee from 'src/modules/profile/components/employee/menu-panel-employee.vue';
|
import MenuPanelEmployee from 'src/modules/profile/components/employee/menu-panel-employee.vue';
|
||||||
import MenuPanelPreferences from 'src/modules/profile/components/shared/menu-panel-preferences.vue';
|
import MenuPanelPreferences from 'src/modules/profile/components/shared/menu-panel-preferences.vue';
|
||||||
import MenuPanelSchedulePresets from 'src/modules/profile/components/shared/menu-panel-schedule-presets.vue';
|
|
||||||
import MenuTemplate from 'src/modules/profile/components/shared/menu-template.vue';
|
import MenuTemplate from 'src/modules/profile/components/shared/menu-template.vue';
|
||||||
import { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models';
|
import { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models';
|
||||||
import { useAuthStore } from 'src/stores/auth-store';
|
import { useAuthStore } from 'src/stores/auth-store';
|
||||||
|
|
@ -16,7 +15,6 @@
|
||||||
PERSONAL_INFO: 'personal_info',
|
PERSONAL_INFO: 'personal_info',
|
||||||
EMPLOYEE_INFO: 'employee_info',
|
EMPLOYEE_INFO: 'employee_info',
|
||||||
PREFERENCES: 'references',
|
PREFERENCES: 'references',
|
||||||
SCHEDULE_PRESETS: 'schedule_presets',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const employee_profile = defineModel<EmployeeProfile>({ default: new EmployeeProfile });
|
const employee_profile = defineModel<EmployeeProfile>({ default: new EmployeeProfile });
|
||||||
|
|
@ -24,6 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
<q-card
|
<q-card
|
||||||
flat
|
flat
|
||||||
class="rounded-5 bg-transparent q-pa-none"
|
class="rounded-5 bg-transparent q-pa-none"
|
||||||
|
|
@ -49,11 +48,6 @@
|
||||||
icon="display_settings"
|
icon="display_settings"
|
||||||
:label="$q.screen.lt.md ? '' : $t('profile.preferences.tab_title')"
|
:label="$q.screen.lt.md ? '' : $t('profile.preferences.tab_title')"
|
||||||
/>
|
/>
|
||||||
<q-tab
|
|
||||||
:name="PanelNames.SCHEDULE_PRESETS"
|
|
||||||
icon="list_alt"
|
|
||||||
:label="$q.screen.lt.md ? '' : $t('profile.schedule_presets.tab_title')"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #panels>
|
<template #panels>
|
||||||
|
|
@ -77,13 +71,8 @@
|
||||||
>
|
>
|
||||||
<MenuPanelPreferences />
|
<MenuPanelPreferences />
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel
|
|
||||||
:name="PanelNames.SCHEDULE_PRESETS"
|
|
||||||
class="q-pa-none"
|
|
||||||
>
|
|
||||||
<MenuPanelSchedulePresets />
|
|
||||||
</q-tab-panel>
|
|
||||||
</template>
|
</template>
|
||||||
</MenuTemplate>
|
</MenuTemplate>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -3,102 +3,42 @@
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
import MenuPanelInputField from 'src/modules/profile/components/shared/menu-panel-input-field.vue';
|
import MenuPanelInputField from 'src/modules/profile/components/shared/menu-panel-input-field.vue';
|
||||||
import MenuPanelSelectField from 'src/modules/profile/components/shared/menu-panel-select-field.vue';
|
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { deepEqual } from 'src/utils/deep-equal';
|
|
||||||
import { unwrapAndClone } from 'src/utils/unwrap-and-clone';
|
|
||||||
import { useAuthStore } from 'src/stores/auth-store';
|
|
||||||
import { useEmployeeStore } from 'src/stores/employee-store';
|
import { useEmployeeStore } from 'src/stores/employee-store';
|
||||||
import { CAN_APPROVE_PAY_PERIODS } from 'src/modules/shared/models/user.models';
|
|
||||||
import type { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models';
|
|
||||||
|
|
||||||
const COMPANY_OPTIONS = [
|
|
||||||
{ label: 'Targo', value: 271583 },
|
|
||||||
{ label: 'Solucom', value: 271585 }
|
|
||||||
];
|
|
||||||
const SUPERVISOR_OPTIONS = [{ label: 'AAA', value: '1' }, { label: 'BBB', value: '2' }, { label: 'CCC', value: '3' }, { label: 'DDD', value: '4' }];
|
|
||||||
|
|
||||||
const auth_store = useAuthStore();
|
|
||||||
const employee_store = useEmployeeStore();
|
const employee_store = useEmployeeStore();
|
||||||
|
|
||||||
const is_editing = ref<boolean>(false);
|
|
||||||
const current_company_option = ref(COMPANY_OPTIONS.find(option => option.value === employee_store.employee.company_name) ?? { label: '', value: 0 })
|
|
||||||
let initial_info: EmployeeProfile = unwrapAndClone(employee_store.employee);
|
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = () => {
|
|
||||||
if (!is_editing.value) {
|
|
||||||
is_editing.value = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_editing.value = false;
|
|
||||||
initial_info = unwrapAndClone(employee_store.employee); // update initial value for future possible resets
|
|
||||||
employee_store.employee.company_name = current_company_option.value.value;
|
|
||||||
|
|
||||||
if (!deepEqual(employee_store.employee, initial_info)) {
|
|
||||||
// save the new data here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onReset = () => {
|
|
||||||
employee_store.employee = unwrapAndClone(initial_info);
|
|
||||||
is_editing.value = false;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-form
|
<div class="column q-pa-md full-height">
|
||||||
class="q-pa-md full-height"
|
|
||||||
@submit="onSubmit"
|
|
||||||
@reset="onReset"
|
|
||||||
>
|
|
||||||
<div :class="$q.screen.lt.md ? 'column' : 'row'">
|
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.job_title"
|
v-model="employee_store.employee.job_title"
|
||||||
class="col"
|
class="col-auto"
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.employee.job_title')"
|
:label-string="$t('profile.employee.job_title')"
|
||||||
/>
|
/>
|
||||||
<MenuPanelSelectField
|
<MenuPanelInputField
|
||||||
v-model="current_company_option"
|
v-model="employee_store.employee.company_name"
|
||||||
:options="COMPANY_OPTIONS"
|
class="col-auto"
|
||||||
class="col"
|
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.employee.company')"
|
:label-string="$t('profile.employee.company')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<MenuPanelInputField
|
||||||
|
|
||||||
<div>
|
|
||||||
<MenuPanelSelectField
|
|
||||||
v-model="employee_store.employee.supervisor_full_name"
|
v-model="employee_store.employee.supervisor_full_name"
|
||||||
:options="SUPERVISOR_OPTIONS"
|
class="col-auto"
|
||||||
:label-string="$t('profile.employee.supervisor')"
|
:label-string="$t('profile.employee.supervisor')"
|
||||||
:is-editing="is_editing"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div :class="$q.screen.lt.md ? 'column' : 'row'">
|
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.email"
|
v-model="employee_store.employee.email"
|
||||||
class="col"
|
class="col-auto"
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.employee.email')"
|
:label-string="$t('profile.employee.email')"
|
||||||
/>
|
/>
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.first_work_day"
|
v-model="employee_store.employee.first_work_day"
|
||||||
readonly
|
|
||||||
class="col-auto"
|
class="col-auto"
|
||||||
type="date"
|
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.employee.hired_date')"
|
:label-string="$t('profile.employee.hired_date')"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<!-- DEV NOTE: May revisit later for changes by employee that will need approval -->
|
||||||
|
<!-- <div
|
||||||
v-if="CAN_APPROVE_PAY_PERIODS.includes(auth_store.user?.role ?? 'GUEST')"
|
v-if="CAN_APPROVE_PAY_PERIODS.includes(auth_store.user?.role ?? 'GUEST')"
|
||||||
class="absolute-bottom"
|
class="absolute-bottom"
|
||||||
:class="$q.screen.lt.md ? 'column' : 'row'"
|
:class="$q.screen.lt.md ? 'column' : 'row'"
|
||||||
|
|
@ -121,6 +61,6 @@
|
||||||
class="q-ma-sm q-py-xs"
|
class="q-ma-sm q-py-xs"
|
||||||
:label="is_editing ? $t('shared.label.save') : $t('shared.label.update')"
|
:label="is_editing ? $t('shared.label.save') : $t('shared.label.update')"
|
||||||
/>
|
/>
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</q-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -4,90 +4,44 @@
|
||||||
>
|
>
|
||||||
import MenuPanelInputField from 'src/modules/profile/components/shared/menu-panel-input-field.vue';
|
import MenuPanelInputField from 'src/modules/profile/components/shared/menu-panel-input-field.vue';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { deepEqual } from 'src/utils/deep-equal';
|
|
||||||
import { unwrapAndClone } from 'src/utils/unwrap-and-clone';
|
|
||||||
import { useEmployeeStore } from 'src/stores/employee-store';
|
import { useEmployeeStore } from 'src/stores/employee-store';
|
||||||
import type { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models';
|
|
||||||
|
|
||||||
const employee_store = useEmployeeStore();
|
const employee_store = useEmployeeStore();
|
||||||
const is_editing = ref<boolean>(false);
|
|
||||||
const initial_info = ref<EmployeeProfile>(unwrapAndClone(employee_store.employee));
|
|
||||||
|
|
||||||
const onSubmit = () => {
|
|
||||||
if (!is_editing.value) {
|
|
||||||
is_editing.value = true;
|
|
||||||
initial_info.value = unwrapAndClone(employee_store.employee);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_editing.value = false;
|
|
||||||
initial_info.value = unwrapAndClone(employee_store.employee); // update initial value for future possible resets
|
|
||||||
|
|
||||||
if (!deepEqual(employee_store.employee, initial_info)) {
|
|
||||||
// save the new data here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onReset = () => {
|
|
||||||
employee_store.employee = unwrapAndClone(initial_info.value);
|
|
||||||
is_editing.value = false;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-form
|
<div class="column q-pa-md full-height">
|
||||||
class="q-pa-md full-height"
|
|
||||||
@submit="onSubmit"
|
|
||||||
@reset="onReset"
|
|
||||||
>
|
|
||||||
<div :class="$q.screen.lt.md ? 'column' : 'row'">
|
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.first_name"
|
v-model="employee_store.employee.first_name"
|
||||||
type="text"
|
class="col-auto"
|
||||||
class="col"
|
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.personal.first_name')"
|
:label-string="$t('profile.personal.first_name')"
|
||||||
/>
|
/>
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.last_name"
|
v-model="employee_store.employee.last_name"
|
||||||
class="col"
|
class="col-auto"
|
||||||
type="text"
|
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.personal.last_name')"
|
:label-string="$t('profile.personal.last_name')"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :class="$q.screen.lt.md ? 'column' : 'row'">
|
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.phone_number"
|
v-model="employee_store.employee.phone_number"
|
||||||
class="col"
|
class="col-auto"
|
||||||
type="text"
|
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.personal.phone_number')"
|
:label-string="$t('profile.personal.phone_number')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.birth_date"
|
v-model="employee_store.employee.birth_date"
|
||||||
class="col"
|
class="col-auto"
|
||||||
mask="#### / ## / ##"
|
|
||||||
hint="ex: 1970 / 01 / 01"
|
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.personal.birthdate')"
|
:label-string="$t('profile.personal.birthdate')"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :class="$q.screen.lt.md ? 'column' : 'row'">
|
|
||||||
<MenuPanelInputField
|
<MenuPanelInputField
|
||||||
v-model="employee_store.employee.residence"
|
v-model="employee_store.employee.residence"
|
||||||
class="col"
|
class="col-auto"
|
||||||
:is-editing="is_editing"
|
|
||||||
:label-string="$t('profile.personal.address')"
|
:label-string="$t('profile.personal.address')"
|
||||||
:hint="$t('profile.personal.address_hint')"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
|
<!-- DEV NOTE: May revisit later for changes by employee that will need approval -->
|
||||||
|
<!-- <div
|
||||||
class="absolute-bottom"
|
class="absolute-bottom"
|
||||||
:class="$q.screen.lt.md ? 'column' : 'row'"
|
:class="$q.screen.lt.md ? 'column' : 'row'"
|
||||||
>
|
>
|
||||||
|
|
@ -109,6 +63,6 @@
|
||||||
class="q-ma-sm q-py-xs"
|
class="q-ma-sm q-py-xs"
|
||||||
:label="is_editing ? $t('shared.label.save') : $t('shared.label.update')"
|
:label="is_editing ? $t('shared.label.save') : $t('shared.label.update')"
|
||||||
/>
|
/>
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</q-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -12,8 +12,7 @@
|
||||||
<q-img
|
<q-img
|
||||||
src="src/assets/profile_header_default.png"
|
src="src/assets/profile_header_default.png"
|
||||||
height="15vh"
|
height="15vh"
|
||||||
:width="$q.screen.lt.md ? '80vw' : '40vw'"
|
class="rounded-5 q-mb-md shadow-2"
|
||||||
class="rounded-5 q-mb-md shadow-2 col-auto"
|
|
||||||
fit="cover"
|
fit="cover"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -2,43 +2,41 @@
|
||||||
setup
|
setup
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
import type { ValidationRule } from 'quasar';
|
|
||||||
|
|
||||||
const model = defineModel<string | number | undefined>({ required: true });
|
const model = defineModel<string | number | undefined>({ required: true });
|
||||||
|
|
||||||
const { readonly = false, hint = '' } = defineProps<{
|
defineProps<{
|
||||||
labelString: string;
|
labelString: string;
|
||||||
isEditing: boolean;
|
|
||||||
readonly?: boolean;
|
|
||||||
type?: "number" | "textarea" | "time" | "text" | "tel" | "password" | "email" | "search" | "file" | "url" | "date" | "datetime-local" | undefined;
|
|
||||||
hint?: string;
|
|
||||||
mask?: string;
|
|
||||||
rules?: ValidationRule[];
|
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="model"
|
v-model="model"
|
||||||
|
readonly
|
||||||
dense
|
dense
|
||||||
:stack-label="!isEditing"
|
stack-label
|
||||||
autogrow
|
autogrow
|
||||||
:standout="$q.dark.isActive ? 'bg-blue-grey-3' : 'bg-blue-grey-9'"
|
outlined
|
||||||
debounce="500"
|
|
||||||
label-color="accent"
|
label-color="accent"
|
||||||
label-slot
|
label-slot
|
||||||
class="q-ma-xs"
|
class="q-mx-xs q-my-sm"
|
||||||
input-class="text-weight-light"
|
input-class="text-weight-light"
|
||||||
input-style="font-size: 1.2em"
|
input-style="font-size: 1.5em"
|
||||||
:hide-hint="hint === ''"
|
|
||||||
:hint="isEditing ? hint : ''"
|
|
||||||
:mask="mask"
|
|
||||||
:readonly="readonly || !isEditing"
|
|
||||||
:type="type"
|
|
||||||
:rules="rules"
|
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span class="text-weight-bolder text-accent text-uppercase">{{ labelString }}</span>
|
<span class="text-weight-bolder text-accent text-uppercase">{{ labelString }}</span>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
:deep(.q-field__label) {
|
||||||
|
background-color: var(--q-dark);
|
||||||
|
padding: 0 5px;
|
||||||
|
transform: translateY(-60%) scale(0.75) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.q-field__control-container) {
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,66 +2,72 @@
|
||||||
setup
|
setup
|
||||||
lang="ts"
|
lang="ts"
|
||||||
>
|
>
|
||||||
|
import { dark_mode_options } from 'src/modules/profile/models/preferences.models';
|
||||||
import LanguageSwitch from 'src/modules/shared/components/language-switch.vue';
|
import LanguageSwitch from 'src/modules/shared/components/language-switch.vue';
|
||||||
import { ref } from 'vue';
|
|
||||||
import { Dark } from 'quasar';
|
|
||||||
import { useUiStore } from 'src/stores/ui-store';
|
import { useUiStore } from 'src/stores/ui-store';
|
||||||
|
|
||||||
const ui_store = useUiStore();
|
const ui_store = useUiStore();
|
||||||
const initial_dark_mode_value = Dark.isActive;
|
|
||||||
const is_dark_mode = ref<boolean>(initial_dark_mode_value);
|
|
||||||
|
|
||||||
const toggle_dark_mode = (value: boolean) => {
|
|
||||||
if (ui_store.user_preferences) ui_store.user_preferences.is_dark_mode = value;
|
|
||||||
Dark.set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-form class="q-pa-md column fit">
|
<div class="q-pa-md column fit">
|
||||||
<q-card
|
<div
|
||||||
flat
|
|
||||||
class="col-auto justify-center content-center q-mb-lg q-pa-none"
|
|
||||||
:style="$q.dark.isActive ? 'background-color: #FFF1;' : 'background-color: #0001;'"
|
|
||||||
>
|
|
||||||
<q-card-section class="q-py-none">
|
|
||||||
<span class="text-uppercase text-weight-bold text-accent">{{ $t('profile.preferences.display_options')
|
|
||||||
}}</span>
|
|
||||||
</q-card-section>
|
|
||||||
|
|
||||||
<q-card-section
|
|
||||||
horizontal
|
|
||||||
class="flex-center text-uppercase"
|
|
||||||
>
|
|
||||||
<span class="q-mx-md text-weight-medium">{{ $t('profile.preferences.light_mode') }}</span>
|
|
||||||
<q-toggle
|
|
||||||
v-model="is_dark_mode"
|
|
||||||
@update:model-value="value => toggle_dark_mode(value)"
|
|
||||||
size="xl"
|
|
||||||
class="col-auto"
|
class="col-auto"
|
||||||
checked-icon="dark_mode"
|
style="transform: translate(10px, 12px);"
|
||||||
unchecked-icon="light_mode"
|
|
||||||
/>
|
|
||||||
<span class="q-mx-md text-weight-medium">{{ $t('profile.preferences.dark_mode') }}</span>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
|
|
||||||
<q-card
|
|
||||||
flat
|
|
||||||
class="col-auto justify-center content-center q-mb-lg q-pa-none"
|
|
||||||
:style="$q.dark.isActive ? 'background-color: #FFF1;' : 'background-color: #0001;'"
|
|
||||||
>
|
>
|
||||||
<q-card-section class="q-py-none">
|
<span class="text-uppercase text-weight-bold text-accent bg-dark q-px-sm">
|
||||||
<span class="text-uppercase text-weight-bold text-accent">{{ $t('profile.preferences.language_options')
|
{{ $t('profile.preferences.display_options') }}
|
||||||
}}</span>
|
</span>
|
||||||
</q-card-section>
|
</div>
|
||||||
|
|
||||||
<q-card-section
|
<div
|
||||||
horizontal
|
class="col-auto row justify-center content-center q-mb-sm q-pa-sm rounded-5"
|
||||||
class="flex-center"
|
style="border: 1px solid var(--q-accent);"
|
||||||
|
>
|
||||||
|
<q-item
|
||||||
|
v-for="mode of dark_mode_options"
|
||||||
|
:key="mode.label"
|
||||||
|
clickable
|
||||||
|
dense
|
||||||
|
v-ripple
|
||||||
|
class="col rounded-5 q-ma-sm shadow-4"
|
||||||
|
:class="mode.quasar_value === $q.dark.mode ? 'bg-accent text-white text-weight-bolder' : ''"
|
||||||
|
@click="ui_store.user_preferences.is_dark_mode = mode.value"
|
||||||
|
>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-icon
|
||||||
|
:name="mode.icon"
|
||||||
|
size="md"
|
||||||
|
:color="mode.quasar_value === $q.dark.mode ? 'white' : ''"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
|
<q-item-section class="text-uppercase justify-center">
|
||||||
|
<q-item-label> {{ $t(mode.label) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
|
<q-item-section side>
|
||||||
|
<q-icon
|
||||||
|
v-if="mode.quasar_value === $q.dark.mode"
|
||||||
|
name="check"
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="col-auto row text-uppercase text-weight-bold text-accent"
|
||||||
|
style="transform: translate(10px, 12px);"
|
||||||
|
>
|
||||||
|
<div class="col-auto bg-dark q-px-sm">{{ $t('profile.preferences.language_options') }}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="col-auto justify-center content-center q-pa-sm rounded-5"
|
||||||
|
style="border: 1px solid var(--q-accent);"
|
||||||
>
|
>
|
||||||
<LanguageSwitch class="col-auto" />
|
<LanguageSwitch class="col-auto" />
|
||||||
</q-card-section>
|
</div>
|
||||||
</q-card>
|
</div>
|
||||||
</q-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
<script
|
|
||||||
setup
|
|
||||||
lang="ts"
|
|
||||||
>
|
|
||||||
const model = defineModel<string | number | {label: string, value: unknown} | undefined>();
|
|
||||||
|
|
||||||
const { readonly = false, localizeOptions = false } = defineProps<{
|
|
||||||
options: { label: string, value: string | number }[];
|
|
||||||
labelString: string;
|
|
||||||
isEditing: boolean;
|
|
||||||
readonly?: boolean;
|
|
||||||
localizeOptions?: boolean;
|
|
||||||
type?: "number" | "textarea" | "time" | "text" | "tel" | "password" | "email" | "search" | "file" | "url" | "date" | "datetime-local" | undefined;
|
|
||||||
}>();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<q-select
|
|
||||||
v-model="model"
|
|
||||||
dense
|
|
||||||
:stack-label="!isEditing"
|
|
||||||
:standout="$q.dark.isActive ? 'bg-blue-grey-3' : 'bg-blue-grey-9'"
|
|
||||||
label-color="accent"
|
|
||||||
class="q-ma-xs"
|
|
||||||
popup-content-class="text-weight-medium text-h6 rounded-5"
|
|
||||||
options-selected-class="bg-accent text-white"
|
|
||||||
:menu-offset="[0, 10]"
|
|
||||||
:options="options"
|
|
||||||
:readonly="readonly || !isEditing"
|
|
||||||
:hide-dropdown-icon="!isEditing"
|
|
||||||
:label="labelString"
|
|
||||||
:option-label="opt => localizeOptions ? $t(opt.label) : opt.label ?? opt"
|
|
||||||
hint=''
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span class="text-weight-bolder text-accent text-uppercase">{{ labelString }}</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #selected-item="scope">
|
|
||||||
<span class="text-weight-light" style="font-size: 1.2em;">{{ scope.opt.label }}</span>
|
|
||||||
</template>
|
|
||||||
</q-select>
|
|
||||||
</template>
|
|
||||||
|
|
@ -16,16 +16,17 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="$q.screen.lt.md ? 'column no-wrap flex-center' : 'row'"
|
class="column flex-center"
|
||||||
:style="$q.screen.lt.md ? 'width: 90vw;' : 'width: 40vw;'"
|
|
||||||
>
|
>
|
||||||
<MenuHeader
|
<MenuHeader
|
||||||
:user-first-name="firstName"
|
:user-first-name="firstName"
|
||||||
:user-last-name="lastName"
|
:user-last-name="lastName"
|
||||||
|
class="col-auto"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-card
|
<div class="row col full-width">
|
||||||
class="col-auto q-pa-xs"
|
<div
|
||||||
|
class="col-auto q-pa-xs bg-dark rounded-5 shadow-2"
|
||||||
:class="$q.screen.lt.md ? 'q-mb-sm' : 'q-mr-sm'"
|
:class="$q.screen.lt.md ? 'q-mb-sm' : 'q-mr-sm'"
|
||||||
>
|
>
|
||||||
<q-tabs
|
<q-tabs
|
||||||
|
|
@ -36,7 +37,7 @@
|
||||||
>
|
>
|
||||||
<slot name="tabs"></slot>
|
<slot name="tabs"></slot>
|
||||||
</q-tabs>
|
</q-tabs>
|
||||||
</q-card>
|
</div>
|
||||||
|
|
||||||
<q-card
|
<q-card
|
||||||
class="col"
|
class="col"
|
||||||
|
|
@ -54,6 +55,7 @@
|
||||||
<slot name="panels"></slot>
|
<slot name="panels"></slot>
|
||||||
</q-tab-panels>
|
</q-tab-panels>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,5 +1,17 @@
|
||||||
import type { MessageLanguages } from "src/boot/i18n";
|
import type { MessageLanguages } from "src/boot/i18n";
|
||||||
|
|
||||||
|
export interface DarkModeOption {
|
||||||
|
label: string;
|
||||||
|
value: boolean | null;
|
||||||
|
quasar_value: boolean | "auto";
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
export const dark_mode_options: DarkModeOption[] = [
|
||||||
|
{ label: 'profile.preferences.dark_mode', value: true, quasar_value: true, icon: 'dark_mode'},
|
||||||
|
{ label: 'profile.preferences.light_mode', value: false, quasar_value: false, icon: 'light_mode'},
|
||||||
|
{ label: 'profile.preferences.auto_mode', value: null, quasar_value: "auto", icon: 'brightness_auto'},
|
||||||
|
]
|
||||||
|
|
||||||
export class Preferences {
|
export class Preferences {
|
||||||
id: number;
|
id: number;
|
||||||
notifications: boolean;
|
notifications: boolean;
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,18 @@
|
||||||
clickable
|
clickable
|
||||||
dense
|
dense
|
||||||
v-ripple
|
v-ripple
|
||||||
class="col rounded-5 q-ma-sm shadow-1 "
|
class="col rounded-5 q-ma-sm shadow-4"
|
||||||
:class="locale === $i18n.locale ? 'bg-accent text-white text-weight-bolder' : ''"
|
:class="locale === $i18n.locale ? 'bg-accent text-white text-weight-bolder' : ''"
|
||||||
@click="setDisplayLanguage(locale as MessageLanguages)"
|
@click="setDisplayLanguage(locale as MessageLanguages)"
|
||||||
>
|
>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-img :src="`src/assets/${locale}.png`"/>
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
<q-item-section class="text-uppercase justify-center">
|
<q-item-section class="text-uppercase justify-center">
|
||||||
<q-item-label> {{ $t(`profile.preferences.${locale}`) }}</q-item-label>
|
<q-item-label> {{ $t(`profile.preferences.${locale}`) }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
|
|
||||||
<q-item-section side>
|
<q-item-section side>
|
||||||
<q-icon
|
<q-icon
|
||||||
v-if="locale === $i18n.locale"
|
v-if="locale === $i18n.locale"
|
||||||
|
|
|
||||||
|
|
@ -21,17 +21,17 @@ import { onMounted } from 'vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-page class="bg-secondary column items-center justify-center">
|
<q-page class="bg-secondary row items-center justify-center">
|
||||||
<MenuEmployee
|
<MenuEmployee
|
||||||
v-if="employee_roles.includes(auth_store.user?.role.toUpperCase() ?? 'GUEST')"
|
v-if="employee_roles.includes(auth_store.user?.role.toUpperCase() ?? 'GUEST')"
|
||||||
class="col-sm-12 col-md-10 col-lg-9 col-xl-8"
|
class="col-sm-12 col-md-10 col-lg-7 col-xl-5"
|
||||||
/>
|
/>
|
||||||
</q-page>
|
</q-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
:deep(.q-field--standout.q-field--readonly .q-field__control:before) {
|
:deep(.q-field--outlined.q-field--readonly .q-field__control:before) {
|
||||||
border: none !important;
|
border: 1px solid var(--q-accent);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -64,9 +64,11 @@ export const useUiStore = defineStore('ui', () => {
|
||||||
|
|
||||||
const setPreferences = () => {
|
const setPreferences = () => {
|
||||||
if (user_preferences.value !== undefined) {
|
if (user_preferences.value !== undefined) {
|
||||||
Dark.set(user_preferences.value.is_dark_mode ?? 'auto');
|
// if user_preferences.value.is_dark_mode === null
|
||||||
|
Dark.set(user_preferences.value.is_dark_mode ?? "auto");
|
||||||
locale.value = user_preferences.value.display_language;
|
locale.value = user_preferences.value.display_language;
|
||||||
}
|
}
|
||||||
|
console.log('quasar dark mode: ', q.dark.mode, 'preferences: ', user_preferences.value.is_dark_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user