Files
peakskills/components/home/category-card.tsx
2025-08-21 12:54:48 +02:00

169 lines
5.3 KiB
TypeScript

"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { ChevronDown, ChevronRight, ExternalLink } from "lucide-react";
import { getCategoryIcon } from "@/lib/category-icons";
import { getScoreColors } from "@/lib/score-utils";
import { SkillProgress } from "./skill-progress";
import Link from "next/link";
interface CategoryCardProps {
category: {
category: string;
score: number;
maxScore: number;
};
categoryEval?: {
category: string;
selectedSkillIds: string[];
skills: Array<{
skillId: string;
level: string | null;
}>;
};
skillCategory?: {
category: string;
icon: string;
skills: Array<{
id: string;
name: string;
icon?: string;
}>;
};
}
export function CategoryCard({
category,
categoryEval,
skillCategory,
}: CategoryCardProps) {
const [isExpanded, setIsExpanded] = useState(false);
const skillsCount = categoryEval?.selectedSkillIds?.length || 0;
const evaluatedCount =
categoryEval?.skills.filter((s) => s.level !== null).length || 0;
const CategoryIcon = skillCategory
? getCategoryIcon(skillCategory.icon)
: null;
return (
<div className="bg-white/5 border border-white/10 rounded-lg overflow-hidden transition-colors">
<div
className="p-3 hover:bg-white/10 transition-colors cursor-pointer"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex justify-between items-center mb-2">
<div className="flex items-center gap-2">
{isExpanded ? (
<ChevronDown className="h-4 w-4 text-slate-400" />
) : (
<ChevronRight className="h-4 w-4 text-slate-400" />
)}
{CategoryIcon && <CategoryIcon className="h-4 w-4 text-blue-400" />}
<h4 className="font-medium text-white text-sm">
{category.category}
</h4>
</div>
{skillsCount > 0 ? (
(() => {
const colors = getScoreColors(category.score);
return (
<div
className={`px-2 py-0.5 rounded-full ${colors.bg} border ${colors.border}`}
>
<span className={`text-xs font-medium ${colors.text}`}>
{Math.round((category.score / 3) * 100)}%
</span>
</div>
);
})()
) : (
<div className="px-2 py-0.5 rounded-full bg-slate-500/20 border border-slate-500/30">
<span className="text-xs font-medium text-slate-400">Aucune</span>
</div>
)}
</div>
<div className="text-xs text-slate-400 mb-2">
{skillsCount > 0
? `${evaluatedCount}/${skillsCount} compétences sélectionnées évaluées`
: "Aucune compétence sélectionnée"}
</div>
{skillsCount > 0 ? (
<div className="w-full bg-white/10 rounded-full h-1.5">
{(() => {
const colors = getScoreColors(category.score);
return (
<div
className={`bg-gradient-to-r ${colors.gradient} h-1.5 rounded-full transition-all`}
style={{
width: `${(category.score / category.maxScore) * 100}%`,
}}
></div>
);
})()}
</div>
) : (
<div className="w-full bg-slate-500/10 rounded-full h-1.5"></div>
)}
</div>
{/* Expanded Skills */}
{isExpanded && (
<div className="px-3 pb-3 border-t border-white/10 bg-white/5">
{categoryEval && skillCategory && skillsCount > 0 ? (
<div className="pt-3 space-y-2 max-h-60 overflow-y-auto">
{categoryEval.selectedSkillIds.map((skillId) => {
const skill = skillCategory.skills.find(
(s) => s.id === skillId
);
if (!skill) return null;
const skillEval = categoryEval.skills.find(
(s) => s.skillId === skillId
);
return (
<SkillProgress
key={skillId}
skill={skill}
skillEval={skillEval}
/>
);
})}
</div>
) : (
<div className="pt-3 pb-3 text-center">
<p className="text-slate-400 text-sm mb-3">
Aucune compétence sélectionnée dans cette catégorie
</p>
</div>
)}
<div
className={`${
skillsCount > 0 ? "mt-3 pt-3 border-t border-white/10" : ""
}`}
>
<Button
asChild
className="w-full bg-blue-500 hover:bg-blue-600 text-white"
>
<Link
href={`/evaluation?category=${encodeURIComponent(
category.category
)}`}
>
<ExternalLink className="w-4 h-4 mr-2" />
{skillsCount > 0
? `Évaluer ${category.category}`
: `Commencer l'évaluation ${category.category}`}
</Link>
</Button>
</div>
</div>
)}
</div>
);
}