reorganizations of views & components
This commit is contained in:
256
src/views/warehouses/LocationsView.vue
Normal file
256
src/views/warehouses/LocationsView.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { useCompanyStore } from '../../stores/company';
|
||||
import Spiner from '../../components/ui/Spiner.vue';
|
||||
import CardEmpty from '../../components/CardEmpty.vue';
|
||||
import CreateLocationModal from './modals/CreateLocationModal.vue';
|
||||
import CardLocation from './components/CardLocation.vue';
|
||||
import Pagination from '../../components/Pagination.vue';
|
||||
import CustomPopup from '../../components/CustomPopup.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const companyStore = useCompanyStore();
|
||||
|
||||
const loading = ref(false);
|
||||
const filterQuery = ref([]);
|
||||
const query = ref('');
|
||||
const locationCurrent = ref(null);
|
||||
const openModal = ref(false);
|
||||
const { t, locale } = useI18n();
|
||||
const optionsFilter = ref([]);
|
||||
const openPopup = ref(false);
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getInitData(false);
|
||||
})
|
||||
|
||||
const limit = 10;
|
||||
|
||||
const getInitData = async(reload) => {
|
||||
loading.value = true;
|
||||
filterQuery.value.company = "company="+ localStorage.getItem('id');
|
||||
filterQuery.value.limit = "elements=" + limit;
|
||||
filterQuery.value.page = "page=" + 0;
|
||||
await companyStore.getLocationsCompany(filterQuery.value, reload)
|
||||
optionsFilter.value = [
|
||||
{value: '', label: t('labels.alls')},
|
||||
{value: 'both',label: t('labels.both')},
|
||||
{value: 'loading',label: t('labels.load')},
|
||||
{value: 'unloading',label: t('labels.download')}
|
||||
]
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
watch(locale, () => {
|
||||
optionsFilter.value = [
|
||||
{value: 'both',label: t('labels.both')},
|
||||
{value: 'loading',label: t('labels.load')},
|
||||
{value: 'unloading',label: t('labels.download')}
|
||||
]
|
||||
})
|
||||
|
||||
const getLocationsByPage = async(data) => {
|
||||
loading.value = true;
|
||||
filterQuery.value.company = "company="+ localStorage.getItem('id');
|
||||
filterQuery.value.page = "page=" + data.page;
|
||||
companyStore.locationsCurrentPage = data.page
|
||||
await companyStore.getLocationsCompany(filterQuery.value, true)
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
const getLocationsWithFilters = async(filter) => {
|
||||
loading.value = true;
|
||||
await companyStore.getLocationsCompany(filter, true);
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
watch(query, () => {
|
||||
filterQuery.value.page = "page=" + 0;
|
||||
filterQuery.value.limit = "elements=" + 100;
|
||||
if(query.value.length === 0){
|
||||
clearRequest();
|
||||
filterQuery.value.search = "";
|
||||
getLocationsWithFilters(filterQuery.value);
|
||||
}
|
||||
});
|
||||
|
||||
const search = () => {
|
||||
if(query.value.length >= 2){
|
||||
filterQuery.value.search = "branch_name[$regex]="+ query.value +"&branch_name[$options]=i";
|
||||
getLocationsWithFilters(filterQuery.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const clearFilter = () => {
|
||||
clearRequest();
|
||||
|
||||
filterQuery.value.search = "";
|
||||
filterQuery.value.company = "company="+ localStorage.getItem('id');
|
||||
filterQuery.value.type = "";
|
||||
companyStore.locationsCurrentPage = 0;
|
||||
if(query.value === '' || companyStore.locationType.value !== 'all'){
|
||||
getInitData(true);
|
||||
} else {
|
||||
query.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
const clearRequest = () => {
|
||||
filterQuery.value.page = "page=" + 0;
|
||||
filterQuery.value.limit = "elements="+ limit;
|
||||
}
|
||||
|
||||
const handleSetCurrentLocation = (location) => {
|
||||
openModal.value = true;
|
||||
locationCurrent.value = location;
|
||||
}
|
||||
|
||||
const handleResetCurrentBudget = () => {
|
||||
openModal.value = false;
|
||||
locationCurrent.value = null;
|
||||
}
|
||||
|
||||
const selectedType = async(type) => {
|
||||
companyStore.locationType = type
|
||||
let value = type.value;
|
||||
openPopup.value = false
|
||||
filterQuery.value.limit = "elements=" + limit;
|
||||
companyStore.locationsCurrentPage = 0;
|
||||
filterQuery.value.page = "page=" + 0;
|
||||
filterQuery.value.type = "type=" + value;
|
||||
await getLocationsWithFilters(filterQuery.value);
|
||||
}
|
||||
|
||||
const closePopup = () => {
|
||||
openPopup.value = false
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="openPopup"
|
||||
>
|
||||
<CustomPopup
|
||||
:options="optionsFilter"
|
||||
:value="companyStore.locationType"
|
||||
@change-value="selectedType"
|
||||
@close-popup="closePopup"
|
||||
selected-color="#e3a11e"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<CreateLocationModal
|
||||
v-if="openModal === true"
|
||||
:location="locationCurrent"
|
||||
@reset-location="handleResetCurrentBudget"
|
||||
/>
|
||||
<h2 class="title">{{ t('global.directory') }}</h2>
|
||||
<div class="box-filters">
|
||||
<div class="box-search">
|
||||
<input class="form-control custom-search" type="search" name="" :placeholder="t('directory.querySearch')" id="" @:input="search()" v-model="query" aria-label="Search">
|
||||
</div>
|
||||
<div class="box-directory"
|
||||
@click="openPopup = true"
|
||||
>
|
||||
<span class="clear-sm" v-if="companyStore.locationType === null">{{ t('directory.directory') }}</span>
|
||||
<span class="clear-sm" v-else>{{companyStore.locationType.label}}</span>
|
||||
<i class="fa-solid fa-filter"></i>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-danger bg-dark" type="button" @click="clearFilter">
|
||||
<i class="fa-solid fa-arrow-rotate-right"></i>
|
||||
<span class="clear-sm"> Reset </span><span class="clear-md"> {{ t('labels.filters').toLocaleLowerCase() }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="btn-primary-sm radius-sm"
|
||||
data-toggle="modal" data-target="#locationFormModal"
|
||||
@click="handleSetCurrentLocation(null)"
|
||||
><i class="fa-solid fa-plus"></i> <span class="clear-sm"> {{ t('buttons.add') }}</span> <span class="clear-md"> {{ t('labels.location') }}</span></button>
|
||||
</div>
|
||||
<div v-if="loading" class="spiner-box">
|
||||
<Spiner/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<CardLocation
|
||||
v-if="companyStore.locations.length > 0"
|
||||
v-for="location in companyStore.locations"
|
||||
:key="location._id"
|
||||
:location="location"
|
||||
@set-location="handleSetCurrentLocation(location)"
|
||||
/>
|
||||
<CardEmpty v-else :text="t('directory.msgEmpty')"/>
|
||||
<Pagination
|
||||
:limit="limit"
|
||||
:total="companyStore.locationsTotal"
|
||||
:current-page="companyStore.locationsCurrentPage"
|
||||
@get-elements="getLocationsByPage"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box-filters {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: end;
|
||||
gap: 1rem;
|
||||
margin: 1.5rem 0px;
|
||||
}
|
||||
.box-filter-location {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.section-h4 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.box-custom {
|
||||
background-color: red!important;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.box-directory {
|
||||
padding: 12px 8px;
|
||||
background-color: #FFF;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border: 1px rgb(186, 175, 175) solid;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.box-search {
|
||||
// width: 50%;
|
||||
flex: 1;
|
||||
}
|
||||
.custom-search {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.box-search {
|
||||
width: 60%;
|
||||
}
|
||||
.box-filters {
|
||||
gap: .4rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
.box-search {
|
||||
width: 100%;
|
||||
}
|
||||
.box-filters {
|
||||
gap: .3rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
120
src/views/warehouses/components/CardLocation.vue
Normal file
120
src/views/warehouses/components/CardLocation.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<script setup>
|
||||
import Swal from 'sweetalert2';
|
||||
import { useCompanyStore } from '../../../stores/company';
|
||||
import { useAuthStore } from '../../../stores/auth';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const props = defineProps({
|
||||
location: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
defineEmits(['set-location'])
|
||||
|
||||
const companyStore = useCompanyStore();
|
||||
const authStore = useAuthStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
const handleDeleteLocation = async() => {
|
||||
Swal.fire({
|
||||
title: t('directory.titleDel'),
|
||||
text: t('directory.textDel'),
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonText: t('buttons.delete'),
|
||||
cancelButtonText: t('buttons.cancel'),
|
||||
}).then(async(result) => {
|
||||
if(result.isConfirmed) {
|
||||
Swal.fire({
|
||||
title: t('messages.loading'),
|
||||
html: t('directory.loadingDel') + '..',// add html attribute if you want or remove
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading()
|
||||
},
|
||||
});
|
||||
|
||||
const resp = await companyStore.deleteLocationCompany(props.location._id)
|
||||
|
||||
Swal.close();
|
||||
|
||||
if(resp != null) {
|
||||
Swal.fire({
|
||||
title: t('directory.msgTitleDel'),
|
||||
text: t('directory.msgDel'),
|
||||
icon: "success"
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: t('errors.msgTitleNotDel'),
|
||||
text: t('directory.msgNotDel'),
|
||||
icon: "error"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card-fixed card-location">
|
||||
<div>
|
||||
<p><span>{{ t('directory.name') }}:</span> {{location.branch_name}}</p>
|
||||
<p><span>{{ t('directory.address') }}:</span> <template v-if="location.address">{{location.address}}, </template><template v-if="location.zipcode">CP. {{location.zipcode}}, </template><template v-if="location.city">{{location.city}}, </template><template v-if="location.state">{{location.state}}</template></p>
|
||||
<p><span>{{ t('labels.phone') }}:</span> {{location.phone}}</p>
|
||||
<p><span>{{ t('directory.typeTruckNeed') }}:</span> {{location.truck_type?.map((e) => e).join(', ')}}</p>
|
||||
<p><span>{{ t('global.segments') }}:</span> {{location.categories?.map((e) => e.name).join(', ')}}</p>
|
||||
<p v-if="location.description"><span>{{ t('directory.additionalInfoLocation') }}:</span></p>
|
||||
<div v-if="location.description" class="box-note mb-4">
|
||||
{{ location.description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer" v-if="authStore.user?.job_role === 'owner' || authStore.user?.job_role === 'manager'">
|
||||
<button
|
||||
class="btn btn-dark radius-sm"
|
||||
@click="handleDeleteLocation"
|
||||
>
|
||||
<i class="fa-solid fa-trash" /> <span class="clear-xsm">{{ t('buttons.delete') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="btn-primary-sm radius-sm"
|
||||
@click="$emit('set-location')"
|
||||
data-toggle="modal" data-target="#locationFormModal"
|
||||
>
|
||||
<i class="fa-solid fa-pen-to-square" /> <span class="clear-xsm">{{ t('buttons.edit') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card-location {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.box-note {
|
||||
padding: 12px 16px;
|
||||
background-color: aqua;
|
||||
border-radius: 13px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
p span {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
341
src/views/warehouses/modals/CreateLocationModal.vue
Normal file
341
src/views/warehouses/modals/CreateLocationModal.vue
Normal file
@@ -0,0 +1,341 @@
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import CustomInput from '../../../components/ui/CustomInput.vue';
|
||||
import Segments from '../../../components/ui/Segments.vue';
|
||||
import TruckTypes from '../../../components/ui/TruckTypes.vue';
|
||||
import States from '../../../components/ui/States.vue';
|
||||
import Cities from '../../../components/ui/Cities.vue';
|
||||
import Spiner from '../../../components/ui/Spiner.vue';
|
||||
import { useAuthStore } from '../../../stores/auth';
|
||||
import { useCompanyStore } from '../../../stores/company';
|
||||
import Swal from 'sweetalert2';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { validateEmail } from '../../../helpers/validations';
|
||||
|
||||
const props = defineProps({
|
||||
location: {
|
||||
type: Object,
|
||||
required: false
|
||||
}
|
||||
});
|
||||
|
||||
defineEmits(['reset-location']);
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const companyStore = useCompanyStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
const loading = ref(false);
|
||||
const emails = ref([]);
|
||||
const emailInput = ref('');
|
||||
|
||||
const title = computed(() => {
|
||||
return (props.location) ? t('directory.editLocation') : t('directory.createLocation');
|
||||
});
|
||||
|
||||
const initState = {
|
||||
branch_name: "",
|
||||
phone: "",
|
||||
categories: [],
|
||||
city: "",
|
||||
state: "",
|
||||
location_type: "",
|
||||
truck_type: [],
|
||||
address: "",
|
||||
description: "",
|
||||
zipcode: ""
|
||||
}
|
||||
|
||||
const errors = ref({
|
||||
branch_name: null,
|
||||
address: null,
|
||||
city: null,
|
||||
state: null,
|
||||
location_type: null,
|
||||
zipcode: null
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if(props.location) {
|
||||
locationForm.branch_name = props.location.branch_name;
|
||||
locationForm.phone = props.location.phone;
|
||||
locationForm.categories = props.location.categories;
|
||||
locationForm.city = {
|
||||
city_name: props.location.city
|
||||
};
|
||||
locationForm.state = {
|
||||
state_name: props.location.state
|
||||
};
|
||||
locationForm.truck_type = props.location.truck_type?.map((e) => {
|
||||
return {
|
||||
meta_value: e
|
||||
}
|
||||
});
|
||||
locationForm.location_type = props.location.type;
|
||||
locationForm.zipcode = props.location.zipcode;
|
||||
locationForm.address = props.location.address;
|
||||
locationForm.description = props.location.description;
|
||||
locationForm.zipcode = props.location.zipcode;
|
||||
emails.value = props.location.alert_list || [];
|
||||
} else {
|
||||
Object.assign(locationForm, initState);
|
||||
}
|
||||
})
|
||||
|
||||
const locationForm = reactive({
|
||||
...initState
|
||||
});
|
||||
|
||||
const saveLocation = async() => {
|
||||
validations();
|
||||
if(errors.value.branch_name || errors.value.address || errors.value.city || errors.value.state || errors.value.zipcode || errors.value.location_type) {
|
||||
return;
|
||||
} else {
|
||||
|
||||
const branchData ={
|
||||
branch_name: locationForm.branch_name,
|
||||
phone: locationForm.phone,
|
||||
categories: locationForm.categories?.length <= 0 ? null : locationForm.categories?.map((e) => e._id),
|
||||
city: locationForm.city.city_name,
|
||||
state: locationForm.state.state_name,
|
||||
address: locationForm.address,
|
||||
truck_type: locationForm.truck_type?.length <= 0 ? null : locationForm.truck_type?.map((e) => e.meta_value),
|
||||
description: locationForm.description,
|
||||
company: authStore.user.company,
|
||||
type: locationForm.location_type,
|
||||
zipcode: locationForm.zipcode,
|
||||
alert_list: emails.value.length > 0 ? emails.value : null
|
||||
}
|
||||
|
||||
let result = 'error';
|
||||
let action = t('directory.msgLocationCreated');
|
||||
loading.value = true;
|
||||
|
||||
const localData = {
|
||||
categories: locationForm.categories,
|
||||
}
|
||||
|
||||
if(props.location !== null) {
|
||||
// Se actualiza
|
||||
result = await companyStore.updateLocationCompany(props.location._id, branchData, localData);
|
||||
action = t('directory.msgLocationUpdate');
|
||||
} else {
|
||||
// Se crea
|
||||
result = await companyStore.createLocationCompany(branchData, localData);
|
||||
action = t('directory.msgLocationCreated');
|
||||
}
|
||||
|
||||
loading.value = false;
|
||||
if(result === 'success') {
|
||||
document.getElementById('btnCloseLocationFormModal').click();
|
||||
Swal.fire({
|
||||
title: `<strong>${action}</strong>`,
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: result,
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const addObserver = () => {
|
||||
const trimmedEmail = emailInput.value.trim()
|
||||
|
||||
if (trimmedEmail && validateEmail(trimmedEmail)) {
|
||||
if(emails.value.includes(trimmedEmail)) {
|
||||
Swal.fire({
|
||||
title: t('errors.emailExist'),
|
||||
icon: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
emails.value.push(trimmedEmail)
|
||||
emailInput.value = ''
|
||||
} else if (trimmedEmail) {
|
||||
Swal.fire({
|
||||
title: t('errors.email'),
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const removeObserver = (email) => {
|
||||
emails.value = emails.value.filter((e) => e !== email)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const validations = () => {
|
||||
errors.value = {
|
||||
branch_name: locationForm.branch_name.length < 2 ? t('errors.nameRequired') : null,
|
||||
address: locationForm.address.length <= 4 ? t('errors.address') : null,
|
||||
city: locationForm.city.length <= 0 ? t('errors.city') : null,
|
||||
state: locationForm.state.length <= 0 ? t('errors.state') : null,
|
||||
location_type: locationForm.location_type.length <= 0 ? t('errors.directoryType') : null,
|
||||
zipcode: locationForm.zipcode.length < 5 ? t('errors.zipcode') : null,
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="modal fade" id="locationFormModal" tabindex="-1" role="dialog" aria-labelledby="locationFormModal" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="title mt-2 mb-3">{{ title }}</h2>
|
||||
<button
|
||||
id="btnCloseLocationFormModal"
|
||||
type="button"
|
||||
@click="$emit('reset-location')"
|
||||
class="close bg-white" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body form-content px-5">
|
||||
<form @submit.prevent="saveLocation" autocomplete="off" method="post" ref="formRef">
|
||||
<CustomInput
|
||||
:label="t('directory.name') + '*'"
|
||||
name="name"
|
||||
v-model:field="locationForm.branch_name"
|
||||
:filled="false"
|
||||
:error="errors.branch_name"
|
||||
/>
|
||||
<CustomInput
|
||||
:label="t('directory.address') + '*'"
|
||||
name="address"
|
||||
v-model:field="locationForm.address"
|
||||
:filled="false"
|
||||
:error="errors.address"
|
||||
/>
|
||||
<div class="mb-4 mt-3">
|
||||
<label class="custom-label required">{{ t('directory.state')}}*</label>
|
||||
<States
|
||||
v-model="locationForm.state"
|
||||
/>
|
||||
<span class="error-msg" v-if="errors.state">{{ errors.state }}</span>
|
||||
</div>
|
||||
<div class="mb-4 mt-3">
|
||||
<label class="custom-label required">{{ t('directory.city')}}*</label>
|
||||
<Cities
|
||||
v-model="locationForm.city"
|
||||
/>
|
||||
<span class="error-msg" v-if="errors.city">{{ errors.city }}</span>
|
||||
</div>
|
||||
<div class="d-flex flex-column mb-4">
|
||||
<label class="custom-label required" for="role">{{ t('directory.typeDirectory') + '*'}}</label>
|
||||
<select
|
||||
class="custom-input-light"
|
||||
name="type"
|
||||
id="type"
|
||||
v-model="locationForm.location_type"
|
||||
>
|
||||
<option disabled value="">-- {{ t('labels.select')}} --</option>
|
||||
<!-- <option value="owner">Dueño</option> -->
|
||||
<option value="loading">{{ t('labels.load')}}</option>
|
||||
<option value="unloading">{{ t('labels.download')}}</option>
|
||||
<option value="both">{{ t('labels.both')}}</option>
|
||||
</select>
|
||||
<span class="error-msg" v-if="errors.location_type">{{ errors.location_type }}</span>
|
||||
</div>
|
||||
<CustomInput
|
||||
:label="t('directory.zipCode') + '*'"
|
||||
name="zipcode"
|
||||
type="number"
|
||||
:step="1"
|
||||
v-model:field="locationForm.zipcode"
|
||||
:filled="false"
|
||||
:error="errors.zipcode"
|
||||
/>
|
||||
<CustomInput
|
||||
:label="t('labels.phone')"
|
||||
name="phone"
|
||||
type="number"
|
||||
v-model:field="locationForm.phone"
|
||||
:filled="false"
|
||||
/>
|
||||
<div class="mb-4 mt-3">
|
||||
<label class="custom-label">{{ t('global.segments') }}</label>
|
||||
<Segments
|
||||
v-model="locationForm.categories"
|
||||
:multiple="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-4 mt-3">
|
||||
<label class="custom-label">{{ t('directory.typeTruck') }}</label>
|
||||
<TruckTypes
|
||||
v-model="locationForm.truck_type"
|
||||
:multiple="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
<label class="custom-label" for="description">{{ t('directory.additionalInfoLocation') }}</label>
|
||||
<textarea
|
||||
class="custom-input-light"
|
||||
name="description"
|
||||
id="description"
|
||||
placeholder="Escribe aqui..."
|
||||
v-model="locationForm.description"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="divider mt-4"></div>
|
||||
<div class="box-observers mt-4">
|
||||
<div class="box-input">
|
||||
<div class="input-observer">
|
||||
<CustomInput
|
||||
label="Agregar correo de bodega"
|
||||
name="email"
|
||||
type="email"
|
||||
v-model:field="emailInput"
|
||||
:filled="false"
|
||||
:tooltip="t('messages.observerWarehouse')"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="addObserver"
|
||||
class="btn-leading-input mb-4"
|
||||
>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
<h5 v-if="emails.length > 0">Lista correos de usuarios de bodega:</h5>
|
||||
<div class="box-emails" v-if="emails.length > 0">
|
||||
<div
|
||||
v-for="(email, index) in emails"
|
||||
:key="email"
|
||||
class="observer-email"
|
||||
>
|
||||
<span>{{ email }}</span>
|
||||
<i
|
||||
@click="removeObserver(email)"
|
||||
class="fa-solid fa-xmark icon-delete">
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 text-center">
|
||||
<Spiner v-if="loading"/>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-dark" type="submit">{{ t('buttons.save') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-dark"
|
||||
@click="$emit('reset-location')"
|
||||
data-dismiss="modal">{{ t('buttons.close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user