add: finish translation feature

This commit is contained in:
Alexandro Uc Santos
2024-06-08 17:26:02 -06:00
parent b32b2c310c
commit bb30443faa
15 changed files with 269 additions and 133 deletions

View File

@@ -1,10 +1,11 @@
<script setup>
import Swal from 'sweetalert2';
import { getDateMonthDay } from '../helpers/date_formats';
import { getDateMonthDay } from '../helpers/date_formats';
import { getStatusLoad } from '../helpers/status';
import { useCompanyStore } from '../stores/company';
import { useAuthStore } from '../stores/auth';
import { useAuthStore } from '../stores/auth';
import { useI18n } from 'vue-i18n';
const props = defineProps({
proposal: {
type: Object,
@@ -12,24 +13,27 @@ import { useAuthStore } from '../stores/auth';
}
})
console.log(props.proposal)
const companyStore = useCompanyStore();
const authStore = useAuthStore();
const { t, locale } = useI18n();
const handleWithdrawnProposal = async() => {
Swal.fire({
title: 'Retirar oferta!',
text: '¿Estás seguro de retirar esta oferta?',
title: t('proposals.titleRetireModal'),
text: t('proposals.textRetireModal'),
icon: 'warning',
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonText: 'Si, Retirar',
confirmButtonText: t('proposals.confirmRetire'),
cancelButtonText: 'No',
}).then(async(result) => {
if(result.isConfirmed) {
Swal.fire({
title: 'Por favor espere!',
html: 'Retirando oferta...',// add html attribute if you want or remove
title: t('messages.loading'),
html: t('proposals.loadingRetired') + '...',// add html attribute if you want or remove
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading()
@@ -51,14 +55,14 @@ import { useAuthStore } from '../stores/auth';
if(resp != null) {
Swal.fire({
title: "Oferta retirada!",
text: "Tu oferta ha sido retirada exitosamente.",
title: t('proposals.msgTitleRetire'),
text: t('proposals.msgCancel'),
icon: "success"
});
} else {
Swal.fire({
title: "Oferta no retirada!",
text: "Tu oferta no se pudo retirar, intente más tarde.",
title: "Error",
text: t('proposals.msgNotCancel'),
icon: "error"
});
}
@@ -75,26 +79,26 @@ import { useAuthStore } from '../stores/auth';
<br>
<div class="box-proposal">
<div class="">
<p v-if="proposal.vehicle"><span>Código:</span> {{proposal.vehicle.vehicle_code}}</p>
<p v-if="proposal.vehicle"><span>Segmento:</span> {{proposal._categories}}</p>
<p v-if="proposal.vehicle"><span>Tipo de transporte:</span> {{proposal.vehicle.truck_type}}</p>
<p v-if="proposal.vehicle"><span>Fecha de publicación:</span> {{ getDateMonthDay(proposal.vehicle.published_date) }}</p>
<p v-if="proposal.vehicle"><span>Fecha dispobible:</span> {{ getDateMonthDay(proposal.vehicle.available_date) }}</p>
<p v-if="proposal.vehicle"><span>Disponible en:</span> {{proposal.vehicle.city}}<template v-if="proposal.vehicle.state">, {{proposal.vehicle.state}}</template></p>
<p v-if="proposal.vehicle"><span>Destino:</span> {{proposal.vehicle.destino}}</p>
<p v-if="proposal.vehicle"><span>Placas remolque 1:</span> {{proposal.vehicle.trailer_plate_1}}</p>
<p v-if="proposal.vehicle"><span>Placas remolque 2:</span> {{proposal.vehicle.trailer_plate_2}}</p>
<p v-if="proposal.vehicle" :style="{color: getStatusLoad(proposal.load).color}"><span>Status de la carga:</span> {{ getStatusLoad(proposal.load).status }}</p>
<p v-if="proposal.vehicle"><span>{{ t('labels.codeId') }}:</span> {{proposal.vehicle.vehicle_code}}</p>
<p v-if="proposal.vehicle"><span>{{ t('global.segment') }}:</span> {{proposal.load.categories?.map((e) => e.name).join(', ')}}</p>
<p v-if="proposal.vehicle"><span>{{ t('directory.typeTruck') }}:</span> {{proposal.vehicle.truck_type}}</p>
<p v-if="proposal.vehicle"><span>{{ t('labels.datePublished') }}:</span> {{ getDateMonthDay(proposal.vehicle.published_date) }}</p>
<p v-if="proposal.vehicle"><span>{{ t('labels.dateAvailable') }}:</span> {{ getDateMonthDay(proposal.vehicle.available_date) }}</p>
<p v-if="proposal.vehicle"><span>{{ t('vehicles.availableIn') }}:</span> {{proposal.vehicle.city}}<template v-if="proposal.vehicle.state">, {{proposal.vehicle.state}}</template></p>
<p v-if="proposal.vehicle"><span>{{ t('loads.destination') }}:</span> {{proposal.vehicle.destino}}</p>
<p v-if="proposal.vehicle"><span>{{ t('vehicles.trailerPlates') }} 1:</span> {{proposal.vehicle.trailer_plate_1}}</p>
<p v-if="proposal.vehicle"><span>{{ t('vehicles.trailerPlates') }} 2:</span> {{proposal.vehicle.trailer_plate_2}}</p>
<p v-if="proposal.vehicle" :style="{color: getStatusLoad(proposal.load, locale).color}"><span>{{ t('loads.loadStatus') }}:</span> {{ getStatusLoad(proposal.load, locale).status}}</p>
</div>
<div class="">
<p v-if="proposal.load"> Código de carga:
<p v-if="proposal.load"> {{ t('loads.loadCode') }}:
<span
class="code-enruta"
@click="$emit('set-proposal', {proposal: proposal, modal: 'detail'})"
data-toggle="modal" data-target="#loadDetailModal"
>{{proposal.load.shipment_code}}</span></p>
<p v-if="proposal._driver">Operator: {{proposal._driver}}</p>
<p v-if="proposal._driver">{{ t('labels.operator') }}: {{proposal._driver}}</p>
</div>
</div>
<div class="btn-row">
@@ -104,7 +108,7 @@ import { useAuthStore } from '../stores/auth';
><i class="fa-solid fa-ban"></i> Retirar</button> -->
<div v-if="proposal.is_withdrawn" class="indicator-cancel">
<i class="fa-solid fa-ban"></i>
Retirado
{{ t('proposals.retired') }}
</div>
<button
v-else
@@ -114,14 +118,14 @@ import { useAuthStore } from '../stores/auth';
@click="handleWithdrawnProposal"
>
<i class="fa-solid fa-ban"></i>
Retirar
{{ t('proposals.withdraw') }}
</button>
<button
v-if="authStore.user?.job_role === 'owner' || authStore.user?.job_role === 'manager'"
class="btn-primary-sm radius-sm"
@click="$emit('set-proposal', {proposal: proposal, modal: 'edit'})"
data-toggle="modal" data-target="#makeProposalModal"
><i class="fa-solid fa-pen-to-square"></i> Editar</button>
><i class="fa-solid fa-pen-to-square"></i> {{ t('buttons.edit') }}</button>
</div>
</div>
</template>

View File

@@ -21,8 +21,8 @@
const handleDeleteVehicle = async() => {
Swal.fire({
title: `Eliminar vehiculo "${props.vehicle.vehicle_code}""`,
text: '¿Estás seguro de eliminar este vehiculo?',
title: `${t('vehicles.titleDel')} "${props.vehicle.vehicle_code}""`,
text: t('vehicles.textDel'),
icon: 'warning',
showCancelButton: true,
cancelButtonColor: "#d33",
@@ -32,7 +32,7 @@
if(result.isConfirmed) {
Swal.fire({
title: t('messages.loading'),
html: 'Eliminando vehiculo...',// add html attribute if you want or remove
html: t('vehicles.loadingDel') + '...',// add html attribute if you want or remove
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading()
@@ -43,14 +43,14 @@
if(resp != null) {
Swal.fire({
title: "vehiculo eliminado!",
text: "Tu vehiculo ha sido eliminado exitosamente.",
title: t('vehicles.msgTitleDel'),
text: t('vehicles.msgDel'),
icon: "success"
});
} else {
Swal.fire({
title: "Error!",
text: "Tu vehiculo no se pudo eliminar, intente más tarde.",
text: t('vehicles.msgNotDel'),
icon: "error"
});
}

View File

@@ -9,6 +9,7 @@
import Spiner from './ui/Spiner.vue';
import Swal from 'sweetalert2';
import { useVehiclesStore } from '../stores/vehicles';
import { useI18n } from 'vue-i18n';
const props = defineProps({
vehicle: {
@@ -17,8 +18,6 @@
}
});
console.log(props.vehicle);
defineEmits(['reset-vehicle']);
const initState = {
@@ -70,9 +69,11 @@
const loading = ref(false);
const title = computed(() => {
return (props.vehicle) ? 'Editar vehiculo' : 'Agregar vehiculo';
return (props.vehicle) ? t('vehicles.modalEdit') : t('vehicles.addVehicle');
});
const { t } = useI18n()
const handleSaveVehicle = async() => {
validations();
@@ -94,20 +95,20 @@
};
let localData = {};
let result = 'error';
let action = 'Creado';
let action = t('vehicles.msgVehicleCreated');
loading.value = true;
if(props.vehicle) {
localData = {
categories: vehicleForm.categories,
driver: props.vehicle.driver
};
action = 'actualizado';
action = t('vehicles.msgVehicleUpdate');
result = await vehicleStore.updateVehicleCompany(props.vehicle._id, vehicleData, localData);
} else {
localData = {
categories: vehicleForm.categories
}
action = 'añadido';
action = t('vehicles.msgVehicleCreated');
result = await vehicleStore.createVehicleCompany(vehicleData, localData);
}
@@ -115,7 +116,7 @@
if(result === 'success') {
document.getElementById('btnClosecreateVehicleModal').click();
Swal.fire({
title: `<strong>Vehiculo ${action} con éxito!</strong>`,
title: action,
icon: 'success'
})
} else {
@@ -128,12 +129,12 @@
const validations = () => {
errors.value = {
truck_type: (!vehicleForm.truck_type) ? 'Seleccione tipo de transporte' : null,
categories: (!vehicleForm.categories) ? 'Seleccione al menos un segmento' : null,
vehicle_number: (!vehicleForm.vehicle_number) ? 'Campo es requerido' : null,
state: (!vehicleForm.state) ? 'Seleccione estado' : null,
city: (!vehicleForm.city) ? 'Seleccione municipio' : null,
destino: (!vehicleForm.destino) ? 'Ingrese destino' : null,
truck_type: (!vehicleForm.truck_type) ? t('errors.truck') : null,
categories: (!vehicleForm.categories) ? t('errors.segments') : null,
vehicle_number: (!vehicleForm.vehicle_number) ? t('errors.required') : null,
state: (!vehicleForm.state) ? t('errors.state') : null,
city: (!vehicleForm.city) ? t('errors.city') : null,
destino: (!vehicleForm.destino) ? t('errors.destination') : null,
};
}
</script>
@@ -156,14 +157,14 @@
<form @submit.prevent="handleSaveVehicle" autocomplete="off" class="vehicle-form">
<div class="row mt-4">
<div class="col-lg-6 col-12">
<label class="custom-label">Tipo de Transporte*</label>
<label class="custom-label">{{ t('directory.typeTruck') }}*</label>
<TruckTypes
v-model="vehicleForm.truck_type"
/>
<span class="error-msg" v-if="errors.truck_type">{{ errors.truck_type }}</span>
</div>
<div class="col-lg-6 col-12">
<label class="custom-label">Segmento del transporte*</label>
<label class="custom-label">{{ t('vehicles.segments') }}*</label>
<Segments
v-model="vehicleForm.categories"
:multiple="true"
@@ -174,7 +175,7 @@
<div class="row mt-4">
<div class="col-lg-6 col-12">
<CustomInput
label="Número de Serie*"
:label="t('vehicles.serialNumber') + '*'"
name="vehicle_number"
v-model:field="vehicleForm.vehicle_number"
:filled="false"
@@ -183,7 +184,7 @@
</div>
<div class="col-lg-6 col-12">
<CustomInput
label="Placas Tracto Camión"
:label="t('vehicles.truckPlates')"
name="circulation_serial_number"
v-model:field="vehicleForm.circulation_serial_number"
:filled="false"
@@ -193,7 +194,7 @@
<div class="row">
<div class="col-lg-6 col-12">
<CustomInput
label="Placas Remolque 1"
:label="t('vehicles.trailerPlates') + ' 1'"
name="trailer_plate_1"
v-model:field="vehicleForm.trailer_plate_1"
:filled="false"
@@ -201,7 +202,7 @@
</div>
<div class="col-lg-6 col-12">
<CustomInput
label="Placas Remolque 1"
:label="t('vehicles.trailerPlates') + ' 2'"
name="trailer_plate_2"
v-model:field="vehicleForm.trailer_plate_2"
:filled="false"
@@ -210,14 +211,14 @@
</div>
<div class="row">
<div class="col-lg-6 col-12">
<label class="custom-label">Base de carga por Estado*</label>
<label class="custom-label">{{ t('labels.stateBase') }}*</label>
<States
v-model="vehicleForm.state"
/>
<span class="error-msg" v-if="errors.state">{{ errors.state }}</span>
</div>
<div class="col-lg-6 col-12">
<label class="custom-label">Base de Carga por Municipio*</label>
<label class="custom-label">{{ t('labels.cityBase') }}*</label>
<Cities
v-model="vehicleForm.city"
/>
@@ -226,7 +227,7 @@
</div>
<div class="col-lg-6 col-12 mt-4">
<CustomInput
label="Destino*"
:label="t('loads.destination') + '*'"
type="text"
:filled="false"
name="destino"
@@ -235,12 +236,12 @@
/>
</div>
<div class="d-flex flex-column mt-4">
<label class="custom-label" for="notes">Información Adicional del Transporte:</label>
<label class="custom-label" for="notes">{{ t('vehicles.additionalInfoVehicle') }}:</label>
<textarea
class="custom-input-light"
name="notes"
id="notes"
placeholder="Escribe aqui..."
:placeholder=" t('labels.writeHere') + '...'"
v-model="vehicleForm.notes"
></textarea>
</div>
@@ -248,7 +249,7 @@
<Spiner v-if="loading"/>
<button
v-else
class="btn-primary-sm radius-sm" type="submit">Guardar</button>
class="btn-primary-sm radius-sm" type="submit">{{ t('buttons.save') }}</button>
</div>
</form>
</div>

View File

@@ -4,6 +4,7 @@
import Spiner from './ui/Spiner.vue';
import { useVehiclesStore } from '../stores/vehicles';
import Swal from 'sweetalert2';
import { useI18n } from 'vue-i18n';
const props = defineProps({
vehicle: {
@@ -17,6 +18,8 @@
const companyStore = useCompanyStore();
const vehicleStore = useVehiclesStore();
const { t } = useI18n()
const driverSelected = ref(null);
const drivers = ref([]);
const error = ref(null)
@@ -32,7 +35,7 @@
const handleSetDriver = async() => {
if(driverSelected.value === null) {
error.value = 'Seleccione un conductor';
error.value = t('errors.driver');
return
}
@@ -63,7 +66,7 @@
if(result2 === 'success' ){
document.getElementById('btnCloseeditDriverVehicle').click();
Swal.fire({
title: `<strong>Driver asignado con éxito!</strong>`,
title: `<strong>${t('vehicles.msgAssigedDriver')}</strong>`,
icon: 'success'
});
} else {
@@ -93,7 +96,7 @@
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="title mt-2 mb-3">Cambiar conductor</h2>
<h2 class="title mt-2 mb-3">{{ t('vehicles.changeDriver') }}</h2>
<button
id="btnCloseeditDriverVehicle"
type="button"
@@ -107,17 +110,17 @@
</div>
<div class="modal-body view-proposals">
<div class="custom-selected-field">
<label class="custom-label my-2" for="driver">Conductor asignado:</label>
<label class="custom-label my-2" for="driver">{{ t('vehicles.assignedDriver') }}:</label>
<select
class="custom-input-light"
name="driver"
id="driver"
v-model="driverSelected"
>
<option disabled value="">-- Seleccionar conductor --</option>
<option disabled value="">-- {{ t('vehicles.selectDriver') }} --</option>
<option v-for="driver in drivers" :value="driver">{{driver.first_name}} {{ driver.last_name }}</option>
</select>
<span class="error-msg" v-if="error">{{ error }}</span>
<span class="error-msg mt-2" v-if="error">{{ error }}</span>
</div>
</div>
<div class="modal-footer">
@@ -128,12 +131,12 @@
class="btn btn-dark radius-sm"
data-dismiss="modal"
@click="$emit('reset-vehicle')"
>Cancelar</button>
>{{ t('buttons.cancel') }}</button>
<button
class="btn-primary-sm radius-sm"
@click="handleSetDriver"
>
<span class="clear-xsm">Guardar</span>
<span class="clear-xsm">{{ t('buttons.save') }}</span>
</button>
</div>
</div>

View File

@@ -79,12 +79,10 @@ const closePopup = () => {
<img src="/images/logo-eta.png" class="logo" alt="Eta Viaporte" >
</RouterLink>
<div class="box-register">
<p class="title-header">Tablero de <span class="title-main">Embarques</span> y <span class="title-main">Transportes</span></p>
<p class="title-header">Tablero de <span class="title-main">Embarques</span> y <span class="title-main">Transportes</span></p>
</div>
<a @click="openPopup = true" class="lang"><i class="fa-solid fa-globe"></i> {{ locale }}</a>
</div>
<a
@click="openPopup = true"
class="lang"><i class="fa-solid fa-globe"></i> {{ locale }}</a>
</div>
</template>
@@ -108,10 +106,13 @@ const closePopup = () => {
display: flex;
align-items: center;
align-content: center;
width: 100%;
/* width: 65%; */
}
.box-register{
margin-left: 24px;
display: flex;
flex: 1;
}
.title-header{
font-size: 1.8rem;
@@ -180,7 +181,7 @@ const closePopup = () => {
}
@media (max-width: 568px) {
.logo{
height: 80px;
height: 60px;
}
.title-header{
font-size: 1rem;

View File

@@ -6,7 +6,8 @@
import useDirectionsRender from '../composables/useDirectionRender';
import Cardload from './CardLoad.vue';
import { useLoadsStore } from '../stores/loads';
import { useNotificationsStore } from '../stores/notifications';
import { useNotificationsStore } from '../stores/notifications';
import { useI18n } from 'vue-i18n';
const mapKey = import.meta.env.VITE_MAP_KEY;
@@ -22,6 +23,7 @@ import { useNotificationsStore } from '../stores/notifications';
const isLoadActive = ref(false);
const { getDirections, geocodeAddress } = useDirectionsRender()
const { t } = useI18n();
const props = defineProps({
proposal: {
@@ -59,7 +61,7 @@ import { useNotificationsStore } from '../stores/notifications';
if(addressOrigin.lat && addressOrigin.lng) {
originCoords.value = {lat: Number.parseFloat(addressOrigin.lat), lng: Number.parseFloat(addressOrigin.lng)};
} else {
console.log('No hay coords origin')
// console.log('No hay coords origin')
let startLocation = addressOrigin.street_address1 + ', ' + addressOrigin.city + ', ' + addressOrigin.state + ', ' + addressOrigin.country + ', ' +addressOrigin.zipcode;
originCoords.value = await geocodeAddress(startLocation);
}
@@ -67,7 +69,7 @@ import { useNotificationsStore } from '../stores/notifications';
if(addressDestination.lat && addressDestination.lng) {
destinationCoords.value = {lat: Number.parseFloat(addressDestination.lat), lng: Number.parseFloat(addressDestination.lng)};
} else {
console.log('No hay coords destinatiom')
// console.log('No hay coords destinatiom')
let endLocation = addressDestination.street_address1 + ', ' + addressDestination.city + ', ' + addressDestination.state + ', ' + addressDestination.country + ', ' +addressDestination.zipcode;
destinationCoords.value = await geocodeAddress(endLocation);
}
@@ -100,7 +102,7 @@ import { useNotificationsStore } from '../stores/notifications';
}
} catch (error) {
notyStore.$patch({
text : 'No se pudo cargar mapa',
text : t('errors.map'),
show : true,
error: true
});
@@ -128,7 +130,7 @@ import { useNotificationsStore } from '../stores/notifications';
<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">Detalles de carga</h2>
<h2 class="title mt-2 mb-3">{{ t('loads.loadDetails') }}</h2>
<button
id="btnCloseloadDetailModal"
type="button"
@@ -186,7 +188,7 @@ import { useNotificationsStore } from '../stores/notifications';
/>
</GoogleMap>
</div>
<CardEmpty v-else text="No hay información disponible"/>
<CardEmpty v-else :text="t('loads.noInfo')"/>
</div>
</div>
<div class="modal-footer">
@@ -195,7 +197,7 @@ import { useNotificationsStore } from '../stores/notifications';
class="btn btn-dark"
data-dismiss="modal"
@click="$emit('reset-proposal')"
>Cerrar</button>
>{{ t('buttons.close') }}</button>
</div>
</div>
</div>

View File

@@ -10,6 +10,7 @@
import { useVehiclesStore } from '../stores/vehicles';
// import { saveProposal } from '../services/vehicles'
import Swal from 'sweetalert2';
import { useI18n } from 'vue-i18n';
const mapKey = import.meta.env.VITE_MAP_KEY;
@@ -46,6 +47,7 @@
defineEmits(['reset-load'])
const { t } = useI18n()
onMounted(() => {
window.addEventListener('resize', handleResize);
@@ -86,13 +88,13 @@
const handleSumit = async() => {
if(form.vehicle === ""){
msgError.value = 'Selecciona vehiculo para continuar';
msgError.value = t('errors.vehicle');
setTimeout(() => {
msgError.value = '';
}, 5000);
return;
} else if (form.comments.trim().length <= 0) {
msgError.value = 'Agrega un comentario';
msgError.value = t('errors.comment');
setTimeout(() => {
msgError.value = '';
}, 5000);
@@ -111,7 +113,7 @@
load : props.load._id
}
loadingSubmit.value = true;
action = 'creada';
action = t('proposals.msgOffertDone');
result = await companyStore.createPropsal(formData);
} else {
let formData = {
@@ -127,14 +129,14 @@
_driver: vehicleSelected?.driver.first_name + ' ' + vehicleSelected?.driver.last_name
}
loadingSubmit.value = true;
action = 'actualizada'
action = t('proposals.msgOffertUpdate')
result = await companyStore.updatePropsalLoad(props.proposal._id, formData, localData);
}
if(result === 'success') {
document.getElementById('btnClosemakeProposalModal').click();
Swal.fire({
title: `<strong>Oferta ${action} con éxito!</strong>`,
title: `<strong>${action}</strong>`,
icon: 'success'
})
} else {
@@ -146,8 +148,8 @@
loadingSubmit.value = false;
}
const title = computed(() => (props.proposal) ? 'Modificar oferta' : 'Realizar oferta');
const btnSubmit = computed(() => (props.proposal) ? 'Guardar' : 'Enviar');
const title = computed(() => (props.proposal) ? t('proposals.modOffer') : t('proposals.makeOffer'));
const btnSubmit = computed(() => (props.proposal) ? t('buttons.save') : t('buttons.send'));
</script>
<template>
@@ -174,19 +176,19 @@
<form @submit.prevent="handleSumit" class="box-form mb-4">
<BadgeError :msg="msgError"/>
<div class="custom-selected-field">
<label class="custom-label" for="vehicle">Vehiculo:</label>
<label class="custom-label" for="vehicle">{{ t('labels.vehicle') }}:</label>
<select
class="custom-input-light"
name="vehicle"
id="vehicle"
v-model="form.vehicle"
>
<option disabled value="">-- Seleccionar vehículo --</option>
<option disabled value="">-- {{ t('proposals.selectVehicle') }} --</option>
<option v-for="vehicle in vehiclesStore.vehicles" :value="vehicle._id">{{vehicle.vehicle_code}}</option>
</select>
</div>
<div class="custom-selected-field">
<label class="custom-label" for="comment">Comentario:</label>
<label class="custom-label" for="comment">{{ t('labels.comment') }}:</label>
<textarea
class="custom-input-light"
name="comment"
@@ -247,7 +249,7 @@
class="btn btn-dark"
data-dismiss="modal"
@click="$emit('reset-load')"
>Cerrar</button>
>{{ t('buttons.close') }}</button>
</div>
</div>
</div>

View File

@@ -7,6 +7,7 @@
import States from './ui/States.vue';
import Cities from './ui/Cities.vue';
import Swal from 'sweetalert2';
import { useI18n } from 'vue-i18n';
const props = defineProps({
vehicle: {
@@ -28,6 +29,8 @@
defineEmits(['reset-vehicle']);
const { t } = useI18n()
const formAvailiable = reactive({
available_date: new Date(),
destino: '',
@@ -43,9 +46,9 @@
const handleSetStatusVehicle = async() => {
let vehicleData;
console.log(statusSelected.value);
// console.log(statusSelected.value);
if(statusSelected.value === 'Availiable') {
console.log('check validations');
// console.log('check validations');
validations();
if(errors.value.city || errors.value.state || errors.value.destino ) return;
vehicleData = {
@@ -71,7 +74,7 @@
if(result === 'success') {
document.getElementById('btnCloseeditStatusVehicle').click();
Swal.fire({
title: `<strong>Status del vehiculo actualizado con éxito!</strong>`,
title: `<strong>${t('vehicles.msgStatusUpdate')}</strong>`,
icon: 'success'
})
} else {
@@ -84,9 +87,9 @@
const validations = () => {
errors.value = {
state: (!formAvailiable.state) ? 'Seleccione estado' : null,
city: (!formAvailiable.city) ? 'Seleccione municipio' : null,
destino: (!formAvailiable.destino) ? 'Ingrese destino' : null,
state: (!formAvailiable.state) ? t('errors.state') : null,
city: (!formAvailiable.city) ? t('errors.city') : null,
destino: (!formAvailiable.destino) ? t('errors.destination') : null,
};
}
@@ -97,7 +100,7 @@
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="title mt-2 mb-3">Cambiar status vehiculo</h2>
<h2 class="title mt-2 mb-3">{{ t('vehicles.changeStatus') }}</h2>
<button
id="btnCloseeditStatusVehicle"
type="button"
@@ -112,17 +115,17 @@
<div class="modal-body view-proposals">
<form @submit.prevent="handleSetStatusVehicle">
<div class="custom-selected-field">
<h4 class="custom-label my-3">Status del vehiculo</h4>
<h4 class="custom-label my-3">{{ t('vehicles.statusVehicle') }}</h4>
<div class="d-flex">
<CustomRadioInput
value="Booked"
label="Reservado"
:label="t('vehicles.reserved')"
:name="'status-vehicle' + vehicle._id"
v-model:typeselected="statusSelected"
/>
<CustomRadioInput
value="Availiable"
label="Disponible"
:label="t('vehicles.available')"
:name="'status-vehicle' + vehicle._id"
v-model:typeselected="statusSelected"
/>
@@ -130,28 +133,28 @@
</div>
<div v-if="statusSelected === 'Availiable'">
<CustomInput
label="Fecha de carga*"
:label="t('loads.dateLoad') + '*'"
type="date"
:filled="false"
name="date-load"
v-model:field="formAvailiable.available_date"
/>
<div class="mb-4 mt-3">
<label class="custom-label">Base de carga por Estado</label>
<label class="custom-label">{{ t('labels.stateBase') }}</label>
<States
v-model="formAvailiable.state"
/>
<span class="error-msg" v-if="errors.state">{{ errors.state }}</span>
</div>
<div class="mb-4 mt-3">
<label class="custom-label">Base de Carga por Municipio</label>
<label class="custom-label">{{ t('labels.cityBase') }}</label>
<Cities
v-model="formAvailiable.city"
/>
<span class="error-msg" v-if="errors.city">{{ errors.city }}</span>
</div>
<CustomInput
label="Destino*"
:label="t('loads.destination') + '*'"
type="text"
:filled="false"
name="destino"
@@ -166,7 +169,7 @@
class="btn-primary-sm radius-sm"
type="submit"
>
<span class="clear-xsm">Cuardar</span>
<span class="clear-xsm">{{ t('buttons.save') }}</span>
</button>
</div>
</form>

View File

@@ -18,13 +18,11 @@ export default function useSearchLoads() {
try {
const endpoint = `/v1/loads/find${filterStr}&$sort%5BcreatedAt%5D=-1`;
const {data} = await api.get(endpoint);
console.log(data);
total.value = data.total;
loads.value = data.data;
} catch (error) {
loads.value = [];
total.value = 0;
console.log(error);
}
loading.value = false;
}

View File

@@ -1,32 +1,34 @@
export const getStatusLoad = (load) => {
export const getStatusLoad = (load, locale = 'es') => {
let statusTemp;
let status;
let color;
switch (load.load_status) {
case 'Published':
status = "Publicado";
statusTemp = "Publicado";
color = "#000000";
break;
case 'Loading':
color = "#F44336";
status = "Cargando";
statusTemp = "Cargando";
break;
case 'Transit':
status = "En Transito";
statusTemp = "En Transito";
color = "#ffd22b"
break;
case 'Downloading':
status = "Descargando";
statusTemp = "Descargando";
color = "#428502"
break;
case 'Delivered':
status = "Entregado";
statusTemp = "Entregado";
color = "#000000";
break;
default:
status = 'Sin publicar';
statusTemp = 'Sin publicar';
color = "#000000";
break;
}
status = (locale === 'es') ? statusTemp : load.load_status;
return {
status,
color,

View File

@@ -51,6 +51,13 @@ const en = {
writeHere: 'Write here',
create: 'Create',
date: 'Date',
stateBase: 'Load base by state',
cityBase: 'Load base by city',
datePublished: 'Published date',
dateAvailable: 'Available date',
operator: 'Operator',
vehicle: 'Vehicle',
comment: 'Comment',
},
buttons: {
enter: "Enter here",
@@ -76,9 +83,11 @@ const en = {
accepted: 'Accepted',
confirm: 'Confirm',
search: 'Search',
profile: 'View profile'
profile: 'View profile',
send: 'Send'
},
errors: {
required: 'Field is required',
requireds: "All fields required",
email: "Email is not valid",
weakPassword: "Weak password",
@@ -105,7 +114,12 @@ const en = {
zipcode: 'Enter valid zip code',
date: 'Date is required',
weight: 'Weight is required',
notMatchEmails: 'Emails do not match'
notMatchEmails: 'Emails do not match',
driver: 'Select a driver',
destination: 'Enter destination',
map: 'Could not be loaded',
vehicle: 'Select a vehicle',
comment: 'Add comment',
},
messages: {
sendCode: 'We send you a code to the email, entered!',
@@ -277,7 +291,12 @@ const en = {
msgSave: 'Load saved!',
msgNotSave: '"Could not save upload, try later',
msgPost: 'Load posted!',
msgNotPost: 'Could not post load, please try later'
msgNotPost: 'Could not post load, please try later',
loadDetails: 'Load Details',
noInfo: '"No information available',
trackingLoad: 'Load tracking',
searchLoads: 'Search loads',
},
evidence: {
evidence: "Evidence",
@@ -301,10 +320,27 @@ const en = {
msgTitleCancel: 'Offer cancelled!',
msgCancel: 'The offer was successfully withdrawn.',
msgNotCancel: 'Could not withdraw offer, try later',
titleRetireModal: 'Withdraw offer',
textRetireModal: 'Are you sure to withdraw this offer?',
confirmRetire: 'Yes, Remove',
loadingRetired: 'Withdrawing offer',
msgTitleRetire: 'Offer withdrawn!',
title: 'My offers accepted',
retired: 'Retired',
withdraw: 'Withdraw',
modOffer: 'Modify offer',
makeOffer: 'Make offer',
msgOffertDone: 'Offer successfully completed',
msgOffertUpdate: 'Offer updated successfully',
selectVehicle: 'Select vehicle'
},
vehicles: {
title: 'Vehicles',
modalEdit: 'Edit vehicle',
addVehicle: 'Add vehicle',
search: 'Search vehicles',
infoVehicle: 'Vehicle information',
truckPlates: 'Truck Tract Plates',
@@ -317,7 +353,26 @@ const en = {
availableIn: 'Available in',
available: 'Available',
reserved: 'Reserved',
availableDate: 'Available date'
availableDate: 'Available date',
segments: 'Transportation segment',
titleDel: 'Delete vehicle',
textDel: 'Are you sure to delete this vehicle?',
loadingDel: 'Deleting vehicle',
msgTitleDel: 'Vehicle removed!',
msgDel: 'Your vehicle has been successfully deleted.',
msgNotDel: 'Your vehicle could not be deleted, try again later.',
changeDriver: 'Change driver',
assignedDriver: 'Assigned driver',
selectDriver: 'Select driver',
msgAssigedDriver: 'Driver assigned successfully!',
changeStatus: 'Change vehicle status',
statusVehicle: 'Vehicle status',
msgStatusUpdate: 'Vehicle status updated successfully!',
msgVehicleUpdate: '<strong>Vehicle updated successfully!</strong>',
msgVehicleCreated: '<strong>Vehicle added successfully!</strong>',
},
profile: {
profile: 'User data',
@@ -337,6 +392,10 @@ const en = {
searchByCarrier: 'Search by carrier',
empty: 'No records'
},
shippers: {
searchShipper: "Search by shipper",
empty: 'No uploads published'
},
calendar: {
title: 'Calendar',
helpText: 'Load status indicators'

View File

@@ -53,6 +53,13 @@ const es = {
writeHere: 'Escribe aqui',
create: 'Crear',
date: 'Fecha',
stateBase: 'Base de carga por Estado',
cityBase: 'Base de Carga por Municipio',
datePublished: 'Fecha de publicación',
dateAvailable: 'Fecha dispobible',
operator: 'Operador',
vehicle: 'Vehiculo',
comment: 'Comentario',
},
buttons: {
enter: "Ingresa aqui",
@@ -78,9 +85,11 @@ const es = {
accepted: 'Aceptado',
confirm: 'Confirmar',
search: 'Buscar',
profile: 'Ver perfil'
profile: 'Ver perfil',
send: 'Enviar',
},
errors: {
required: 'Campo es requerido',
requireds: 'Todos los campos con obligatorios',
email: 'Correo electrónico no es valido',
weakPassword: 'Contraseña poco segura',
@@ -107,7 +116,12 @@ const es = {
zipcode: 'Ingrese código postal valido',
date: 'Fecha es requerida',
weight: 'Peso es requerido',
notMatchEmails: 'Los correos electrónicos no coinciden'
notMatchEmails: 'Los correos electrónicos no coinciden',
driver: 'Seleccione un conductor',
destination: 'Ingrese destino',
map: "No se pudo cargar mapa",
vehicle: 'Selecciona un vehiculo',
comment: 'Agrega comentario',
},
messages: {
sendCode: 'Te enviamos un código al correo, ingresado!',
@@ -282,8 +296,13 @@ const es = {
msgSave: 'Carga guardada!',
msgNotSave: 'No se pudo guardar carga, intente más tarde',
msgPost: 'Carga publicada!',
msgNotPost: 'No se pudo publicar carga, intente más tarde'
msgNotPost: 'No se pudo publicar carga, intente más tarde',
loadDetails: 'Detalles de carga',
noInfo: '"No hay información disponible',
trackingLoad: 'Seguimiento de carga',
searchLoads: 'Buscar cargas',
},
evidence: {
evidence: "Evidencias",
@@ -307,10 +326,27 @@ const es = {
msgTitleCancel: 'Oferta cancelada!',
msgCancel: 'La oferta fue retirada exitosamente.',
msgNotCancel: 'No se pudo retirar oferta, intente más tarde',
titleRetireModal: 'Retirar oferta',
textRetireModal: '¿Estás seguro de retirar esta oferta?',
confirmRetire: 'Si, Retirar',
loadingRetired: 'Retirando oferta',
msgTitleRetire: 'Oferta retirada!',
title: 'Mis ofertas aceptadas',
retired: 'Retirado',
withdraw: 'Retirar',
modOffer: 'Modificar oferta',
makeOffer: 'Realizar oferta',
msgOffertDone: 'Oferta realizada con éxito',
msgOffertUpdate: 'Oferta actualizada con éxito',
selectVehicle: 'Seleccionaar vehículo'
},
vehicles: {
title: 'Vehiculos',
modalEdit: 'Editar vehiculo',
addVehicle: 'Agregar vehiculo',
search: 'Buscar vehiculos',
infoVehicle: 'Información del vehiculo',
truckPlates: 'Placas Tracto Camión',
@@ -324,13 +360,26 @@ const es = {
available: 'Disponible',
reserved: 'Reservado',
availableDate: 'Fecha disponible',
segments: 'Segmento del transporte',
titleDel: 'Eliminar Locación!',
textDel: '¿Estás seguro de eliminar este locación?',
loadingDel: 'Eliminando locación',
msgTitleDel: 'Locación eliminado!',
msgDel: 'Tu locación ha sido eliminado exitosamente.',
msgNotDel: 'Tu locación no se pudo eliminar, intente más tarde.',
titleDel: 'Eliminar vehiculo',
textDel: '¿Estás seguro de eliminar este vehiculo?',
loadingDel: 'Eliminando vehiculo',
msgTitleDel: 'Vehiculo eliminado!',
msgDel: 'Tu vehiculo ha sido eliminado exitosamente.',
msgNotDel: 'Tu vehiculo no se pudo eliminar, intente más tarde.',
changeDriver: 'Cambiar conductor',
assignedDriver: 'Conductor asignado',
selectDriver: 'Seleccionar conductor',
msgAssigedDriver: 'Conductor asignado con éxito!',
changeStatus: 'Cambiar status vehiculo',
statusVehicle: 'Estado del vehiculo',
msgStatusUpdate: 'Status del vehiculo actualizado con éxito!',
msgVehicleUpdate: '<strong>Vehiculo actualizado con éxito!</strong>',
msgVehicleCreated: '<strong>Vehiculo añadido con éxito!</strong>',
},
profile: {
profile: 'Datos de usuario',
@@ -350,6 +399,10 @@ const es = {
searchByCarrier: 'Buscar por transportista',
empty: 'No hay registros'
},
shippers: {
searchShipper: "Buscar por embarcador",
empty: 'No hay cargas publicadas'
},
calendar: {
title: 'Calendario',
helpText: 'Indicadores de estado de la carga'

View File

@@ -10,6 +10,7 @@
import Cities from '../components/ui/Cities.vue';
import MakeProposalModal from '../components/MakeProposalModal.vue';
import Pagination from '../components/Pagination.vue';
import { useI18n } from 'vue-i18n';
const filterQuery = ref([]);
const query = ref('');
@@ -25,6 +26,8 @@
getInitData();
});
const { t } = useI18n()
watch(query, () => {
isSearch.value = true;
setFilterUnlimited();
@@ -162,7 +165,7 @@
</script>
<template>
<h2 class="title mb-5">Buscar cargas</h2>
<h2 class="title mb-5">{{ t('loads.searchLoads') }}</h2>
<MakeProposalModal
v-if="currentLoad"
:load="currentLoad"
@@ -171,8 +174,8 @@
<div class="card-filters">
<div class="d-flex mb-2">
<input class="form-control me-2" type="search" name="" placeholder="Buscar embarcador" id="" @:input="search()" v-model="query" aria-label="Search">
<button class="btn btn-outline-dark me-2" type="button" @click="search">Buscar</button>
<input class="form-control me-2" type="search" name="" :placeholder="t('shippers.searchShipper')" id="" @:input="search()" v-model="query" aria-label="Search">
<button class="btn btn-outline-dark me-2" type="button" @click="search">{{ t('buttons.search') }}</button>
<button
class="btn btn-danger" type="button" @click="clearFilter">
<i class="fa-solid fa-arrow-rotate-right"></i>

View File

@@ -7,6 +7,7 @@
import { GoogleMap, Marker, CustomMarker, Polyline } from 'vue3-google-map';
import CardEmpty from '../components/CardEmpty.vue';
import useTrackingLoad from '../composables/useTrackingLoad';
import { useI18n } from 'vue-i18n';
const mapKey = import.meta.env.VITE_MAP_KEY;
@@ -31,6 +32,7 @@
initData();
});
const { t } = useI18n();
const initData = async() => {
const id = route.params['code'];
await getLoadTracking(id)
@@ -88,7 +90,7 @@
</script>
<template>
<h2 class="title text-center mt-5">Seguimiento de carga</h2>
<h2 class="title text-center mt-5">{{ t('loads.trackingLoad') }}</h2>
<Spiner v-if="loading"/>
<div v-else>
<div v-if="load">
@@ -137,7 +139,7 @@
/>
</GoogleMap>
</div>
<CardEmpty v-else text="No hay información disponible"/>
<CardEmpty v-else :text="t('loads.noInfo')"/>
</div>
</template>

View File

@@ -6,6 +6,7 @@
import LoadDetailModal from '../components/LoadDetailModal.vue';
import MakeProposalModal from '../components/MakeProposalModal.vue';
import Pagination from '../components/Pagination.vue';
import { useI18n } from 'vue-i18n';
const companyStore = useCompanyStore();
const loading = ref(false);
@@ -18,6 +19,8 @@
getInitData();
})
const { t } = useI18n();
const getInitData = async() => {
loading.value = true;
const filter = 'elements=' + limit + "&page=0";
@@ -46,7 +49,7 @@
openModal.value = false;
openModalProposal.value = false;
proposalCurrent.value = null;
console.log('clear proposal');
// console.log('clear proposal');
}
</script>
@@ -63,7 +66,7 @@
@reset-load="handleResetCurrentProposal"
/>
<div>
<h2 class="title mb-5">Mis ofertas aceptadas</h2>
<h2 class="title mb-5">{{ t('proposals.title') }}</h2>
<Spiner v-if="loading"/>
<CardProposal
v-else