341 lines
14 KiB
Vue
341 lines
14 KiB
Vue
<script setup>
|
|
import { computed, onMounted, reactive, ref } from 'vue';
|
|
import CustomInput from './ui/CustomInput.vue';
|
|
import Segments from './ui/Segments.vue';
|
|
import TruckTypes from './ui/TruckTypes.vue';
|
|
import States from './ui/States.vue';
|
|
import Cities from './ui/Cities.vue';
|
|
import Spiner from './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> |