Add Font Awesome icons and refactor tech icon handling
- Added Font Awesome dependencies for enhanced icon support. - Refactored tech icon components to utilize Font Awesome icons instead of custom SVGs. - Updated skill data files to include icon properties for various technologies. - Removed obsolete tech icon files to streamline the codebase.
This commit is contained in:
@@ -1,77 +1,263 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
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";
|
||||
|
||||
interface TechIconExternalProps {
|
||||
techId: string;
|
||||
techName: string;
|
||||
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;
|
||||
size?: number;
|
||||
fallbackText?: string;
|
||||
}
|
||||
|
||||
// Service Simple Icons pour récupérer les icônes SVG
|
||||
export function TechIconExternal({
|
||||
techId,
|
||||
techName,
|
||||
className = "w-6 h-6",
|
||||
size = 24,
|
||||
}: TechIconExternalProps) {
|
||||
const [imageError, setImageError] = useState(false);
|
||||
// Mapping des icônes par nom
|
||||
const ICON_MAP: Record<string, IconDefinition | React.ComponentType<any>> = {
|
||||
// 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,
|
||||
|
||||
// URL pour Simple Icons
|
||||
const simpleIconUrl = `https://cdn.jsdelivr.net/npm/simple-icons@v9/${techId}.svg`;
|
||||
"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,
|
||||
|
||||
// URL pour DevIcons
|
||||
const devIconUrl = `https://cdn.jsdelivr.net/gh/devicons/devicon/icons/${techId}/${techId}-original.svg`;
|
||||
// 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,
|
||||
|
||||
if (imageError) {
|
||||
// Fallback vers initiale si l'icône n'existe pas
|
||||
"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<TechIconProps> = ({
|
||||
iconName,
|
||||
className = "w-5 h-5",
|
||||
fallbackText,
|
||||
}) => {
|
||||
if (!iconName) {
|
||||
return (
|
||||
<div
|
||||
className={`${className} bg-muted rounded flex items-center justify-center text-xs font-bold`}
|
||||
>
|
||||
{techName.charAt(0).toUpperCase()}
|
||||
{fallbackText ? fallbackText.charAt(0).toUpperCase() : "?"}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Image
|
||||
src={simpleIconUrl}
|
||||
alt={`${techName} icon`}
|
||||
width={size}
|
||||
height={size}
|
||||
className={className}
|
||||
onError={() => setImageError(true)}
|
||||
style={{ filter: "brightness(0) saturate(100%) invert(0.5)" }} // Pour s'adapter au thème
|
||||
/>
|
||||
);
|
||||
}
|
||||
const IconComponent = ICON_MAP[iconName];
|
||||
|
||||
// Mapping des IDs pour Simple Icons (ils utilisent parfois des noms différents)
|
||||
export const SIMPLE_ICONS_MAPPING: Record<string, string> = {
|
||||
react: "react",
|
||||
vue: "vuedotjs",
|
||||
typescript: "typescript",
|
||||
nextjs: "nextdotjs",
|
||||
nodejs: "nodedotjs",
|
||||
python: "python",
|
||||
express: "express",
|
||||
postgresql: "postgresql",
|
||||
mongodb: "mongodb",
|
||||
redis: "redis",
|
||||
docker: "docker",
|
||||
kubernetes: "kubernetes",
|
||||
aws: "amazonwebservices",
|
||||
terraform: "terraform",
|
||||
jenkins: "jenkins",
|
||||
githubactions: "githubactions",
|
||||
reactnative: "react",
|
||||
flutter: "flutter",
|
||||
swift: "swift",
|
||||
kotlin: "kotlin",
|
||||
expo: "expo",
|
||||
tailwindcss: "tailwindcss",
|
||||
webpack: "webpack",
|
||||
if (!IconComponent) {
|
||||
return (
|
||||
<div
|
||||
className={`${className} bg-muted rounded flex items-center justify-center text-xs font-bold`}
|
||||
>
|
||||
{fallbackText
|
||||
? fallbackText.charAt(0).toUpperCase()
|
||||
: iconName.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Font Awesome icon (IconDefinition has prefix, iconName, and icon properties)
|
||||
if (typeof IconComponent === "object" && "prefix" in IconComponent && "iconName" in IconComponent) {
|
||||
return (
|
||||
<FontAwesomeIcon
|
||||
icon={IconComponent as IconDefinition}
|
||||
className={className}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Lucide icon (React component)
|
||||
if (typeof IconComponent === "function") {
|
||||
const LucideIcon = IconComponent as React.ComponentType<any>;
|
||||
return <LucideIcon className={className} />;
|
||||
}
|
||||
|
||||
// Fallback if something goes wrong
|
||||
return (
|
||||
<div
|
||||
className={`${className} bg-muted rounded flex items-center justify-center text-xs font-bold`}
|
||||
>
|
||||
{fallbackText
|
||||
? fallbackText.charAt(0).toUpperCase()
|
||||
: iconName.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TechIcon;
|
||||
|
||||
Reference in New Issue
Block a user