salix-front/src/components/UserPanel.vue

273 lines
8.2 KiB
Vue

<script setup>
import { onMounted, computed, ref } from 'vue';
import { Dark, Quasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import axios from 'axios';
import { useState } from 'src/composables/useState';
import { useSession } from 'src/composables/useSession';
import { localeEquivalence } from 'src/i18n/index';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnRow from 'components/ui/VnRow.vue';
import FetchData from 'components/FetchData.vue';
import { useClipboard } from 'src/composables/useClipboard';
import { useRole } from 'src/composables/useRole';
import VnAvatar from './ui/VnAvatar.vue';
const state = useState();
const session = useSession();
const router = useRouter();
const { t, locale } = useI18n();
const { copyText } = useClipboard();
const userLocale = computed({
get() {
return locale.value;
},
set(value) {
locale.value = value;
value = localeEquivalence[value] ?? value;
try {
/* @vite-ignore */
import(`../../node_modules/quasar/lang/${value}.mjs`).then((lang) => {
Quasar.lang.set(lang.default);
});
} catch (error) {
//
}
},
});
const darkMode = computed({
get() {
return Dark.isActive;
},
set(value) {
Dark.set(value);
},
});
const user = state.getUser();
const warehousesData = ref();
const companiesData = ref();
const accountBankData = ref();
onMounted(async () => {
updatePreferences();
});
function updatePreferences() {
if (user.value.darkMode !== null) {
darkMode.value = user.value.darkMode;
}
if (user.value.lang) {
locale.value = user.value.lang;
userLocale.value = user.value.lang;
}
}
async function saveDarkMode(value) {
const query = `/UserConfigs/${user.value.id}`;
await axios.patch(query, {
darkMode: value,
});
user.value.darkMode = value;
}
async function saveLanguage(value) {
const query = `/VnUsers/${user.value.id}`;
await axios.patch(query, {
lang: value,
});
user.value.lang = value;
}
function logout() {
session.destroy();
router.push('/login');
}
function copyUserToken() {
copyText(session.getToken(), { label: 'components.userPanel.copyToken' });
}
function localUserData() {
state.setUser(user.value);
}
function saveUserData(param, value) {
axios.post('UserConfigs/setUserConfig', { [param]: value });
localUserData();
}
const isEmployee = computed(() => useRole().isEmployee());
</script>
<template>
<FetchData
url="Warehouses"
order="name"
@on-fetch="(data) => (warehousesData = data)"
auto-load
/>
<FetchData
v-if="isEmployee"
url="Companies"
order="name"
@on-fetch="(data) => (companiesData = data)"
auto-load
/>
<FetchData
v-if="isEmployee"
url="Accountings"
order="name"
@on-fetch="(data) => (accountBankData = data)"
auto-load
/>
<QMenu anchor="bottom left" class="bg-vn-section-color">
<div class="row no-wrap q-pa-md">
<div class="col column">
<div class="text-h6 q-ma-sm q-mb-none">
{{ t('components.userPanel.settings') }}
</div>
<QToggle
v-model="userLocale"
@update:model-value="saveLanguage"
:label="t(`globals.lang['${userLocale}']`)"
icon="public"
color="primary"
false-value="es"
true-value="en"
/>
<QToggle
v-model="darkMode"
@update:model-value="saveDarkMode"
:label="t(`globals.darkMode`)"
checked-icon="dark_mode"
color="primary"
unchecked-icon="light_mode"
/>
</div>
<QSeparator vertical inset class="q-mx-lg" />
<div class="col column items-center q-mb-sm">
<VnAvatar
:worker-id="user.id"
:title="user.name"
size="xxl"
color="transparent"
/>
<QBtn
v-if="isEmployee"
class="q-mt-sm q-px-md"
:to="`/worker/${user.id}`"
color="primary"
:label="t('globals.myAccount')"
dense
/>
<div class="text-subtitle1 q-mt-md">
<strong>{{ user.nickname }}</strong>
</div>
<div
class="text-subtitle3 text-grey-7 q-mb-xs copyText"
@click="copyUserToken()"
>
@{{ user.name }}
</div>
<QBtn
id="logout"
color="primary"
flat
:label="t('globals.logOut')"
size="sm"
icon="logout"
@click="logout()"
v-close-popup
dense
/>
</div>
</div>
<QSeparator inset class="q-mx-lg" />
<div class="col q-gutter-xs q-pa-md">
<VnRow>
<VnSelect
:label="t('components.userPanel.localWarehouse')"
v-model="user.localWarehouseFk"
:options="warehousesData"
option-label="name"
option-value="id"
input-debounce="0"
hide-selected
@update:model-value="localUserData"
/>
<VnSelect
:label="t('components.userPanel.localBank')"
v-model="user.localBankFk"
:options="accountBankData"
option-label="bank"
option-value="id"
input-debounce="0"
hide-selected
@update:model-value="localUserData"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>
{{ `${opt.id}: ${opt.bank}` }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</VnRow>
<VnRow>
<VnSelect
:label="t('components.userPanel.localCompany')"
hide-selected
v-model="user.localCompanyFk"
:options="companiesData"
option-label="code"
option-value="id"
input-debounce="0"
@update:model-value="localUserData"
/>
<VnSelect
:label="t('components.userPanel.userWarehouse')"
hide-selected
v-model="user.warehouseFk"
:options="warehousesData"
option-label="name"
option-value="id"
input-debounce="0"
@update:model-value="(v) => saveUserData('warehouseFk', v)"
/>
</VnRow>
<VnRow>
<VnSelect
:label="t('components.userPanel.userCompany')"
hide-selected
v-model="user.companyFk"
:options="companiesData"
option-label="code"
option-value="id"
style="flex: 0"
dense
input-debounce="0"
@update:model-value="(v) => saveUserData('companyFk', v)"
/>
</VnRow>
</div>
</QMenu>
</template>
<style lang="scss" scoped>
.copyText {
&:hover {
cursor: alias;
}
}
</style>