Add skill removal functionality and enhance UI components

- Integrated onRemoveSkill functionality in SkillEvaluation, SkillSelector, and SkillEvaluationCard components for better skill management.
- Updated UI to improve user experience when removing skills, including tooltip descriptions and styling adjustments.
- Added new skills to backend, devops, frontend, and mobile JSON files for comprehensive skill coverage.
This commit is contained in:
Julien Froidefond
2025-08-20 16:06:09 +02:00
parent fe63f9592a
commit 5c510ebd07
22 changed files with 1758 additions and 42 deletions

View File

@@ -1,4 +1,4 @@
import { ExternalLink, BookOpen, Target, Info } from "lucide-react";
import { ExternalLink, Info, X } from "lucide-react";
import {
Tooltip,
TooltipContent,
@@ -11,6 +11,7 @@ interface SkillEvaluationCardProps {
skill: Skill;
currentLevel: SkillLevel;
onUpdateSkill: (skillId: string, level: SkillLevel) => void;
onRemoveSkill: (skillId: string) => void;
}
function getLevelColor(level: Exclude<SkillLevel, null>) {
@@ -43,6 +44,7 @@ export function SkillEvaluationCard({
skill,
currentLevel,
onUpdateSkill,
onRemoveSkill,
}: SkillEvaluationCardProps) {
const TechIcon = getTechIcon(skill.id);
@@ -131,27 +133,19 @@ export function SkillEvaluationCard({
);
})}
{/* Goal buttons */}
<div className="flex items-center gap-1 ml-2 border-l border-white/10 pl-2">
{/* Remove button */}
<div className="flex items-center ml-2 border-l border-white/10 pl-2">
<Tooltip>
<TooltipTrigger asChild>
<button className="p-1 rounded-lg hover:bg-white/10 transition-colors">
<BookOpen className="h-3 w-3 text-slate-400 hover:text-blue-400" />
<button
onClick={() => onRemoveSkill(skill.id)}
className="p-1 rounded-lg hover:bg-red-500/20 transition-colors"
>
<X className="h-3 w-3 text-slate-400 hover:text-red-400" />
</button>
</TooltipTrigger>
<TooltipContent>
<p className="text-xs">Envie d'apprendre</p>
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<button className="p-1 rounded-lg hover:bg-white/10 transition-colors">
<Target className="h-3 w-3 text-slate-400 hover:text-green-400" />
</button>
</TooltipTrigger>
<TooltipContent>
<p className="text-xs">Peut encadrer</p>
<p className="text-xs">Supprimer cette technologie</p>
</TooltipContent>
</Tooltip>
</div>

View File

@@ -5,12 +5,14 @@ interface SkillEvaluationGridProps {
currentCategory: SkillCategory;
currentEvaluation: CategoryEvaluation;
onUpdateSkill: (category: string, skillId: string, level: SkillLevel) => void;
onRemoveSkill: (category: string, skillId: string) => void;
}
export function SkillEvaluationGrid({
currentCategory,
currentEvaluation,
onUpdateSkill,
onRemoveSkill,
}: SkillEvaluationGridProps) {
const getSkillLevel = (skillId: string): SkillLevel => {
const skillEval = currentEvaluation?.skills.find(
@@ -52,6 +54,9 @@ export function SkillEvaluationGrid({
onUpdateSkill={(skillId, level) =>
onUpdateSkill(currentCategory.category, skillId, level)
}
onRemoveSkill={(skillId) =>
onRemoveSkill(currentCategory.category, skillId)
}
/>
);
})}

View File

@@ -94,6 +94,7 @@ export function SkillEvaluation({
currentCategory={currentCategory}
currentEvaluation={currentEvaluation}
onUpdateSkill={onUpdateSkill}
onRemoveSkill={onRemoveSkill}
/>
)}
</div>

View File

@@ -11,8 +11,7 @@ import {
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Plus, Search, X } from "lucide-react";
import { Plus, Search } from "lucide-react";
import { SkillCategory, CategoryEvaluation } from "@/lib/types";
import { getTechIcon } from "./icons/tech-icons";
@@ -41,9 +40,9 @@ export function SkillSelector({
(evaluation) => evaluation.category === selectedCategory
);
if (!currentCategory || !currentEvaluation) return null;
if (!currentCategory) return null;
const selectedSkillIds = currentEvaluation.selectedSkillIds || [];
const selectedSkillIds = currentEvaluation?.selectedSkillIds || [];
const filteredSkills = currentCategory.skills.filter(
(skill) =>
@@ -67,7 +66,10 @@ export function SkillSelector({
<h4 className="text-lg font-medium">Mes compétences sélectionnées</h4>
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<Button size="sm" className="gap-2">
<Button
size="sm"
className="gap-2 bg-blue-500 hover:bg-blue-600 text-white shadow-lg"
>
<Plus className="h-4 w-4" />
Ajouter une compétence
</Button>
@@ -147,24 +149,17 @@ export function SkillSelector({
</div>
{selectedSkills.length > 0 ? (
<div className="flex flex-wrap gap-2">
{selectedSkills.map((skill) => (
<Badge
key={skill.id}
variant="secondary"
className="gap-2 pr-1 cursor-pointer hover:bg-destructive/10 transition-colors"
>
{skill.name}
<Button
variant="ghost"
size="sm"
className="h-auto p-0.5 hover:bg-destructive hover:text-destructive-foreground"
onClick={() => onRemoveSkill(selectedCategory, skill.id)}
>
<X className="h-3 w-3" />
</Button>
</Badge>
))}
<div className="bg-muted/30 rounded-lg p-4">
<div className="flex items-center justify-between">
<p className="text-sm text-muted-foreground">
{selectedSkills.length} compétence
{selectedSkills.length > 1 ? "s" : ""} sélectionnée
{selectedSkills.length > 1 ? "s" : ""}
</p>
<div className="text-xs text-muted-foreground">
Supprimez directement depuis les lignes ci-dessous
</div>
</div>
</div>
) : (
<div className="text-center py-8 text-muted-foreground border-2 border-dashed border-muted rounded-lg">