forked from verdnatura/salix-front
Merge pull request 'feature/ms-68-WorkersDepartments' (#45) from feature/ms-68-WorkersDepartments into dev
Reviewed-on: hyervoni/salix-front-mindshore#45
This commit is contained in:
commit
59e2e20827
|
@ -26,10 +26,6 @@ const closeButton = ref(null);
|
||||||
const countriesOptions = ref([]);
|
const countriesOptions = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const setCountriesOptions = (data) => {
|
|
||||||
countriesOptions.value = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDataSaved = (data) => {
|
const onDataSaved = (data) => {
|
||||||
emit('onDataSaved', data);
|
emit('onDataSaved', data);
|
||||||
closeForm();
|
closeForm();
|
||||||
|
@ -43,7 +39,7 @@ const closeForm = () => {
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
url="Countries"
|
url="Countries"
|
||||||
@on-fetch="(data) => setCountriesOptions(data)"
|
@on-fetch="(data) => (countriesOptions = data)"
|
||||||
:filter="countriesFilter"
|
:filter="countriesFilter"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import FormModel from 'components/FormModel.vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['onDataSaved']);
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
parentId: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const departmentChildData = reactive({
|
||||||
|
name: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const closeButton = ref(null);
|
||||||
|
const isLoading = ref(false);
|
||||||
|
|
||||||
|
const onDataSaved = () => {
|
||||||
|
emit('onDataSaved');
|
||||||
|
closeForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeForm = () => {
|
||||||
|
if (closeButton.value) closeButton.value.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if ($props.parentId) departmentChildData.parentId = $props.parentId;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FormModel
|
||||||
|
:form-initial-data="departmentChildData"
|
||||||
|
:observe-form-changes="false"
|
||||||
|
:default-actions="false"
|
||||||
|
url-create="departments/createChild"
|
||||||
|
@on-data-saved="onDataSaved()"
|
||||||
|
>
|
||||||
|
<template #form="{ data }">
|
||||||
|
<span ref="closeButton" class="close-icon" v-close-popup>
|
||||||
|
<QIcon name="close" size="sm" />
|
||||||
|
</span>
|
||||||
|
<h1 class="title">{{ t('New department') }}</h1>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md" style="min-width: 250px">
|
||||||
|
<div class="col">
|
||||||
|
<VnInput :label="t('Name')" v-model="data.name" />
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
<div class="q-mt-lg row justify-end">
|
||||||
|
<QBtn
|
||||||
|
:label="t('globals.cancel')"
|
||||||
|
type="reset"
|
||||||
|
color="primary"
|
||||||
|
flat
|
||||||
|
class="q-ml-sm"
|
||||||
|
:disabled="isLoading"
|
||||||
|
:loading="isLoading"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
:label="t('globals.save')"
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
:disabled="isLoading"
|
||||||
|
:loading="isLoading"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</FormModel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.close-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Name: Nombre
|
||||||
|
New department: Nuevo departamento
|
||||||
|
</i18n>
|
|
@ -58,7 +58,7 @@ const $props = defineProps({
|
||||||
mapper: {
|
mapper: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: null,
|
default: null,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['onFetch', 'onDataSaved']);
|
const emit = defineEmits(['onFetch', 'onDataSaved']);
|
||||||
|
@ -129,7 +129,7 @@ async function save() {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const body = $props.mapper ? $props.mapper(formData.value) : formData.value
|
const body = $props.mapper ? $props.mapper(formData.value) : formData.value;
|
||||||
if ($props.urlCreate) {
|
if ($props.urlCreate) {
|
||||||
await axios.post($props.urlCreate, body);
|
await axios.post($props.urlCreate, body);
|
||||||
notify('globals.dataCreated', 'positive');
|
notify('globals.dataCreated', 'positive');
|
||||||
|
@ -179,11 +179,14 @@ watch(formUrl, async () => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<QBanner v-if="$props.observeFormChanges && hasChanges" class="text-white bg-warning">
|
<QBanner
|
||||||
|
v-if="$props.observeFormChanges && hasChanges"
|
||||||
|
class="text-white bg-warning full-width"
|
||||||
|
>
|
||||||
<QIcon name="warning" size="md" class="q-mr-md" />
|
<QIcon name="warning" size="md" class="q-mr-md" />
|
||||||
<span>{{ t('globals.changesToSave') }}</span>
|
<span>{{ t('globals.changesToSave') }}</span>
|
||||||
</QBanner>
|
</QBanner>
|
||||||
<div class="column items-center">
|
<div class="column items-center full-width">
|
||||||
<QForm
|
<QForm
|
||||||
v-if="formData"
|
v-if="formData"
|
||||||
@submit="save"
|
@submit="save"
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
|
||||||
|
import CreateDepartmentChild from '../CreateDepartmentChild.vue';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const router = useRouter();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
|
||||||
|
const treeRef = ref(null);
|
||||||
|
const showCreateNodeFormVal = ref(false);
|
||||||
|
const creationNodeSelectedId = ref(null);
|
||||||
|
const expanded = ref([]);
|
||||||
|
|
||||||
|
const nodes = ref([{ id: null, name: t('Departments'), sons: true, children: [{}] }]);
|
||||||
|
|
||||||
|
const fetchedChildrensSet = ref(new Set());
|
||||||
|
|
||||||
|
const onNodeExpanded = (nodeKeysArray) => {
|
||||||
|
// Verificar si el nodo ya fue expandido
|
||||||
|
if (!fetchedChildrensSet.value.has(nodeKeysArray.at(-1))) {
|
||||||
|
fetchedChildrensSet.value.add(nodeKeysArray.at(-1));
|
||||||
|
fetchNodeLeaves(nodeKeysArray.at(-1)); // Llamar a la función para obtener los nodos hijos
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchNodeLeaves = async (nodeKey) => {
|
||||||
|
try {
|
||||||
|
const node = treeRef.value.getNodeByKey(nodeKey);
|
||||||
|
if (!node || node.sons === 0) return;
|
||||||
|
|
||||||
|
const params = { parentId: node.id };
|
||||||
|
const response = await axios.get('/departments/getLeaves', { params });
|
||||||
|
|
||||||
|
// Si hay datos en la respuesta y tiene hijos, agregarlos al nodo actual
|
||||||
|
if (response.data) {
|
||||||
|
node.children = response.data;
|
||||||
|
node.children.forEach((node) => {
|
||||||
|
if (node.sons) node.children = [{}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching department leaves');
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeNode = (node) => {
|
||||||
|
quasar
|
||||||
|
.dialog({
|
||||||
|
title: 'Are you sure you want to delete it?',
|
||||||
|
message: 'Delete department',
|
||||||
|
ok: {
|
||||||
|
push: true,
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
cancel: true,
|
||||||
|
})
|
||||||
|
.onOk(async () => {
|
||||||
|
try {
|
||||||
|
await axios.post(`/Departments/${node.id}/removeChild`, node.id);
|
||||||
|
notify('department.departmentRemoved', 'positive');
|
||||||
|
await fetchNodeLeaves(node.parentFk);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Error removing department');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const showCreateNodeForm = (nodeId) => {
|
||||||
|
showCreateNodeFormVal.value = true;
|
||||||
|
creationNodeSelectedId.value = nodeId;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onNodeCreated = async () => {
|
||||||
|
await fetchNodeLeaves(creationNodeSelectedId.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const redirectToDepartmentSummary = (id) => {
|
||||||
|
if (!id) return;
|
||||||
|
router.push({ name: 'DepartmentSummary', params: { id: id } });
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QCard class="full-width" style="max-width: 800px">
|
||||||
|
<QTree
|
||||||
|
ref="treeRef"
|
||||||
|
:nodes="nodes"
|
||||||
|
node-key="id"
|
||||||
|
label-key="name"
|
||||||
|
v-model:expanded="expanded"
|
||||||
|
@update:expanded="onNodeExpanded($event)"
|
||||||
|
>
|
||||||
|
<template #default-header="prop">
|
||||||
|
<div
|
||||||
|
class="row justify-between full-width q-pr-md cursor-pointer"
|
||||||
|
@click.stop="redirectToDepartmentSummary(prop.node.id)"
|
||||||
|
>
|
||||||
|
<span class="text-uppercase">
|
||||||
|
{{ prop.node.name }}
|
||||||
|
</span>
|
||||||
|
<div class="row justify-between" style="max-width: max-content">
|
||||||
|
<QIcon
|
||||||
|
v-if="prop.node.id"
|
||||||
|
name="delete"
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
class="q-pr-xs cursor-pointer"
|
||||||
|
@click.stop="removeNode(prop.node)"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('Remove') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
<QIcon
|
||||||
|
name="add"
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click.stop="showCreateNodeForm(prop.node.id)"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('Create') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</QTree>
|
||||||
|
<QDialog
|
||||||
|
v-model="showCreateNodeFormVal"
|
||||||
|
transition-show="scale"
|
||||||
|
transition-hide="scale"
|
||||||
|
>
|
||||||
|
<CreateDepartmentChild
|
||||||
|
:parent-id="creationNodeSelectedId"
|
||||||
|
@on-data-saved="onNodeCreated()"
|
||||||
|
/>
|
||||||
|
</QDialog>
|
||||||
|
</QCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Departments: Departamentos
|
||||||
|
Remove: Quitar
|
||||||
|
Create: Crear
|
||||||
|
Are you sure you want to delete it?: ¿Seguro que quieres eliminarlo?
|
||||||
|
Delete department: Eliminar departamento
|
||||||
|
</i18n>
|
|
@ -568,7 +568,7 @@ export default {
|
||||||
landed: 'Landed',
|
landed: 'Landed',
|
||||||
hour: 'Hour',
|
hour: 'Hour',
|
||||||
agency: 'Agency',
|
agency: 'Agency',
|
||||||
total: 'Total'
|
total: 'Total',
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
clientFk: 'Client',
|
clientFk: 'Client',
|
||||||
|
@ -577,7 +577,7 @@ export default {
|
||||||
agencyModeFk: 'Agency',
|
agencyModeFk: 'Agency',
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
newOrder: 'New Order'
|
newOrder: 'New Order',
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
basket: 'Basket',
|
basket: 'Basket',
|
||||||
|
@ -603,8 +603,27 @@ export default {
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
quantity: 'Quantity',
|
quantity: 'Quantity',
|
||||||
price: 'Price',
|
price: 'Price',
|
||||||
amount: 'Amount'
|
amount: 'Amount',
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
department: {
|
||||||
|
pageTitles: {
|
||||||
|
basicData: 'Basic data',
|
||||||
|
department: 'Department',
|
||||||
|
summary: 'Summary',
|
||||||
|
},
|
||||||
|
name: 'Name',
|
||||||
|
code: 'Code',
|
||||||
|
chat: 'Chat',
|
||||||
|
bossDepartment: 'Boss Department',
|
||||||
|
email: 'Email',
|
||||||
|
selfConsumptionCustomer: 'Self-consumption customer',
|
||||||
|
telework: 'Telework',
|
||||||
|
notifyOnErrors: 'Notify on errors',
|
||||||
|
worksInProduction: 'Works in production',
|
||||||
|
hasToRefill: 'Fill in days without physical check-ins',
|
||||||
|
hasToSendMail: 'Send check-ins by email',
|
||||||
|
departmentRemoved: 'Department removed',
|
||||||
},
|
},
|
||||||
worker: {
|
worker: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
@ -614,6 +633,7 @@ export default {
|
||||||
summary: 'Summary',
|
summary: 'Summary',
|
||||||
notifications: 'Notifications',
|
notifications: 'Notifications',
|
||||||
workerCreate: 'New worker',
|
workerCreate: 'New worker',
|
||||||
|
department: 'Department',
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
|
|
|
@ -477,7 +477,7 @@ export default {
|
||||||
landed: 'F. entrega',
|
landed: 'F. entrega',
|
||||||
hour: 'Hora',
|
hour: 'Hora',
|
||||||
agency: 'Agencia',
|
agency: 'Agencia',
|
||||||
total: 'Total'
|
total: 'Total',
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
clientFk: 'Cliente',
|
clientFk: 'Cliente',
|
||||||
|
@ -486,7 +486,7 @@ export default {
|
||||||
agencyModeFk: 'Agencia',
|
agencyModeFk: 'Agencia',
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
newOrder: 'Nuevo Pedido'
|
newOrder: 'Nuevo Pedido',
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
basket: 'Cesta',
|
basket: 'Cesta',
|
||||||
|
@ -512,8 +512,8 @@ export default {
|
||||||
description: 'Descripción',
|
description: 'Descripción',
|
||||||
quantity: 'Cantidad',
|
quantity: 'Cantidad',
|
||||||
price: 'Precio',
|
price: 'Precio',
|
||||||
amount: 'Monto'
|
amount: 'Monto',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
shelving: {
|
shelving: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
@ -606,6 +606,25 @@ export default {
|
||||||
country: 'País',
|
country: 'País',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
department: {
|
||||||
|
pageTitles: {
|
||||||
|
basicData: 'Basic data',
|
||||||
|
department: 'Departamentos',
|
||||||
|
summary: 'Resumen',
|
||||||
|
},
|
||||||
|
name: 'Nombre',
|
||||||
|
code: 'Código',
|
||||||
|
chat: 'Chat',
|
||||||
|
bossDepartment: 'Jefe de departamento',
|
||||||
|
email: 'Email',
|
||||||
|
selfConsumptionCustomer: 'Cliente autoconsumo',
|
||||||
|
telework: 'Teletrabaja',
|
||||||
|
notifyOnErrors: 'Notificar errores',
|
||||||
|
worksInProduction: 'Pertenece a producción',
|
||||||
|
hasToRefill: 'Completar días sin registros físicos',
|
||||||
|
hasToSendMail: 'Enviar fichadas por mail',
|
||||||
|
departmentRemoved: 'Departamento eliminado',
|
||||||
|
},
|
||||||
worker: {
|
worker: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
workers: 'Trabajadores',
|
workers: 'Trabajadores',
|
||||||
|
@ -614,6 +633,7 @@ export default {
|
||||||
summary: 'Resumen',
|
summary: 'Resumen',
|
||||||
notifications: 'Notificaciones',
|
notifications: 'Notificaciones',
|
||||||
workerCreate: 'Nuevo trabajador',
|
workerCreate: 'Nuevo trabajador',
|
||||||
|
department: 'Departamentos',
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
name: 'Nombre',
|
name: 'Nombre',
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
import FormModel from 'components/FormModel.vue';
|
||||||
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const workersOptions = ref([]);
|
||||||
|
const clientsOptions = ref([]);
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<fetch-data
|
||||||
|
url="Workers/search"
|
||||||
|
@on-fetch="(data) => (workersOptions = data)"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<fetch-data url="Clients" @on-fetch="(data) => (clientsOptions = data)" auto-load />
|
||||||
|
<FormModel
|
||||||
|
:url="`Departments/${route.params.id}`"
|
||||||
|
model="department"
|
||||||
|
auto-load
|
||||||
|
class="full-width"
|
||||||
|
>
|
||||||
|
<template #form="{ data, validate }">
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<VnInput
|
||||||
|
:label="t('department.name')"
|
||||||
|
v-model="data.name"
|
||||||
|
:rules="validate('department.name')"
|
||||||
|
clearable
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<VnInput
|
||||||
|
v-model="data.code"
|
||||||
|
:label="t('department.code')"
|
||||||
|
:rules="validate('department.code')"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<VnInput
|
||||||
|
:label="t('department.chat')"
|
||||||
|
v-model="data.chatName"
|
||||||
|
:rules="validate('department.chat')"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<VnInput
|
||||||
|
v-model="data.notificationEmail"
|
||||||
|
:label="t('department.email')"
|
||||||
|
:rules="validate('department.email')"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<VnSelectFilter
|
||||||
|
:label="t('department.bossDepartment')"
|
||||||
|
v-model="data.workerFk"
|
||||||
|
:options="workersOptions"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
hide-selected
|
||||||
|
map-options
|
||||||
|
:rules="validate('department.workerFk')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<VnSelectFilter
|
||||||
|
:label="t('department.selfConsumptionCustomer')"
|
||||||
|
v-model="data.clientFk"
|
||||||
|
:options="clientsOptions"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
hide-selected
|
||||||
|
map-options
|
||||||
|
:rules="validate('department.clientFk')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('department.telework')"
|
||||||
|
v-model="data.isTeleworking"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('department.notifyOnErrors')"
|
||||||
|
v-model="data.hasToMistake"
|
||||||
|
:false-value="0"
|
||||||
|
:true-value="1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('department.worksInProduction')"
|
||||||
|
v-model="data.isProduction"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('department.hasToRefill')"
|
||||||
|
v-model="data.hasToRefill"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<div class="col">
|
||||||
|
<QCheckbox
|
||||||
|
:label="t('department.hasToSendMail')"
|
||||||
|
v-model="data.hasToSendMail"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</VnRow>
|
||||||
|
</template>
|
||||||
|
</FormModel>
|
||||||
|
</template>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<script setup>
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import DepartmentDescriptor from 'pages/Department/Card/DepartmentDescriptor.vue';
|
||||||
|
import LeftMenu from 'components/LeftMenu.vue';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256">
|
||||||
|
<QScrollArea class="fit">
|
||||||
|
<DepartmentDescriptor />
|
||||||
|
<QSeparator />
|
||||||
|
<LeftMenu source="card" />
|
||||||
|
</QScrollArea>
|
||||||
|
</QDrawer>
|
||||||
|
<QPageContainer>
|
||||||
|
<QPage>
|
||||||
|
<QToolbar class="bg-vn-dark justify-end">
|
||||||
|
<div id="st-data"></div>
|
||||||
|
<QSpace />
|
||||||
|
<div id="st-actions"></div>
|
||||||
|
</QToolbar>
|
||||||
|
<div class="q-pa-md column items-center">
|
||||||
|
<RouterView></RouterView>
|
||||||
|
</div>
|
||||||
|
</QPage>
|
||||||
|
</QPageContainer>
|
||||||
|
</template>
|
|
@ -0,0 +1,129 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
|
||||||
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
|
import useCardDescription from 'src/composables/useCardDescription';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
|
||||||
|
const entityId = computed(() => {
|
||||||
|
return $props.id || route.params.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const department = ref();
|
||||||
|
|
||||||
|
const data = ref(useCardDescription());
|
||||||
|
|
||||||
|
const setData = (entity) => {
|
||||||
|
if (!entity) return;
|
||||||
|
data.value = useCardDescription(entity.name, entity.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeDepartment = () => {
|
||||||
|
console.log('entityId: ', entityId.value);
|
||||||
|
quasar
|
||||||
|
.dialog({
|
||||||
|
title: 'Are you sure you want to delete it?',
|
||||||
|
message: 'Delete department',
|
||||||
|
ok: {
|
||||||
|
push: true,
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
cancel: true,
|
||||||
|
})
|
||||||
|
.onOk(async () => {
|
||||||
|
try {
|
||||||
|
await axios.post(
|
||||||
|
`/Departments/${entityId.value}/removeChild`,
|
||||||
|
entityId.value
|
||||||
|
);
|
||||||
|
router.push({ name: 'WorkerDepartment' });
|
||||||
|
notify('department.departmentRemoved', 'positive');
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Error removing department');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<CardDescriptor
|
||||||
|
module="Department"
|
||||||
|
data-key="departmentData"
|
||||||
|
:url="`Departments/${entityId}`"
|
||||||
|
:title="data.title"
|
||||||
|
:subtitle="data.subtitle"
|
||||||
|
:summary="$props.summary"
|
||||||
|
@on-fetch="
|
||||||
|
(data) => {
|
||||||
|
department = data;
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #menu="{}">
|
||||||
|
<QItem v-ripple clickable @click="removeDepartment()">
|
||||||
|
<QItemSection>{{ t('Delete') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
<template #body="{ entity }">
|
||||||
|
<VnLv :label="t('department.chat')" :value="entity.chatName" dash />
|
||||||
|
<VnLv :label="t('department.email')" :value="entity.notificationEmail" dash />
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.selfConsumptionCustomer')"
|
||||||
|
:value="entity.client?.name"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.bossDepartment')"
|
||||||
|
:value="entity.worker?.user?.name"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<QCardActions>
|
||||||
|
<QBtn
|
||||||
|
size="md"
|
||||||
|
icon="vn:worker"
|
||||||
|
color="primary"
|
||||||
|
:to="{
|
||||||
|
name: 'WorkerList',
|
||||||
|
query: {
|
||||||
|
params: JSON.stringify({ departmentFk: entityId }),
|
||||||
|
},
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<QTooltip>{{ t('Department workers') }}</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
</QCardActions>
|
||||||
|
</template>
|
||||||
|
</CardDescriptor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Department workers: Trabajadores del departamento
|
||||||
|
</i18n>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, computed } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
const departmentUrl = ref();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
departmentUrl.value = (await getUrl('')) + `departments/${entityId.value}/`;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CardSummary
|
||||||
|
ref="summary"
|
||||||
|
:url="`Departments/${entityId}`"
|
||||||
|
class="full-width"
|
||||||
|
style="max-width: 900px"
|
||||||
|
>
|
||||||
|
<template #header="{ entity }">
|
||||||
|
<div>{{ entity.name }}</div>
|
||||||
|
</template>
|
||||||
|
<template #body="{ entity: department }">
|
||||||
|
<QCard class="column">
|
||||||
|
<a class="header" :href="department + `basic-data`">
|
||||||
|
{{ t('Basic data') }}
|
||||||
|
<QIcon name="open_in_new" color="primary" />
|
||||||
|
</a>
|
||||||
|
<div class="full-width row wrap justify-between content-between">
|
||||||
|
<div class="column" style="min-width: 50%">
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.name')"
|
||||||
|
:value="department.name"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.code')"
|
||||||
|
:value="department.code"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.chat')"
|
||||||
|
:value="department.chatName"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.bossDepartment')"
|
||||||
|
:value="department.worker?.user?.name"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.email')"
|
||||||
|
:value="department.notificationEmail"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.selfConsumptionCustomer')"
|
||||||
|
:value="department.client?.name"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="column" style="min-width: 50%">
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.telework')"
|
||||||
|
:value="department.isTeleworking"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.notifyOnErrors')"
|
||||||
|
:value="Boolean(department.hasToMistake)"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.worksInProduction')"
|
||||||
|
:value="department.isProduction"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.hasToRefill')"
|
||||||
|
:value="department.hasToRefill"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
<VnLv
|
||||||
|
:label="t('department.hasToSendMail')"
|
||||||
|
:value="department.hasToSendMail"
|
||||||
|
dash
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</QCard>
|
||||||
|
</template>
|
||||||
|
</CardSummary>
|
||||||
|
</template>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<script setup>
|
||||||
|
import VnTree from 'components/ui/VnTree.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QPage class="column items-center q-pa-md">
|
||||||
|
<VnTree />
|
||||||
|
</QPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Search worker: Buscar trabajador
|
||||||
|
You can search by worker id or name: Puedes buscar por id o nombre del trabajador
|
||||||
|
</i18n>
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
path: '/department',
|
||||||
|
name: 'Department',
|
||||||
|
meta: {
|
||||||
|
title: 'department',
|
||||||
|
icon: 'vn:greuge',
|
||||||
|
},
|
||||||
|
component: RouterView,
|
||||||
|
redirect: { name: 'DepartmentCard' },
|
||||||
|
menus: {
|
||||||
|
main: [],
|
||||||
|
card: ['DepartmentBasicData'],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'DepartmentCard',
|
||||||
|
path: 'department/:id',
|
||||||
|
component: () => import('src/pages/Department/Card/DepartmentCard.vue'),
|
||||||
|
redirect: { name: 'DepartmentSummary' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'DepartmentSummary',
|
||||||
|
path: 'summary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary',
|
||||||
|
icon: 'launch',
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import('src/pages/Department/Card/DepartmentSummary.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DepartmentBasicData',
|
||||||
|
path: 'basic-data',
|
||||||
|
meta: {
|
||||||
|
title: 'basicData',
|
||||||
|
icon: 'vn:settings',
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import('src/pages/Department/Card/DepartmentBasicData.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -10,6 +10,7 @@ import Route from './route';
|
||||||
import Supplier from './Supplier';
|
import Supplier from './Supplier';
|
||||||
import Travel from './travel';
|
import Travel from './travel';
|
||||||
import Order from './order';
|
import Order from './order';
|
||||||
|
import Department from './department';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
Customer,
|
Customer,
|
||||||
|
@ -24,4 +25,5 @@ export default [
|
||||||
Travel,
|
Travel,
|
||||||
Order,
|
Order,
|
||||||
invoiceIn,
|
invoiceIn,
|
||||||
|
Department,
|
||||||
];
|
];
|
||||||
|
|
|
@ -10,8 +10,9 @@ export default {
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'WorkerMain' },
|
redirect: { name: 'WorkerMain' },
|
||||||
menus: {
|
menus: {
|
||||||
main: ['WorkerList'],
|
main: ['WorkerList', 'WorkerDepartment'],
|
||||||
card: ['WorkerNotificationsManager'],
|
card: ['WorkerNotificationsManager'],
|
||||||
|
departmentCard: ['BasicData'],
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,15 @@ export default {
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Worker/WorkerList.vue'),
|
component: () => import('src/pages/Worker/WorkerList.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'department',
|
||||||
|
name: 'WorkerDepartment',
|
||||||
|
meta: {
|
||||||
|
title: 'department',
|
||||||
|
icon: 'vn:greuge',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Worker/WorkerDepartment.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: 'create',
|
||||||
name: 'WorkerCreate',
|
name: 'WorkerCreate',
|
||||||
|
|
|
@ -8,8 +8,9 @@ import wagon from './modules/wagon';
|
||||||
import supplier from './modules/Supplier';
|
import supplier from './modules/Supplier';
|
||||||
import route from './modules/route';
|
import route from './modules/route';
|
||||||
import travel from './modules/travel';
|
import travel from './modules/travel';
|
||||||
|
import department from './modules/department';
|
||||||
import shelving from 'src/router/modules/shelving';
|
import shelving from 'src/router/modules/shelving';
|
||||||
import order from "src/router/modules/order";
|
import order from 'src/router/modules/order';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
|
@ -61,6 +62,7 @@ const routes = [
|
||||||
route,
|
route,
|
||||||
supplier,
|
supplier,
|
||||||
travel,
|
travel,
|
||||||
|
department,
|
||||||
{
|
{
|
||||||
path: '/:catchAll(.*)*',
|
path: '/:catchAll(.*)*',
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
|
|
Loading…
Reference in New Issue