mirror of
https://github.com/lukaszraczylo/beat-delivery-methodology.git
synced 2026-06-09 23:04:13 +00:00
Add assessment page.
This commit is contained in:
@@ -14,7 +14,8 @@ const navItems = [
|
||||
{ path: '/practices', label: 'Practices' },
|
||||
{ path: '/onboarding', label: 'Onboarding' },
|
||||
{ path: '/anti-patterns', label: 'Anti-Patterns' },
|
||||
{ path: '/reference', label: 'Reference' }
|
||||
{ path: '/reference', label: 'Reference' },
|
||||
{ path: '/assessment', label: 'Assessment' }
|
||||
]
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
export const assessmentCategories = [
|
||||
{
|
||||
id: 'focus',
|
||||
title: 'Focus & Deep Work',
|
||||
icon: 'fas fa-brain',
|
||||
gradient: 'from-blue-500 to-cyan-500',
|
||||
color: 'blue'
|
||||
},
|
||||
{
|
||||
id: 'communication',
|
||||
title: 'Communication',
|
||||
icon: 'fas fa-comments',
|
||||
gradient: 'from-purple-500 to-pink-500',
|
||||
color: 'purple'
|
||||
},
|
||||
{
|
||||
id: 'autonomy',
|
||||
title: 'Autonomy & Trust',
|
||||
icon: 'fas fa-user-shield',
|
||||
gradient: 'from-green-500 to-emerald-500',
|
||||
color: 'green'
|
||||
},
|
||||
{
|
||||
id: 'sustainability',
|
||||
title: 'Sustainability',
|
||||
icon: 'fas fa-leaf',
|
||||
gradient: 'from-amber-500 to-orange-500',
|
||||
color: 'amber'
|
||||
}
|
||||
]
|
||||
|
||||
export const assessmentQuestions = [
|
||||
// Focus & Deep Work
|
||||
{
|
||||
id: 1,
|
||||
category: 'focus',
|
||||
question: 'How often do you get uninterrupted blocks of 2+ hours for focused work?',
|
||||
options: [
|
||||
{ value: 1, label: 'Rarely or never', description: 'Constant interruptions throughout the day' },
|
||||
{ value: 2, label: 'Sometimes', description: 'Maybe once or twice a week' },
|
||||
{ value: 3, label: 'Often', description: 'Most days I can find some focus time' },
|
||||
{ value: 4, label: 'Always', description: 'I have protected focus blocks daily' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
category: 'focus',
|
||||
question: 'How many meetings do you have in a typical week?',
|
||||
options: [
|
||||
{ value: 1, label: '10+ hours', description: 'Meetings dominate my calendar' },
|
||||
{ value: 2, label: '5-10 hours', description: 'Significant meeting load' },
|
||||
{ value: 3, label: '2-5 hours', description: 'Moderate amount of meetings' },
|
||||
{ value: 4, label: 'Under 2 hours', description: 'Minimal meeting time' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
category: 'focus',
|
||||
question: 'How is productivity measured on your team?',
|
||||
options: [
|
||||
{ value: 1, label: 'Hours worked / time online', description: 'Presence-based metrics' },
|
||||
{ value: 2, label: 'Tasks completed / velocity', description: 'Activity-based metrics' },
|
||||
{ value: 3, label: 'Mix of activity and outcomes', description: 'Some outcome focus' },
|
||||
{ value: 4, label: 'Outcomes delivered', description: 'Results matter, not hours' }
|
||||
]
|
||||
},
|
||||
|
||||
// Communication
|
||||
{
|
||||
id: 4,
|
||||
category: 'communication',
|
||||
question: 'How are most decisions communicated and documented?',
|
||||
options: [
|
||||
{ value: 1, label: 'Verbal only', description: 'Discussed but rarely written down' },
|
||||
{ value: 2, label: 'Scattered notes', description: 'Some docs, but hard to find' },
|
||||
{ value: 3, label: 'Mostly documented', description: 'Important decisions get written' },
|
||||
{ value: 4, label: 'Always written first', description: 'Write-first culture' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
category: 'communication',
|
||||
question: 'What\'s the expected response time to messages?',
|
||||
options: [
|
||||
{ value: 1, label: 'Immediate', description: 'Expected to respond within minutes' },
|
||||
{ value: 2, label: 'Within hours', description: 'Same-day responses expected' },
|
||||
{ value: 3, label: 'Within a day', description: '24-hour response is acceptable' },
|
||||
{ value: 4, label: 'Async-friendly', description: 'Response when working, no pressure' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
category: 'communication',
|
||||
question: 'How are urgent issues escalated?',
|
||||
options: [
|
||||
{ value: 1, label: 'Everything is urgent', description: 'No clear priority system' },
|
||||
{ value: 2, label: 'Depends on who\'s asking', description: 'Urgency varies by person' },
|
||||
{ value: 3, label: 'Some prioritization', description: 'We try to triage' },
|
||||
{ value: 4, label: 'Clear escalation path', description: 'Urgent = phone, else async' }
|
||||
]
|
||||
},
|
||||
|
||||
// Autonomy & Trust
|
||||
{
|
||||
id: 7,
|
||||
category: 'autonomy',
|
||||
question: 'How is work assigned to team members?',
|
||||
options: [
|
||||
{ value: 1, label: 'Top-down assignment', description: 'Manager decides who does what' },
|
||||
{ value: 2, label: 'Mostly assigned', description: 'Some choice, but limited' },
|
||||
{ value: 3, label: 'Collaborative', description: 'Team discusses, then assigns' },
|
||||
{ value: 4, label: 'Pull-based', description: 'Developers choose from prioritized work' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
category: 'autonomy',
|
||||
question: 'Can developers choose their own tools and approaches?',
|
||||
options: [
|
||||
{ value: 1, label: 'No', description: 'Strict standardization' },
|
||||
{ value: 2, label: 'Limited', description: 'Some flexibility within constraints' },
|
||||
{ value: 3, label: 'Mostly yes', description: 'Freedom with guidelines' },
|
||||
{ value: 4, label: 'Full autonomy', description: 'Trust makers to make decisions' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
category: 'autonomy',
|
||||
question: 'Can team members push back on work they disagree with?',
|
||||
options: [
|
||||
{ value: 1, label: 'No', description: 'Expected to comply' },
|
||||
{ value: 2, label: 'Discouraged', description: 'Possible but not welcomed' },
|
||||
{ value: 3, label: 'Sometimes', description: 'Depends on the situation' },
|
||||
{ value: 4, label: 'Encouraged', description: 'Challenges are valued' }
|
||||
]
|
||||
},
|
||||
|
||||
// Sustainability
|
||||
{
|
||||
id: 10,
|
||||
category: 'sustainability',
|
||||
question: 'How often does your team work overtime?',
|
||||
options: [
|
||||
{ value: 1, label: 'Frequently', description: 'Overtime is normal' },
|
||||
{ value: 2, label: 'Often', description: 'Regular crunch periods' },
|
||||
{ value: 3, label: 'Sometimes', description: 'Occasional overtime' },
|
||||
{ value: 4, label: 'Rarely', description: 'Sustainable pace is protected' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
category: 'sustainability',
|
||||
question: 'What happens when deadlines conflict with capacity?',
|
||||
options: [
|
||||
{ value: 1, label: 'Work harder', description: 'Team pushes through' },
|
||||
{ value: 2, label: 'Negotiate later', description: 'Promise now, adjust later' },
|
||||
{ value: 3, label: 'Discuss options', description: 'Some scope flexibility' },
|
||||
{ value: 4, label: 'Cut scope', description: 'We never cut rest, only scope' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
category: 'sustainability',
|
||||
question: 'Do team members have time for learning and exploration?',
|
||||
options: [
|
||||
{ value: 1, label: 'No', description: 'Always feature work' },
|
||||
{ value: 2, label: 'Personal time only', description: 'Learning is on your own time' },
|
||||
{ value: 3, label: 'Sometimes', description: 'When we have slack' },
|
||||
{ value: 4, label: 'Protected time', description: '20% for exploration built in' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
export const beatRecommendations = {
|
||||
focus: {
|
||||
low: {
|
||||
title: 'Your Focus is Under Attack',
|
||||
description: 'Constant interruptions and meetings are destroying your team\'s ability to do deep work. Research shows it takes 52 minutes to reach focus and 23 minutes to recover from interruption.',
|
||||
recommendations: [
|
||||
'Establish 4-hour daily sacred blocks where no meetings or interruptions are allowed',
|
||||
'Limit meetings to 2 hours per week maximum',
|
||||
'Measure outcomes, not hours worked or time online',
|
||||
'Let makers choose when their focus time occurs'
|
||||
],
|
||||
beatPrinciple: 'Protect the focus state above all else. The uninterrupted mind produces the best work.'
|
||||
},
|
||||
medium: {
|
||||
title: 'Focus Needs Protection',
|
||||
description: 'You have some focus time, but it\'s inconsistent. With more structure, your team could dramatically increase productivity.',
|
||||
recommendations: [
|
||||
'Formalize sacred blocks and make them non-negotiable',
|
||||
'Audit your meeting calendar - can 50% become async?',
|
||||
'Create clear signals for when someone is in focus mode',
|
||||
'Track interruption patterns and address the sources'
|
||||
],
|
||||
beatPrinciple: 'Presence does not equal productivity. A maker in focus for four hours outproduces a maker in meetings for eight.'
|
||||
},
|
||||
high: {
|
||||
title: 'Strong Focus Culture',
|
||||
description: 'Your team values deep work. BEAT can help you maintain and strengthen this culture as you scale.',
|
||||
recommendations: [
|
||||
'Document your focus practices for new team members',
|
||||
'Continue protecting what\'s working',
|
||||
'Share your approach with other teams',
|
||||
'Watch for gradual erosion of focus time'
|
||||
],
|
||||
beatPrinciple: 'Interruptions are not free. Every "quick question" costs more than it appears.'
|
||||
}
|
||||
},
|
||||
communication: {
|
||||
low: {
|
||||
title: 'Communication is Chaotic',
|
||||
description: 'Without written documentation and async practices, knowledge is lost, decisions are forgotten, and everyone stays chained to chat.',
|
||||
recommendations: [
|
||||
'Adopt a "write first" policy for all decisions',
|
||||
'Set expectation: responses within 24 working hours, not minutes',
|
||||
'Create clear channels: urgent = phone, everything else waits',
|
||||
'Replace daily standups with written async check-ins'
|
||||
],
|
||||
beatPrinciple: 'Writing is thinking made visible. Decisions not documented did not happen.'
|
||||
},
|
||||
medium: {
|
||||
title: 'Communication Needs Structure',
|
||||
description: 'You have some good practices, but inconsistency leads to confusion about when to interrupt vs. when to wait.',
|
||||
recommendations: [
|
||||
'Define clear response time expectations',
|
||||
'Create templates for common communication (check-ins, decisions)',
|
||||
'Establish when sync communication is appropriate',
|
||||
'Build a searchable knowledge base'
|
||||
],
|
||||
beatPrinciple: 'Synchronous time is expensive. Spend it wisely. If it can be written, write it.'
|
||||
},
|
||||
high: {
|
||||
title: 'Effective Async Communication',
|
||||
description: 'Your team communicates well asynchronously. Keep refining and documenting these practices.',
|
||||
recommendations: [
|
||||
'Mentor other teams in async practices',
|
||||
'Continuously improve documentation',
|
||||
'Maintain clear escalation paths',
|
||||
'Review and prune old documentation regularly'
|
||||
],
|
||||
beatPrinciple: 'Response time is not reaction time. Async means responding when working, not responding immediately.'
|
||||
}
|
||||
},
|
||||
autonomy: {
|
||||
low: {
|
||||
title: 'Trust is Missing',
|
||||
description: 'Top-down control stifles creativity and ownership. Developers who can\'t make decisions become disengaged and stop innovating.',
|
||||
recommendations: [
|
||||
'Shift from assigning work to letting developers pull work',
|
||||
'Provide goals and constraints, not detailed instructions',
|
||||
'Trust makers to choose their tools and approaches',
|
||||
'Create safe space for pushing back on poorly conceived work'
|
||||
],
|
||||
beatPrinciple: 'Trust makers to make. Those who build the thing decide how to build it.'
|
||||
},
|
||||
medium: {
|
||||
title: 'Autonomy is Inconsistent',
|
||||
description: 'Some freedom exists, but it varies. Building genuine trust requires consistent practices.',
|
||||
recommendations: [
|
||||
'Define clear boundaries: what decisions can makers own?',
|
||||
'Make "pull not push" the default for work assignment',
|
||||
'Encourage challenges and alternative proposals',
|
||||
'Remove approval bottlenecks where possible'
|
||||
],
|
||||
beatPrinciple: 'The maker\'s "no" is valid. This is not insubordination—it is ownership.'
|
||||
},
|
||||
high: {
|
||||
title: 'High-Trust Environment',
|
||||
description: 'Your team operates with real autonomy. This is rare and valuable—protect it.',
|
||||
recommendations: [
|
||||
'Document how autonomy works for new members',
|
||||
'Guard against creeping micromanagement',
|
||||
'Share your culture openly',
|
||||
'Continue empowering individual decision-making'
|
||||
],
|
||||
beatPrinciple: 'Pull, don\'t push. Work is not assigned. Work is pulled by those with capacity and interest.'
|
||||
}
|
||||
},
|
||||
sustainability: {
|
||||
low: {
|
||||
title: 'Burnout Risk is High',
|
||||
description: 'Regular overtime and no time for learning is a recipe for burnout, turnover, and declining quality.',
|
||||
recommendations: [
|
||||
'Plan at 80% capacity, leaving slack for life',
|
||||
'When deadlines conflict, cut scope—never cut rest',
|
||||
'Protect 20% time for learning and exploration',
|
||||
'Make overtime a red flag, not a badge of honor'
|
||||
],
|
||||
beatPrinciple: 'Sustainable pace is not optional. Overtime is a red flag, not a badge of honor.'
|
||||
},
|
||||
medium: {
|
||||
title: 'Sustainability Needs Attention',
|
||||
description: 'You\'re managing, but there are warning signs. Building in more slack now prevents bigger problems later.',
|
||||
recommendations: [
|
||||
'Track overtime patterns and address root causes',
|
||||
'Formally protect exploration time',
|
||||
'Review capacity planning—are you over 80%?',
|
||||
'Watch for burnout warning signs'
|
||||
],
|
||||
beatPrinciple: 'The team\'s health is the Enabler\'s responsibility. Someone must watch for warning signs.'
|
||||
},
|
||||
high: {
|
||||
title: 'Sustainable Pace Culture',
|
||||
description: 'Your team has built healthy work habits. This enables long-term high performance.',
|
||||
recommendations: [
|
||||
'Maintain your boundaries under pressure',
|
||||
'Help other teams learn sustainable practices',
|
||||
'Continue investing in learning time',
|
||||
'Celebrate sustainable delivery over heroics'
|
||||
],
|
||||
beatPrinciple: 'Exploration time is not a reward. It is a requirement. This is how we stay sharp.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const overallAssessment = {
|
||||
struggling: {
|
||||
range: [12, 24],
|
||||
title: 'Significant Opportunity for Improvement',
|
||||
icon: 'fas fa-exclamation-triangle',
|
||||
color: 'red',
|
||||
description: 'Your team faces significant challenges that BEAT is designed to solve. The good news: there\'s tremendous potential for improvement.',
|
||||
callToAction: 'Start with the biggest pain point. Small changes compound over time.'
|
||||
},
|
||||
developing: {
|
||||
range: [25, 36],
|
||||
title: 'Building Better Practices',
|
||||
icon: 'fas fa-seedling',
|
||||
color: 'amber',
|
||||
description: 'Your team has some good foundations but inconsistent practices. BEAT can provide the structure to level up.',
|
||||
callToAction: 'Focus on making existing good practices consistent and documented.'
|
||||
},
|
||||
strong: {
|
||||
range: [37, 42],
|
||||
title: 'Strong Foundation',
|
||||
icon: 'fas fa-chart-line',
|
||||
color: 'blue',
|
||||
description: 'Your team already practices many BEAT principles. Formalizing them will help you scale and onboard new members.',
|
||||
callToAction: 'Document what works and share it with your organization.'
|
||||
},
|
||||
excellent: {
|
||||
range: [43, 48],
|
||||
title: 'BEAT-Ready Team',
|
||||
icon: 'fas fa-star',
|
||||
color: 'green',
|
||||
description: 'Congratulations! Your team is already aligned with BEAT principles. Consider adopting the framework formally.',
|
||||
callToAction: 'You\'re ready to fully adopt BEAT and become ambassadors for these practices.'
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,11 @@ const routes = [
|
||||
path: '/reference',
|
||||
name: 'Reference',
|
||||
component: () => import('@/views/ReferenceView.vue')
|
||||
},
|
||||
{
|
||||
path: '/assessment',
|
||||
name: 'Assessment',
|
||||
component: () => import('@/views/AssessmentView.vue')
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { assessmentCategories, assessmentQuestions, beatRecommendations, overallAssessment } from '@/data/assessment'
|
||||
|
||||
const currentStep = ref(0) // 0 = intro, 1-12 = questions, 13 = results
|
||||
const answers = ref({})
|
||||
const showResults = ref(false)
|
||||
|
||||
const totalQuestions = assessmentQuestions.length
|
||||
const currentQuestion = computed(() => assessmentQuestions[currentStep.value - 1])
|
||||
const progress = computed(() => Math.round((Object.keys(answers.value).length / totalQuestions) * 100))
|
||||
|
||||
const startAssessment = () => {
|
||||
currentStep.value = 1
|
||||
answers.value = {}
|
||||
showResults.value = false
|
||||
}
|
||||
|
||||
const selectAnswer = (questionId, value) => {
|
||||
answers.value[questionId] = value
|
||||
if (currentStep.value < totalQuestions) {
|
||||
setTimeout(() => {
|
||||
currentStep.value++
|
||||
}, 300)
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
showResults.value = true
|
||||
currentStep.value = totalQuestions + 1
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
if (currentStep.value > 1) {
|
||||
currentStep.value--
|
||||
}
|
||||
}
|
||||
|
||||
const restartAssessment = () => {
|
||||
currentStep.value = 0
|
||||
answers.value = {}
|
||||
showResults.value = false
|
||||
}
|
||||
|
||||
// Calculate scores
|
||||
const categoryScores = computed(() => {
|
||||
const scores = {}
|
||||
assessmentCategories.forEach(cat => {
|
||||
const categoryQuestions = assessmentQuestions.filter(q => q.category === cat.id)
|
||||
const categoryAnswers = categoryQuestions.map(q => answers.value[q.id] || 0)
|
||||
const total = categoryAnswers.reduce((a, b) => a + b, 0)
|
||||
const max = categoryQuestions.length * 4
|
||||
scores[cat.id] = {
|
||||
score: total,
|
||||
max,
|
||||
percentage: Math.round((total / max) * 100),
|
||||
level: total <= max * 0.4 ? 'low' : total <= max * 0.7 ? 'medium' : 'high'
|
||||
}
|
||||
})
|
||||
return scores
|
||||
})
|
||||
|
||||
const totalScore = computed(() => {
|
||||
return Object.values(answers.value).reduce((a, b) => a + b, 0)
|
||||
})
|
||||
|
||||
const overallLevel = computed(() => {
|
||||
const score = totalScore.value
|
||||
if (score <= 24) return overallAssessment.struggling
|
||||
if (score <= 36) return overallAssessment.developing
|
||||
if (score <= 42) return overallAssessment.strong
|
||||
return overallAssessment.excellent
|
||||
})
|
||||
|
||||
const getRecommendation = (categoryId) => {
|
||||
const level = categoryScores.value[categoryId]?.level || 'low'
|
||||
return beatRecommendations[categoryId][level]
|
||||
}
|
||||
|
||||
const colorClasses = {
|
||||
blue: {
|
||||
bg: 'bg-blue-50 dark:bg-blue-900/20',
|
||||
border: 'border-blue-200 dark:border-blue-800',
|
||||
text: 'text-blue-600 dark:text-blue-400',
|
||||
gradient: 'from-blue-500 to-blue-600',
|
||||
progress: 'bg-blue-500'
|
||||
},
|
||||
purple: {
|
||||
bg: 'bg-purple-50 dark:bg-purple-900/20',
|
||||
border: 'border-purple-200 dark:border-purple-800',
|
||||
text: 'text-purple-600 dark:text-purple-400',
|
||||
gradient: 'from-purple-500 to-purple-600',
|
||||
progress: 'bg-purple-500'
|
||||
},
|
||||
green: {
|
||||
bg: 'bg-green-50 dark:bg-green-900/20',
|
||||
border: 'border-green-200 dark:border-green-800',
|
||||
text: 'text-green-600 dark:text-green-400',
|
||||
gradient: 'from-green-500 to-green-600',
|
||||
progress: 'bg-green-500'
|
||||
},
|
||||
amber: {
|
||||
bg: 'bg-amber-50 dark:bg-amber-900/20',
|
||||
border: 'border-amber-200 dark:border-amber-800',
|
||||
text: 'text-amber-600 dark:text-amber-400',
|
||||
gradient: 'from-amber-500 to-amber-600',
|
||||
progress: 'bg-amber-500'
|
||||
},
|
||||
red: {
|
||||
bg: 'bg-red-50 dark:bg-red-900/20',
|
||||
border: 'border-red-200 dark:border-red-800',
|
||||
text: 'text-red-600 dark:text-red-400',
|
||||
gradient: 'from-red-500 to-red-600',
|
||||
progress: 'bg-red-500'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50 dark:from-gray-900 dark:via-indigo-900/10 dark:to-purple-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-indigo-300 dark:bg-indigo-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-purple-300 dark:bg-purple-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-clipboard-check text-white text-2xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Team Assessment</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
Discover how BEAT can help your team deliver better and faster.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Intro Screen -->
|
||||
<section v-if="currentStep === 0" class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<div class="glass p-6 sm:p-8 rounded-2xl text-center">
|
||||
<div class="w-20 h-20 rounded-full bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center mx-auto mb-6">
|
||||
<i class="fas fa-tasks text-white text-3xl"></i>
|
||||
</div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
How BEAT-Ready is Your Team?
|
||||
</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6 leading-relaxed">
|
||||
Answer 12 quick questions about your current practices. We'll analyze your responses and show you specifically how BEAT principles can help your team.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-8">
|
||||
<div v-for="cat in assessmentCategories" :key="cat.id" class="p-3 rounded-lg" :class="colorClasses[cat.color].bg">
|
||||
<i :class="[cat.icon, colorClasses[cat.color].text]" class="text-xl mb-2"></i>
|
||||
<div class="text-xs text-gray-600 dark:text-gray-400">{{ cat.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center justify-center gap-3 sm:gap-4 text-xs sm:text-sm text-gray-500 dark:text-gray-500 mb-6">
|
||||
<span><i class="fas fa-clock mr-1"></i> 3-5 min</span>
|
||||
<span><i class="fas fa-shield-alt mr-1"></i> Anonymous</span>
|
||||
<span><i class="fas fa-chart-bar mr-1"></i> Instant results</span>
|
||||
</div>
|
||||
|
||||
<button @click="startAssessment" class="btn-primary w-full sm:w-auto">
|
||||
<i class="fas fa-play mr-2"></i>
|
||||
Start Assessment
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Question Screen -->
|
||||
<section v-else-if="!showResults" class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between text-sm text-gray-600 dark:text-gray-400 mb-2">
|
||||
<span>Question {{ currentStep }} of {{ totalQuestions }}</span>
|
||||
<span>{{ progress }}% complete</span>
|
||||
</div>
|
||||
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full bg-gradient-to-r from-indigo-500 to-purple-500 transition-all duration-500 ease-out rounded-full"
|
||||
:style="{ width: `${progress}%` }"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Badge -->
|
||||
<div class="mb-4">
|
||||
<span
|
||||
class="inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs font-medium"
|
||||
:class="[colorClasses[assessmentCategories.find(c => c.id === currentQuestion.category)?.color || 'blue'].bg, colorClasses[assessmentCategories.find(c => c.id === currentQuestion.category)?.color || 'blue'].text]"
|
||||
>
|
||||
<i :class="assessmentCategories.find(c => c.id === currentQuestion.category)?.icon"></i>
|
||||
{{ assessmentCategories.find(c => c.id === currentQuestion.category)?.title }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Question Card -->
|
||||
<div class="glass p-6 sm:p-8 rounded-2xl">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-6">
|
||||
{{ currentQuestion.question }}
|
||||
</h2>
|
||||
|
||||
<div class="space-y-3">
|
||||
<button
|
||||
v-for="option in currentQuestion.options"
|
||||
:key="option.value"
|
||||
@click="selectAnswer(currentQuestion.id, option.value)"
|
||||
class="w-full p-4 rounded-xl border-2 text-left transition-all duration-200 hover:shadow-md min-h-[60px]"
|
||||
:class="[
|
||||
answers[currentQuestion.id] === option.value
|
||||
? 'border-indigo-500 bg-indigo-50 dark:bg-indigo-900/20'
|
||||
: 'border-gray-200 dark:border-gray-700 hover:border-indigo-300 dark:hover:border-indigo-600'
|
||||
]"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div
|
||||
class="w-6 h-6 rounded-full border-2 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
:class="[
|
||||
answers[currentQuestion.id] === option.value
|
||||
? 'border-indigo-500 bg-indigo-500'
|
||||
: 'border-gray-300 dark:border-gray-600'
|
||||
]"
|
||||
>
|
||||
<i v-if="answers[currentQuestion.id] === option.value" class="fas fa-check text-white text-xs"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-gray-900 dark:text-gray-100">{{ option.label }}</div>
|
||||
<div class="text-sm text-gray-500 dark:text-gray-500">{{ option.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between mt-6 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<button
|
||||
v-if="currentStep > 1"
|
||||
@click="goBack"
|
||||
class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors min-w-[44px] min-h-[44px] px-3 sm:px-4 py-2 flex items-center justify-center"
|
||||
>
|
||||
<i class="fas fa-arrow-left mr-2"></i>
|
||||
<span class="hidden sm:inline">Back</span>
|
||||
</button>
|
||||
<div v-else></div>
|
||||
|
||||
<div class="hidden sm:flex items-center gap-1">
|
||||
<div
|
||||
v-for="i in totalQuestions"
|
||||
:key="i"
|
||||
class="w-2 h-2 rounded-full transition-colors"
|
||||
:class="[
|
||||
i === currentStep ? 'bg-indigo-500' :
|
||||
answers[i] ? 'bg-indigo-300 dark:bg-indigo-700' :
|
||||
'bg-gray-300 dark:bg-gray-600'
|
||||
]"
|
||||
></div>
|
||||
</div>
|
||||
<div class="sm:hidden text-sm text-gray-500 dark:text-gray-500">
|
||||
{{ currentStep }}/{{ totalQuestions }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Results Screen -->
|
||||
<section v-else class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<!-- Overall Score -->
|
||||
<div class="glass p-6 sm:p-8 rounded-2xl mb-8 text-center">
|
||||
<div
|
||||
class="w-20 h-20 rounded-full flex items-center justify-center mx-auto mb-4"
|
||||
:class="colorClasses[overallLevel.color].bg"
|
||||
>
|
||||
<i :class="[overallLevel.icon, colorClasses[overallLevel.color].text]" class="text-3xl"></i>
|
||||
</div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2">
|
||||
{{ overallLevel.title }}
|
||||
</h2>
|
||||
<div class="text-3xl sm:text-4xl font-bold gradient-text mb-4">
|
||||
{{ totalScore }} / 48
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-400 max-w-xl mx-auto mb-4">
|
||||
{{ overallLevel.description }}
|
||||
</p>
|
||||
<div
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg"
|
||||
:class="[colorClasses[overallLevel.color].bg, colorClasses[overallLevel.color].border]"
|
||||
>
|
||||
<i class="fas fa-lightbulb" :class="colorClasses[overallLevel.color].text"></i>
|
||||
<span class="text-sm font-medium" :class="colorClasses[overallLevel.color].text">{{ overallLevel.callToAction }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Breakdown -->
|
||||
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Category Breakdown</h3>
|
||||
<div class="grid sm:grid-cols-2 gap-4 mb-8">
|
||||
<div
|
||||
v-for="cat in assessmentCategories"
|
||||
:key="cat.id"
|
||||
class="glass p-5 rounded-xl"
|
||||
>
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div
|
||||
class="w-10 h-10 rounded-lg bg-gradient-to-br flex items-center justify-center"
|
||||
:class="cat.gradient"
|
||||
>
|
||||
<i :class="cat.icon" class="text-white"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100">{{ cat.title }}</div>
|
||||
<div class="text-sm" :class="colorClasses[cat.color].text">
|
||||
{{ categoryScores[cat.id]?.percentage }}% ({{ categoryScores[cat.id]?.score }}/{{ categoryScores[cat.id]?.max }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full rounded-full transition-all duration-500"
|
||||
:class="colorClasses[cat.color].progress"
|
||||
:style="{ width: `${categoryScores[cat.id]?.percentage}%` }"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detailed Recommendations -->
|
||||
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">How BEAT Can Help</h3>
|
||||
<div class="space-y-6">
|
||||
<div
|
||||
v-for="cat in assessmentCategories"
|
||||
:key="cat.id"
|
||||
class="glass p-5 sm:p-6 rounded-xl"
|
||||
>
|
||||
<div class="flex items-start gap-4 mb-4">
|
||||
<div
|
||||
class="w-12 h-12 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
:class="cat.gradient"
|
||||
>
|
||||
<i :class="cat.icon" class="text-white text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-bold text-gray-900 dark:text-gray-100">{{ getRecommendation(cat.id).title }}</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">{{ getRecommendation(cat.id).description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 mb-4">
|
||||
<div
|
||||
v-for="rec in getRecommendation(cat.id).recommendations"
|
||||
:key="rec"
|
||||
class="flex items-start gap-3 p-3 rounded-lg"
|
||||
:class="colorClasses[cat.color].bg"
|
||||
>
|
||||
<i class="fas fa-check-circle mt-0.5" :class="colorClasses[cat.color].text"></i>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ rec }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-3 p-3 rounded-lg bg-gray-50 dark:bg-gray-800 border-l-4" :class="colorClasses[cat.color].border">
|
||||
<i class="fas fa-quote-left text-gray-400 mt-1"></i>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 italic">{{ getRecommendation(cat.id).beatPrinciple }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CTA -->
|
||||
<div class="mt-8 p-6 sm:p-8 rounded-2xl bg-gradient-to-br from-indigo-600 via-purple-600 to-pink-600 text-center">
|
||||
<h3 class="text-xl sm:text-2xl font-bold text-white mb-3">Ready to Transform Your Team?</h3>
|
||||
<p class="text-white/80 mb-6 max-w-xl mx-auto">
|
||||
Explore the full BEAT manifesto and start implementing these practices today.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<RouterLink to="/values" class="bg-white text-indigo-600 px-6 py-3 rounded-lg font-medium hover:bg-gray-100 transition-colors min-h-[44px] flex items-center justify-center">
|
||||
<i class="fas fa-book-open mr-2"></i>
|
||||
Read the Manifesto
|
||||
</RouterLink>
|
||||
<button @click="restartAssessment" class="bg-white/20 text-white px-6 py-3 rounded-lg font-medium hover:bg-white/30 transition-colors min-h-[44px] flex items-center justify-center">
|
||||
<i class="fas fa-redo mr-2"></i>
|
||||
Retake Assessment
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user