add: translations of profile & proposals

This commit is contained in:
Alexandro Uc Santos
2024-06-01 17:17:34 -06:00
parent 2de6b5b4fd
commit 97f4f93fd3
14 changed files with 267 additions and 124 deletions

View File

@@ -3,6 +3,7 @@
import useAttachments from '../composables/useAttachments';
import Spiner from './ui/Spiner.vue';
import { useLoadsStore } from '../stores/loads';
import { useI18n } from 'vue-i18n';
const loadStore = useLoadsStore();
const { getAttachmentLoad, loading, attachments } = useAttachments();
@@ -11,7 +12,7 @@
console.log('se ejcyta attach');
getAttachmentLoad();
})
const { t } = useI18n();
const clearLoad = () => {
loadStore.openAttachmentsModal = false;
loadStore.currentLoad = null;
@@ -24,7 +25,7 @@
<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">Evidencias adjuntas</h2>
<h2 class="title mt-2 mb-3">{{ t('evidence.title') }}</h2>
<button
id="btnCloseAttachmentModal"
type="button"
@@ -39,12 +40,12 @@
<Spiner v-if="loading"/>
<div v-else>
<div v-if="!attachments || attachments.total == 0" class="card-body">
<p class="empty">No hay evidencias subidas</p>
<p class="empty">{{ t('evidence.empty') }}</p>
</div>
<div v-else class="card-body">
<div class="attachment" v-for="data in attachments.data">
<p v-if="data.type == 'Loading'">Evidencia de carga</p>
<p v-else>Evidencia de descarga</p>
<p v-if="data.type == 'Loading'">{{ t('evidence.loadEvidence') }}</p>
<p v-else>{{ t('evidence.downloadEvidence') }}</p>
<img
:src="`https://api.etaviaporte.com/api/v1/public-load-attachments/download/${data._id}`"
:alt="data.type"
@@ -58,7 +59,7 @@
type="button"
class="btn btn-dark"
@click="clearLoad"
data-dismiss="modal">Cerrar</button>
data-dismiss="modal">{{ t('buttons.close') }}</button>
</div>
</div>
</div>

View File

@@ -184,7 +184,7 @@
@click="openAttachmentsModal"
>
<i class="fa-solid fa-image"></i>
Evidencias
{{ t('evidence.evidence') }}
</button>
<button
v-if="(authStore.user?.job_role === 'owner' || authStore.user?.job_role === 'manager') || authStore.user._id === props.load.posted_by"

View File

@@ -8,6 +8,7 @@
import { useAuthStore } from '../stores/auth';
import { useNotificationsStore } from '../stores/notifications';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
const emailForm = reactive({
email: '',
@@ -21,6 +22,8 @@ import { useRouter } from 'vue-router';
const notifications = useNotificationsStore();
const router = useRouter();
const { t } = useI18n();
const hangleSave = () => {
msgError.value = '';
msgSuccess.value = '';
@@ -31,19 +34,19 @@ import { useRouter } from 'vue-router';
return;
} else {
Swal.fire({
title: '¿Estás seguro de cambiar el correo electrónico?',
title: t('profile.questionChangeEmail'),
// text: '',
html: '<span>Al confirmar esta acción, cerraremos tu sesión actual para actualizar tu correo electrónico. Serás redirigido a la página de inicio de sesión. Recuerda que tu contraseña se restablecerá. Necesitaras recuperarla, puedes hacerlo en la sección <span class="font-bold">¿Olvidaste tu contraseña?</span>.</span>',
html: t('profile.msgInfoEmail'),
icon: 'warning',
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonText: 'Confirmar',
cancelButtonText: 'Cancelar',
confirmButtonText: t('buttons.confirm'),
cancelButtonText: t('buttons.cancel'),
}).then( async(result) => {
if(result.isConfirmed) {
Swal.fire({
title: 'Por favor espere!',
html: 'Guardando cambios...',
title: t('messages.loading'),
html: t('messages.savingChanes') + '...',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading()
@@ -53,7 +56,7 @@ import { useRouter } from 'vue-router';
const userData = {
"email" : emailForm.email,
};
console.log(userData);
// console.log(userData);
loading.value = true;
const response = await auth.updateProfile(userData)
loading.value = false;
@@ -63,7 +66,7 @@ import { useRouter } from 'vue-router';
} else {
clearMessages();
notifications.$patch({
text : 'Correo electrónico se ha cambiando exitosamente!',
text : t('profile.msgChangeEmail'),
show : true,
error: false
});
@@ -80,11 +83,11 @@ import { useRouter } from 'vue-router';
const validations = () => {
if(emailForm.email.trim() == '') {
return 'Todos los campos con obligatorios';
return t('errors.requireds');
} else if (!validateEmail(emailForm.email)) {
return 'Correo electrónico no es valido'
return t('errors.email')
} else if (emailForm.email !== emailForm.email2) {
return 'Los correos electrónico no coinciden'
return t('errors.notMatchEmails')
} else {
return '';
}
@@ -106,19 +109,19 @@ import { useRouter } from 'vue-router';
ref="formRef1"
>
<br/>
<h3 class="title">Cambiar correo electrónico</h3>
<h3 class="title">{{ t('profile.titleFormEmail') }}</h3>
<br/>
<NotificationBadge :msg="msgError" v-if="msgError != ''"/>
<NotificationBadge :msg="msgSuccess" v-if="msgSuccess != ''" :is-error="false"/>
<CustomInput
label=" Nuevo Correo electrónico*:"
:label="t('profile.newEmail') + '*:'"
type="email"
name="email"
:filled="false"
v-model:field="emailForm.email"
/>
<CustomInput
label="Confirmar Correo electrónico*:"
:label="t('profile.confirmEmail') + '*:'"
type="email"
name="email2"
:step="1"
@@ -129,13 +132,13 @@ import { useRouter } from 'vue-router';
<div>
<i class="fa-solid fa-triangle-exclamation warning"></i>
</div>
<span>Al confirmar esta acción, cerraremos tu sesión actual para actualizar tu correo electrónico. Serás redirigido a la página de inicio de sesión. Recuerda que tu contraseña se restablecerá. Necesitaras recuperarla, puedes hacerlo en la sección <span class="font-bold">¿Olvidaste tu contraseña?</span>.</span>
<span v-html="t('profile.msgInfoEmail')"></span>
</div>
<div class="mt-5 text-center">
<Spiner v-if="loading"/>
<button
v-else
class="btn btn-dark btn-block" type="submit">Guardar</button>
class="btn btn-dark btn-block" type="submit">{{ t('buttons.save') }}</button>
</div>
</form>
</template>

View File

@@ -7,6 +7,7 @@
import { useAuthStore } from '../stores/auth';
import { useRouter } from 'vue-router';
import { useNotificationsStore } from '../stores/notifications';
import { useI18n } from 'vue-i18n';
const pwdForm = reactive({
pwd: '',
@@ -24,6 +25,7 @@
const loading = ref(false)
const msgError = ref('');
const msgSuccess = ref('');
const { t } = useI18n()
const hangleSave = async() => {
msgError.value = '';
@@ -42,7 +44,7 @@
}
const result = await recoveryPassword(data);
if(result.msg === 'success' && result.data !== null) {
msgSuccess.value = 'Te enviamos un código al correo, ingresado!';
msgSuccess.value = t('messages.sendCode')
pwdForm.checksum = result.data.checksum;
step.value = 2;
clearMessages();
@@ -58,7 +60,7 @@
msgError.value = '';
msgSuccess.value = '';
if(pwdForm.code.length < 6) {
msgError.value = 'Ingresa código valido';
msgError.value = t('errors.code');
clearMessages();
return;
} else {
@@ -81,7 +83,7 @@
});
clearMessages();
notifications.$patch({
text : 'Contraseña se ha cambiando exitosamente!',
text : t('messages.changePassword'),
show : true,
error: false
});
@@ -121,9 +123,9 @@
const pass = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/;
if(!pass.test(pwdForm.pwd)) {
return 'Contraseña poco segura';
return t('errors.weakPassword')
} else if (pwdForm.pwd !== pwdForm.pwd2) {
return 'Las contraseñas no coinciden';
return t('errors.matchPassword');
} else {
return '';
}
@@ -146,20 +148,20 @@
v-if="step === 1"
>
<br/>
<h3 class="title">Cambiar contraseña</h3>
<h3 class="title">{{ t('profile.changePassword') }}</h3>
<br/>
<NotificationBadge :msg="msgError" v-if="msgError != ''"/>
<NotificationBadge :msg="msgSuccess" v-if="msgSuccess != ''" :is-error="false"/>
<CustomInput
label=" Nueva contraseña*:"
:label="t('labels.password2') + '*:'"
type="password"
name="pwd"
:filled="false"
v-model:field="pwdForm.pwd"
help-text="La Contraseña debe ser mínimo 8 caracteres, al menos una mayúscula, al menos una minúscula, y un digito."
:help-text="t('login.helptext')"
/>
<CustomInput
label="Confirme contraseña*:"
:label="t('labels.password3') + '*:'"
type="password"
name="pwd2"
:step="1"
@@ -168,26 +170,26 @@
/>
<div class="warning-info">
<div><i class="fa-solid fa-triangle-exclamation warning"></i></div>
Esta acción cerrara su sesión actual y debera volver a iniciar sesión con su nueva contraseña
{{ t('profile.helpTextResetPass') }}
</div>
<div class="mt-5 text-center">
<Spiner v-if="loading"/>
<button
v-else
class="btn btn-dark btn-block" type="submit">Continuar</button>
class="btn btn-dark btn-block" type="submit">{{ t('buttons.continue') }}</button>
</div>
</form>
<form v-if="step === 2" @submit.prevent="handleConfirmChange" class="mx-5">
<div class="d-flex justify-content-center align-items-center mb-4 mt-4">
<a
@click="handleBack(1)"
class="btn-text ms-2"><i class="fa-solid fa-arrow-left"></i> Volver</a>
class="btn-text ms-2"><i class="fa-solid fa-arrow-left"></i> {{ t('buttons.back') }}</a>
</div>
<NotificationBadge :msg="msgError" v-if="msgError != ''"/>
<NotificationBadge :msg="msgSuccess" :is-error="false" v-if="msgSuccess != ''"/>
<p class="help-info">Te enviamos un código de verificación al correo electrónico, ingresalo para confirmar la recuperacion de contraseña. No olvides revisar en la carpeta spam</p>
<p class="help-info">{{ t('login.helptextCode') }}</p>
<CustomInput
label="Ingresa el código"
:label="t('labels.code') + '*:'"
name="code"
:filled="false"
type="text"
@@ -202,7 +204,7 @@
<Spiner v-if="loading"/>
<button
v-else
class="btn btn-dark btn-block" type="submit">Confirmar</button>
class="btn btn-dark btn-block" type="submit">{{ t('buttons.confirm') }}</button>
</div>
</form>
</template>

View File

@@ -107,7 +107,7 @@
origin.city = loadStore.currentLoad.origin?.city ? { city_name: loadStore.currentLoad.origin.city } : null;
origin.country = loadStore.currentLoad.origin.country;
origin.postalCode = loadStore.currentLoad.origin.zipcode;
origin.ref = loadStore.currentLoad.origin.landmark;
originRef.value = loadStore.currentLoad.origin.landmark;
destination.locationName = loadStore.currentLoad.destination.company_name;
destination.address = loadStore.currentLoad.destination.street_address1;
@@ -115,7 +115,7 @@
destination.city = loadStore.currentLoad.destination?.city ? { city_name: loadStore.currentLoad.destination.city } : null;
destination.country = loadStore.currentLoad.destination.country;
destination.postalCode = loadStore.currentLoad.destination.zipcode;
destination.ref = loadStore.currentLoad.destination.landmark;
destinationRef.value = loadStore.currentLoad.destination.landmark;
getCoordsMap();
}
@@ -146,7 +146,7 @@
origin.address = locationLoadSelected.value.address;
origin.state = { state_name: locationLoadSelected.value.state };
origin.city = { city_name: locationLoadSelected.value.city };
origin.ref = locationLoadSelected.value.description;
originRef.value = locationLoadSelected.value.description;
});
watch(locationDownloadSelected, () => {
@@ -154,7 +154,7 @@
destination.address = locationDownloadSelected.value.address;
destination.state = { state_name: locationDownloadSelected.value.state };
destination.city = { city_name: locationDownloadSelected.value.city };
destination.ref = locationDownloadSelected.value.description;
destinationRef.value = locationDownloadSelected.value.description;
});
const getLocations = async() => {
@@ -207,7 +207,7 @@
city: '',
country: '',
postalCode: '',
ref: '',
// ref: '',
});
const destination = reactive({
@@ -217,7 +217,7 @@
city: '',
country: '',
postalCode: '',
ref: '',
// ref: '',
});
const setLoadData = () => {
@@ -236,7 +236,7 @@
state : origin.state?.state_name,
city : origin.city?.city_name,
country : origin?.country,
landmark : origin?.ref,
landmark : originRef.value,
zipcode : origin?.postalCode,
lat : originCoords.value?.lat,
lng : originCoords.value?.lng
@@ -247,7 +247,7 @@
state : destination.state?.state_name,
city : destination.city?.city_name,
country : destination?.country,
landmark : destination?.ref,
landmark : destinationRef.value,
zipcode : destination?.postalCode,
lat : destinationCoords.value?.lat,
lng : destinationCoords.value?.lng
@@ -402,7 +402,7 @@
:filled="false"
name="date-load"
:required="submited ? true : false"
:error="(submited && !formLoad.dateLoad) ? 'Fecha es requerida' : null"
:error="(submited && !formLoad.dateLoad) ? t('errors.date') : null"
v-model:field="formLoad.dateLoad"
/>
<Custominput
@@ -411,7 +411,7 @@
:filled="false"
name="date-download"
:required="submited ? true : false"
:error="(submited && !formLoad.dateDownload) ? 'Fecha es requerida' : null"
:error="(submited && !formLoad.dateDownload) ? t('errors.date') : null"
v-model:field="formLoad.dateDownload"
/>
<Custominput
@@ -420,7 +420,7 @@
:filled="false"
name="weight"
:required="submited ? true : false"
:error="(submited && !formLoad.weight) ? 'Ingrese peso en KG' : null"
:error="(submited && !formLoad.weight) ? t('errors.weight') : null"
v-model:field="formLoad.weight"
/>
</div>
@@ -524,7 +524,7 @@
type="text"
:filled="false"
name="ref-origin"
v-model:field="origin.ref"
v-model:field="originRef"
/>
</div>
<div class="form-section">
@@ -594,7 +594,7 @@
type="text"
:filled="false"
name="ref-destination"
v-model:field="destination.ref"
v-model:field="destinationRef"
/>
</div>
</div>

View File

@@ -51,8 +51,8 @@ import { watch } from 'vue';
<h3>{{auth.user?.first_name}} {{ auth.user?.last_name }}</h3>
<p>{{ auth.user?.email }}</p>
<p>{{ auth.user?.phone }}</p>
<p class="section-prefs">Preferencias de usuario</p>
<p class="label-item">Idioma:</p>
<p class="section-prefs">{{ t('global.prefs') }}</p>
<p class="label-item">{{ t('global.lang') }}:</p>
<CustomRadioInput
value="es"
:label="t('global.es')"
@@ -71,7 +71,7 @@ import { watch } from 'vue';
data-toggle="modal"
data-target="#editProfileModal"
@click="handleEditProfile()"
>Editar perfil</button>
>{{ t('buttons.editProfile') }}</button>
</div>
</div>
</template>

View File

@@ -7,11 +7,13 @@
import VehicleInfo from './VehicleInfo.vue';
import Swal from 'sweetalert2'
import CardEmpty from './CardEmpty.vue';
import { useI18n } from 'vue-i18n';
const loadsStore = useLoadsStore();
const authStore = useAuthStore();
const isLoading = ref(false);
const isLoadingActions = ref(false);
const { t } = useI18n();
onMounted(() => {
getProposalsData()
@@ -41,7 +43,6 @@ import CardEmpty from './CardEmpty.vue';
isLoadingActions.value = true;
let load = await loadsStore.updateLoad(load_id, loadData);
if(load != null) {
const index = loadsStore.loads.findIndex((load) => load._id === load_id);
loadsStore.loads[index] = {
@@ -63,21 +64,21 @@ import CardEmpty from './CardEmpty.vue';
...formData
};
Swal.fire({
title: "Oferta aceptada!",
text: "La oferta fue aceptada exitosamente.",
title: t('proposals.titleOfferAccept'),
text: t('proposals.msgOfferAccept'),
icon: "success"
});
} else {
Swal.fire({
title: "Error!",
text: "No se pudo actualizar oferta, intente más tarde.",
text: t('proposals.msgErrorAcceptOffer'),
icon: "error"
});
}
} else {
Swal.fire({
title: "Error!",
text: "No se pudo aceptar oferta, intente más tarde.",
text: t('proposals.msgNotAcceptOffer'),
icon: "error"
});
}
@@ -89,12 +90,12 @@ import CardEmpty from './CardEmpty.vue';
const proposal_id = proposal._id;
const load_id = proposal.load._id;
const {isConfirmed} = await Swal.fire({
title: 'Cancelar oferta!',
text: '¿Estás seguro de cancelar esta oferta?',
title: t('proposals.titleCanceModal'),
text: t('proposals.textCancelModal'),
icon: 'warning',
cancelButtonColor: "#d33",
showCancelButton: true,
confirmButtonText: 'Si, cancelar',
confirmButtonText: t('proposals.confirmCancel'),
cancelButtonText: 'No'
})
if( isConfirmed ) {
@@ -126,21 +127,21 @@ import CardEmpty from './CardEmpty.vue';
...formData
};
Swal.fire({
title: "Oferta cancelada!",
text: "La oferta fue retirada exitosamente.",
title: t('proposals.msgTitleCancel'),
text: t('proposals.msgCancel'),
icon: "success"
});
} else {
Swal.fire({
title: "Error!",
text: "No se pudo retirar oferta, intente más tarde",
text: t('proposals.msgNotCancel'),
icon: "error"
});
}
} else {
Swal.fire({
title: "Error!",
text: "Algo salio mal, intente más tarde",
text: t('errors.generic'),
icon: "error"
});
}
@@ -155,7 +156,7 @@ import CardEmpty from './CardEmpty.vue';
<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">Ofertas</h2>
<h2 class="title mt-2 mb-3">{{ t('loads.offers') }}</h2>
<button
id="btnCloseProposalsModal"
type="button"
@@ -170,14 +171,14 @@ import CardEmpty from './CardEmpty.vue';
<div v-if="loadsStore.proposalsOfLoads.length > 0" v-for="proposal in loadsStore.proposalsOfLoads" class="card-fixed card-proposal">
<div class="row">
<div class="col-lg-6 col-md-12">
<p>Empresa: <span>{{ proposal.carrier.company_name }}</span></p>
<p>Licitador: <span>{{ proposal.bidder.first_name }} {{ proposal.bidder.last_name }}</span></p>
<p># de registro del transportista: <span v-if="proposal.vehicle">{{proposal.vehicle.vehicle_code}}</span></p>
<p>{{ t('global.company') }}: <span>{{ proposal.carrier.company_name }}</span></p>
<p>{{ t('proposals.bidder') }}: <span>{{ proposal.bidder.first_name }} {{ proposal.bidder.last_name }}</span></p>
<p>{{ t('proposals.numCarrier') }}: <span v-if="proposal.vehicle">{{proposal.vehicle.vehicle_code}}</span></p>
</div>
<div class="col-lg-6 col-md-12">
<p>Fecha: <span>{{ getDateMonthDay(proposal.createdAt) }}</span></p>
<p>Tipo de Transporte: <span v-if="proposal.vehicle">{{proposal.vehicle.truck_type}}</span></p>
<p>Transportista: <span v-if="proposal._driver">{{proposal._driver}}</span></p>
<p>{{ t('labels.date') }}: <span>{{ getDateMonthDay(proposal.createdAt) }}</span></p>
<p>{{ t('directory.typeTruck') }}: <span v-if="proposal.vehicle">{{proposal.vehicle.truck_type}}</span></p>
<p>{{ t('global.carrier') }}: <span v-if="proposal._driver">{{proposal._driver}}</span></p>
</div>
</div>
<div v-if="proposal.comment" class="box-note">
@@ -188,7 +189,7 @@ import CardEmpty from './CardEmpty.vue';
<div class="d-flex justify-content-end gap-3" v-else>
<div v-if="proposal.is_accepted" class="indicator-check">
<i class="fa-solid fa-check"></i>
Aceptado
{{ t('buttons.accepted') }}
</div>
<button v-if="!proposal.is_accepted"
type="button"
@@ -196,7 +197,7 @@ import CardEmpty from './CardEmpty.vue';
@click="handleAceptedProposal(proposal)"
>
<i class="fa-solid fa-check"></i>
Aceptar
{{ t('buttons.accept') }}
</button>
<button
v-if="proposal.load.load_status !== 'Delivered' && proposal.is_accepted"
@@ -204,11 +205,11 @@ import CardEmpty from './CardEmpty.vue';
@click="handleCancelProposal(proposal)"
>
<i class="fa-solid fa-ban clear-sm"></i>
Cancelar
{{ t('buttons.cancel') }}
</button>
</div>
</div>
<CardEmpty v-else text="No hay ofertas"/>
<CardEmpty v-else :text="t('proposals.empty')"/>
</div>
</div>
<div class="modal-footer">
@@ -216,7 +217,7 @@ import CardEmpty from './CardEmpty.vue';
type="button"
class="btn btn-dark"
@click="clearMoal"
data-dismiss="modal">Cerrar</button>
data-dismiss="modal">{{ t('buttons.close') }}</button>
</div>
</div>
</div>

View File

@@ -1,5 +1,6 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
defineProps({
vehicle: {
@@ -8,6 +9,8 @@ import { ref } from 'vue';
}
})
const { t } = useI18n()
const isShow = ref(false);
const toogle = () => {
@@ -19,27 +22,27 @@ import { ref } from 'vue';
<a
@click="toogle"
class="btn-text mt-4 mb-2"
>Información del vehiculo <i class="fa-solid" :class="[isShow ? 'fa-chevron-up' : 'fa-chevron-down']"></i></a>
>{{ t('vehicles.infoVehicle') }} <i class="fa-solid" :class="[isShow ? 'fa-chevron-up' : 'fa-chevron-down']"></i></a>
<div v-if="isShow">
<div class="divider"></div>
<!-- <h2 class="my-3">Información del vehiculo</h2> -->
<div class="row my-2">
<div class="col-lg-6">
<p>Código: <span>{{ vehicle.vehicle_code }}</span></p>
<p>Tipo de transporte: <span>{{ vehicle.truck_type }}</span></p>
<p>Número de Serie: <span>{{ vehicle.vehicle_number }}</span></p>
<p>Segmento: <span>{{ vehicle._categories }}</span></p>
<p>{{ t('labels.codeId') }}: <span>{{ vehicle.vehicle_code }}</span></p>
<p>{{ t('directory.typeTruck') }}: <span>{{ vehicle.truck_type }}</span></p>
<p>{{ t('vehicles.serialNumber') }}: <span>{{ vehicle.vehicle_number }}</span></p>
<p>{{ t('global.segment') }}: <span>{{ vehicle._categories }}</span></p>
</div>
<div class="col-lg-6">
<p>Placas Tracto Camión: <span>{{ vehicle.circulation_serial_number }}</span></p>
<p>Placas Remolque 1: <span>{{ vehicle.trailer_plate_1 }}</span></p>
<p>Placas Remolque 2: <span>{{ vehicle.trailer_plate_2 }}</span></p>
<p>Base de carga: <span>{{ vehicle.city }}, {{ vehicle.state }}</span></p>
<p>{{ t('vehicles.truckPlates') }}: <span>{{ vehicle.circulation_serial_number }}</span></p>
<p>{{ t('vehicles.trailerPlates') }} 1: <span>{{ vehicle.trailer_plate_1 }}</span></p>
<p>{{ t('vehicles.trailerPlates') }} 2: <span>{{ vehicle.trailer_plate_2 }}</span></p>
<p>{{ t('vehicles.chargingBase') }}: <span>{{ vehicle.city }}, {{ vehicle.state }}</span></p>
</div>
</div>
<div class="col-12">
<p>Información Adicional del Transporte: <span>{{ vehicle.notes }}</span></p>
<p>{{ t('vehicles.additionalInfoVehicle') }}: <span>{{ vehicle.notes }}</span></p>
</div>
</div>
</template>

View File

@@ -2,9 +2,11 @@
import { ref } from 'vue';
import VueMultiselect from 'vue-multiselect'
import { searchProducts } from '../../services/public';
import { useI18n } from 'vue-i18n';
const options = ref([]);
const isLoading = ref(false);
const { t } = useI18n();
// defineProps(['selectedCategory']);
defineProps({
@@ -43,18 +45,18 @@
:disabled="disabled"
@search-change="searchProductFn"
@remove="$emit('clear-option')"
placeholder="Busca por producto"
label="name"
track-by="name"
selectLabel="Presione para seleccionar"
selectedLabel="Selecionado"
deselectLabel="Presione para remover seleción"
:placeholder="t('labels.selectProduct')"
:selectLabel="t('global.helpSelected')"
:selectedLabel="t('global.selected')"
:deselectLabel="t('global.removeSelected')"
>
<template #noResult>
Oops! No se encontro coincidencias.
{{ t('global.notFound') }}
</template>
<template #noOptions>
Lista vacia.
{{ t('global.emptyList') }}
</template>
</VueMultiselect>
</template>

View File

@@ -17,6 +17,7 @@ const en = {
selectTruck: 'Search by type of transport',
selectState: 'Search by state',
selectCity: 'Search by city',
selectProduct: 'Search by product',
names: 'Name(s)',
lastnames: 'Last name',
phone: 'Phone',
@@ -49,6 +50,7 @@ const en = {
additionalInformation: 'Additional information',
writeHere: 'Write here',
create: 'Create',
date: 'Date',
},
buttons: {
enter: "Enter here",
@@ -68,7 +70,12 @@ const en = {
delete: "Delete",
cancel: "Cancel",
add: 'Add',
post: 'Post'
post: 'Post',
editProfile: 'Edit profile',
accept: 'Accept',
accepted: 'Accepted',
confirm: 'Confirm',
search: 'Search',
},
errors: {
requireds: "All fields required",
@@ -95,6 +102,9 @@ const en = {
state: 'Select state',
directoryType: 'select directory type',
zipcode: 'Enter valid zip code',
date: 'Date is required',
weight: 'Weight is required',
notMatchEmails: 'Emails do not match'
},
messages: {
sendCode: 'We send you a code to the email, entered!',
@@ -105,7 +115,8 @@ const en = {
createdUser: 'User created successfully!',
updatedUser: 'User successfully updated!',
msgCreatedUser: 'When creating a new user, you inform the account beneficiary that they must use their email to set a password in the <span class="font-bold">Forgot my password</span> section so they can log in.',
loading: 'Please wait!'
loading: 'Please wait!',
savingChanes: 'Saving changes',
},
global: {
signIn: "Sign In",
@@ -145,7 +156,9 @@ const en = {
segments: 'Segments',
segment: 'Segment',
notification: "Notification",
pagination: 'Pagination'
pagination: 'Pagination',
lang: 'Language',
prefs: 'User Preferences'
},
login: {
title: 'Sign in',
@@ -250,12 +263,60 @@ const en = {
loadingDel: 'Removing load',
msgTitleDel: 'Load removed!',
msgDel: 'Your load has been successfully deleted.',
msgNotDel: '"Your load could not be deleted, please try later.',
msgNotDel: 'Your load could not be deleted, please try later.',
msgSave: 'Load saved!',
msgNotSave: '"Could not save upload, try later',
msgPost: 'Load posted!',
msgNotPost: 'Could not post load, please try later'
},
evidence: {
evidence: "Evidence",
title: "Attached evidence",
loadEvidence: 'Load evidence',
downloadEvidence: 'Download evidence',
empty: 'There is no evidence uploaded'
},
proposals: {
numCarrier: 'carrier registration #',
bidder: 'Bidder',
empty: 'There are no offers yet',
msgOfferAccept: "The offer was successfully accepted.",
titleOfferAccept: 'Offer accepted!',
msgErrorAcceptOffer: 'Could not update offer, try later.',
msgNotAcceptOffer: 'Could not accept offer, try again later.',
titleCanceModal: 'Cancel offer',
textCancelModal: 'Are you sure to cancel this offer?',
confirmCancel: 'Yes, cancel',
msgTitleCancel: 'Offer cancelled!',
msgCancel: 'The offer was successfully withdrawn.',
msgNotCancel: 'Could not withdraw offer, try later',
},
vehicles: {
infoVehicle: 'Vehicle information',
truckPlates: 'Truck Tract Plates',
trailerPlates: 'Trailer Plates',
chargingBase: 'Charging Base',
additionalInfoVehicle: 'Additional Transportation Information',
serialNumber: 'Serial Number',
},
profile: {
profile: 'User data',
changePassword: 'Change password',
changeEmail: 'Change email',
msgUpdateUser: 'Updated user',
titleFormEmail: 'Change email',
newEmail: 'New Email',
confirmEmail: 'Confirm Email',
msgInfoEmail: '<span>By confirming this action, we will close your current session to update your email. You will be redirected to the login page. Remember that your password will be reset. You will need to recover it, you can do so in the <span class="font-bold">Forgot your password?</span> section.</span>',
questionChangeEmail: 'Are you sure to change the email?',
msgChangeEmail: 'Email has been changed successfully!',
helpTextResetPass: 'This action will log you out of your current session and you will need to log in again with your new password.'
},
carriers: {
title: '<span class="title-main">Carriers</span> directory',
searchByCarrier: 'Search by carrier'
}
};

View File

@@ -19,6 +19,7 @@ const es = {
selectTruck: 'Busca por tipo de transporte',
selectState: 'Busca por estado',
selectCity: 'Busca por ciudad',
selectProduct: 'Buscar por producto',
names: 'Nombre(s)',
lastnames: 'Apellido(s)',
phone1: 'Teléfono',
@@ -51,6 +52,7 @@ const es = {
additionalInformation: 'Información adicional',
writeHere: 'Escribe aqui',
create: 'Crear',
date: 'Fecha',
},
buttons: {
enter: "Ingresa aqui",
@@ -70,7 +72,12 @@ const es = {
delete: "Eliminar",
cancel: "Cancelar",
add: 'Agregar',
post: 'Publicar'
post: 'Publicar',
editProfile: 'Editar perfil',
accept: 'Aceptar',
accepted: 'Aceptado',
confirm: 'Confirmar',
search: 'Buscar',
},
errors: {
requireds: 'Todos los campos con obligatorios',
@@ -97,7 +104,9 @@ const es = {
state: 'Seleccione estado',
directoryType: 'seleccione el tipo de directorio',
zipcode: 'Ingrese código postal valido',
date: 'Fecha es requerida',
weight: 'Peso es requerido',
notMatchEmails: 'Los correos electrónicos no coinciden'
},
messages: {
sendCode: 'Te enviamos un código al correo, ingresado!',
@@ -108,7 +117,8 @@ const es = {
createdUser: 'Usuario creado con éxito!',
updatedUser: 'Usuario actualizado con éxito!',
msgCreatedUser: 'Al crear un nuevo usuario, informa al beneficiario de la cuenta, que debe utilizar su correo electrónico para establecer una contraseña en la sección <span class="font-bold">Olvidé mi contraseña</span> y así poder iniciar sesión.',
loading: 'Por favor espere!'
loading: 'Por favor espere!',
savingChanes: 'Guardando cambios',
},
global: {
signIn: 'Ingresar',
@@ -149,6 +159,8 @@ const es = {
segment: 'Segmento',
notification: "Notificación",
pagination: 'Paginación',
lang: 'Idioma',
prefs: 'Preferencias de usuario',
},
login: {
title: 'Iniciar sesión',
@@ -247,6 +259,9 @@ const es = {
addressNameDownload: 'Nombre locación de descarga',
locationsRegistered: 'Locaciones registradas',
selectedLocation: 'Seleccionar locación',
labelPrice: 'Precio en MXN',
labelWeight: 'Peso de la carga en kg',
notes: 'Notas',
titleDel: 'Eliminar carga!',
textDel: '¿Estás seguro de eliminar esta carga?',
@@ -256,10 +271,58 @@ const es = {
msgNotDel: '"Tu carga no se pudo eliminar, intente más tarde.',
msgSave: 'Carga guardada!',
msgNotSave: '"No se pudo guardar carga, intente más tarde',
msgNotSave: 'No se pudo guardar carga, intente más tarde',
msgPost: 'Carga publicada!',
msgNotPost: 'No se pudo publicar carga, intente más tarde'
},
evidence: {
evidence: "Evidencias",
title: "Evidencias adjuntas",
loadEvidence: 'Evidencia de carga',
downloadEvidence: 'Evidencia de descarga',
empty: 'No hay evidencias subidas',
},
proposals: {
numCarrier: '# de registro del transportista',
bidder: 'Licitador',
empty: 'No hay ofertas todavía',
msgOfferAccept: "La oferta fue aceptada exitosamente.",
titleOfferAccept: 'Oferta aceptada!',
msgErrorAcceptOffer: 'No se pudo actualizar oferta, intente más tarde.',
msgNotAcceptOffer: 'No se pudo aceptar oferta, intente más tarde.',
titleCanceModal: 'Cancelar oferta',
textCancelModal: '¿Estás seguro de cancelar esta oferta?',
confirmCancel: 'Si, cancelar',
msgTitleCancel: 'Oferta cancelada!',
msgCancel: 'La oferta fue retirada exitosamente.',
msgNotCancel: 'No se pudo retirar oferta, intente más tarde',
},
vehicles: {
infoVehicle: 'Información del vehiculo',
truckPlates: 'Placas Tracto Camión',
trailerPlates: 'Placas Remolque',
chargingBase: 'Base de carga',
additionalInfoVehicle: 'Información Adicional del Transporte',
serialNumber: 'Número de Serie',
},
profile: {
profile: 'Datos de usuario',
changePassword: 'Cambiar contraseña',
changeEmail: 'Cambiar correo',
msgUpdateUser: 'Usuario actualizado',
titleFormEmail: 'Cambiar correo electrónico',
newEmail: 'Nuevo Correo electrónico',
confirmEmail: 'Confirmar Correo electrónico',
msgInfoEmail: '<span>Al confirmar esta acción, cerraremos tu sesión actual para actualizar tu correo electrónico. Serás redirigido a la página de inicio de sesión. Recuerda que tu contraseña se restablecerá. Necesitaras recuperarla, puedes hacerlo en la sección <span class="font-bold">¿Olvidaste tu contraseña?</span>.</span>',
questionChangeEmail: '¿Estás seguro de cambiar el correo electrónico?',
msgChangeEmail: 'Correo electrónico se ha cambiando exitosamente!',
helpTextResetPass: 'Esta acción cerrara su sesión actual y debera volver a iniciar sesión con su nueva contraseña'
},
carriers: {
title: 'Directorio de <span class="title-main">Transportistas</span>',
searchByCarrier: 'Buscar por transportista'
}
};

View File

@@ -8,6 +8,7 @@
import States from '../components/ui/States.vue';
import Cities from '../components/ui/Cities.vue';
import Pagination from '../components/Pagination.vue';
import { useI18n } from 'vue-i18n';
const {loading, companies, getCompaniesData, companiesTotal, currentCompaniesPage} = useDirectory();
const query = ref('');
@@ -17,6 +18,8 @@ import Pagination from '../components/Pagination.vue';
const selectedCities = ref([]);
const filterQuery = ref([]);
const { t } = useI18n()
const limit = 10;
onMounted(() => {
@@ -129,11 +132,12 @@ import Pagination from '../components/Pagination.vue';
<template>
<div>
<h2 class="title mb-5">Directorios de <span class="title-main">Transportistas</span></h2>
<!-- <h2 class="title mb-5">Directorios de <span class="title-main">Transportistas</span></h2> -->
<h2 class="title mb-5" v-html="t('carriers.title')"></h2>
<div class="card-filters">
<div class="d-flex mb-2">
<input class="form-control me-2" type="search" name="" placeholder="Buscar transportista" 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('carriers.searchByCarrier')" 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 NotificationBadge from '../components/ui/NotificationBadge.vue';
import FormChangePassword from '../components/FormChangePassword.vue';
import FormChangeEmail from '../components/FormChangeEmail.vue';
import { useI18n } from 'vue-i18n';
const auth = useAuthStore();
@@ -23,6 +24,8 @@
phone1: '',
})
const { t } = useI18n()
onMounted(() => {
if(user.value) {
getData()
@@ -58,10 +61,10 @@
const result = await auth.updateProfile(userData)
loading.value = false;
if(result.msg === 'success') {
msgSuccess.value = 'Usuario actualizado';
msgSuccess.value = t('errors.msgUpdateUser');
clearMessages();
} else {
msgError.value = 'Algo salio mal, intente más tarde';
msgError.value = t('errors.generic');
clearMessages();
}
}
@@ -76,11 +79,11 @@
const validatiosUser = () => {
if(userForm.name.trim().length < 3) {
return 'Ingresa nombre(s) valido';
return t('errors.name');
} else if(userForm.lastName.trim().length < 2) {
return 'Ingresa apellido(s) valido';
return t('errors.lastname');
} else if(userForm.phone1.trim().length < 10) {
return 'Ingresa teléfono valido';
return t('errors.phone');
} else {
return '';
}
@@ -98,15 +101,15 @@
<a class="btn-text"
:class="[(form === 0) ? 'selection' : '']"
@click="setForm(0)"
>Datos usuario</a>
>{{ t('profile.profile') }}</a>
<a class="btn-text"
:class="[(form === 1) ? 'selection' : '']"
@click="setForm(1)"
>Cambiar correo</a>
>{{ t('profile.changeEmail') }}</a>
<a class="btn-text"
:class="[(form === 2) ? 'selection' : '']"
@click="setForm(2)"
>Cambiar contraseña</a>
>{{ t('profile.changePassword') }}</a>
</div>
<br/>
<div class="divider"></div>
@@ -118,26 +121,26 @@
v-if="form === 0"
>
<br/>
<h3 class="title">Datos de usuario</h3>
<h3 class="title">{{ t('profile.profile') }}</h3>
<br/>
<NotificationBadge :msg="msgError" v-if="msgError != ''"/>
<NotificationBadge :msg="msgSuccess" v-if="msgSuccess != ''" :is-error="false"/>
<CustomInput
label="Nombres(s)*:"
:label="t('labels.names')+'*:'"
type="text"
name="name"
:filled="false"
v-model:field="userForm.name"
/>
<CustomInput
label="Apellidos(s)*:"
:label="t('labels.lastnames')+'*:'"
type="text"
name="lastname"
:filled="false"
v-model:field="userForm.lastName"
/>
<CustomInput
label="Teléfono*:"
:label="t('labels.phone')+'*:'"
type="number"
name="phone1"
:step="1"
@@ -148,7 +151,7 @@
<Spiner v-if="loading"/>
<button
v-else
class="btn btn-dark btn-block" type="submit">Guardar</button>
class="btn btn-dark btn-block" type="submit">{{ t('buttons.save') }}</button>
</div>
</form>
<FormChangeEmail v-if="form === 1"/>