All files / components/composite RSVPButton.vue

97.36% Statements 37/38
88.88% Branches 8/9
100% Functions 2/2
97.36% Lines 37/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92  1x 1x   1x 1x 1x 1x 1x 1x   1x 1x 1x 1x                                     1x         1x                           1x         1x 1x 31x 31x 31x         31x 1x 96x 87x     96x 9x 96x 7x 96x 1x 96x 1x 96x   96x         96x 1x 1x    
<template>
  <div class="flex flex-wrap gap-2" data-testid="rsvp-buttons">
    <BaseButton
      v-for="option in rsvpOptions"
      :key="option.status"
      :variant="getButtonVariant(option.status)"
      :disabled="disabled"
      :data-testid="`rsvp-${option.status}`"
      size="md"
      @click="handleSelect(option.status)"
    >
      <span class="mr-1.5">{{ option.icon }}</span>
      {{ option.label }}
    </BaseButton>
  </div>
</template>
 
<script setup lang="ts">
/**
 * RSVPButton
 * @description Composite component for RSVP status selection (Yes/No/Maybe)
 * Shows visual feedback for current selection
 */
 
import type { AttendanceStatus } from '~/types'
 
interface Props {
  /** Current user's RSVP status */
  currentStatus?: AttendanceStatus | null
  /** Disabled state (e.g., during submission) */
  disabled?: boolean
}
 
const props = withDefaults(defineProps<Props>(), {
  currentStatus: null,
  disabled: false
})
 
const emit = defineEmits<{
  /** Emitted when user selects a status */
  submit: [status: AttendanceStatus]
}>()
 
interface RSVPOption {
  status: AttendanceStatus
  label: string
  icon: string
}
 
/**
 * i18n
 */
const { t } = useI18n()
 
/**
 * RSVP options configuration
 */
const rsvpOptions = computed<RSVPOption[]>(() => [
  { status: 'yes', label: t('rsvp.yes'), icon: '✓' },
  { status: 'no', label: t('rsvp.no'), icon: '✗' },
  { status: 'maybe', label: t('rsvp.maybe'), icon: '?' }
])
 
/**
 * Get button variant based on selection state
 */
const getButtonVariant = (status: AttendanceStatus): 'primary' | 'secondary' | 'ghost' | 'danger' => {
  if (props.currentStatus !== status) {
    return 'secondary'
  }
 
  // Selected state - use appropriate variant
  switch (status) {
    case 'yes':
      return 'primary'
    case 'no':
      return 'danger'
    case 'maybe':
      return 'secondary'
    default:
      return 'secondary'
  }
}
 
/**
 * Handle status selection
 */
const handleSelect = (status: AttendanceStatus): void => {
  emit('submit', status)
}
</script>