Files
whatsappNucleo/app/components/messages/content/MessagePoll.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

109 lines
2.9 KiB
Vue

<template>
<div class="min-w-[200px] max-w-[280px]">
<!-- Poll header -->
<div class="flex items-center gap-2 mb-2">
<UIcon name="i-lucide-bar-chart-2" class="w-5 h-5" :class="iconClass" />
<span class="font-medium" :class="textClass">Encuesta</span>
</div>
<!-- Poll question -->
<p class="font-medium mb-3" :class="textClass">
{{ poll.name }}
</p>
<!-- Poll options -->
<div class="space-y-2">
<div
v-for="(option, index) in poll.options"
:key="index"
class="relative rounded-lg overflow-hidden"
:class="optionBgClass"
>
<!-- Background bar for vote count -->
<div
v-if="poll.votes && poll.votes[index]"
class="absolute inset-y-0 left-0 transition-all duration-300"
:class="voteBgClass"
:style="{ width: getVotePercentage(index) + '%' }"
/>
<!-- Option content -->
<div class="relative flex items-center justify-between px-3 py-2">
<span class="text-sm" :class="optionTextClass">{{ option }}</span>
<span
v-if="poll.votes && poll.votes[index]"
class="text-xs font-medium"
:class="voteCountClass"
>
{{ poll.votes[index] }}
</span>
</div>
</div>
</div>
<!-- Poll footer -->
<div class="flex items-center justify-between mt-3 text-xs" :class="mutedTextClass">
<span>{{ totalVotes }} voto{{ totalVotes !== 1 ? 's' : '' }}</span>
<span v-if="poll.selectableCount > 1">
Seleccion multiple ({{ poll.selectableCount }})
</span>
</div>
</div>
</template>
<script setup lang="ts">
interface PollInfo {
name: string
options: string[]
votes?: number[]
selectableCount?: number
}
interface Props {
poll: PollInfo
fromMe?: boolean
}
const props = withDefaults(defineProps<Props>(), {
fromMe: false
})
const totalVotes = computed(() => {
if (!props.poll.votes) return 0
return props.poll.votes.reduce((sum, v) => sum + v, 0)
})
const getVotePercentage = (index: number): number => {
if (!props.poll.votes || totalVotes.value === 0) return 0
return Math.round((props.poll.votes[index] / totalVotes.value) * 100)
}
const textClass = computed(() =>
props.fromMe ? 'text-white' : 'text-[var(--wa-text)]'
)
const iconClass = computed(() =>
props.fromMe ? 'text-white/80' : 'text-[var(--wa-green)]'
)
const mutedTextClass = computed(() =>
props.fromMe ? 'text-white/60' : 'text-[var(--wa-text-muted)]'
)
const optionBgClass = computed(() =>
props.fromMe ? 'bg-white/10' : 'bg-[var(--wa-bg-light)]'
)
const optionTextClass = computed(() =>
props.fromMe ? 'text-white' : 'text-[var(--wa-text)]'
)
const voteBgClass = computed(() =>
props.fromMe ? 'bg-white/20' : 'bg-[var(--wa-green)]/20'
)
const voteCountClass = computed(() =>
props.fromMe ? 'text-white/70' : 'text-[var(--wa-text-muted)]'
)
</script>