add: observer input & tooltips

This commit is contained in:
Alexandro Uc Santos
2025-04-26 14:17:12 -06:00
parent 228609db46
commit 4c8b0470d2
6 changed files with 244 additions and 6 deletions

View File

@@ -10,6 +10,7 @@
import { useCompanyStore } from '../stores/company';
import Swal from 'sweetalert2';
import { useI18n } from 'vue-i18n';
import { validateEmail } from '../helpers/validations';
const props = defineProps({
location: {
@@ -27,6 +28,8 @@
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');
@@ -139,6 +142,33 @@
}
}
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,
@@ -251,6 +281,42 @@
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 observador de bodega"
name="email"
type="email"
v-model:field="emailInput"
:filled="false"
:tooltip="t('messages.observerWarehouse')"
/>
</div>
<button
type="button"
@click="addObserver"
class="btn btn-dark"
>
Agregar
</button>
</div>
<h5 v-if="emails.length > 0">Lista de observadores:</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

View File

@@ -17,6 +17,7 @@
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
import {getDateTime } from '../helpers/date_formats';
import { validateEmail } from '../helpers/validations';
const loadStore = useLoadsStore();
@@ -43,6 +44,8 @@
const locationDownloadSelected = ref(null)
const originRef = ref('')
const destinationRef = ref('')
const emails = ref([]);
const emailInput = ref('');
const errors = ref({
segment: null,
@@ -362,6 +365,31 @@
? t('loads.create')
: t('loads.edit')
)
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)
}
</script>
<template>
@@ -425,14 +453,14 @@
:error="(submited && !formLoad.weight) ? t('errors.weight') : null"
v-model:field="formLoad.weight"
/>
</div>
<div class="form-section">
<div class="mb-4 mt-3">
<label class="custom-label">{{ t('loads.product') }}</label>
<Products
v-model="formLoad.terms"
/>
</div>
</div>
<div class="form-section">
<Custominput
:label="t('loads.labelPrice')"
type="Number"
@@ -455,6 +483,41 @@
name="owner"
v-model:field="formLoad.owner"
/>
<div class="box-observers mt-4">
<div class="box-input">
<div class="input-observer">
<Custominput
label="Agregar cliente observador"
name="email"
type="email"
v-model:field="emailInput"
:filled="false"
:tooltip="t('messages.observerClient')"
/>
</div>
<button
type="button"
@click="addObserver"
class="btn btn-dark"
>
Agregar
</button>
</div>
<h5 v-if="emails.length > 0">Lista de observadores:</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>
</div>
<div class="form-box">

View File

@@ -39,6 +39,9 @@
step: {
type: Number,
default: 0.1
},
tooltip: {
type: String,
}
})
@@ -48,11 +51,24 @@
<template>
<div class="d-flex flex-column gap-2 mb-4">
<label
<!-- <label
class="custom-label"
:class="[label.includes('*') ? 'required' : '']"
:for="name"
>{{ label }}</label>
>{{ label }}</label> -->
<div class="label-box">
<label
class="custom-label label-text"
:class="[label.includes('*') ? 'required' : '']"
:for="name"
>{{ label }}</label>
<div class="help-icon" v-if="tooltip">
<div class="tooltip">
{{ tooltip }}
</div>
</div>
</div>
<input
class="custom-input"
:class="[
@@ -86,4 +102,50 @@
font-size: 12px;
font-weight: 400;
}
.label-box {
display: flex;
flex-direction: row;
width: 100%;
align-items: center;
}
.label-text {
flex: 1;
}
/* Estilo del ícono de ayuda */
.help-icon {
position: relative;
font-size: 20px;
color: #666;
cursor: pointer;
}
/* Tooltip oculto inicialmente */
.tooltip {
position: absolute;
top: 100%;
left: 50%;
width: 180px;
padding: 8px;
background: #333;
color: white;
font-size: 12px;
text-align: center;
border-radius: 5px;
opacity: 0;
pointer-events: none;
transform: translateX(-50%);
margin-top: 8px;
transition: opacity 0.3s ease;
}
/* Mostrar tooltip al pasar el mouse */
.help-icon:hover .tooltip,
.help-icon:active .tooltip {
opacity: 1;
pointer-events: auto;
}
</style>