import { useRef, useState, useEffect } from 'react'
import { motion } from 'framer-motion'
import type { Skill } from '../types'
import { calculateSkillOffset } from '../lib/utils'
const GAUGE_RADIUS = 34
const GAUGE_CIRCUMFERENCE = 2 * Math.PI * GAUGE_RADIUS
interface SkillGaugeProps {
skill: Skill
delay: number
isVisible: boolean
}
function SkillGauge({ skill, delay, isVisible }: SkillGaugeProps) {
const [animated, setAnimated] = useState(false)
const strokeColor = skill.color === 'coral' ? '#FF6B6B' : '#00897B'
const hoverBg = skill.color === 'coral' ? 'hover:bg-coral-light' : 'hover:bg-teal-light'
const targetOffset = calculateSkillOffset(skill.level, GAUGE_RADIUS)
useEffect(() => {
if (isVisible && !animated) {
const timer = setTimeout(() => setAnimated(true), delay)
return () => clearTimeout(timer)
}
}, [isVisible, animated, delay])
return (
{skill.name}
{skill.category}
)
}
interface SkillCategoryProps {
label: string
skills: Skill[]
isVisible: boolean
baseDelay: number
}
function SkillCategory({ label, skills, isVisible, baseDelay }: SkillCategoryProps) {
return (
{label}
{skills.map((skill, index) => (
))}
)
}
const skillsData: Skill[] = [
{ name: 'Python', level: 90, category: 'Technical', color: 'teal' },
{ name: 'SQL', level: 88, category: 'Technical', color: 'teal' },
{ name: 'Power BI', level: 92, category: 'Technical', color: 'teal' },
{ name: 'JS / TS', level: 70, category: 'Technical', color: 'teal' },
{ name: 'Data Analysis', level: 95, category: 'Technical', color: 'teal' },
{ name: 'Dashboard Dev', level: 88, category: 'Technical', color: 'teal' },
{ name: 'Algorithm Design', level: 82, category: 'Technical', color: 'teal' },
{ name: 'Data Pipelines', level: 80, category: 'Technical', color: 'teal' },
{ name: 'Medicines Optimisation', level: 95, category: 'Clinical', color: 'coral' },
{ name: 'Pop. Health Analytics', level: 90, category: 'Clinical', color: 'coral' },
{ name: 'NICE TA', level: 85, category: 'Clinical', color: 'coral' },
{ name: 'Health Economics', level: 80, category: 'Clinical', color: 'coral' },
{ name: 'Clinical Pathways', level: 82, category: 'Clinical', color: 'coral' },
{ name: 'CD Assurance', level: 88, category: 'Clinical', color: 'coral' },
{ name: 'Budget Mgmt', level: 90, category: 'Strategic', color: 'teal' },
{ name: 'Stakeholder Engagement', level: 88, category: 'Strategic', color: 'teal' },
{ name: 'Pharma Negotiation', level: 85, category: 'Strategic', color: 'teal' },
{ name: 'Team Development', level: 82, category: 'Strategic', color: 'teal' },
]
export function Skills() {
const sectionRef = useRef(null)
const [isVisible, setIsVisible] = useState(false)
useEffect(() => {
const element = sectionRef.current
if (!element) return
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true)
observer.unobserve(element)
}
},
{ threshold: 0.15, rootMargin: '0px' }
)
observer.observe(element)
return () => observer.disconnect()
}, [])
const technicalSkills = skillsData.filter(s => s.category === 'Technical')
const clinicalSkills = skillsData.filter(s => s.category === 'Clinical')
const strategicSkills = skillsData.filter(s => s.category === 'Strategic')
return (
)
}