diff --git a/package-lock.json b/package-lock.json index 9ffdc9c..2ee69bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "portfolio", "version": "0.0.0", "dependencies": { + "lucide-react": "^0.562.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.3.0" @@ -81,6 +82,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -936,7 +938,6 @@ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "optional": true, - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -1258,17 +1259,6 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, - "node_modules/@types/node": { - "version": "22.5.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", - "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "undici-types": "~6.19.2" - } - }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -1318,6 +1308,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1670,6 +1661,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", @@ -1688,8 +1680,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/call-bind": { "version": "1.0.7", @@ -2247,6 +2238,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", @@ -3564,6 +3556,7 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -3732,6 +3725,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.562.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz", + "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4248,6 +4250,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -4454,6 +4457,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -4800,7 +4804,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "optional": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4812,7 +4815,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5122,7 +5124,6 @@ "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", "dev": true, "optional": true, - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -5141,8 +5142,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -5310,14 +5310,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -5377,6 +5369,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.5.tgz", "integrity": "sha512-pXqR0qtb2bTwLkev4SE3r4abCNioP3GkjvIDLlzziPpXtHgiJIjuKl+1GN6ESOT3wMjG3JTeARopj2SwYaHTOA==", "dev": true, + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", diff --git a/package.json b/package.json index 22d1b47..1316bb6 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "preview": "vite preview" }, "dependencies": { + "lucide-react": "^0.562.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.3.0" diff --git a/src/assets/images/angular-icon.svg b/src/assets/images/angular-icon.svg new file mode 100644 index 0000000..09c59e9 --- /dev/null +++ b/src/assets/images/angular-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/mysql-logo-svgrepo-com.svg b/src/assets/images/mysql-logo-svgrepo-com.svg new file mode 100644 index 0000000..c976100 --- /dev/null +++ b/src/assets/images/mysql-logo-svgrepo-com.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/assets/images/mysql-new.svg b/src/assets/images/mysql-new.svg new file mode 100644 index 0000000..5d04ae2 --- /dev/null +++ b/src/assets/images/mysql-new.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/images/skill-icons-5.svg b/src/assets/images/skill-icons-5.svg new file mode 100644 index 0000000..41b8b4f --- /dev/null +++ b/src/assets/images/skill-icons-5.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/About.jsx b/src/components/About.jsx index a3ed73b..4025c58 100644 --- a/src/components/About.jsx +++ b/src/components/About.jsx @@ -32,10 +32,10 @@ const About = () => {

Front-end Developer
based in Lahore, Punjab 📍

- I'm Rustam Ali Kazmi, a Frontend Developer with 1.5 years of hands-on experience working on real-time enterprise-level web applications. + I'm Rustam Ali Kazmi, a Full-Stack Developer with 2.5 years of hands-on experience working on real-time enterprise-level web applications.

- I specialize in building scalable, maintainable, and performance-optimized frontends using modern framework technology like Angular and libary like React, JavaScript, and Tailwind CSS. I’ve worked extensively on integrating RESTful APIs, managing application state, and delivering seamless user experiences. + I specialize in building scalable, maintainable, and performance-optimized solutions using modern framework technology like Angular, Nextjs and libary like React, JavaScript, and Bootstrap,Tailwind CSS. I’ve worked extensively on integrating RESTful APIs, managing application state,managing databases write queries and delivering seamless user experiences.

diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx index a4a835d..4c6e70a 100644 --- a/src/components/Footer.jsx +++ b/src/components/Footer.jsx @@ -5,7 +5,7 @@ import { FiGithub } from 'react-icons/fi' const Footer = () => { return (
-

Copyright © 2023. All rights are reserved

+

Copyright © 2025. All rights are reserved

diff --git a/src/components/HeroSection.jsx b/src/components/HeroSection.jsx index 7f32ef8..f603fc5 100644 --- a/src/components/HeroSection.jsx +++ b/src/components/HeroSection.jsx @@ -1,10 +1,10 @@ -import React from "react"; import { CiLinkedin } from "react-icons/ci"; import { FiGithub } from "react-icons/fi"; import skillIcon1 from "../assets/images/skill-icons-1.svg" import skillIcon2 from "../assets/images/skill-icons-2.svg" import skillIcon3 from "../assets/images/skill-icons-3.svg" import skillIcon4 from "../assets/images/skill-icons-4.svg" +import skillIcon5 from "../assets/images/skill-icons-5.svg" const HeroSection = () => { return ( @@ -12,15 +12,15 @@ const HeroSection = () => {
-

Front-End

+

Full-Stack

{" "} Developer{" "} - in Punjab + in Lahore

- Hi, I'm Rustam Ali Kazmi. A passionate Front-end Developer + Hi, I'm Rustam Ali Kazmi. A passionate Full Stack Developer based in Lahore, Punjab. 📍

@@ -68,6 +68,13 @@ const HeroSection = () => { alt="Tailwind&Sass" /> +
  • + Angular&MySQL +
  • diff --git a/src/components/ImageLightbox.jsx b/src/components/ImageLightbox.jsx new file mode 100644 index 0000000..8bdb903 --- /dev/null +++ b/src/components/ImageLightbox.jsx @@ -0,0 +1,140 @@ +import { useState, useEffect } from 'react' + +const ImageLightbox = ({ images = [], isOpen, onClose, initialIndex = 0 }) => { + const [currentIndex, setCurrentIndex] = useState(initialIndex) + + useEffect(() => { + setCurrentIndex(initialIndex) + }, [initialIndex]) + + useEffect(() => { + const handleKeyDown = (e) => { + if (!isOpen || !images.length) return + + switch (e.key) { + case 'Escape': + onClose() + break + case 'ArrowLeft': + goToPrevious() + break + case 'ArrowRight': + goToNext() + break + } + } + + document.addEventListener('keydown', handleKeyDown) + return () => document.removeEventListener('keydown', handleKeyDown) + }, [isOpen, currentIndex, images.length]) + + const goToNext = () => { + if (images.length > 0) { + setCurrentIndex((prev) => (prev + 1) % images.length) + } + } + + const goToPrevious = () => { + if (images.length > 0) { + setCurrentIndex((prev) => (prev - 1 + images.length) % images.length) + } + } + + // Don't render if not open or no images + if (!isOpen || !images || images.length === 0) return null + + const currentImage = images[currentIndex] + if (!currentImage) return null + + return ( +
    + {/* Close button */} + + + {/* Previous button */} + {images.length > 1 && ( + + )} + + {/* Next button */} + {images.length > 1 && ( + + )} + + {/* Main image container */} +
    +
    + {currentImage.alt} +
    + + {/* Image info */} +
    +

    + {currentImage.alt} +

    + + {/* Image counter */} + {images.length > 1 && ( +

    + {currentIndex + 1} of {images.length} +

    + )} +
    +
    + + {/* Thumbnail navigation */} + {images.length > 1 && ( +
    + {images.map((image, index) => ( + + ))} +
    + )} + + {/* Click outside to close */} +
    +
    + ) +} + +export default ImageLightbox \ No newline at end of file diff --git a/src/components/ProjectCard.jsx b/src/components/ProjectCard.jsx new file mode 100644 index 0000000..56e53a5 --- /dev/null +++ b/src/components/ProjectCard.jsx @@ -0,0 +1,150 @@ +import { useState } from 'react' +import { Eye, ExternalLink, GitBranch, Code2 } from 'lucide-react' + +const ProjectCard = ({ project, onImageClick }) => { + const [imageError, setImageError] = useState({}) + + const handleImageError = (index) => { + setImageError(prev => ({ ...prev, [index]: true })) + } + + const handleImageClick = (index) => { + onImageClick(project.images, index) + } + + return ( +
    + {/* Project Header */} +
    +
    +
    +
    + +
    +

    + {project.title} +

    +
    + + {project.status} + +
    + +

    {project.period}

    + +

    + {project.description} +

    +
    + + {/* Screenshots Section */} +
    +
    + {project.images.slice(0, 4).map((image, index) => ( +
    handleImageClick(index)} + > + {!imageError[index] ? ( + {image.alt} handleImageError(index)} + /> + ) : ( +
    +
    +
    🖼️
    +
    {image.alt}
    +
    +
    + )} + +
    + + + View + +
    +
    + ))} +
    +
    + + {/* Content Area - Flexible */} +
    + {/* Tech Stack */} +
    +

    Tech Stack

    +
    + {project.techStack.slice(0, 5).map((tech, index) => ( + + {tech} + + ))} + {project.techStack.length > 5 && ( + + +{project.techStack.length - 5} + + )} +
    +
    + + {/* Key Features */} +
    +

    Key Features

    +
    + {project.keyFeatures.slice(0, 3).map((feature, index) => ( +
    +
    + {feature} +
    + ))} +
    +
    +
    + + {/* Action Buttons - Always at bottom */} +
    +
    + {project.liveLink && ( + + + Live Demo + + )} + {project.githubLink && ( + + + Code + + )} + {!project.liveLink && !project.githubLink && ( +
    + + In Development +
    + )} +
    +
    +
    + ) +} + +export default ProjectCard \ No newline at end of file diff --git a/src/components/Projects.jsx b/src/components/Projects.jsx index 4872817..bb18e82 100644 --- a/src/components/Projects.jsx +++ b/src/components/Projects.jsx @@ -1,42 +1,111 @@ -import React from 'react' +import { useState } from 'react' +import { Building2, Truck, Briefcase, FolderOpen } from 'lucide-react' +import ImageLightbox from './ImageLightbox' +import ProjectCard from './ProjectCard' import memershipDashboardImg from '../assets/screenshots/membership-dashboard.png' import metricsDashboardImg from '../assets/screenshots/metrics-dashboard.png' import loginPageImg from '../assets/screenshots/login-page.png' import departmentImg from '../assets/screenshots/department.png' const Projects = () => { - return ( -
    -
    -

    Projects

    - -
    -

    🕌 MMS – Mosque Management System

    -

    Feb 2025 – Present (Work in Progress)

    + const [lightboxOpen, setLightboxOpen] = useState(false) + const [selectedImages, setSelectedImages] = useState([]) + const [selectedImageIndex, setSelectedImageIndex] = useState(0) -

    - A real-time web application built to streamline mosque operations like member management, donation tracking, mosque events, and more — targeted for mosques in the USA, Europe, and Russia. -

    + const projects = [ + { + id: 1, + title: "MMS – Mosque Management System", + icon: Building2, + period: "Feb 2024 - Present", + status: "Work in Progress", + description: "A comprehensive real-time web application designed to streamline mosque operations including member management, donation tracking, event coordination, and administrative tasks. Specifically tailored for mosques across the USA, Europe, and Russia with multi-language support.", + techStack: ["Angular 16+", "RxJS", "Angular Material", "SCSS", "Chart.js", "REST APIs", "Stripe", "Cloudinary", "TypeScript", "Node.js"], + keyFeatures: ["Real-time analytics dashboard", "Cloudinary photo management", "Stripe payment integration", "Multi-step responsive forms"], + images: [ + { src: loginPageImg, alt: "Secure Login Interface" }, + { src: metricsDashboardImg, alt: "Analytics Dashboard" }, + { src: memershipDashboardImg, alt: "Member Management System" }, + { src: departmentImg, alt: "Department Organization" } + ], + liveLink: null, + githubLink: null + }, + { + id: 2, + title: "Numeo Freight Management Platform", + icon: Truck, + period: "2022 - Present", + status: "Live", + description: "Freight Management Platform (FMP): Web platform for managing freight operations, load tracking, payments, and carrier engagement. Built a real-time load matching system improving carrier efficiency. Optimized search/filtering with advanced algorithms, reducing database load by 40%. Designed a microservices architecture with Rush.js monorepo for scalable deployment.", + techStack: ["React", "Node.js", "Rush.js", "Microservices", "REST APIs", "WebSocket", "MongoDB", "Redis", "Docker", "AWS"], + keyFeatures: ["Real-time load matching system", "Advanced search algorithms", "Carrier engagement platform", "Microservices architecture"], + images: [ + { src: "https://via.placeholder.com/400x300/4F46E5/white?text=Freight+Dashboard", alt: "Freight Management Dashboard" }, + { src: "https://via.placeholder.com/400x300/7C3AED/white?text=Load+Tracking", alt: "Real-time Load Tracking System" } + ], + liveLink: "https://agent.numeo.ai/", + githubLink: null + }, + { + id: 3, + title: "Tamakun Job Seeking Platform", + icon: Briefcase, + period: "2025", + status: "Live", + description: "A comprehensive job seeking and recruitment platform connecting job seekers with employers across the UAE. Features advanced job matching algorithms, real-time application tracking, employer dashboards, and seamless candidate management. Built with modern web technologies to provide an intuitive user experience for both job seekers and recruiters.", + techStack: ["React", "Next.js", "Tailwind CSS", "Node.js", "MongoDB", "Vercel", "Express", "JWT", "Stripe"], + keyFeatures: ["Advanced job matching algorithms", "Real-time application tracking", "Employer dashboard & analytics", "Candidate profile management"], + images: [ + { src: "https://via.placeholder.com/400x300/F59E0B/white?text=Job+Portal+Homepage", alt: "Job Portal Homepage" }, + { src: "https://via.placeholder.com/400x300/EF4444/white?text=Job+Search+Dashboard", alt: "Job Search Dashboard" } + ], + liveLink: "https://www.tamakun.ae/", + githubLink: null + } + ] -

    - Tech Stack: Angular 16+, RxJS, Angular Material, SCSS, Chart.js, REST APIs, Stripe, Cloudinary -

    + const openLightbox = (images, index) => { + setSelectedImages(images) + setSelectedImageIndex(index) + setLightboxOpen(true) + } -

    - My Contributions: Developed reusable components, implemented real-time charts, handled photo uploads via Cloudinary, integrated Stripe for secure donations, and built responsive multi-step forms with full API connectivity. -

    + return ( +
    +
    + {/* Header Section */} +
    + +

    + Featured Projects +

    +

    + Discover my latest work in web development, showcasing modern technologies, + innovative solutions, and user-centric design principles +

    +
    -
    - Login Page - Metrics Dashboard - MMS Members Page - departments + {/* Projects Grid - 2 columns on desktop, 1 on mobile */} +
    + {projects.map((project) => ( + + ))} +
    -

    Project is currently in development. Live link will be added upon launch.

    + {/* Image Lightbox */} + setLightboxOpen(false)} + initialIndex={selectedImageIndex} + />
    -
    -
    ) } diff --git a/src/index.css b/src/index.css index bffa81a..65c6262 100644 --- a/src/index.css +++ b/src/index.css @@ -67,4 +67,17 @@ height: 22rem; width: 22rem; } - } \ No newline at end of file + } + +/* Line clamp utility for text truncation */ +.line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* Aspect ratio utility for images */ +.aspect-video { + aspect-ratio: 16 / 9; +} \ No newline at end of file