feat: add AboutSummary component with personal introduction and game preview
feat: create Chip component for displaying technology tags feat: implement ExperienceCard component to showcase job experiences feat: add Experience component to list multiple job experiences feat: create Footer component with social links and copyright information feat: implement Hero component for the landing section with social links feat: add ImageCarousel component for displaying project images feat: create Navbar component with scroll effect and navigation links feat: implement ProjectItem component to display individual project details feat: add Skills component to showcase technical skills feat: create data module with skills, jobs, and projects information feat: define types for Skill, Job, and Project in types module chore: update package.json with new dependencies for Tailwind CSS and Lucide icons chore: add CV PDF file to public directory chore: remove unused SVG files from public directory chore: add new images for background and hero sections feat: implement formatDate utility function for date formatting
This commit is contained in:
114
components/project-item.tsx
Normal file
114
components/project-item.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import Link from "next/link";
|
||||
import { Project } from "@/lib/types";
|
||||
import Chip from "@/components/chip";
|
||||
import ImageCarousel from "@/components/image-carousel";
|
||||
import {
|
||||
Eye,
|
||||
CloudDownload,
|
||||
AppWindow,
|
||||
Smartphone,
|
||||
Globe,
|
||||
MonitorCog,
|
||||
Gamepad2,
|
||||
Github,
|
||||
} from "lucide-react";
|
||||
|
||||
const PlaceholderIcon = ({ category }: { category: Project["category"] }) => {
|
||||
const iconProps = { size: 128, className: "text-white/80" };
|
||||
switch (category) {
|
||||
case "Desktop":
|
||||
return <AppWindow {...iconProps} />;
|
||||
case "Mobile":
|
||||
return <Smartphone {...iconProps} />;
|
||||
case "Web":
|
||||
return <Globe {...iconProps} />;
|
||||
case "Api":
|
||||
return <MonitorCog {...iconProps} />;
|
||||
case "Game":
|
||||
return <Gamepad2 {...iconProps} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
interface ProjectItemProps {
|
||||
project: Project;
|
||||
}
|
||||
|
||||
const ProjectItem = ({ project }: ProjectItemProps) => {
|
||||
const ImageDisplay = (
|
||||
<div className="bg-gradient-to-r from-violet-600 to-indigo-600 shadow-lg w-full h-[40rem] flex items-center justify-center rounded-lg">
|
||||
{project.thumbnails && project.thumbnails.length > 0 ? (
|
||||
<ImageCarousel
|
||||
id={`carousel-${project.id}`}
|
||||
thumbnails={project.thumbnails}
|
||||
/>
|
||||
) : (
|
||||
<PlaceholderIcon category={project.category} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row items-center justify-between w-full h-full gap-8 text-white p-4">
|
||||
<div className="flex flex-col w-full gap-4 md:w-1/3 backdrop-blur-2xl glass-effect glossy-effect bottom p-4 rounded-md h-full">
|
||||
<div className="prose prose-invert">
|
||||
<h1>{project.name}</h1>
|
||||
<p className="whitespace-pre-wrap">{project.short_description}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies.map((tech) => (
|
||||
<Chip key={tech} text={tech} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href={`/projects/${project.name}`}
|
||||
className="text-center glass-effect glossy-effect bottom gloss-highlight p-2 rounded-2xl bg-yellow-400 hover:bg-yellow-500 text-black font-bold"
|
||||
>
|
||||
Read more
|
||||
</Link>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-2 w-full">
|
||||
{project.github_url && (
|
||||
<a
|
||||
href={project.github_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-1 flex items-center justify-center gap-2 text-center glass-effect glossy-effect bottom gloss-highlight p-2 rounded-2xl bg-yellow-400 hover:bg-yellow-500 text-black font-bold"
|
||||
>
|
||||
<Github size={20} /> CODE
|
||||
</a>
|
||||
)}
|
||||
{project.visit_url && (
|
||||
<a
|
||||
href={project.visit_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-1 flex items-center justify-center gap-2 text-center glass-effect glossy-effect bottom gloss-highlight p-2 rounded-2xl bg-yellow-400 hover:bg-yellow-500 text-black font-bold"
|
||||
>
|
||||
<Eye size={20} /> LIVE
|
||||
</a>
|
||||
)}
|
||||
{project.download_url && (
|
||||
<a
|
||||
href={project.download_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-1 flex items-center justify-center gap-2 text-center glass-effect glossy-effect bottom gloss-highlight p-2 rounded-2xl bg-yellow-400 hover:bg-yellow-500 text-black font-bold"
|
||||
>
|
||||
<CloudDownload size={20} /> DOWNLOAD
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-full mt-4 md:hidden">{ImageDisplay}</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:flex md:w-1/2">{ImageDisplay}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectItem;
|
Reference in New Issue
Block a user