added tech logo
This commit is contained in:
parent
8bb93301b9
commit
ea9ba687a8
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -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}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -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",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user