diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 49d51f8..4204022 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -17,7 +17,7 @@ import UsersIcon from '@mui/icons-material/People' import ThemeRegistry from '@/components/ThemeRegistry/ThemeRegistry' export const metadata = { - title: 'Next.js MUI Starter Template', + title: 'd4m13n.dev', description: 'Next.js App Router + Material UI v5 Starter Template' } diff --git a/src/app/page.tsx b/src/app/page.tsx index be56b05..f03cc71 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,16 +5,26 @@ import { useState } from 'react'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import Fade from '@mui/material/Fade'; +import Button from '@mui/material/Button'; +import Tabs from '@mui/material/Tabs'; +import Tab from '@mui/material/Tab'; import TypingAnimation from '@/components/TypingAnimation'; +import ProjectMasonry from '@/components/ProjectMasonry'; +import projects from '@/data/projects'; export default function HomePage() { const [showContent, setShowContent] = useState(false); + const [activeTab, setActiveTab] = useState(0); + + const handleTabChange = (event: React.SyntheticEvent, newValue: number) => { + setActiveTab(newValue); + }; return ( <> {!showContent && ( - - Damien's Website + + + d4m13n + + .dev - - This is a test sentence. - - {/* Add more content here */} + + + + + + + + + + + {activeTab === 0 && ( + + + + )} + + {activeTab === 1 && ( + + + + )} + {activeTab === 2 && ( + + + About Me + + + I'm a passionate developer with expertise in modern web technologies. + I love creating responsive, user-friendly applications that solve real-world problems. + + + When I'm not coding, you can find me exploring new technologies, contributing to open-source projects, + or enjoying outdoor activities. + + + )} + + {activeTab === 3 && ( + + + Contact + + + Feel free to reach out to me for collaboration opportunities or just to say hello! + + + + )} diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx new file mode 100644 index 0000000..c2f9c9e --- /dev/null +++ b/src/components/ProjectCard.tsx @@ -0,0 +1,313 @@ +import React, { useState } from 'react'; +import { + Box, + Card, + CardContent, + CardMedia, + Typography, + Button, + IconButton, + Chip, + Stack, + useTheme, + useMediaQuery +} from '@mui/material'; +import GitHubIcon from '@mui/icons-material/GitHub'; +import LaunchIcon from '@mui/icons-material/Launch'; +import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew'; +import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; + +// Define the project image interface +interface ProjectImage { + src: string; + alt: string; +} + +// Define the repository interface +interface Repository { + name: string; + url: string; +} + +// Define the project interface +export interface Project { + id: string; + title: string; + description: string; + technologies: string[]; + images: ProjectImage[]; + repositories?: Repository[]; // Multiple repositories with names + demoUrl?: string; +} + +interface ProjectCardProps { + project: Project; +} + +const ProjectCard: React.FC = ({ project }) => { + const [currentImageIndex, setCurrentImageIndex] = useState(0); + const [isHovered, setIsHovered] = useState(false); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + + // Colors and effects based on specifications + const cardBgColor = theme.palette.grey[900]; // Dark grey from theme + const textColor = '#ffffff'; // Crisp white + const dropShadow = '0px 4px 8px rgba(0,0,0,0.3)'; + const ambientGlow = '0px 0px 15px rgba(255, 255, 255, 0.15)'; // White glow + const enhancedGlow = '0px 0px 20px rgba(255, 255, 255, 0.3)'; // Enhanced white glow + const titleColor = '#4fd1ff'; // Same blue as active tab + const titleGlow = '0px 0px 10px rgba(255, 255, 255, 0.15), 0px 0px 20px rgba(255, 255, 255, 0.1)'; // White glow for title + + // Handle image navigation + const handlePrevImage = (e: React.MouseEvent) => { + e.stopPropagation(); + setCurrentImageIndex(prev => + prev === 0 ? project.images.length - 1 : prev - 1 + ); + }; + + const handleNextImage = (e: React.MouseEvent) => { + e.stopPropagation(); + setCurrentImageIndex(prev => + prev === project.images.length - 1 ? 0 : prev + 1 + ); + }; + + return ( + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + sx={{ + backgroundColor: cardBgColor, // Use the deep blue background color + color: textColor, + boxShadow: isHovered ? enhancedGlow : dropShadow, + transition: 'all 0.3s ease-in-out', + height: '100%', // Ensure card takes full height + display: 'flex', + flexDirection: 'column', + position: 'relative', + overflow: 'hidden', + '&:hover': { + transform: 'translateY(-5px)', + boxShadow: enhancedGlow, + }, + }} + > + {project.images.length > 0 && ( + + + + {/* Image navigation controls - only show if there are multiple images */} + {project.images.length > 1 && ( + <> + + + + + + + + + {/* Image counter indicator */} + + {currentImageIndex + 1} / {project.images.length} + + + )} + + )} + + + + {project.title} + + + + {project.description} + + + + {project.technologies.map((tech, index) => ( + + ))} + + + + {/* Repository buttons */} + {project.repositories && project.repositories.length > 0 && ( + <> + {project.repositories.map((repo, index) => ( + + ))} + + )} + + {/* Demo button */} + {project.demoUrl && ( + + )} + + + + ); +}; + +export default ProjectCard; \ No newline at end of file diff --git a/src/components/ProjectMasonry.tsx b/src/components/ProjectMasonry.tsx new file mode 100644 index 0000000..778c68c --- /dev/null +++ b/src/components/ProjectMasonry.tsx @@ -0,0 +1,90 @@ +import React, { useEffect, useState } from 'react'; +import { Box, Grid, useMediaQuery, useTheme } from '@mui/material'; +import ProjectCard, { Project } from './ProjectCard'; + +interface ProjectMasonryProps { + projects: Project[]; +} + +const ProjectMasonry: React.FC = ({ projects }) => { + const theme = useTheme(); + const isXs = useMediaQuery(theme.breakpoints.only('xs')); + const isSm = useMediaQuery(theme.breakpoints.only('sm')); + const isMd = useMediaQuery(theme.breakpoints.only('md')); + + // Assign varying widths to projects + const getProjectWidths = () => { + return projects.map((project, index) => { + // Create a pattern of varying widths + // This creates a more interesting masonry layout + if (isXs) return 12; // On mobile, all cards are full width + + // Create a pattern for varying widths + const patterns = [ + // Pattern 1: [6, 6, 12, 6, 6] + [6, 6, 12, 6, 6], + // Pattern 2: [8, 4, 4, 8, 12] + [8, 4, 4, 8, 12], + // Pattern 3: [4, 8, 4, 8, 4, 8] + [4, 8, 4, 8, 4, 8] + ]; + + // Select a pattern based on the index + const patternIndex = Math.floor(index / 5) % patterns.length; + const pattern = patterns[patternIndex]; + const positionInPattern = index % pattern.length; + + return pattern[positionInPattern]; + }); + }; + + const projectWidths = getProjectWidths(); + + return ( + + + {projects.map((project, index) => ( + + + + ))} + + + ); +}; + +export default ProjectMasonry; \ No newline at end of file diff --git a/src/components/TypingAnimation.tsx b/src/components/TypingAnimation.tsx index 391d826..d037577 100644 --- a/src/components/TypingAnimation.tsx +++ b/src/components/TypingAnimation.tsx @@ -116,7 +116,7 @@ const TypingAnimation: React.FC = ({ // Blue glow for "Damien" const blueGlowEffects = { - textShadow: '0 0 10px rgba(25, 118, 210, 0.35), 0 0 20px rgba(25, 118, 210, 0.25)', + textShadow: '0 0 10px rgba(79, 209, 255, 0.15), 0 0 20px rgba(79, 209, 255, 0.1)', filter: 'drop-shadow(0 2px 4px rgba(0, 0, 0, 0.25))' }; @@ -132,7 +132,7 @@ const TypingAnimation: React.FC = ({ const fullTitleText = titleText; // Find where "Damien" starts in the full text - const damienStartIndex = fullTitleText.toLowerCase().indexOf('damien'); + const damienStartIndex = fullTitleText.toLowerCase().indexOf('d4m13n'); // If "Damien" isn't in the text (shouldn't happen, but just in case) if (damienStartIndex === -1) { @@ -159,7 +159,7 @@ const TypingAnimation: React.FC = ({ key={i} component="span" sx={{ - color: '#1976d2', /* Material UI primary blue */ + color: '#4fd1ff', /* Same blue as active tab */ ...blueGlowEffects }} > diff --git a/src/data/projects.ts b/src/data/projects.ts new file mode 100644 index 0000000..18f3755 --- /dev/null +++ b/src/data/projects.ts @@ -0,0 +1,181 @@ +import { Project } from '@/components/ProjectCard'; + +// Sample project data +const projects: Project[] = [ + { + id: '1', + title: 'E-Commerce Platform', + description: 'A full-featured e-commerce platform with product management, shopping cart, and payment processing capabilities.', + technologies: ['React', 'Node.js', 'MongoDB', 'Stripe'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?ecommerce', + alt: 'E-commerce dashboard' + }, + { + src: 'https://source.unsplash.com/random/800x600?shopping', + alt: 'Shopping cart interface' + }, + { + src: 'https://source.unsplash.com/random/800x600?payment', + alt: 'Payment processing screen' + } + ], + repositories: [ + { name: 'Frontend', url: 'https://github.com/username/ecommerce-frontend' }, + { name: 'Backend', url: 'https://github.com/username/ecommerce-api' } + ], + demoUrl: 'https://ecommerce-demo.example.com' + }, + { + id: '2', + title: 'Weather App', + description: 'A responsive weather application that provides real-time weather data and forecasts for locations worldwide.', + technologies: ['JavaScript', 'React', 'OpenWeather API', 'CSS'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?weather', + alt: 'Weather app interface' + }, + { + src: 'https://source.unsplash.com/random/800x600?forecast', + alt: 'Forecast view' + } + ], + repositories: [ + { name: 'Repo', url: 'https://github.com/username/weather-app' } + ], + demoUrl: 'https://weather-app-demo.example.com' + }, + { + id: '3', + title: 'Task Management System', + description: 'A comprehensive task management system with features like task assignment, progress tracking, and deadline notifications.', + technologies: ['TypeScript', 'Angular', 'Firebase', 'Material UI'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?tasks', + alt: 'Task management dashboard' + } + ], + repositories: [ + { name: 'Repo', url: 'https://github.com/username/task-management' } + ], + demoUrl: 'https://task-app-demo.example.com' + }, + { + id: '4', + title: 'Portfolio Website', + description: 'A personal portfolio website showcasing projects, skills, and professional experience with a modern, responsive design.', + technologies: ['HTML', 'CSS', 'JavaScript', 'GSAP'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?portfolio', + alt: 'Portfolio homepage' + }, + { + src: 'https://source.unsplash.com/random/800x600?website', + alt: 'Projects section' + }, + { + src: 'https://source.unsplash.com/random/800x600?design', + alt: 'Contact form' + } + ], + repositories: [ + { name: 'Repo', url: 'https://github.com/username/portfolio' } + ], + demoUrl: 'https://portfolio-demo.example.com' + }, + { + id: '5', + title: 'Recipe Finder', + description: 'An application that allows users to search for recipes based on ingredients, dietary restrictions, and cuisine preferences.', + technologies: ['React', 'Redux', 'Spoonacular API', 'Styled Components'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?recipe', + alt: 'Recipe search interface' + }, + { + src: 'https://source.unsplash.com/random/800x600?food', + alt: 'Recipe details' + } + ], + repositories: [ + { name: 'Repo', url: 'https://github.com/username/recipe-finder' } + ], + demoUrl: 'https://recipe-finder-demo.example.com' + }, + { + id: '6', + title: 'Fitness Tracker', + description: 'A fitness tracking application that helps users monitor workouts, set goals, and track progress over time.', + technologies: ['React Native', 'Firebase', 'Redux', 'Chart.js'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?fitness', + alt: 'Fitness tracker dashboard' + }, + { + src: 'https://source.unsplash.com/random/800x600?workout', + alt: 'Workout tracking screen' + }, + { + src: 'https://source.unsplash.com/random/800x600?exercise', + alt: 'Progress charts' + } + ], + repositories: [ + { name: 'Repo', url: 'https://github.com/username/fitness-tracker' } + ], + demoUrl: 'https://fitness-app-demo.example.com' + }, + { + id: '7', + title: 'Chat Application', + description: 'A real-time chat application with features like private messaging, group chats, and file sharing capabilities.', + technologies: ['Socket.io', 'Express', 'MongoDB', 'React'], + images: [ + { + src: 'https://source.unsplash.com/random/800x600?chat', + alt: 'Chat interface' + }, + { + src: 'https://source.unsplash.com/random/800x600?messaging', + alt: 'Messaging screen' + } + ], + repositories: [ + { name: 'Repo', url: 'https://github.com/username/chat-app' } + ], + demoUrl: 'https://chat-app-demo.example.com' + }, + // { + // id: '8', + // title: 'Budget Tracker', + // description: 'A financial management application that helps users track income, expenses, and savings goals with visual reports.', + // technologies: ['Vue.js', 'Node.js', 'PostgreSQL', 'D3.js'], + // images: [ + // { + // src: 'https://source.unsplash.com/random/800x600?budget', + // alt: 'Budget dashboard' + // }, + // { + // src: 'https://source.unsplash.com/random/800x600?finance', + // alt: 'Expense tracking' + // }, + // { + // src: 'https://source.unsplash.com/random/800x600?money', + // alt: 'Financial reports' + // } + // ], + // repositories: [ + // { name: 'Frontend', url: 'https://github.com/username/budget-tracker-ui' }, + // { name: 'API', url: 'https://github.com/username/budget-tracker-api' } + // ], + // demoUrl: 'https://budget-app-demo.example.com' + // } +]; + +export default projects; \ No newline at end of file