That's the icon in the background.
This commit is contained in:
BIN
public/images/growth-symbol.png
Normal file
BIN
public/images/growth-symbol.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
@@ -58,8 +58,8 @@ const updateTextValue = (event) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="py-4">
|
<div class="py-5 first:pt-0">
|
||||||
<p class="text-white mb-3">{{ question.text }}</p>
|
<p class="text-white font-medium leading-relaxed mb-4">{{ question.text }}</p>
|
||||||
|
|
||||||
<!-- Text-only question (no radio buttons) -->
|
<!-- Text-only question (no radio buttons) -->
|
||||||
<div v-if="isTextOnly">
|
<div v-if="isTextOnly">
|
||||||
@@ -67,7 +67,7 @@ const updateTextValue = (event) => {
|
|||||||
:value="modelValue.text_value"
|
:value="modelValue.text_value"
|
||||||
@input="updateTextValue"
|
@input="updateTextValue"
|
||||||
rows="3"
|
rows="3"
|
||||||
class="w-full rounded-lg border border-gray-600 bg-surface px-3 py-2 text-white placeholder-gray-500 focus:border-primary focus:ring-1 focus:ring-primary"
|
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..."
|
placeholder="Enter your response..."
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,18 +83,27 @@ const updateTextValue = (event) => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Details textarea (conditional) -->
|
<!-- Details textarea (conditional) -->
|
||||||
<div v-if="showDetails" class="mt-2">
|
<Transition
|
||||||
<label class="block text-sm text-gray-400 mb-1">
|
enter-active-class="transition-all duration-300 ease-out"
|
||||||
Details{{ detailsRequired ? ' (required)' : ' (optional)' }}
|
enter-from-class="opacity-0 -translate-y-1 max-h-0"
|
||||||
</label>
|
enter-to-class="opacity-100 translate-y-0 max-h-40"
|
||||||
<textarea
|
leave-active-class="transition-all duration-200 ease-in"
|
||||||
:value="modelValue.text_value"
|
leave-from-class="opacity-100 translate-y-0 max-h-40"
|
||||||
@input="updateTextValue"
|
leave-to-class="opacity-0 -translate-y-1 max-h-0"
|
||||||
rows="2"
|
>
|
||||||
class="w-full rounded-lg border border-gray-600 bg-surface px-3 py-2 text-white placeholder-gray-500 focus:border-primary focus:ring-1 focus:ring-primary text-sm"
|
<div v-if="showDetails" class="mt-2">
|
||||||
placeholder="Enter details..."
|
<label class="block text-sm text-gray-400 mb-1">
|
||||||
></textarea>
|
Details{{ detailsRequired ? ' (required)' : ' (optional)' }}
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -29,36 +29,29 @@ const handleChange = (value) => {
|
|||||||
const getSegmentClasses = (index) => {
|
const getSegmentClasses = (index) => {
|
||||||
const classes = [
|
const classes = [
|
||||||
'px-6',
|
'px-6',
|
||||||
'py-3',
|
'py-2.5',
|
||||||
'text-sm',
|
'text-sm',
|
||||||
'font-medium',
|
'font-medium',
|
||||||
'select-none',
|
'select-none',
|
||||||
'transition-colors',
|
'transition-all',
|
||||||
'bg-primary',
|
'duration-200',
|
||||||
'text-gray-900',
|
'bg-white/5',
|
||||||
|
'text-gray-400',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'hover:bg-primary-dark',
|
'hover:bg-white/10',
|
||||||
'peer-checked:bg-primary-dark',
|
'hover:text-gray-200',
|
||||||
|
'peer-checked:bg-primary',
|
||||||
'peer-checked:text-gray-900',
|
'peer-checked:text-gray-900',
|
||||||
|
'peer-checked:font-semibold',
|
||||||
'peer-focus-visible:ring-2',
|
'peer-focus-visible:ring-2',
|
||||||
'peer-focus-visible:ring-primary-dark',
|
'peer-focus-visible:ring-primary',
|
||||||
'peer-focus-visible:ring-offset-2',
|
'peer-focus-visible:ring-offset-2',
|
||||||
'peer-focus-visible:ring-offset-surface',
|
'peer-focus-visible:ring-offset-surface',
|
||||||
]
|
]
|
||||||
|
|
||||||
// First segment
|
|
||||||
if (index === 0) {
|
|
||||||
classes.push('rounded-l-lg')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last segment
|
|
||||||
if (index === props.options.length - 1) {
|
|
||||||
classes.push('rounded-r-lg')
|
|
||||||
}
|
|
||||||
|
|
||||||
// All except last: add divider
|
// All except last: add divider
|
||||||
if (index < props.options.length - 1) {
|
if (index < props.options.length - 1) {
|
||||||
classes.push('border-r', 'border-primary-dark/40')
|
classes.push('border-r', 'border-white/10')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disabled state
|
// Disabled state
|
||||||
@@ -71,7 +64,7 @@ const getSegmentClasses = (index) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div role="radiogroup" :aria-label="name" class="inline-flex">
|
<div role="radiogroup" :aria-label="name" class="inline-flex rounded-lg overflow-hidden border border-white/10">
|
||||||
<label
|
<label
|
||||||
v-for="(option, index) in options"
|
v-for="(option, index) in options"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
|
|||||||
@@ -43,20 +43,33 @@ const scoreData = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const panelBorderClass = computed(() => {
|
||||||
|
if (props.score >= 10) return 'border-green-500/20'
|
||||||
|
if (props.score >= 5) return 'border-amber-500/20'
|
||||||
|
if (props.score >= 1) return 'border-red-500/20'
|
||||||
|
return 'border-white/10'
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="inline-flex items-center gap-3">
|
<div
|
||||||
|
v-if="visible"
|
||||||
|
class="inline-flex items-center gap-3 bg-white/5 backdrop-blur-sm border rounded-xl px-5 py-3 transition-all duration-500"
|
||||||
|
:class="panelBorderClass"
|
||||||
|
>
|
||||||
<div class="flex items-baseline gap-2">
|
<div class="flex items-baseline gap-2">
|
||||||
<span class="text-4xl font-bold" :class="scoreData.textClass">
|
<span class="text-3xl font-bold" :class="scoreData.textClass">
|
||||||
{{ score }}
|
{{ score }}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm text-gray-400">points</span>
|
<span class="text-xs uppercase tracking-wider text-gray-500">
|
||||||
|
points
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
scoreData.bgClass,
|
scoreData.bgClass,
|
||||||
'px-4 py-2 rounded-lg text-white font-semibold text-sm',
|
'px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider text-white shadow-sm',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ scoreData.label }}
|
{{ scoreData.label }}
|
||||||
|
|||||||
@@ -13,7 +13,16 @@ const pageTitle = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex flex-col">
|
<div class="min-h-screen flex flex-col">
|
||||||
<PageHeader :title="pageTitle" />
|
<PageHeader :title="pageTitle" />
|
||||||
<main class="flex-1">
|
|
||||||
|
<!-- Growth symbol watermark -->
|
||||||
|
<img
|
||||||
|
src="/images/growth-symbol.png"
|
||||||
|
alt=""
|
||||||
|
aria-hidden="true"
|
||||||
|
class="fixed bottom-0 right-0 w-[600px] translate-x-[15%] translate-y-[15%] opacity-[0.03] pointer-events-none select-none z-0"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<main class="flex-1 relative z-10">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -100,66 +100,77 @@ const hasScoredAnswers = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
<Head :title="`${session.category.name} Questionnaire`" />
|
<Head :title="`${session.category.name} Questionnaire`" />
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto px-4 py-8">
|
<div class="max-w-3xl mx-auto px-4 py-10">
|
||||||
<div class="flex items-center justify-between mb-6">
|
<!-- Title area -->
|
||||||
<h1 class="text-3xl font-bold text-white">{{ session.category.name }} Questionnaire</h1>
|
<div class="mb-10">
|
||||||
<ScoreIndicator :score="score" :visible="hasScoredAnswers" />
|
<div class="flex items-center justify-between">
|
||||||
|
<h1 class="text-2xl font-bold text-white">{{ session.category.name }} Questionnaire</h1>
|
||||||
|
<ScoreIndicator :score="score" :visible="hasScoredAnswers" />
|
||||||
|
</div>
|
||||||
|
<div class="h-px bg-gradient-to-r from-primary/40 via-primary/10 to-transparent mt-4"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- User Info Section -->
|
<div class="space-y-8">
|
||||||
<div class="bg-surface/50 rounded-lg p-6 mb-6">
|
<!-- User Info Section -->
|
||||||
<h2 class="text-xl font-semibold text-white mb-4">Basic Information</h2>
|
<div class="bg-white/[0.03] border border-white/[0.06] rounded-xl p-8">
|
||||||
|
<h2 class="text-lg font-semibold text-white mb-5">Basic Information</h2>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-sm font-medium text-gray-400 mb-1">Name</span>
|
<span class="block text-sm font-medium text-gray-400 mb-1">Name</span>
|
||||||
<span class="text-white">{{ session.user.name }}</span>
|
<span class="text-white text-[15px]">{{ session.user.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-sm font-medium text-gray-400 mb-1">Email</span>
|
<span class="block text-sm font-medium text-gray-400 mb-1">Email</span>
|
||||||
<span class="text-white">{{ session.user.email }}</span>
|
<span class="text-white text-[15px]">{{ session.user.email }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Question Groups -->
|
<!-- Question Groups -->
|
||||||
<div
|
<div
|
||||||
v-for="group in questionGroups"
|
v-for="group in questionGroups"
|
||||||
:key="group.id"
|
:key="group.id"
|
||||||
class="bg-surface/50 rounded-lg p-6 mb-6"
|
class="bg-white/[0.03] border border-white/[0.06] rounded-xl p-8"
|
||||||
>
|
>
|
||||||
<h2 class="text-xl font-semibold text-white mb-1">{{ group.name }}</h2>
|
<div class="flex items-center gap-3 mb-1">
|
||||||
<p v-if="group.description" class="text-gray-400 text-sm mb-2">{{ group.description }}</p>
|
<div class="w-2 h-2 rounded-full bg-primary/60"></div>
|
||||||
<p v-if="group.scoring_instructions" class="text-amber-400 text-sm italic mb-4">{{ group.scoring_instructions }}</p>
|
<h2 class="text-lg font-semibold text-white">{{ group.name }}</h2>
|
||||||
|
</div>
|
||||||
|
<p v-if="group.description" class="text-gray-400 text-sm mb-2">{{ group.description }}</p>
|
||||||
|
<p v-if="group.scoring_instructions" class="text-amber-400 text-sm italic mb-4">{{ group.scoring_instructions }}</p>
|
||||||
|
|
||||||
<div class="divide-y divide-gray-700">
|
<div class="divide-y divide-white/[0.06]">
|
||||||
<QuestionCard
|
<QuestionCard
|
||||||
v-for="question in group.questions"
|
v-for="question in group.questions"
|
||||||
:key="question.id"
|
:key="question.id"
|
||||||
:question="question"
|
:question="question"
|
||||||
:modelValue="answerData[question.id]"
|
:modelValue="answerData[question.id]"
|
||||||
@update:modelValue="updateAnswer(question.id, $event)"
|
@update:modelValue="updateAnswer(question.id, $event)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Additional Comments -->
|
<!-- Additional Comments -->
|
||||||
<div class="bg-surface/50 rounded-lg p-6 mb-6">
|
<div class="bg-white/[0.03] border border-white/[0.06] rounded-xl p-8">
|
||||||
<h2 class="text-xl font-semibold text-white mb-4">Additional Comments</h2>
|
<h2 class="text-lg font-semibold text-white mb-5">Additional Comments</h2>
|
||||||
<textarea
|
<textarea
|
||||||
v-model="additionalComments.additional_comments"
|
v-model="additionalComments.additional_comments"
|
||||||
@input="saveComments"
|
@input="saveComments"
|
||||||
rows="4"
|
rows="4"
|
||||||
class="w-full rounded-lg border border-gray-600 bg-surface px-3 py-2 text-white placeholder-gray-500 focus:border-primary focus:ring-1 focus:ring-primary"
|
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 any additional comments to support your decision..."
|
placeholder="Enter any additional comments to support your decision..."
|
||||||
></textarea>
|
></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Complete button - now enabled -->
|
<!-- Complete button - now enabled -->
|
||||||
<div class="flex justify-end mt-8">
|
<div class="mt-12 pt-8 border-t border-white/[0.06]">
|
||||||
<AppButton size="lg" @click="completeSession" data-cy="complete-session">
|
<div class="flex justify-end">
|
||||||
Complete
|
<AppButton size="lg" @click="completeSession" data-cy="complete-session">
|
||||||
</AppButton>
|
Complete
|
||||||
|
</AppButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user