added tech logo

This commit is contained in:
kinou-p 2025-10-02 14:12:10 +02:00
parent 8bb93301b9
commit ea9ba687a8
6 changed files with 140 additions and 49 deletions

View File

@ -7,11 +7,12 @@ interface ProjectCardProps {
description: string; description: string;
icon: React.ReactNode; icon: React.ReactNode;
image?: string; image?: string;
technologies?: { name: string; iconUrl?: string }[];
delay?: number; delay?: number;
projectId?: string; projectId?: string;
} }
export const ProjectCard = ({ title, description, icon, image, delay = 0, projectId }: ProjectCardProps) => { export const ProjectCard = ({ title, description, icon, image, technologies, delay = 0, projectId }: ProjectCardProps) => {
const navigate = useNavigate(); const navigate = useNavigate();
const handleClick = () => { const handleClick = () => {
@ -47,9 +48,35 @@ export const ProjectCard = ({ title, description, icon, image, delay = 0, projec
<CardTitle className="text-xl pr-20">{title}</CardTitle> <CardTitle className="text-xl pr-20">{title}</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<CardDescription className="text-base leading-relaxed"> <CardDescription className="text-base leading-relaxed mb-4">
{description} {description}
</CardDescription> </CardDescription>
{technologies && technologies.length > 0 && (
<div className="flex flex-wrap gap-2">
{technologies.slice(0, 6).map((tech, index) => (
<div
key={tech.name}
className="w-8 h-8 rounded bg-background/50 p-1.5 flex items-center justify-center"
title={tech.name}
>
{tech.iconUrl ? (
<img
src={tech.iconUrl}
alt={tech.name}
className="w-full h-full object-contain"
/>
) : (
<span className="text-xs">?</span>
)}
</div>
))}
{technologies.length > 6 && (
<div className="w-8 h-8 rounded bg-background/50 flex items-center justify-center text-xs text-muted-foreground">
+{technologies.length - 6}
</div>
)}
</div>
)}
</CardContent> </CardContent>
</Card> </Card>
</motion.div> </motion.div>

View File

@ -4,11 +4,12 @@ import { Badge } from "@/components/ui/badge";
interface SkillBadgeProps { interface SkillBadgeProps {
name: string; name: string;
icon?: string; icon?: string;
iconUrl?: string;
color?: string; color?: string;
delay?: number; delay?: number;
} }
export const SkillBadge = ({ name, icon, color = "default", delay = 0 }: SkillBadgeProps) => { export const SkillBadge = ({ name, icon, iconUrl, color = "default", delay = 0 }: SkillBadgeProps) => {
return ( return (
<motion.div <motion.div
initial={{ opacity: 0, scale: 0.8 }} initial={{ opacity: 0, scale: 0.8 }}
@ -21,7 +22,11 @@ export const SkillBadge = ({ name, icon, color = "default", delay = 0 }: SkillBa
variant="secondary" variant="secondary"
className="text-base py-2 px-4 font-medium hover:bg-primary hover:text-primary-foreground transition-colors" className="text-base py-2 px-4 font-medium hover:bg-primary hover:text-primary-foreground transition-colors"
> >
{icon && <span className="mr-2">{icon}</span>} {iconUrl ? (
<img src={iconUrl} alt={`${name} logo`} className="mr-2 w-5 h-5" />
) : icon ? (
<span className="mr-2">{icon}</span>
) : null}
{name} {name}
</Badge> </Badge>
</motion.div> </motion.div>

View File

@ -1,6 +1,7 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { useLanguage } from "@/contexts/LanguageContext"; import { useLanguage } from "@/contexts/LanguageContext";
import { ProjectCard } from "@/components/ProjectCard"; import { ProjectCard } from "@/components/ProjectCard";
import { projectsData } from "@/data/projects";
import { Server, Gamepad2, Cloud, Terminal, Box, Globe, Scale } from "lucide-react"; import { Server, Gamepad2, Cloud, Terminal, Box, Globe, Scale } from "lucide-react";
export const ProjectsSection = () => { export const ProjectsSection = () => {
@ -70,6 +71,7 @@ export const ProjectsSection = () => {
description={t(`projects.items.${project.key}.description`)} description={t(`projects.items.${project.key}.description`)}
icon={project.icon} icon={project.icon}
image={project.image} image={project.image}
technologies={projectsData[project.key]?.technologies}
delay={index * 0.1} delay={index * 0.1}
projectId={project.key} projectId={project.key}
/> />

View File

@ -6,17 +6,73 @@ export const SkillsSection = () => {
const { t } = useLanguage(); const { t } = useLanguage();
const languages = [ const languages = [
{ name: "JavaScript", icon: "📜" }, {
{ name: "TypeScript", icon: "📘" }, name: "JavaScript",
{ name: "Python", icon: "🐍" }, iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/javascript/javascript-original.svg"
{ name: "C/C++", icon: "⚙️" }, },
{
name: "TypeScript",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/typescript/typescript-original.svg"
},
{
name: "Python",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/python/python-original.svg"
},
{
name: "C/C++",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/cplusplus/cplusplus-original.svg"
},
{
name: "HTML5",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/html5/html5-original.svg"
},
{
name: "CSS3",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/css3/css3-original.svg"
},
]; ];
const frameworks = [ const frameworks = [
{ name: "React", icon: "⚛️" }, {
{ name: "Node.js", icon: "📗" }, name: "React",
{ name: "Docker", icon: "🐳" }, iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/react/react-original.svg"
{ name: "Linux", icon: "🐧" }, },
{
name: "Node.js",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/nodejs/nodejs-original.svg"
},
{
name: "NestJS",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/nestjs/nestjs-original.svg"
},
{
name: "Docker",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg"
},
{
name: "Linux",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/linux/linux-original.svg"
},
{
name: "PostgreSQL",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/postgresql/postgresql-original.svg"
},
{
name: "MongoDB",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/mongodb/mongodb-original.svg"
},
{
name: "MySQL",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/mysql/mysql-original.svg"
},
{
name: "Ansible",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/ansible/ansible-original.svg"
},
{
name: "WordPress",
iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/wordpress/wordpress-original.svg"
},
]; ];
return ( return (
@ -52,7 +108,7 @@ export const SkillsSection = () => {
<SkillBadge <SkillBadge
key={skill.name} key={skill.name}
name={skill.name} name={skill.name}
icon={skill.icon} iconUrl={skill.iconUrl}
delay={index * 0.1} delay={index * 0.1}
/> />
))} ))}
@ -73,7 +129,7 @@ export const SkillsSection = () => {
<SkillBadge <SkillBadge
key={skill.name} key={skill.name}
name={skill.name} name={skill.name}
icon={skill.icon} iconUrl={skill.iconUrl}
delay={index * 0.1} delay={index * 0.1}
/> />
))} ))}

View File

@ -10,7 +10,7 @@ export interface ProjectData {
solution: { fr: string; en: string }; solution: { fr: string; en: string };
images: string[]; images: string[];
mainImage: string; mainImage: string;
technologies: { name: string; color?: string; icon?: string }[]; technologies: { name: string; color?: string; icon?: string; iconUrl?: string }[];
githubUrl?: string; githubUrl?: string;
demoUrl?: string; demoUrl?: string;
} }
@ -62,12 +62,12 @@ export const projectsData: Record<string, ProjectData> = {
mainImage: "/images/projects/homemade_nas.png", mainImage: "/images/projects/homemade_nas.png",
images: ["/images/projects/homemade_nas.png"], images: ["/images/projects/homemade_nas.png"],
technologies: [ technologies: [
{ name: "OpenMediaVault" }, { name: "OpenMediaVault", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/debian/debian-original.svg" },
{ name: "Docker" }, { name: "Docker", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg" },
{ name: "Traefik" }, { name: "Traefik", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/kubernetes/kubernetes-plain.svg" },
{ name: "Linux" }, { name: "Linux", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/linux/linux-original.svg" },
{ name: "Home Assistant" }, { name: "Home Assistant", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/python/python-original.svg" },
{ name: "Portainer" }, { name: "Portainer", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg" },
], ],
}, },
transcendence: { transcendence: {
@ -116,12 +116,12 @@ export const projectsData: Record<string, ProjectData> = {
mainImage: "/images/projects/pong.png", mainImage: "/images/projects/pong.png",
images: ["/images/projects/pong.png"], images: ["/images/projects/pong.png"],
technologies: [ technologies: [
{ name: "React", icon: "⚛️" }, { name: "React", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/react/react-original.svg" },
{ name: "TypeScript" }, { name: "TypeScript", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/typescript/typescript-original.svg" },
{ name: "NestJS" }, { name: "NestJS", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/nestjs/nestjs-original.svg" },
{ name: "PostgreSQL" }, { name: "PostgreSQL", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/postgresql/postgresql-original.svg" },
{ name: "WebSocket" }, { name: "WebSocket", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/javascript/javascript-original.svg" },
{ name: "Docker" }, { name: "Docker", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg" },
], ],
}, },
cloud: { cloud: {
@ -170,11 +170,11 @@ export const projectsData: Record<string, ProjectData> = {
mainImage: "/images/projects/cloud_1.png", mainImage: "/images/projects/cloud_1.png",
images: ["/images/projects/cloud_1.png"], images: ["/images/projects/cloud_1.png"],
technologies: [ technologies: [
{ name: "Docker", icon: "🐳" }, { name: "Docker", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/docker/docker-original.svg" },
{ name: "Ansible" }, { name: "Ansible", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/ansible/ansible-original.svg" },
{ name: "WordPress" }, { name: "WordPress", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/wordpress/wordpress-original.svg" },
{ name: "MySQL" }, { name: "MySQL", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/mysql/mysql-original.svg" },
{ name: "Linux" }, { name: "Linux", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/linux/linux-original.svg" },
], ],
}, },
minishell: { minishell: {
@ -223,10 +223,10 @@ export const projectsData: Record<string, ProjectData> = {
mainImage: "/images/projects/minishell.png", mainImage: "/images/projects/minishell.png",
images: ["/images/projects/minishell.png"], images: ["/images/projects/minishell.png"],
technologies: [ technologies: [
{ name: "C" }, { name: "C", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/c/c-original.svg" },
{ name: "Linux" }, { name: "Linux", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/linux/linux-original.svg" },
{ name: "POSIX" }, { name: "POSIX", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/unix/unix-original.svg" },
{ name: "Make" }, { name: "Make", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/cmake/cmake-original.svg" },
], ],
}, },
cube3d: { cube3d: {
@ -275,10 +275,10 @@ export const projectsData: Record<string, ProjectData> = {
mainImage: "/images/projects/cub3d.png", mainImage: "/images/projects/cub3d.png",
images: ["/images/projects/cub3d.png"], images: ["/images/projects/cub3d.png"],
technologies: [ technologies: [
{ name: "C" }, { name: "C", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/c/c-original.svg" },
{ name: "MiniLibX" }, { name: "MiniLibX", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/c/c-original.svg" },
{ name: "Raycasting" }, { name: "Raycasting", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/cplusplus/cplusplus-original.svg" },
{ name: "Make" }, { name: "Make", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/cmake/cmake-original.svg" },
], ],
}, },
etsidemain: { etsidemain: {
@ -336,10 +336,10 @@ export const projectsData: Record<string, ProjectData> = {
"/images/sites/etsidemain/tel.png" "/images/sites/etsidemain/tel.png"
], ],
technologies: [ technologies: [
{ name: "HTML5" }, { name: "HTML5", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/html5/html5-original.svg" },
{ name: "CSS3" }, { name: "CSS3", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/css3/css3-original.svg" },
{ name: "JavaScript" }, { name: "JavaScript", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/javascript/javascript-original.svg" },
{ name: "SEO" }, { name: "SEO", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/google/google-original.svg" },
], ],
demoUrl: "https://etsidemain.com", demoUrl: "https://etsidemain.com",
}, },
@ -398,11 +398,11 @@ export const projectsData: Record<string, ProjectData> = {
"/images/sites/avopieces/tel.png" "/images/sites/avopieces/tel.png"
], ],
technologies: [ technologies: [
{ name: "React", icon: "⚛️" }, { name: "React", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/react/react-original.svg" },
{ name: "Node.js", icon: "📗" }, { name: "Node.js", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/nodejs/nodejs-original.svg" },
{ name: "MongoDB" }, { name: "MongoDB", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/mongodb/mongodb-original.svg" },
{ name: "OpenAI" }, { name: "OpenAI", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/python/python-original.svg" },
{ name: "TypeScript" }, { name: "TypeScript", iconUrl: "https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/typescript/typescript-original.svg" },
], ],
demoUrl: "https://avopieces.fr", demoUrl: "https://avopieces.fr",
}, },

View File

@ -69,6 +69,7 @@ const ProjectPageContent = () => {
key={tech.name} key={tech.name}
name={tech.name} name={tech.name}
icon={tech.icon} icon={tech.icon}
iconUrl={tech.iconUrl}
delay={index * 0.05} delay={index * 0.05}
/> />
))} ))}