"use client"; import { useState, useEffect } from "react"; import { Plus, Edit, Trash2, Code2, Palette, Database, Cloud, Shield, Smartphone, Layers, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { useToast } from "@/hooks/use-toast"; import { SkillCategory, Team } from "@/lib/types"; import { AdminManagementService, Skill, } from "@/services/admin-management-service"; import { TechIcon } from "@/components/icons/tech-icon"; import { TreeCategoryHeader, TreeItemRow, } from "@/components/admin"; import { TreeViewPage } from "../tree-view-page"; import { useTreeView } from "@/hooks/use-tree-view"; import { useFormDialog } from "@/hooks/use-form-dialog"; interface SkillsManagementProps { skillCategories: SkillCategory[]; teams: Team[]; } interface SkillFormData { name: string; categoryId: string; description: string; icon: string; } export function SkillsManagement({ skillCategories, teams, }: SkillsManagementProps) { const [searchTerm, setSearchTerm] = useState(""); const [editingSkill, setEditingSkill] = useState(null); const [skillFormData, setSkillFormData] = useState({ name: "", categoryId: "", description: "", icon: "", }); const { toast } = useToast(); const { isCreateDialogOpen, isEditDialogOpen, openCreateDialog, closeCreateDialog, openEditDialog, closeEditDialog } = useFormDialog(); // État des skills const [skills, setSkills] = useState([]); const [isLoading, setIsLoading] = useState(true); // Utilisation du hook factorisé const { filteredDataByCategory: filteredSkillsByCategory, expandedCategories, toggleCategory, expandAll, collapseAll, } = useTreeView({ data: skills, searchFields: ['name', 'description'], groupBy: (skill) => skill.category, searchTerm, onSearchChange: setSearchTerm, }); // Charger les skills depuis l'API const fetchSkills = async () => { try { setIsLoading(true); const skillsData = await AdminManagementService.getSkills(); setSkills(skillsData); } catch (error) { console.error("Error fetching skills:", error); toast({ title: "Erreur", description: "Impossible de charger les skills", variant: "destructive", }); } finally { setIsLoading(false); } }; // Charger les skills au montage du composant useEffect(() => { fetchSkills(); }, []); const handleCreateSkill = async () => { if (!skillFormData.name || !skillFormData.categoryId) { toast({ title: "Erreur", description: "Veuillez remplir tous les champs obligatoires", variant: "destructive", }); return; } try { const categoryIndex = parseInt(skillFormData.categoryId); const category = skillCategories[categoryIndex]; const skillData = { ...skillFormData, category: category.category, }; const newSkill = await AdminManagementService.createSkill(skillData); setSkills([...skills, newSkill]); setSkillFormData({ name: "", categoryId: "", description: "", icon: "" }); closeCreateDialog(); toast({ title: "Succès", description: "Skill créée avec succès", }); } catch (error: any) { toast({ title: "Erreur", description: error.message || "Erreur lors de la création de la skill", variant: "destructive", }); } }; const handleEditSkill = (skill: any) => { setEditingSkill(skill); const categoryIndex = skillCategories.findIndex( (cat) => cat.category === skill.category ); setSkillFormData({ name: skill.name, categoryId: categoryIndex !== -1 ? categoryIndex.toString() : "", description: skill.description, icon: skill.icon, }); openEditDialog(); }; const handleUpdateSkill = async () => { if (!editingSkill || !skillFormData.name || !skillFormData.categoryId) { toast({ title: "Erreur", description: "Veuillez remplir tous les champs obligatoires", variant: "destructive", }); return; } try { const categoryIndex = parseInt(skillFormData.categoryId); const category = skillCategories[categoryIndex]; const skillData = { id: editingSkill.id, ...skillFormData, category: category.category, usageCount: editingSkill.usageCount, }; const updatedSkill = await AdminManagementService.updateSkill(skillData); const updatedSkills = skills.map((skill) => skill.id === editingSkill.id ? updatedSkill : skill ); setSkills(updatedSkills); closeEditDialog(); setEditingSkill(null); setSkillFormData({ name: "", categoryId: "", description: "", icon: "" }); toast({ title: "Succès", description: "Skill mise à jour avec succès", }); } catch (error: any) { toast({ title: "Erreur", description: error.message || "Erreur lors de la mise à jour de la skill", variant: "destructive", }); } }; const handleDeleteSkill = async (skillId: string) => { if ( confirm( "Êtes-vous sûr de vouloir supprimer cette skill ? Cette action est irréversible." ) ) { try { await AdminManagementService.deleteSkill(skillId); setSkills(skills.filter((s) => s.id !== skillId)); toast({ title: "Succès", description: "Skill supprimée avec succès", }); } catch (error: any) { toast({ title: "Erreur", description: error.message || "Erreur lors de la suppression de la skill", variant: "destructive", }); } } }; const resetForm = () => { setSkillFormData({ name: "", categoryId: "", description: "", icon: "" }); }; // Fonction pour obtenir l'icône de la catégorie const getCategoryIcon = (category: string) => { const categoryName = category.toLowerCase(); if (categoryName.includes("frontend") || categoryName.includes("front")) return Code2; if (categoryName.includes("backend") || categoryName.includes("back")) return Layers; if ( categoryName.includes("design") || categoryName.includes("ui") || categoryName.includes("ux") ) return Palette; if (categoryName.includes("data") || categoryName.includes("database")) return Database; if (categoryName.includes("cloud") || categoryName.includes("devops")) return Cloud; if (categoryName.includes("security") || categoryName.includes("securité")) return Shield; if ( categoryName.includes("mobile") || categoryName.includes("android") || categoryName.includes("ios") ) return Smartphone; return Code2; // Par défaut }; const headerActions = ( Créer une nouvelle skill
setSkillFormData({ ...skillFormData, name: e.target.value }) } placeholder="Ex: React, Node.js, PostgreSQL" />