plan implementation 6, 7, 8, 9, 10
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { Head } from '@inertiajs/vue3'
|
||||
import AppLayout from '@/Layouts/AppLayout.vue'
|
||||
import AppButton from '@/Components/AppButton.vue'
|
||||
@@ -10,19 +11,101 @@ const props = defineProps({
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
score: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
result: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
categoryName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const resultDisplay = computed(() => {
|
||||
switch (props.result) {
|
||||
case 'go':
|
||||
return {
|
||||
label: 'GO',
|
||||
description: 'Pursue this opportunity.',
|
||||
bgClass: 'bg-green-500/10 border-green-500/30',
|
||||
textClass: 'text-green-500',
|
||||
badgeClass: 'bg-green-500',
|
||||
}
|
||||
case 'consult_leadership':
|
||||
return {
|
||||
label: 'Consult Leadership',
|
||||
description: 'Speak to SL or SSL leadership before proceeding.',
|
||||
bgClass: 'bg-amber-500/10 border-amber-500/30',
|
||||
textClass: 'text-amber-500',
|
||||
badgeClass: 'bg-amber-500',
|
||||
}
|
||||
case 'no_go':
|
||||
default:
|
||||
return {
|
||||
label: 'NO GO',
|
||||
description: 'Do not pursue this opportunity.',
|
||||
bgClass: 'bg-red-500/10 border-red-500/30',
|
||||
textClass: 'text-red-500',
|
||||
badgeClass: 'bg-red-500',
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Session Result" />
|
||||
<Head :title="`${categoryName} - Result`" />
|
||||
|
||||
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||
<h1 class="text-3xl font-bold text-white mb-6">Session Result</h1>
|
||||
<h1 class="text-3xl font-bold text-white mb-6">{{ categoryName }} — Result</h1>
|
||||
|
||||
<div class="bg-surface/50 rounded-lg p-6 mb-8">
|
||||
<p class="text-gray-400 text-center">Your result will appear here</p>
|
||||
<!-- Result Card -->
|
||||
<div class="rounded-lg p-8 mb-8 border" :class="resultDisplay.bgClass">
|
||||
<div class="text-center">
|
||||
<div class="mb-4">
|
||||
<span
|
||||
class="inline-block px-6 py-3 rounded-lg text-white text-2xl font-bold"
|
||||
:class="resultDisplay.badgeClass"
|
||||
>
|
||||
{{ resultDisplay.label }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-5xl font-bold mb-2" :class="resultDisplay.textClass">
|
||||
{{ score }} points
|
||||
</p>
|
||||
<p class="text-gray-400 text-lg mt-4">
|
||||
{{ resultDisplay.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Session Details -->
|
||||
<div class="bg-surface/50 rounded-lg p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold text-white mb-4">Session Details</h2>
|
||||
<dl class="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<dt class="text-gray-400">Category</dt>
|
||||
<dd class="text-white font-medium">{{ categoryName }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-400">Client</dt>
|
||||
<dd class="text-white font-medium">{{ session.basic_info?.client_name ?? 'N/A' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-400">Lead Firm</dt>
|
||||
<dd class="text-white font-medium">{{ session.basic_info?.lead_firm_name ?? 'N/A' }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-gray-400">Completed</dt>
|
||||
<dd class="text-white font-medium">{{ new Date(session.completed_at).toLocaleDateString() }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<!-- Again button -->
|
||||
<div class="flex justify-center">
|
||||
<AppButton size="lg" href="/">
|
||||
Again
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<script setup>
|
||||
import { Head, router } from '@inertiajs/vue3'
|
||||
import { computed, reactive } from 'vue'
|
||||
import { Head, useForm, router } from '@inertiajs/vue3'
|
||||
import AppLayout from '@/Layouts/AppLayout.vue'
|
||||
import AppButton from '@/Components/AppButton.vue'
|
||||
import QuestionCard from '@/Components/QuestionCard.vue'
|
||||
import ScoreIndicator from '@/Components/ScoreIndicator.vue'
|
||||
|
||||
defineOptions({ layout: AppLayout })
|
||||
|
||||
@@ -10,33 +13,225 @@ const props = defineProps({
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
questionGroups: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
answers: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
score: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
})
|
||||
|
||||
const handleComplete = () => {
|
||||
router.put(`/sessions/${props.session.id}`)
|
||||
// Basic info form (unchanged from Step 8)
|
||||
const basicInfoForm = useForm({
|
||||
basic_info: {
|
||||
client_name: props.session.basic_info?.client_name ?? '',
|
||||
client_contact: props.session.basic_info?.client_contact ?? '',
|
||||
lead_firm_name: props.session.basic_info?.lead_firm_name ?? '',
|
||||
lead_firm_contact: props.session.basic_info?.lead_firm_contact ?? '',
|
||||
},
|
||||
})
|
||||
|
||||
const saveBasicInfo = () => {
|
||||
basicInfoForm.put(`/sessions/${props.session.id}`, {
|
||||
preserveScroll: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Answer management
|
||||
const answerData = reactive({})
|
||||
|
||||
// Initialize answers from existing data
|
||||
const initializeAnswers = () => {
|
||||
props.questionGroups.forEach(group => {
|
||||
group.questions.forEach(question => {
|
||||
const existing = props.answers[question.id]
|
||||
answerData[question.id] = {
|
||||
value: existing?.value ?? null,
|
||||
text_value: existing?.text_value ?? '',
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
initializeAnswers()
|
||||
|
||||
// Save a single answer with partial reload including score
|
||||
let saveTimeout = null
|
||||
const saveAnswer = (questionId) => {
|
||||
clearTimeout(saveTimeout)
|
||||
saveTimeout = setTimeout(() => {
|
||||
router.put(`/sessions/${props.session.id}`, {
|
||||
answers: {
|
||||
[questionId]: answerData[questionId],
|
||||
},
|
||||
}, {
|
||||
preserveScroll: true,
|
||||
preserveState: true,
|
||||
only: ['answers', 'score'],
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const updateAnswer = (questionId, newValue) => {
|
||||
answerData[questionId] = newValue
|
||||
saveAnswer(questionId)
|
||||
}
|
||||
|
||||
// Additional comments
|
||||
const additionalComments = useForm({
|
||||
additional_comments: props.session.additional_comments ?? '',
|
||||
})
|
||||
|
||||
let commentsTimeout = null
|
||||
const saveComments = () => {
|
||||
clearTimeout(commentsTimeout)
|
||||
commentsTimeout = setTimeout(() => {
|
||||
additionalComments.put(`/sessions/${props.session.id}`, {
|
||||
preserveScroll: true,
|
||||
preserveState: true,
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// Session completion
|
||||
let completing = false
|
||||
const completeSession = () => {
|
||||
completing = true
|
||||
router.put(`/sessions/${props.session.id}`, {
|
||||
complete: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Check if any scored answers have been given
|
||||
const hasScoredAnswers = computed(() => {
|
||||
return props.score > 0
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head :title="`${session.category.name} Questionnaire`" />
|
||||
|
||||
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||
<h1 class="text-3xl font-bold text-white mb-6">{{ session.category.name }} Questionnaire</h1>
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h1 class="text-3xl font-bold text-white">{{ session.category.name }} Questionnaire</h1>
|
||||
<ScoreIndicator :score="score" :visible="hasScoredAnswers" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="bg-surface/50 rounded-lg p-6">
|
||||
<h2 class="text-xl font-semibold text-white mb-4">Basic Info Form</h2>
|
||||
<p class="text-gray-400">Client and lead firm information will appear here</p>
|
||||
<!-- Basic Info Section (unchanged from Step 8) -->
|
||||
<div class="bg-surface/50 rounded-lg p-6 mb-6">
|
||||
<h2 class="text-xl font-semibold text-white mb-4">Basic Information</h2>
|
||||
<p class="text-gray-400 text-sm mb-6">All fields are required before you can proceed to the questionnaire.</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label for="client_name" class="block text-sm font-medium text-gray-400 mb-1">Client Name</label>
|
||||
<input
|
||||
id="client_name"
|
||||
v-model="basicInfoForm.basic_info.client_name"
|
||||
type="text"
|
||||
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"
|
||||
placeholder="Enter client name"
|
||||
/>
|
||||
<p v-if="basicInfoForm.errors['basic_info.client_name']" class="text-red-500 text-sm mt-1">
|
||||
{{ basicInfoForm.errors['basic_info.client_name'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="client_contact" class="block text-sm font-medium text-gray-400 mb-1">Client Contact</label>
|
||||
<input
|
||||
id="client_contact"
|
||||
v-model="basicInfoForm.basic_info.client_contact"
|
||||
type="text"
|
||||
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"
|
||||
placeholder="Enter client contact"
|
||||
/>
|
||||
<p v-if="basicInfoForm.errors['basic_info.client_contact']" class="text-red-500 text-sm mt-1">
|
||||
{{ basicInfoForm.errors['basic_info.client_contact'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="lead_firm_name" class="block text-sm font-medium text-gray-400 mb-1">Lead Firm Name</label>
|
||||
<input
|
||||
id="lead_firm_name"
|
||||
v-model="basicInfoForm.basic_info.lead_firm_name"
|
||||
type="text"
|
||||
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"
|
||||
placeholder="Enter lead firm name"
|
||||
/>
|
||||
<p v-if="basicInfoForm.errors['basic_info.lead_firm_name']" class="text-red-500 text-sm mt-1">
|
||||
{{ basicInfoForm.errors['basic_info.lead_firm_name'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="lead_firm_contact" class="block text-sm font-medium text-gray-400 mb-1">Lead Firm Contact</label>
|
||||
<input
|
||||
id="lead_firm_contact"
|
||||
v-model="basicInfoForm.basic_info.lead_firm_contact"
|
||||
type="text"
|
||||
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"
|
||||
placeholder="Enter lead firm contact"
|
||||
/>
|
||||
<p v-if="basicInfoForm.errors['basic_info.lead_firm_contact']" class="text-red-500 text-sm mt-1">
|
||||
{{ basicInfoForm.errors['basic_info.lead_firm_contact'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-surface/50 rounded-lg p-6">
|
||||
<h2 class="text-xl font-semibold text-white mb-4">Questions</h2>
|
||||
<p class="text-gray-400">Category questions will appear here</p>
|
||||
<div class="flex justify-end mt-6">
|
||||
<AppButton
|
||||
@click="saveBasicInfo"
|
||||
:loading="basicInfoForm.processing"
|
||||
:disabled="basicInfoForm.processing"
|
||||
>
|
||||
Save Basic Info
|
||||
</AppButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Question Groups -->
|
||||
<div
|
||||
v-for="group in questionGroups"
|
||||
:key="group.id"
|
||||
class="bg-surface/50 rounded-lg p-6 mb-6"
|
||||
>
|
||||
<h2 class="text-xl font-semibold text-white mb-1">{{ group.name }}</h2>
|
||||
<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">
|
||||
<QuestionCard
|
||||
v-for="question in group.questions"
|
||||
:key="question.id"
|
||||
:question="question"
|
||||
:modelValue="answerData[question.id]"
|
||||
@update:modelValue="updateAnswer(question.id, $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Additional Comments -->
|
||||
<div class="bg-surface/50 rounded-lg p-6 mb-6">
|
||||
<h2 class="text-xl font-semibold text-white mb-4">Additional Comments</h2>
|
||||
<textarea
|
||||
v-model="additionalComments.additional_comments"
|
||||
@input="saveComments"
|
||||
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"
|
||||
placeholder="Enter any additional comments to support your decision..."
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Complete button - now enabled -->
|
||||
<div class="flex justify-end mt-8">
|
||||
<AppButton size="lg" @click="handleComplete">
|
||||
<AppButton size="lg" @click="completeSession">
|
||||
Complete
|
||||
</AppButton>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user