"use client"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import { faReact, faVuejs, faJs, faNodeJs, faPython, faJava, faPhp, faGolang, faRust, faDocker, faAws, faGoogle, faMicrosoft, faGitAlt, faLinux, faApple, faWindows, faAndroid, faSwift, faGithub, faGitlab, faBitbucket, faFigma, faSketch, faWordpress, faShopify, faSlack, faDiscord, faDropbox, faGoogle as faGoogleBrands, faYarn, faNpm, faConfluence, faJira, faNotion, } from "@fortawesome/free-brands-svg-icons"; import { faServer, faDatabase, faCloud, faCode, faCog, faDesktop, faMobile, faShield, faPalette, faRocket, faCube, faPlug, faTools, faNetworkWired, faLock, faEye, faSearch, faBug, faFlask, faLayerGroup, faSync, faBolt, faGlobe, faHdd, faMemory, faSignal, faTerminal, faFileCode, faPuzzlePiece, faAtom, faWrench, faCodeBranch, faBroadcastTower, faInfinity, faChartLine, faUserShield, faKey, faSitemap, faClipboardCheck, faUsers, faComment, faHeadset, faBookOpen, faLightbulb, faSpinner, faBoxes, faStream, } from "@fortawesome/free-solid-svg-icons"; import { Monitor, Smartphone, Shield, BarChart3, Palette, Server, } from "lucide-react"; interface TechIconProps { iconName?: string; className?: string; fallbackText?: string; } // Mapping des icônes par nom const ICON_MAP: Record> = { // Brands "fab-react": faReact, "fab-vue": faVuejs, "fab-js": faJs, "fab-node": faNodeJs, "fab-python": faPython, "fab-java": faJava, "fab-php": faPhp, "fab-golang": faGolang, "fab-rust": faRust, "fab-docker": faDocker, "fab-aws": faAws, "fab-google": faGoogle, "fab-microsoft": faMicrosoft, "fab-git": faGitAlt, "fab-linux": faLinux, "fab-apple": faApple, "fab-windows": faWindows, "fab-android": faAndroid, "fab-swift": faSwift, "fab-github": faGithub, "fab-gitlab": faGitlab, "fab-bitbucket": faBitbucket, "fab-figma": faFigma, "fab-sketch": faSketch, "fab-wordpress": faWordpress, "fab-shopify": faShopify, "fab-slack": faSlack, "fab-discord": faDiscord, "fab-dropbox": faDropbox, "fab-yarn": faYarn, "fab-npm": faNpm, "fab-confluence": faConfluence, "fab-jira": faJira, "fab-notion": faNotion, // Solid icons "fas-server": faServer, "fas-database": faDatabase, "fas-cloud": faCloud, "fas-code": faCode, "fas-cog": faCog, "fas-desktop": faDesktop, "fas-mobile": faMobile, "fas-shield": faShield, "fas-palette": faPalette, "fas-rocket": faRocket, "fas-cube": faCube, "fas-plug": faPlug, "fas-tools": faTools, "fas-network": faNetworkWired, "fas-lock": faLock, "fas-eye": faEye, "fas-search": faSearch, "fas-bug": faBug, "fas-flask": faFlask, "fas-layers": faLayerGroup, "fas-sync": faSync, "fas-bolt": faBolt, "fas-globe": faGlobe, "fas-hdd": faHdd, "fas-memory": faMemory, "fas-signal": faSignal, "fas-terminal": faTerminal, "fas-file-code": faFileCode, "fas-puzzle": faPuzzlePiece, "fas-atom": faAtom, "fas-wrench": faWrench, "fas-code-branch": faCodeBranch, "fas-broadcast": faBroadcastTower, "fas-infinity": faInfinity, "fas-chart-line": faChartLine, "fas-user-shield": faUserShield, "fas-key": faKey, "fas-sitemap": faSitemap, "fas-check": faClipboardCheck, "fas-users": faUsers, "fas-comment": faComment, "fas-headset": faHeadset, "fas-book": faBookOpen, "fas-lightbulb": faLightbulb, "fas-spinner": faSpinner, "fas-boxes": faBoxes, "fas-stream": faStream, // Lucide icons (pour certaines catégories ou icônes spéciales) "lucide-monitor": Monitor, "lucide-smartphone": Smartphone, "lucide-shield": Shield, "lucide-bar-chart": BarChart3, "lucide-palette": Palette, "lucide-server": Server, }; export const TechIcon: React.FC = ({ iconName, className = "w-5 h-5", fallbackText, }) => { if (!iconName) { return (
{fallbackText ? fallbackText.charAt(0).toUpperCase() : "?"}
); } const IconComponent = ICON_MAP[iconName]; if (!IconComponent) { return (
{fallbackText ? fallbackText.charAt(0).toUpperCase() : iconName.charAt(0).toUpperCase()}
); } // Font Awesome icon (IconDefinition has prefix, iconName, and icon properties) if (typeof IconComponent === "object" && "prefix" in IconComponent && "iconName" in IconComponent) { return ( ); } // Lucide icon (React component) if (typeof IconComponent === "function") { const LucideIcon = IconComponent as React.ComponentType; return ; } // Fallback if something goes wrong return (
{fallbackText ? fallbackText.charAt(0).toUpperCase() : iconName.charAt(0).toUpperCase()}
); }; export default TechIcon;