110 lines
3.9 KiB
Vue
110 lines
3.9 KiB
Vue
<script setup>
|
|
import { computed } from 'vue'
|
|
import RadioButtonGroup from '@/Components/RadioButtonGroup.vue'
|
|
|
|
const props = defineProps({
|
|
question: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
modelValue: {
|
|
type: Object,
|
|
default: () => ({ value: null, text_value: '' }),
|
|
},
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
const hasRadioButtons = computed(() => {
|
|
return props.question.has_yes || props.question.has_no || props.question.has_na
|
|
})
|
|
|
|
const showDetails = computed(() => {
|
|
const d = props.question.details
|
|
if (!d) return false
|
|
if (d === 'required' || d === 'optional') return true
|
|
if (d === 'req_on_yes' && props.modelValue.value === 'yes') return true
|
|
if (d === 'req_on_no' && props.modelValue.value === 'no') return true
|
|
return false
|
|
})
|
|
|
|
const detailsRequired = computed(() => {
|
|
const d = props.question.details
|
|
if (d === 'required') return true
|
|
if (d === 'req_on_yes' && props.modelValue.value === 'yes') return true
|
|
if (d === 'req_on_no' && props.modelValue.value === 'no') return true
|
|
return false
|
|
})
|
|
|
|
const isTextOnly = computed(() => {
|
|
return !hasRadioButtons.value && props.question.details
|
|
})
|
|
|
|
const availableOptions = computed(() => {
|
|
const opts = []
|
|
if (props.question.has_yes) opts.push({ value: 'yes', label: 'Yes' })
|
|
if (props.question.has_no) opts.push({ value: 'no', label: 'No' })
|
|
if (props.question.has_na) opts.push({ value: 'not_applicable', label: 'N/A' })
|
|
return opts
|
|
})
|
|
|
|
const updateValue = (value) => {
|
|
emit('update:modelValue', { ...props.modelValue, value })
|
|
}
|
|
|
|
const updateTextValue = (event) => {
|
|
emit('update:modelValue', { ...props.modelValue, text_value: event.target.value })
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="py-5 first:pt-0">
|
|
<p class="text-white font-medium leading-relaxed mb-4">{{ question.text }}</p>
|
|
|
|
<!-- Text-only question (no radio buttons) -->
|
|
<div v-if="isTextOnly">
|
|
<textarea
|
|
:value="modelValue.text_value"
|
|
@input="updateTextValue"
|
|
rows="3"
|
|
class="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-3 text-white placeholder-gray-600 focus:border-primary/50 focus:ring-1 focus:ring-primary/20 transition-colors duration-200"
|
|
placeholder="Enter your response..."
|
|
></textarea>
|
|
</div>
|
|
|
|
<!-- Radio button question -->
|
|
<div v-if="hasRadioButtons">
|
|
<RadioButtonGroup
|
|
:modelValue="modelValue.value"
|
|
@update:modelValue="updateValue($event)"
|
|
:name="`question-${question.id}`"
|
|
:options="availableOptions"
|
|
class="mb-3"
|
|
/>
|
|
|
|
<!-- Details textarea (conditional) -->
|
|
<Transition
|
|
enter-active-class="transition-all duration-300 ease-out"
|
|
enter-from-class="opacity-0 -translate-y-1 max-h-0"
|
|
enter-to-class="opacity-100 translate-y-0 max-h-40"
|
|
leave-active-class="transition-all duration-200 ease-in"
|
|
leave-from-class="opacity-100 translate-y-0 max-h-40"
|
|
leave-to-class="opacity-0 -translate-y-1 max-h-0"
|
|
>
|
|
<div v-if="showDetails" class="mt-2">
|
|
<label class="block text-sm text-gray-400 mb-1">
|
|
Details{{ detailsRequired ? ' (required)' : ' (optional)' }}
|
|
</label>
|
|
<textarea
|
|
:value="modelValue.text_value"
|
|
@input="updateTextValue"
|
|
rows="2"
|
|
class="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-3 text-white placeholder-gray-600 focus:border-primary/50 focus:ring-1 focus:ring-primary/20 text-sm transition-colors duration-200"
|
|
placeholder="Enter details..."
|
|
></textarea>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
</div>
|
|
</template>
|