Files
WebETA/src/components/CreateLocationModal.vue
2025-06-05 20:36:15 -06:00

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">&times;</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>