From b2896c379fa023a8c0c5f41b68012ae6cc9c5f7c Mon Sep 17 00:00:00 2001 From: Mohammed Al-yaseen Date: Mon, 28 Jul 2025 10:40:33 +0300 Subject: [PATCH] ProjectsShowcase: add details modal --- .../ProjectsShowcase/ProjectsShowcase.tsx | 269 ++++++++++++++- .../ProjectsShowcaseSelector.module.css | 318 ++++++++++++++++++ src/app/layout.tsx | 17 +- 3 files changed, 593 insertions(+), 11 deletions(-) diff --git a/src/app/components/ProjectsShowcase/ProjectsShowcase.tsx b/src/app/components/ProjectsShowcase/ProjectsShowcase.tsx index 8b3c793..5efdd7c 100644 --- a/src/app/components/ProjectsShowcase/ProjectsShowcase.tsx +++ b/src/app/components/ProjectsShowcase/ProjectsShowcase.tsx @@ -1,8 +1,8 @@ // File: src/components/home/ProjectsShowcase.tsx -import { EyeOutlined, LeftOutlined, RightOutlined } from "@ant-design/icons"; -import { Badge, Button, Card, Col, Row, Tag, Typography } from "antd"; -import { motion, useAnimation } from "framer-motion"; +import { CloseOutlined, EyeOutlined, GithubOutlined, LeftOutlined, LinkOutlined, RightOutlined } from "@ant-design/icons"; +import { Badge, Button, Card, Carousel, Col, Modal, Row, Tag, Typography } from "antd"; +import { AnimatePresence, motion, useAnimation } from "framer-motion"; import Image from "next/image"; import React, { useEffect, useState } from "react"; import styles from "./ProjectsShowcaseSelector.module.css"; @@ -17,6 +17,13 @@ interface Project { category: string; technologies: string[]; featured: boolean; + detailedDescription: string; + images: string[]; + liveUrl?: string; + githubUrl?: string; + features: string[]; + duration: string; + teamSize: string; } // Sample project data @@ -30,6 +37,24 @@ const projectsData: Project[] = [ category: "Web Application", technologies: ["React", "Node.js", "TensorFlow", "AWS"], featured: true, + detailedDescription: "A comprehensive financial analytics platform that leverages artificial intelligence to provide real-time insights into market trends, portfolio performance, and risk assessment. The platform features advanced data visualization, predictive analytics, and automated reporting capabilities.", + images: [ + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500" + ], + liveUrl: "https://fintech-demo.com", + githubUrl: "https://github.com/company/fintech-dashboard", + features: [ + "Real-time data visualization with interactive charts", + "AI-powered predictive analytics", + "Automated risk assessment", + "Multi-device responsive design", + "Advanced security and encryption" + ], + duration: "6 months", + teamSize: "8 developers" }, { id: "p2", @@ -40,6 +65,23 @@ const projectsData: Project[] = [ category: "Enterprise Software", technologies: ["Angular", ".NET Core", "SQL Server", "Azure"], featured: true, + detailedDescription: "A robust healthcare management system designed to streamline patient care workflows, manage electronic health records, and ensure compliance with healthcare regulations. The system includes appointment scheduling, billing management, and advanced reporting features.", + images: [ + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500" + ], + liveUrl: "https://healthcare-demo.com", + githubUrl: "https://github.com/company/healthcare-system", + features: [ + "Electronic Health Records (EHR)", + "Appointment scheduling and management", + "Billing and insurance processing", + "HIPAA compliance features", + "Advanced reporting and analytics" + ], + duration: "8 months", + teamSize: "12 developers" }, { id: "p3", @@ -50,6 +92,25 @@ const projectsData: Project[] = [ category: "E-commerce", technologies: ["Next.js", "Stripe", "MongoDB", "GraphQL"], featured: true, + detailedDescription: "A modern e-commerce platform that connects multiple vendors with customers through a unified marketplace. Features include advanced search, personalized recommendations, secure payment processing, and comprehensive inventory management.", + images: [ + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500" + ], + liveUrl: "https://marketplace-demo.com", + githubUrl: "https://github.com/company/ecommerce-marketplace", + features: [ + "Multi-vendor marketplace", + "Advanced search and filtering", + "Secure payment processing", + "Inventory management system", + "Real-time notifications" + ], + duration: "7 months", + teamSize: "10 developers" }, { id: "p4", @@ -60,6 +121,23 @@ const projectsData: Project[] = [ category: "IoT", technologies: ["Python", "MQTT", "Kubernetes", "TensorFlow"], featured: false, + detailedDescription: "An Internet of Things platform designed for smart city applications, enabling real-time monitoring of urban infrastructure, traffic management, and environmental data collection with advanced analytics capabilities.", + images: [ + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500" + ], + liveUrl: "https://smartcity-demo.com", + githubUrl: "https://github.com/company/smart-city-platform", + features: [ + "Real-time sensor data collection", + "Traffic flow optimization", + "Environmental monitoring", + "Predictive maintenance alerts", + "Interactive city dashboard" + ], + duration: "10 months", + teamSize: "15 developers" }, { id: "p5", @@ -70,6 +148,23 @@ const projectsData: Project[] = [ category: "Mobile & Web", technologies: ["React Native", "Node.js", "PostgreSQL", "Google Maps API"], featured: false, + detailedDescription: "A comprehensive logistics and fleet management system that provides real-time tracking, route optimization, and delivery management. The platform includes mobile apps for drivers and web dashboards for managers.", + images: [ + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500" + ], + liveUrl: "https://logistics-demo.com", + githubUrl: "https://github.com/company/logistics-system", + features: [ + "Real-time GPS tracking", + "Route optimization algorithms", + "Driver mobile application", + "Delivery status updates", + "Analytics and reporting" + ], + duration: "5 months", + teamSize: "6 developers" }, { id: "p6", @@ -80,12 +175,31 @@ const projectsData: Project[] = [ category: "Education", technologies: ["Vue.js", "Django", "WebRTC", "Docker"], featured: false, + detailedDescription: "A modern virtual learning environment that provides interactive online education with video conferencing, personalized learning paths, and comprehensive progress tracking for students and educators.", + images: [ + "/api/placeholder/800/500", + "/api/placeholder/800/500", + "/api/placeholder/800/500" + ], + liveUrl: "https://learning-demo.com", + githubUrl: "https://github.com/company/virtual-learning", + features: [ + "Video conferencing and screen sharing", + "Personalized learning paths", + "Progress tracking and analytics", + "Interactive whiteboard", + "Assignment and grading system" + ], + duration: "9 months", + teamSize: "11 developers" }, ]; const ProjectsShowcase: React.FC = () => { const [currentIndex, setCurrentIndex] = useState(0); const [visibleProjects, setVisibleProjects] = useState([]); + const [selectedProject, setSelectedProject] = useState(null); + const [isModalVisible, setIsModalVisible] = useState(false); const controls = useAnimation(); // Determine number of projects to show based on screen width @@ -148,6 +262,18 @@ const ProjectsShowcase: React.FC = () => { } }; + const handleProjectClick = (project: Project) => { + setSelectedProject(project); + setIsModalVisible(true); + }; + + const handleModalClose = () => { + setIsModalVisible(false); + setTimeout(() => { + setSelectedProject(null); + }, 300); + }; + return (
@@ -181,6 +307,7 @@ const ProjectsShowcase: React.FC = () => { > handleProjectClick(project)} cover={
{
+ + {/* Project Details Modal */} + + {isModalVisible && selectedProject && ( + } + > + +
+
+ + {selectedProject.title} + + + {selectedProject.category} + +
+
+ {selectedProject.liveUrl && ( + + )} + {selectedProject.githubUrl && ( + + )} +
+
+ +
+
+ + {selectedProject.images.map((image, index) => ( +
+ {`${selectedProject.title} +
+ ))} +
+
+ +
+
+ + Project Overview + + + {selectedProject.detailedDescription} + +
+ +
+
+ + Key Features + +
    + {selectedProject.features.map((feature, index) => ( + + {feature} + + ))} +
+
+ +
+ + Project Details + +
+
+ Duration: + {selectedProject.duration} +
+
+ Team Size: + {selectedProject.teamSize} +
+
+ Technologies: +
+ {selectedProject.technologies.map((tech) => ( + + {tech} + + ))} +
+
+
+
+
+
+
+
+
+ )} +
); }; diff --git a/src/app/components/ProjectsShowcase/ProjectsShowcaseSelector.module.css b/src/app/components/ProjectsShowcase/ProjectsShowcaseSelector.module.css index 9ddd4b0..aa28e1d 100644 --- a/src/app/components/ProjectsShowcase/ProjectsShowcaseSelector.module.css +++ b/src/app/components/ProjectsShowcase/ProjectsShowcaseSelector.module.css @@ -52,6 +52,12 @@ transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); border: none; + cursor: pointer; +} + +.projectCard:hover { + transform: translateY(-8px); + box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15); } .projectImageContainer { @@ -164,6 +170,263 @@ } +/* Modal Styles */ +.projectModal { + border-radius: 16px; + overflow: hidden; +} + +.projectModal :global(.ant-modal-content) { + border-radius: 16px; + overflow: hidden; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); +} + +.projectModal :global(.ant-modal-header) { + display: none; +} + +.projectModal :global(.ant-modal-body) { + padding: 0; +} + +.closeIcon { + font-size: 18px; + color: #666; + transition: color 0.3s ease; +} + +.closeIcon:hover { + color: #333; +} + +.modalContent { + background: #fff; + border-radius: 16px; + overflow: hidden; +} + +.modalHeader { + padding: 32px 32px 24px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + position: relative; +} + +.modalHeader::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('data:image/svg+xml,'); + opacity: 0.3; +} + +.modalTitleSection { + position: relative; + z-index: 1; +} + +.modalTitle { + color: white !important; + font-size: 2.2rem !important; + font-weight: 700 !important; + margin-bottom: 12px !important; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.modalCategory { + background: rgba(255, 255, 255, 0.2) !important; + border: 1px solid rgba(255, 255, 255, 0.3) !important; + color: white !important; + font-weight: 500; + padding: 4px 12px; + border-radius: 20px; +} + +.modalActions { + position: absolute; + top: 32px; + right: 32px; + display: flex; + gap: 12px; + z-index: 1; +} + +.actionButton { + height: 40px; + border-radius: 20px; + font-weight: 500; + transition: all 0.3s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.actionButton:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); +} + +.modalBody { + padding: 0; +} + +.projectImages { + position: relative; + background: #f8f9fa; +} + +.imageCarousel { + border-radius: 0; +} + +.carouselItem { + position: relative; + height: 400px; + overflow: hidden; +} + +.modalImage { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.carouselItem:hover .modalImage { + transform: scale(1.02); +} + +.carouselDots { + bottom: 20px; +} + +.carouselDots :global(.ant-carousel .slick-dots li button) { + background: rgba(255, 255, 255, 0.5); + border-radius: 50%; + width: 8px; + height: 8px; +} + +.carouselDots :global(.ant-carousel .slick-dots li.slick-active button) { + background: #6e48aa; +} + +.projectDetails { + padding: 32px; + background: white; +} + +.detailSection { + margin-bottom: 32px; +} + +.detailSection:last-child { + margin-bottom: 0; +} + +.sectionTitle { + font-size: 1.4rem !important; + font-weight: 600 !important; + margin-bottom: 16px !important; + color: #333; + position: relative; +} + +.sectionTitle::after { + content: ''; + position: absolute; + bottom: -4px; + left: 0; + width: 40px; + height: 3px; + background: linear-gradient(90deg, #667eea, #764ba2); + border-radius: 2px; +} + +.projectDescription { + font-size: 1.1rem; + line-height: 1.7; + color: #555; + margin-bottom: 0; +} + +.detailGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 32px; + margin-top: 32px; +} + +.featuresList { + list-style: none; + padding: 0; + margin: 0; +} + +.featureItem { + position: relative; + padding: 12px 0 12px 24px; + font-size: 1rem; + color: #555; + line-height: 1.6; + border-bottom: 1px solid #f0f0f0; +} + +.featureItem:last-child { + border-bottom: none; +} + +.featureItem::before { + content: '✓'; + position: absolute; + left: 0; + top: 12px; + color: #6e48aa; + font-weight: bold; + font-size: 14px; +} + +.projectInfo { + display: flex; + flex-direction: column; + gap: 16px; +} + +.infoItem { + display: flex; + align-items: flex-start; + gap: 12px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + border-left: 4px solid #6e48aa; +} + +.infoItem:last-child { + flex-direction: column; + gap: 8px; +} + +.modalTechnologies { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 8px; +} + +.modalTechTag { + background: #e6f7ff; + border: 1px solid #91d5ff; + color: #1890ff; + font-weight: 500; + border-radius: 16px; + padding: 4px 12px; + font-size: 0.85rem; +} + +/* Responsive Design */ @media (max-width: 768px) { .projectsSection { padding: 60px 0; @@ -176,4 +439,59 @@ .projectImageContainer { height: 180px; } + + .projectModal { + margin: 16px; + max-width: calc(100vw - 32px); + } + + .modalHeader { + padding: 24px 20px 20px; + } + + .modalTitle { + font-size: 1.8rem !important; + } + + .modalActions { + position: static; + margin-top: 16px; + justify-content: flex-start; + } + + .projectDetails { + padding: 24px 20px; + } + + .detailGrid { + grid-template-columns: 1fr; + gap: 24px; + } + + .carouselItem { + height: 250px; + } + + .actionButton { + height: 36px; + font-size: 0.9rem; + } +} + +@media (max-width: 480px) { + .modalHeader { + padding: 20px 16px 16px; + } + + .modalTitle { + font-size: 1.5rem !important; + } + + .projectDetails { + padding: 20px 16px; + } + + .carouselItem { + height: 200px; + } } \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a70800e..32dd2eb 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,12 +7,14 @@ import "./globals.css"; import { themeConfig } from "./theme/themeConfig"; // Modern font (Inter + Orbitron backup) -const inter = Inter({ subsets: ["latin"] }); -const orbitron = { - className: "font-orbitron", - style: - "@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');", -}; +const inter = Inter({ + subsets: ["latin"], + display: "swap", + fallback: ["system-ui", "arial"], + adjustFontFallback: true, + preload: true, + variable: "--font-inter", +}); export const metadata: Metadata = { title: "Tech Master | Dubai To Stars", @@ -24,7 +26,7 @@ export default function RootLayout({ children: React.ReactNode; }) { return ( - + {/* ThreeJS CDN */} {/* Orbitron Font */} -