0
0
Fork 0

Se crea formulario de creacion de cliente

This commit is contained in:
carlosfonseca 2023-12-14 06:49:40 -05:00
parent 0097d2d7f8
commit 0a41ce6aa9
4 changed files with 416 additions and 10 deletions

View File

@ -0,0 +1,260 @@
<script setup>
import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import CustomerCreateNewPostcode from './CustomerCreateNewPostcode.vue';
import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
const { t } = useI18n();
const newClientForm = reactive({
active: true,
name: null,
salesPersonFk: null,
businessTypeFk: null,
fi: null,
socialName: null,
street: null,
postcode: null,
city: null,
provinceFk: null,
countryFk: null,
userName: null,
email: null,
isEqualizated: false,
});
const workersOptions = ref([]);
const businessTypesOptions = ref([]);
const citiesLocationOptions = ref([]);
const provincesLocationOptions = ref([]);
const countriesOptions = ref([]);
const onFetchWorkers = (workers) => {
workersOptions.value = [...workers];
};
const onFetchBusinessTypes = (businessTypes) => {
businessTypesOptions.value = [...businessTypes];
};
const onFetchCitiesLocation = (citiesLocation) => {
citiesLocationOptions.value = [...citiesLocation];
};
const onFetchProvincesLocation = (provincesLocation) => {
provincesLocationOptions.value = [...provincesLocation];
};
const onFetchCountries = (countries) => {
countriesOptions.value = [...countries];
};
</script>
<template>
<FetchData
@on-fetch="(data) => onFetchWorkers(data)"
auto-load
url="Workers/search?departmentCodes"
/>
<FetchData
@on-fetch="(data) => onFetchBusinessTypes(data)"
auto-load
url="BusinessTypes"
/>
<FetchData
@on-fetch="(data) => onFetchCitiesLocation(data)"
auto-load
url="Towns/location"
/>
<FetchData
@on-fetch="(data) => onFetchProvincesLocation(data)"
auto-load
url="Provinces/location"
/>
<FetchData url="Countries" @on-fetch="(data) => onFetchCountries(data)" auto-load />
<QPage>
<QToolbar class="bg-vn-dark">
<div id="st-data"></div>
<QSpace />
<div id="st-actions"></div>
</QToolbar>
<FormModel
:form-initial-data="newClientForm"
:observe-form-changes="false"
model="client"
url-create="Clients/createWithUser"
>
<template #form="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QInput :label="t('Comercial name')" v-model="data.name" />
</div>
<div class="col">
<VnSelectFilter
:label="t('Salesperson')"
:options="workersOptions"
hide-selected
option-label="name"
option-value="id"
v-model="data.salesPersonFk"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Business type')"
:options="businessTypesOptions"
hide-selected
option-label="description"
option-value="code"
v-model="data.businessTypeFk"
/>
</div>
<div class="col">
<QInput v-model="data.fi" :label="t('Tax number')" />
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QInput
:label="t('Business name')"
:rules="validate('Client.socialName')"
v-model="data.socialName"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QInput
:label="t('Street')"
:rules="validate('Client.street')"
v-model="data.street"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QInput v-model="data.postcode" :label="t('Postcode')">
<template #append>
<QBtn
class="cursor-pointer"
color="primary"
dense
icon="add"
round
size="xs"
>
<QPopupProxy
cover
transition-hide="scale"
transition-show="scale"
>
<CustomerCreateNewPostcode />
</QPopupProxy>
</QBtn>
</template>
</QInput>
</div>
<div class="col">
<!-- ciudades -->
<VnSelectFilter
:label="t('City')"
:options="citiesLocationOptions"
hide-selected
option-label="name"
option-value="name"
v-model="data.city"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
<QItemLabel caption>
{{
`${scope.opt.name}, ${scope.opt.province.name} (${scope.opt.province.country.country})`
}}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Province')"
:options="provincesLocationOptions"
hide-selected
option-label="name"
option-value="id"
v-model="data.provinceFk"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{
`${scope.opt.name} (${scope.opt.country.country})`
}}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</div>
<div class="col">
<VnSelectFilter
:label="t('Country')"
:options="countriesOptions"
hide-selected
option-label="country"
option-value="id"
v-model="data.countryFk"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QInput v-model="data.userName" :label="t('Web user')" />
</div>
<div class="col">
<QInput v-model="data.email" :label="t('Email')" />
</div>
</VnRow>
<QCheckbox
:label="t('Is equalizated')"
v-model="newClientForm.isEqualizated"
/>
</template>
</FormModel>
</QPage>
</template>
<style lang="scss" scoped>
.card {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-gap: 20px;
}
</style>
<i18n>
es:
Comercial name: Nombre comercial
Salesperson: Comercial
Business type: Tipo de negocio
Tax number: NIF / CIF
Business name: Razón social
Street: Dirección fiscal
Postcode: Código postal
City: Población
Province: Provincia
Country: País
Web user: Usuario web
Email: Email
Is equalizated: Recargo de equivalencia
</i18n>

View File

