Files
whatsappNucleo/app/components/messages/EventSendModal.vue
josedario87 cb846d0c56
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m8s
Feat: Agregar soporte para envío de Contacts, Polls y Events
- Backend: Nuevo soporte en endpoint /send para tipos contact, poll, event
- UI: Modales para crear y enviar contactos, encuestas y eventos
- Visualización: Componentes MessagePoll y MessageEvent para mostrar mensajes recibidos
- Tipos: Agregar PollInfo, EventInfo y tipo 'event' a MessageType
2025-12-04 12:06:35 -06:00

258 lines
7.0 KiB
Vue

<template>
<UModal v-model:open="isOpen">
<template #content>
<UCard>
<template #header>
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold text-white">Crear Evento</h3>
<UButton
variant="ghost"
icon="i-lucide-x"
size="sm"
@click="isOpen = false"
/>
</div>
</template>
<div class="space-y-4 max-h-[60vh] overflow-y-auto">
<!-- Event name -->
<div>
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
Nombre del evento *
</label>
<UInput
v-model="eventName"
placeholder="Reunión de equipo"
icon="i-lucide-calendar"
/>
</div>
<!-- Start date/time -->
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
Fecha inicio *
</label>
<UInput
v-model="startDate"
type="date"
/>
</div>
<div>
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
Hora inicio *
</label>
<UInput
v-model="startTime"
type="time"
/>
</div>
</div>
<!-- End date/time (optional) -->
<div class="flex items-center gap-2 mb-2">
<UCheckbox v-model="hasEndDate" />
<span class="text-sm text-[var(--wa-text-muted)]">Agregar fecha de fin</span>
</div>
<div v-if="hasEndDate" class="grid grid-cols-2 gap-3">
<div>
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
Fecha fin
</label>
<UInput
v-model="endDate"
type="date"
/>
</div>
<div>
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
Hora fin
</label>
<UInput
v-model="endTime"
type="time"
/>
</div>
</div>
<!-- Description -->
<div>
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
Descripción (opcional)
</label>
<UTextarea
v-model="description"
placeholder="Detalles del evento..."
:rows="2"
/>
</div>
<!-- Location -->
<div class="flex items-center gap-2 mb-2">
<UCheckbox v-model="hasLocation" />
<span class="text-sm text-[var(--wa-text-muted)]">Agregar ubicación</span>
</div>
<div v-if="hasLocation" class="space-y-3 p-3 rounded-lg bg-[var(--wa-bg-light)]">
<UInput
v-model="locationName"
placeholder="Nombre del lugar"
icon="i-lucide-map-pin"
/>
<UInput
v-model="locationAddress"
placeholder="Dirección"
icon="i-lucide-navigation"
/>
<div class="grid grid-cols-2 gap-3">
<UInput
v-model.number="latitude"
type="number"
step="any"
placeholder="Latitud"
/>
<UInput
v-model.number="longitude"
type="number"
step="any"
placeholder="Longitud"
/>
</div>
<p class="text-xs text-[var(--wa-text-muted)]">
Las coordenadas son opcionales pero permiten mostrar el mapa
</p>
</div>
</div>
<template #footer>
<div class="flex justify-end gap-2">
<UButton variant="ghost" @click="isOpen = false">
Cancelar
</UButton>
<UButton
:disabled="!isValid"
:loading="isSending"
@click="handleSend"
>
Crear evento
</UButton>
</div>
</template>
</UCard>
</template>
</UModal>
</template>
<script setup lang="ts">
interface EventData {
name: string
startDate: string
endDate?: string
description?: string
location?: {
name?: string
address?: string
latitude?: number
longitude?: number
}
}
const isOpen = defineModel<boolean>('open', { default: false })
const emit = defineEmits<{
send: [event: EventData]
}>()
const isSending = ref(false)
// Form fields
const eventName = ref('')
const startDate = ref('')
const startTime = ref('')
const hasEndDate = ref(false)
const endDate = ref('')
const endTime = ref('')
const description = ref('')
const hasLocation = ref(false)
const locationName = ref('')
const locationAddress = ref('')
const latitude = ref<number | undefined>(undefined)
const longitude = ref<number | undefined>(undefined)
const isValid = computed(() => {
return eventName.value.trim() && startDate.value && startTime.value
})
const handleSend = async () => {
if (!isValid.value) return
isSending.value = true
try {
const startDateTime = new Date(`${startDate.value}T${startTime.value}`)
const eventData: EventData = {
name: eventName.value.trim(),
startDate: startDateTime.toISOString()
}
if (hasEndDate.value && endDate.value && endTime.value) {
const endDateTime = new Date(`${endDate.value}T${endTime.value}`)
eventData.endDate = endDateTime.toISOString()
}
if (description.value.trim()) {
eventData.description = description.value.trim()
}
if (hasLocation.value) {
eventData.location = {}
if (locationName.value.trim()) {
eventData.location.name = locationName.value.trim()
}
if (locationAddress.value.trim()) {
eventData.location.address = locationAddress.value.trim()
}
if (latitude.value !== undefined && longitude.value !== undefined) {
eventData.location.latitude = latitude.value
eventData.location.longitude = longitude.value
}
}
emit('send', eventData)
// Reset form
resetForm()
isOpen.value = false
} finally {
isSending.value = false
}
}
const resetForm = () => {
eventName.value = ''
startDate.value = ''
startTime.value = ''
hasEndDate.value = false
endDate.value = ''
endTime.value = ''
description.value = ''
hasLocation.value = false
locationName.value = ''
locationAddress.value = ''
latitude.value = undefined
longitude.value = undefined
}
// Reset form when modal opens
watch(isOpen, (open) => {
if (open) {
resetForm()
// Set default start date to today
const today = new Date()
startDate.value = today.toISOString().split('T')[0]
startTime.value = '12:00'
}
})
</script>