All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m8s
- 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
202 lines
5.1 KiB
Vue
202 lines
5.1 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 Encuesta</h3>
|
|
<UButton
|
|
variant="ghost"
|
|
icon="i-lucide-x"
|
|
size="sm"
|
|
@click="isOpen = false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="space-y-4">
|
|
<!-- Poll question -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-1">
|
|
Pregunta
|
|
</label>
|
|
<UInput
|
|
v-model="pollName"
|
|
placeholder="¿Cuál es tu opción favorita?"
|
|
icon="i-lucide-help-circle"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Options -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-[var(--wa-text-muted)] mb-2">
|
|
Opciones (mínimo 2, máximo 12)
|
|
</label>
|
|
|
|
<div class="space-y-2">
|
|
<div
|
|
v-for="(option, index) in options"
|
|
:key="index"
|
|
class="flex items-center gap-2"
|
|
>
|
|
<span class="text-sm text-[var(--wa-text-muted)] w-6">
|
|
{{ index + 1 }}.
|
|
</span>
|
|
<UInput
|
|
v-model="options[index]"
|
|
:placeholder="`Opción ${index + 1}`"
|
|
class="flex-1"
|
|
/>
|
|
<UButton
|
|
v-if="options.length > 2"
|
|
variant="ghost"
|
|
icon="i-lucide-x"
|
|
size="xs"
|
|
color="error"
|
|
@click="removeOption(index)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<UButton
|
|
v-if="options.length < 12"
|
|
variant="outline"
|
|
icon="i-lucide-plus"
|
|
size="sm"
|
|
class="mt-2"
|
|
@click="addOption"
|
|
>
|
|
Agregar opción
|
|
</UButton>
|
|
</div>
|
|
|
|
<!-- Allow multiple selection -->
|
|
<div class="flex items-center justify-between p-3 rounded-lg bg-[var(--wa-bg-light)]">
|
|
<div>
|
|
<p class="text-sm font-medium text-white">Selección múltiple</p>
|
|
<p class="text-xs text-[var(--wa-text-muted)]">
|
|
Permitir seleccionar más de una opción
|
|
</p>
|
|
</div>
|
|
<USwitch v-model="allowMultiple" />
|
|
</div>
|
|
|
|
<!-- Max selections (only if multiple) -->
|
|
<div v-if="allowMultiple" class="flex items-center gap-3">
|
|
<label class="text-sm text-[var(--wa-text-muted)]">
|
|
Máximo de selecciones:
|
|
</label>
|
|
<UInput
|
|
v-model.number="maxSelections"
|
|
type="number"
|
|
:min="1"
|
|
:max="validOptions.length"
|
|
class="w-20"
|
|
/>
|
|
</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 encuesta
|
|
</UButton>
|
|
</div>
|
|
</template>
|
|
</UCard>
|
|
</template>
|
|
</UModal>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
interface PollData {
|
|
name: string
|
|
options: string[]
|
|
selectableCount: number
|
|
}
|
|
|
|
const isOpen = defineModel<boolean>('open', { default: false })
|
|
|
|
const emit = defineEmits<{
|
|
send: [poll: PollData]
|
|
}>()
|
|
|
|
const isSending = ref(false)
|
|
|
|
const pollName = ref('')
|
|
const options = ref<string[]>(['', ''])
|
|
const allowMultiple = ref(false)
|
|
const maxSelections = ref(1)
|
|
|
|
const validOptions = computed(() =>
|
|
options.value.filter(o => o.trim())
|
|
)
|
|
|
|
const isValid = computed(() => {
|
|
return pollName.value.trim() && validOptions.value.length >= 2
|
|
})
|
|
|
|
const addOption = () => {
|
|
if (options.value.length < 12) {
|
|
options.value.push('')
|
|
}
|
|
}
|
|
|
|
const removeOption = (index: number) => {
|
|
if (options.value.length > 2) {
|
|
options.value.splice(index, 1)
|
|
}
|
|
}
|
|
|
|
const handleSend = async () => {
|
|
if (!isValid.value) return
|
|
|
|
isSending.value = true
|
|
try {
|
|
const poll: PollData = {
|
|
name: pollName.value.trim(),
|
|
options: validOptions.value,
|
|
selectableCount: allowMultiple.value
|
|
? Math.min(maxSelections.value, validOptions.value.length)
|
|
: 1
|
|
}
|
|
|
|
emit('send', poll)
|
|
|
|
// Reset form
|
|
resetForm()
|
|
isOpen.value = false
|
|
} finally {
|
|
isSending.value = false
|
|
}
|
|
}
|
|
|
|
const resetForm = () => {
|
|
pollName.value = ''
|
|
options.value = ['', '']
|
|
allowMultiple.value = false
|
|
maxSelections.value = 1
|
|
}
|
|
|
|
// Reset form when modal opens
|
|
watch(isOpen, (open) => {
|
|
if (open) {
|
|
resetForm()
|
|
}
|
|
})
|
|
|
|
// Adjust max selections when options change
|
|
watch(validOptions, (opts) => {
|
|
if (maxSelections.value > opts.length) {
|
|
maxSelections.value = opts.length || 1
|
|
}
|
|
})
|
|
</script>
|