@ -0,0 +1,127 @@
<script setup>
import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import FetchData from 'components/FetchData.vue';
import useNotify from 'src/composables/useNotify';
import VnRow from 'components/ui/VnRow.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
const { notify } = useNotify();
const { t } = useI18n();
const data = reactive({
city: null,
code: null,
countryFk: null,
provinceFk: null,
townFk: null,
});
const countriesOptions = ref([]);
const isLoading = ref(false);
const provincesOptions = ref([]);
const townsLocationOptions = ref([]);
const onFetchTownsLocation = (townsLocation) => {
townsLocationOptions.value = [...townsLocation];
};
const onFetchProvinces = (provinces) => {
provincesOptions.value = [...provinces];
};
const onFetchCountries = (countries) => {
countriesOptions.value = [...countries];
};
async function save() {
isLoading.value = true;
try {
const { city, code, countryFk, provinceFk } = data;
const payload = {
city: city.name,
code,
countryFk,
provinceFk,
townFk: city.id,
};
await axios.patch('/postcodes', payload);
} catch (err) {
notify('errors.create', 'negative');
}
isLoading.value = false;
}
</script>
<template>
<FetchData
@on-fetch="(data) => onFetchTownsLocation(data)"
auto-load
url="Towns/location"
/>
<FetchData @on-fetch="(data) => onFetchProvinces(data)" auto-load url="Provinces" />
<FetchData @on-fetch="(data) => onFetchCountries(data)" auto-load url="Countries" />
<div class="q-pa-lg">
<h6 class="q-my-xs">New postcode</h6>
<p>Please, ensure you put the correct data!</p>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<QInput label="Postcode" v-model="data.code" />
</div>
<div class="col">
<VnSelectFilter
:options="townsLocationOptions"
hide-selected
label="City"
option-label="name"
option-value="city"
v-model="data.city"
/>
</div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-xl">
<div class="col">
<VnSelectFilter
:options="provincesOptions"
hide-selected
label="Province"
option-label="name"
option-value="id"
v-model="data.provinceFk"
/>
</div>
<div class="col">
<VnSelectFilter
:options="countriesOptions"
hide-selected
label="Country"
option-label="country"
option-value="id"
v-model="data.countryFk"
/>
</div>
</VnRow>
<div class="flex justify-end">
<QBtn class="q-mr-lg" color="primary" label="Cancel" outline v-close-popup />
<QBtn @click="save" color="primary" label="Save" v-close-popup />
</div>
</div>
<QInnerLoading
:showing="isLoading"
:label="t('globals.pleaseWait')"
color="primary"
/>
</template>
<style lang="scss" scoped>
.card {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-gap: 20px;
}
</style>

View File

@ -28,25 +28,29 @@ function viewSummary(id) {
}, },
}); });
} }
const redirectToCreateView = () => {
router.push({ name: 'CustomerCreate' });
};
</script> </script>
<template> <template>
<template v-if="stateStore.isHeaderMounted()"> <template v-if="stateStore.isHeaderMounted()">
<Teleport to="#searchbar"> <Teleport to="#searchbar">
<VnSearchbar <VnSearchbar
data-key="CustomerList"
:label="t('Search customer')"
:info="t('You can search by customer id or name')" :info="t('You can search by customer id or name')"
:label="t('Search customer')"
data-key="CustomerList"
/> />
</Teleport> </Teleport>
<Teleport to="#actions-append"> <Teleport to="#actions-append">
<div class="row q-gutter-x-sm"> <div class="row q-gutter-x-sm">
<QBtn <QBtn
flat
@click="stateStore.toggleRightDrawer()" @click="stateStore.toggleRightDrawer()"
round
dense dense
flat
icon="menu" icon="menu"
round
> >
<QTooltip bottom anchor="bottom right"> <QTooltip bottom anchor="bottom right">
{{ t('globals.collapseMenu') }} {{ t('globals.collapseMenu') }}
@ -55,7 +59,7 @@ function viewSummary(id) {
</div> </div>
</Teleport> </Teleport>
</template> </template>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above> <QDrawer :width="256" show-if-above side="right" v-model="stateStore.rightDrawer">
<QScrollArea class="fit text-grey-8"> <QScrollArea class="fit text-grey-8">
<CustomerFilter data-key="CustomerList" /> <CustomerFilter data-key="CustomerList" />
</QScrollArea> </QScrollArea>
@ -63,18 +67,18 @@ function viewSummary(id) {
<QPage class="column items-center q-pa-md"> <QPage class="column items-center q-pa-md">
<div class="card-list"> <div class="card-list">
<VnPaginate <VnPaginate
data-key="CustomerList"
url="/Clients/filter"
order="id DESC"
auto-load auto-load
data-key="CustomerList"
order="id DESC"
url="/Clients/filter"
> >
<template #body="{ rows }"> <template #body="{ rows }">
<CardList <CardList
v-for="row of rows" :id="row.id"
:key="row.id" :key="row.id"
:title="row.name" :title="row.name"
:id="row.id"
@click="navigate(row.id)" @click="navigate(row.id)"
v-for="row of rows"
> >
<template #list-items> <template #list-items>
<VnLv :label="t('customer.list.email')" :value="row.email" /> <VnLv :label="t('customer.list.email')" :value="row.email" />
@ -103,6 +107,12 @@ function viewSummary(id) {
</template> </template>
</VnPaginate> </VnPaginate>
</div> </div>
<QPageSticky :offset="[20, 20]">
<QBtn @click="redirectToCreateView()" color="primary" fab icon="add" />
<QTooltip>
{{ t('New client') }}
</QTooltip>
</QPageSticky>
</QPage> </QPage>
</template> </template>
@ -117,4 +127,5 @@ function viewSummary(id) {
es: es:
Search customer: Buscar cliente Search customer: Buscar cliente
You can search by customer id or name: Puedes buscar por id o nombre del cliente You can search by customer id or name: Puedes buscar por id o nombre del cliente
New client: Nuevo cliente
</i18n> </i18n>

View File

@ -29,6 +29,14 @@ export default {
}, },
component: () => import('src/pages/Customer/CustomerList.vue'), component: () => import('src/pages/Customer/CustomerList.vue'),
}, },
{
path: 'create',
name: 'CustomerCreate',
meta: {
title: 'create',
},
component: () => import('src/pages/Customer/CustomerCreate.vue'),
},
{ {
path: 'payments', path: 'payments',
name: 'CustomerPayments', name: 'CustomerPayments',