├── .gitattributes ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── sitemap.xml ├── manifest.json ├── vite.svg └── index.html ├── src ├── assets │ ├── mylogonew.webp │ ├── profilePicnew.webp │ └── constants │ │ └── index.js ├── setupTests.js ├── App.test.js ├── index.css ├── reportWebVitals.js ├── components │ ├── Home.jsx │ ├── ProjectFilter.jsx │ ├── TechnologyCard.jsx │ ├── Technologies.jsx │ ├── ProjectCard.jsx │ ├── BlogCard.jsx │ ├── Blog.jsx │ ├── Projects.jsx │ ├── TechnologyDetails.jsx │ ├── AllBlogs.jsx │ ├── Navbar.jsx │ ├── Hero.jsx │ └── Contact.jsx ├── generate-sitemap.js ├── index.js ├── App.jsx └── logo.svg ├── tailwind.config.js ├── .gitignore ├── package.json └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilshanDe/Portfolio/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilshanDe/Portfolio/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilshanDe/Portfolio/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/mylogonew.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilshanDe/Portfolio/HEAD/src/assets/mylogonew.webp -------------------------------------------------------------------------------- /src/assets/profilePicnew.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DilshanDe/Portfolio/HEAD/src/assets/profilePicnew.webp -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Allow: / 4 | Sitemap: https://chamikadamith.me/sitemap.xml 5 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./src/**/*.{js,jsx,ts,tsx}", 5 | ], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [], 10 | } -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | :root{ 8 | font-family: "Inter", sans-serif; 9 | background: #000000; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | http://www.chamikadamith.me/ 8 | 9 | 2025-01-04 10 | 11 | monthly 12 | 13 | 0.8 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/components/Home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Hero from './Hero' 3 | import Technologies from './Technologies' 4 | import Projects from './Projects' 5 | import Blog from './Blog' 6 | import Contact from './Contact' 7 | 8 | const Home = () => { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 |
17 | ) 18 | } 19 | 20 | export default Home -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | react-portfolio-main/src/assets/profilePicnew.webp 25 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/generate-sitemap.js: -------------------------------------------------------------------------------- 1 | const { SitemapStream, streamToPromise } = require('sitemap'); 2 | const fs = require('fs'); 3 | 4 | const sitemap = new SitemapStream({ hostname: 'https://dilshansilva.me' }); 5 | 6 | streamToPromise( 7 | sitemap 8 | .pipe(fs.createWriteStream('../public/sitemap.xml')) 9 | .on('error', (err) => { 10 | console.error('Error writing sitemap:', err); 11 | }) 12 | ) 13 | .then(() => { 14 | console.log('Sitemap successfully generated!'); 15 | }) 16 | .catch((err) => { 17 | console.error('Error during sitemap generation:', err); 18 | }); 19 | 20 | sitemap.write({ url: '/', changefreq: 'monthly', priority: 0.8 }); 21 | sitemap.end(); 22 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import { SpeedInsights } from "@vercel/speed-insights/react" 7 | import { Analytics } from "@vercel/analytics/react" 8 | import { BrowserRouter } from 'react-router-dom'; 9 | 10 | const root = ReactDOM.createRoot(document.getElementById('root')); 11 | root.render( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | 21 | // If you want to start measuring performance in your app, pass a function 22 | // to log results (for example: reportWebVitals(console.log)) 23 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 24 | reportWebVitals(); -------------------------------------------------------------------------------- /src/components/ProjectFilter.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | export function ProjectFilter({ categories, selectedCategory, onSelectCategory }) { 5 | return ( 6 |
7 | {categories.map((category) => ( 8 | 26 | ))} 27 |
28 | ); 29 | } -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from "react-router-dom"; 2 | import Home from "./components/Home"; 3 | import Navbar from "./components/Navbar"; 4 | import AllBlogs from "./components/AllBlogs"; 5 | 6 | 7 | export default function App() { 8 | return ( 9 |
10 |
11 |
12 |
15 |
17 |
18 | 19 |
20 | 21 | 22 | 23 | } /> 24 | } /> 25 | 26 |
27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/TechnologyCard.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { TechnologyDetails } from "./TechnologyDetails"; 3 | import { motion } from "framer-motion"; 4 | 5 | export function TechnologyCard({ icon: Icon, name, description }) { 6 | const [isHovered, setIsHovered] = useState(false); 7 | 8 | return ( 9 |
setIsHovered(true)} 11 | onMouseLeave={() => setIsHovered(false)} 12 | className="relative group cursor-pointer h-[200px] transition-transform duration-300 hover:scale-105" 13 | > 14 |
15 | 21 |
22 | 23 |
24 |

{name}

25 |

30 | {description} 31 |

32 | 33 |
34 |
35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/components/Technologies.jsx: -------------------------------------------------------------------------------- 1 | import { motion } from 'framer-motion'; 2 | import { TechnologyCard } from './TechnologyCard'; 3 | import { technologies } from '../assets/constants'; 4 | 5 | export default function Technologies() { 6 | return ( 7 |
8 |
9 | 16 | 22 | Technologies 23 | 24 | 30 | Leveraging cutting-edge technologies to build innovative solutions 31 | 32 | 33 | 34 | 42 | {technologies.map((tech) => ( 43 | 44 | ))} 45 | 46 |
47 |
48 | ); 49 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-portfolio", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@chakra-ui/react": "^2.10.2", 7 | "@emailjs/browser": "^4.4.1", 8 | "@emotion/react": "^11.13.3", 9 | "@emotion/styled": "^11.13.0", 10 | "@fortawesome/free-brands-svg-icons": "^6.7.2", 11 | "@fortawesome/react-fontawesome": "^0.2.2", 12 | "@radix-ui/react-icons": "^1.3.0", 13 | "@tabler/icons-react": "^3.31.0", 14 | "@testing-library/jest-dom": "^5.17.0", 15 | "@testing-library/react": "^13.4.0", 16 | "@testing-library/user-event": "^13.5.0", 17 | "@vercel/analytics": "^1.4.1", 18 | "@vercel/speed-insights": "^1.1.0", 19 | "animejs": "^3.2.2", 20 | "axios": "^1.7.9", 21 | "class-variance-authority": "^0.7.0", 22 | "clsx": "^2.1.1", 23 | "framer-motion": "^11.11.8", 24 | "lucide-react": "^0.344.0", 25 | "marked": "^12.0.1", 26 | "motion": "^11.15.0", 27 | "react": "^18.3.1", 28 | "react-dom": "^18.3.1", 29 | "react-icon": "^1.0.0", 30 | "react-icons": "^5.4.0", 31 | "react-intersection-observer": "^9.13.1", 32 | "react-router-dom": "^6.22.0", 33 | "react-scripts": "5.0.1", 34 | "react-scroll": "^1.9.0", 35 | "sitemap": "^8.0.0", 36 | "tailwind-merge": "^2.5.3", 37 | "tailwindcss-animate": "^1.0.7", 38 | "web-vitals": "^2.1.4" 39 | }, 40 | "scripts": { 41 | "start": "react-scripts start", 42 | "build": "react-scripts build", 43 | "test": "react-scripts test", 44 | "eject": "react-scripts eject", 45 | "generate-sitemap": "node src/generate-sitemap.js" 46 | }, 47 | "eslintConfig": { 48 | "extends": [ 49 | "react-app", 50 | "react-app/jest" 51 | ] 52 | }, 53 | "browserslist": { 54 | "production": [ 55 | ">0.2%", 56 | "not dead", 57 | "not op_mini all" 58 | ], 59 | "development": [ 60 | "last 1 chrome version", 61 | "last 1 firefox version", 62 | "last 1 safari version" 63 | ] 64 | }, 65 | "devDependencies": { 66 | "tailwindcss": "^3.4.13" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/components/ProjectCard.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ExternalLink } from "lucide-react"; 3 | import { motion } from "framer-motion"; 4 | 5 | export function ProjectCard({ 6 | title, 7 | description, 8 | image, 9 | technologies = [], 10 | link, 11 | }) { 12 | return ( 13 | 19 |
20 |
21 | {title} 26 | {link && ( 27 | 33 | 34 | 35 | )} 36 |
37 | 38 |
39 |

{title}

40 |

{description}

41 |
42 | 43 |
44 | {technologies.map((tech) => ( 45 | 49 | {tech} 50 | 51 | ))} 52 |
53 |
54 |
55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Dilshan 28 | 29 | 30 | 31 | 32 | 33 | 40 | 41 | 42 |
43 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/components/BlogCard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { CalendarDays, ArrowUpRight } from 'lucide-react'; 3 | import { motion } from 'framer-motion'; 4 | 5 | export function BlogCard({ post }) { 6 | return ( 7 | 11 | {/* Gradient Overlay */} 12 |
13 | 14 | {/* Image Section */} 15 |
16 | {post.title} 21 |
22 |
23 | 24 | {/* Content Section */} 25 |
26 |
27 | 28 | 29 |
30 | 31 |

32 | {post.title} 33 |

34 | 35 |

{post.excerpt}

36 | 37 | {/* Read More Section */} 38 | 52 |
53 | 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /src/components/Blog.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BlogCard } from "./BlogCard"; 3 | import { BLOGPOST } from "../assets/constants"; 4 | import { motion } from "framer-motion"; 5 | import { Link } from "react-router-dom"; 6 | 7 | export default function Blog() { 8 | return ( 9 |
14 |
15 |
16 |
17 |
18 | 19 |
20 |
21 |
22 | 28 | Latest Articles 29 | 30 |
31 | 32 | 38 | Explore the future of technology through my curated insights and 39 | discoveries 40 | 41 |
42 | 43 |
44 |
45 | {BLOGPOST.map((post, index) => ( 46 | 47 | ))} 48 |
49 | 50 |
51 | 55 | View All 56 | 57 |
58 |
59 |
60 |
61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Projects.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { PROJECTS } from "../assets/constants"; 3 | import { ProjectCard } from "./ProjectCard"; 4 | import { ProjectFilter } from "./ProjectFilter"; 5 | import { motion } from "framer-motion"; 6 | 7 | const ALL_CATEGORIES = ["All", "UI design", "Applications", "Web development"]; 8 | const INITIAL_DISPLAY_COUNT = 6; 9 | 10 | export default function Projects() { 11 | const [selectedCategory, setSelectedCategory] = useState("All"); 12 | const [visibleProjectsCount, setVisibleProjectsCount] = useState( 13 | INITIAL_DISPLAY_COUNT 14 | ); 15 | 16 | const filteredProjects = 17 | selectedCategory === "All" 18 | ? PROJECTS 19 | : PROJECTS.filter((project) => project.category === selectedCategory); 20 | 21 | const displayedProjects = filteredProjects.slice(0, visibleProjectsCount); 22 | 23 | const handleViewMore = () => { 24 | setVisibleProjectsCount((prevCount) => prevCount + 6); 25 | }; 26 | 27 | return ( 28 |
29 |
30 | 31 |
32 |
33 | 39 | Featured Projects 40 | 41 | 47 | Explore my latest work and innovations 48 | 49 |
50 | 51 |
52 | { 56 | setSelectedCategory(category); 57 | setVisibleProjectsCount(INITIAL_DISPLAY_COUNT); 58 | }} 59 | /> 60 |
61 | 62 |
63 | {displayedProjects.map((project, index) => ( 64 | 72 | ))} 73 |
74 | 75 | {visibleProjectsCount < filteredProjects.length && ( 76 |
77 | 83 |
84 | )} 85 |
86 |
87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /src/components/TechnologyDetails.jsx: -------------------------------------------------------------------------------- 1 | import { motion } from 'framer-motion'; 2 | import { FaJava, FaNode, FaPython, FaDocker, FaAws } from "react-icons/fa"; 3 | 4 | import { SiMongodb, SiKubernetes, SiTensorflow, SiPytorch, SiFirebase, SiDart, SiKeras, SiScikitlearn, SiJupyter, SiPandas, SiNumpy, SiAnaconda, SiGooglecloud, SiReact, SiHtml5, SiTailwindcss, SiFlutter, SiJavascript, SiSupabase, SiExpress } from "react-icons/si"; 5 | 6 | import { DiMysql } from "react-icons/di"; 7 | import { AiFillOpenAI } from "react-icons/ai"; 8 | import { IoLogoVercel } from "react-icons/io5"; 9 | 10 | 11 | const techStacks = { 12 | "Frontend Development": [ 13 | { icon: SiReact, name: "React", color: "from-cyan-400 to-blue-500" }, 14 | { icon: SiReact, name: "React Native", color: "from-blue-400 to-cyan-500" }, 15 | { icon: SiHtml5, name: "HTML5", color: "from-orange-500 to-red-500" }, 16 | { icon: SiDart, name: "Dart", color: "from-blue-500 to-teal-400" }, 17 | { icon: SiJavascript, name: "JavaScript", color: "from-yellow-400 to-orange-500" }, 18 | { icon: SiTailwindcss, name: "Tailwind CSS", color: "from-cyan-400 to-blue-500" }, 19 | { icon: SiFlutter, name: "Flutter", color: "from-blue-400 to-cyan-300" } 20 | ], 21 | "Backend Systems": [ 22 | { icon: FaNode, name: "Node.js", color: "from-green-500 to-gray-500" }, 23 | { icon: SiMongodb, name: "MongoDB", color: "from-teal-400 to-blue-500" }, 24 | { icon: FaPython, name: "Python", color: "from-yellow-400 to-green-500" }, 25 | { icon: FaJava, name: "Java", color: "from-orange-400 to-red-500" }, 26 | { icon: SiFirebase, name: "Firebase", color: "from-yellow-400 to-orange-500" }, 27 | { icon: SiExpress, name: "Express.js", color: "from-gray-700 to-gray-900" }, 28 | ], 29 | "Web Technologies": [ 30 | 31 | { icon: DiMysql, name: "MySQL", color: "from-pink-400 to-purple-500" }, 32 | { icon: SiMongodb, name: "MongoDB", color: "from-green-400 to-emerald-600" }, 33 | { icon: SiFirebase, name: "Firebase", color: "from-yellow-400 to-orange-500" }, 34 | { icon: SiSupabase, name: "Supabase", color: "from-green-400 to-teal-500" }, 35 | 36 | ], 37 | "AI/ML": [ 38 | { icon: SiTensorflow, name: "TensorFlow", color: "from-orange-400 to-yellow-500" }, 39 | { icon: SiPytorch, name: "PyTorch", color: "from-red-400 to-orange-500" }, 40 | { icon: AiFillOpenAI, name: "OpenAI", color: "from-blue-400 to-indigo-500" }, 41 | { icon: SiScikitlearn, name: "Scikit-learn", color: "from-blue-500 to-cyan-500" }, 42 | { icon: SiKeras, name: "Keras", color: "from-red-500 to-pink-500" }, 43 | { icon: SiJupyter, name: "Jupyter", color: "from-orange-500 to-amber-500" }, 44 | { icon: SiPandas, name: "Pandas", color: "from-blue-600 to-purple-600" }, 45 | { icon: SiNumpy, name: "NumPy", color: "from-blue-400 to-blue-600" }, 46 | { icon: SiAnaconda, name: "Anaconda", color: "from-green-400 to-emerald-500" }, 47 | { icon: SiGooglecloud, name: "Google AI", color: "from-blue-500 to-green-500" } 48 | ], 49 | "System Architecture": [ 50 | { icon: FaDocker, name: "Docker", color: "from-blue-400 to-green-500" }, 51 | { icon: SiKubernetes, name: "Kubernetes", color: "from-teal-400 to-blue-500" }, 52 | { icon: FaAws, name: "AWS", color: "from-yellow-400 to-orange-500" } 53 | ], 54 | 55 | "Cloud Computing": [ 56 | { icon: FaAws, name: "AWS", color: "from-yellow-400 to-orange-500" }, 57 | { icon: IoLogoVercel, name: "Vercel", color: "from-black to-gray-500" } 58 | ] 59 | }; 60 | 61 | export function TechnologyDetails({ category, isHovered }) { 62 | const technologies = techStacks[category] || []; 63 | 64 | return ( 65 | 70 |
71 | {technologies.map(({ icon: Icon, name, color }) => ( 72 | 79 |
82 | 83 |
84 | {name} 85 |
86 | ))} 87 |
88 |
89 | ); 90 | } 91 | -------------------------------------------------------------------------------- /src/components/AllBlogs.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'react-router-dom'; 2 | import { BookOpen, Calendar, Clock3 } from 'lucide-react'; 3 | import React, { useEffect, useState } from "react"; 4 | import axios from "axios"; 5 | import { FaCaretLeft } from "react-icons/fa"; 6 | 7 | 8 | export default function AllBlogs() { 9 | const [posts, setPosts] = useState([]); 10 | const [loading, setLoading] = useState(true); 11 | const [error, setError] = useState(null); 12 | 13 | useEffect(() => { 14 | const fetchPosts = async () => { 15 | try { 16 | const response = await axios.get("https://api.rss2json.com/v1/api.json", { 17 | params: { 18 | rss_url: "", 19 | }, 20 | }); 21 | const fetchedPosts = response.data.items; 22 | 23 | const parseContent = (content) => { 24 | const parser = new DOMParser(); 25 | const doc = parser.parseFromString(content, "text/html"); 26 | const images = Array.from(doc.querySelectorAll("img")).map((img) => img.src); 27 | return images; 28 | }; 29 | 30 | const postsWithImages = fetchedPosts.map((post) => { 31 | const images = parseContent(post.content); 32 | return { 33 | ...post, 34 | images, 35 | excerpt: post.description.replace(/<\/?[^>]+(>|$)/g, "").trim(), 36 | readTime: "5 min read", 37 | }; 38 | }); 39 | 40 | setPosts(postsWithImages); 41 | } catch (error) { 42 | console.error("Error fetching Medium posts:", error); 43 | setError("Failed to fetch posts"); 44 | } finally { 45 | setLoading(false); 46 | } 47 | }; 48 | 49 | fetchPosts(); 50 | }, []); 51 | 52 | if (loading) { 53 | return
Loading...
; 54 | } 55 | 56 | if (error) { 57 | return
{error}
; 58 | } 59 | 60 | return ( 61 |
62 |
63 | 64 | Back 65 | 66 |
67 |
68 | {posts.map((post) => ( 69 |
73 |
74 | {post.images.length > 0 ? ( 75 | {post.title} 80 | ) : ( 81 |
82 | No Image Available 83 |
84 | )} 85 |
86 | 87 | {post.category || "General"} 88 | 89 |
90 |
91 | 92 |
93 |

94 | 96 | {post.title} 97 | 98 |

99 |

100 | {post.excerpt} 101 |

102 | 103 |
104 |
105 |
106 | 107 | {new Date(post.pubDate).toLocaleDateString()} 108 |
109 |
110 | 111 | {post.readTime} 112 |
113 |
114 | 115 | 119 | Read More 120 | 121 | 122 |
123 |
124 |
125 | ))} 126 |
127 |
128 | ); 129 | } -------------------------------------------------------------------------------- /src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { motion } from "framer-motion"; 3 | import { Github, Instagram, Linkedin, Mail } from "lucide-react"; 4 | import { RiCloseFill, RiMenu3Line } from "react-icons/ri"; 5 | import { Link } from 'react-scroll'; 6 | 7 | 8 | const navVariants = { 9 | hidden: { y: -50, opacity: 0 }, 10 | visible: { 11 | y: 0, 12 | opacity: 1, 13 | transition: { 14 | duration: 0.8, 15 | ease: "easeOut", 16 | }, 17 | }, 18 | }; 19 | 20 | const iconVariants = { 21 | hover: { 22 | scale: 1.2, 23 | rotate: 5, 24 | transition: { duration: 0.2 }, 25 | }, 26 | }; 27 | 28 | const linkVariants = { 29 | hover: { 30 | scale: 1.1, 31 | color: "#F87171", 32 | transition: { duration: 0.2 }, 33 | }, 34 | }; 35 | 36 | function Navbar() { 37 | const [isOpen, setIsOpen] = useState(false); 38 | 39 | const toggleMenu = () => { 40 | setIsOpen(!isOpen); 41 | }; 42 | 43 | return ( 44 | 50 |
51 |
52 | 53 | 57 | DD 58 | 59 | 60 | 61 |
62 | {[ 63 | { label: "Home", to: "home" }, 64 | { label: "Technologies", to: "technologies" }, 65 | { label: "Projects", to: "projects" }, 66 | { label: "Blog", to: "blog" }, 67 | { label: "Contact", to: "contacts" }, 68 | ].map((link) => ( 69 | 75 | 82 | {link.label} 83 | 84 | 85 | ))} 86 |
87 | 88 |
89 | {[ 90 | { 91 | icon: Linkedin, 92 | href: "https://www.linkedin.com/in/dilshan-de-silva-7940142a9", 93 | label: "LinkedIn", 94 | }, 95 | { 96 | icon: Github, 97 | href: "https://github.com/DilshanDe", 98 | label: "GitHub", 99 | }, 100 | { 101 | icon: Instagram, 102 | href: "https://www.instagram.com/dilshandesilwa/", 103 | label: "Instagram", 104 | }, 105 | { 106 | icon: Mail, 107 | href: "mailto:dilshansilwa54@gmail.com", 108 | label: "Email", 109 | }, 110 | ].map((item) => ( 111 | 120 | 121 | 122 | ))} 123 |
124 | 125 |
126 | 133 |
134 |
135 |
136 | {isOpen && ( 137 |
138 |
139 | 143 | Home 144 | 145 | 149 | Technologies 150 | 151 | 155 | Projects 156 | 157 | 161 | Blog 162 | 163 | 167 | Contacts 168 | 169 | 170 |
171 | {[ 172 | { 173 | icon: Linkedin, 174 | href: "https://www.linkedin.com/in/dilshan-de-silva-7940142a9", 175 | 176 | label: "LinkedIn", 177 | }, 178 | { 179 | icon: Github, 180 | href: "https://github.com/DilshanDe", 181 | label: "GitHub", 182 | }, 183 | { 184 | icon: Instagram, 185 | href: "https://www.instagram.com/dilshandesilwa/", 186 | 187 | label: "Instagram", 188 | }, 189 | { 190 | icon: Mail, 191 | href: "mailto:dilshansilwa54@gmail.com", 192 | label: "Email", 193 | }, 194 | ].map((item) => ( 195 | 204 | 205 | 206 | ))} 207 |
208 |
209 |
210 | )} 211 |
212 | ); 213 | } 214 | 215 | export default Navbar; 216 | -------------------------------------------------------------------------------- /src/assets/constants/index.js: -------------------------------------------------------------------------------- 1 | 2 | import { Code2, Database, Globe, Cpu, Brain, Cloud } from 'lucide-react'; 3 | 4 | 5 | export const HERO_CONTENT = `Passionate and detail-oriented Full Stack Software Developer specializing in Flutter with Firebase and React Native for mobile application development. Experienced in designing, developing, and maintaining high-performance web and mobile applications. Skilled in both front-end and back-end technologies, with expertise in modern frameworks and databases. Adept at problem-solving, optimizing performance, and collaborating with teams to deliver high-quality software solutions. Eager to leverage technical expertise and innovation to create impactful digital experiences.`; 6 | 7 | export const ABOUT_TEXT = `I am a dedicated and versatile full stack developer with a passion for creating efficient and user-friendly web applications. With 2 years of professional experience, I have worked with a variety of technologies, including React, Next.js, Java, Node.js, MySQL, and MongoDB. My journey in web development began with a deep curiosity for how things work, and it has evolved into a career where I continuously strive to learn and adapt to new challenges. I thrive in collaborative environments and enjoy solving complex problems to deliver high-quality solutions. Outside of coding, I enjoy staying active, exploring new technologies, and contributing to open-source projects.`; 8 | 9 | export const EXPERIENCES = [ 10 | { 11 | year: "2023 - Present", 12 | role: "Full Stack Developer", 13 | company: "Google", 14 | description: `Led a team in developing and maintaining web applications using JavaScript, React.js, and Node.js. Implemented RESTful APIs and integrated with MongoDB databases. Collaborated with stakeholders to define project requirements and timelines.`, 15 | technologies: ["Javascript", "React.js", "Next.js", "mongoDB"], 16 | }, 17 | { 18 | year: "2022 - 2023", 19 | role: "Frontend Developer", 20 | company: "Adobe", 21 | description: `Designed and developed user interfaces for web applications using Next.js and React. Worked closely with backend developers to integrate frontend components with Node.js APIs. Implemented responsive designs and optimized frontend performance.`, 22 | technologies: ["HTML", "CSS", "Vue.js", "mySQL"], 23 | }, 24 | { 25 | year: "2021 - 2022", 26 | role: "Full Stack Developer", 27 | company: "Facebook", 28 | description: `Developed and maintained web applications using JavaScript, React.js, and Node.js. Designed and implemented RESTful APIs for data communication. Collaborated with cross-functional teams to deliver high-quality software products on schedule.`, 29 | technologies: ["Python", "Svelte", "Three.js", "Postgres"], 30 | }, 31 | { 32 | year: "2020 - 2021", 33 | role: "Software Engineer", 34 | company: "Paypal", 35 | description: `Contributed to the development of web applications using JavaScript, React.js, and Node.js. Managed databases and implemented data storage solutions using MongoDB. Worked closely with product managers to prioritize features and enhancements.`, 36 | technologies: ["Ruby", "Rails", "PHP", "Sqlite"], 37 | }, 38 | ]; 39 | 40 | export const PROJECTS = [ 41 | { 42 | title: "Computer Service Management System", 43 | description: "A MERN stack-based Computer Service Management System enabling real-time service tracking, automated invoicing, and efficient repair management with a user-friendly interface.", 44 | image: "https://i.postimg.cc/gJvzw2gd/photo-2025-03-14-09-51-30.jpg", 45 | technologies: ["React", "express", "TailwindCSS","Framer Motion"], 46 | category: "Web development", 47 | link: "https://github.com/DilshanDe/Computer-Service-Center-managment-System" 48 | }, 49 | { 50 | title: "Travel Companion App", 51 | description: "Travel Companion App is a Flutter & Firebase app for trip planning, hotel booking, and destination exploration. It features real-time tracking, authentication, and cloud storage, ensuring a seamless travel experience.", 52 | image: "https://i.postimg.cc/brC0Wb1Z/OIP-22.jpg", 53 | technologies: ["Flutter", "Dart", "Firebase"], 54 | category: "Applications", 55 | link: "https://github.com/DilshanDe/Travel-App" 56 | }, 57 | 58 | { 59 | title: "FullStack Social Media App", 60 | description: "Developed a full-stack social media application using React Native and Supabase, featuring user authentication, profile management, real-time posts, and interactive social features, ensuring a responsive and engaging user experience.", 61 | image: "https://i.postimg.cc/HLYPHmtn/welcome.png", 62 | technologies: ["React Native","Superbase"], 63 | category: "Applications", 64 | link: "https://github.com/DilshanDe/Social-Media-App" 65 | }, 66 | { 67 | title: "Weather Forecast App", 68 | description: "Weather Forecast App – A React Native app with real-time updates, location tracking, and a sleek Tailwind CSS UI. Features dynamic themes, weather icons, and smooth API integration.", 69 | image: "https://i.postimg.cc/NFHQFCL4/OIP-20.jpg", 70 | technologies: ["React Native", "Tailwind CSS"], 71 | category: "Applications", 72 | link: "https://github.com/DilshanDe/Weather-App" 73 | }, 74 | { 75 | title: "Portfolio", 76 | description: "Modern and minimalist portfolio design for creative professionals", 77 | image: "https://images.unsplash.com/photo-1517292987719-0369a794ec0f?auto=format&fit=crop&q=80&w=800", 78 | technologies: ["React", "Framer Motion", "TailwindCSS"], 79 | category: "Web development", 80 | link: "https://github.com/DilshanDe/Portfolio", 81 | }, 82 | { 83 | title: "Chat Application", 84 | description: "A React Native chat app powered by Firebase for instant messaging, secure authentication, and real-time sync. Showcases expertise in backend integration and real-time data handling.", 85 | image: "https://i.postimg.cc/vmSBmNG1/OIP-21.jpg", 86 | technologies: ["React", "Firebase"], 87 | category: "Applications", 88 | link: "https://github.com/DilshanDe/Chat-App-React-Native", 89 | }, 90 | { 91 | title: "Salon Booking App", 92 | description: "Salon Booking App is a Flutter & Dart app for seamless salon scheduling with real-time booking & Firebase integration.", 93 | image: "https://i.postimg.cc/LsswwBdp/R-5.png", 94 | technologies: ["Flutter", "Dart", "Firebase"], 95 | category: "Applications", 96 | link: "https://github.com/DilshanDe/Salon-Booking-App" 97 | }, 98 | { 99 | title: "News App", 100 | description: "A real-time news app built with Flutter and NewsAPI. Users can browse top headlines, filter by category, and search for specific topics. Features a clean UI, responsive design, and smooth API integration for live news updates..", 101 | image: "https://i.postimg.cc/wxrDJgYw/OIP-1.jpg", 102 | technologies: ["Flutter", "Dart", "NewsAPi"], 103 | category: "Applications", 104 | link: "https://github.com/DilshanDe/News-App" 105 | }, 106 | 107 | { 108 | title: "Flutter Counter App (BLoC)", 109 | description: "A basic counter app built with Flutter using BLoC for state management, showcasing clean architecture and reactive state handling.", 110 | image: "https://i.postimg.cc/2y8VVg1h/OIP.jpg", 111 | technologies: ["Flutter", "Dart", "BLoC"], 112 | category: "Applications", 113 | link: "https://github.com/DilshanDe/Counter-App" 114 | }, 115 | { 116 | title: "Flutter Package Delivery App(Ongoing)", 117 | description: "The app includes user authentication, package tracking, payment processing, and an admin panel. Real-time updates and UI design tips were key elements in creating a user-friendly experience. The app features GPS integration for location tracking and ResourPay for payment processing. I implemented state management using inherited widgets and classes to ensure clean and maintainable code.", 118 | image: "https://i.postimg.cc/PxCcjMPv/fast-delivery.png", 119 | technologies: ["Flutter", "Dart","Firebase"], 120 | category: "Applications", 121 | link: "https://github.com/DilshanDe/Package-Delivery-App" 122 | }, 123 | { 124 | title: "Simple Login Screen Ui", 125 | description: "Simple login Screen Ui Using Flutter", 126 | image: "https://i.postimg.cc/mkK3mY2R/OIP-4.jpg", 127 | technologies: ["Flutter", "Dart"], 128 | category: "Applications", 129 | link: "https://github.com/DilshanDe/Login-Screen-App-Ui" 130 | }, 131 | { 132 | title: "Computer Service Management System Ui", 133 | description: "Computer service Managment System ui using a Figma", 134 | image: "https://i.postimg.cc/gJvzw2gd/photo-2025-03-14-09-51-30.jpg", 135 | technologies: ["Figma"], 136 | category: "UI design", 137 | link: "https://www.figma.com/design/NFAa0RmpgJlJXyUFYqfnQ1/Group-Project?node-id=0-1&p=f&t=SyIWpbTxBEFEE4jt-0" 138 | }, 139 | ]; 140 | 141 | export const CONTACT = { 142 | address: "Rathmalana, SriLanka ", 143 | phoneNo: "+94 761191988 ", 144 | email: "dilshansilwa54@gmail.com", 145 | }; 146 | 147 | export const BLOGPOST = [ 148 | 149 | ]; 150 | 151 | export const technologies = [ 152 | { 153 | icon: Code2, 154 | name: "Frontend Development", 155 | description: "Building responsive and interactive user interfaces with modern frameworks", 156 | delay: 0.1 157 | }, 158 | { 159 | icon: Database, 160 | name: "Backend Systems", 161 | description: "Designing scalable server architectures and APIs", 162 | delay: 0.2 163 | }, 164 | { 165 | icon: Globe, 166 | name: "Web Technologies", 167 | description: "Creating seamless web experiences with cutting-edge tools", 168 | delay: 0.3 169 | }, 170 | { 171 | icon: Brain, 172 | name: "AI/ML", 173 | description: "Developing intelligent systems with machine learning and artificial intelligence", 174 | delay: 0.4 175 | } 176 | ]; -------------------------------------------------------------------------------- /src/components/Hero.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { motion, useScroll, useTransform } from 'framer-motion'; 3 | import { Download, Mail, Sparkles } from 'lucide-react'; 4 | import profilePic from '../assets/profilePicnew.webp'; 5 | import { HERO_CONTENT } from '../assets/constants'; 6 | 7 | const containerVariants = { 8 | hidden: { opacity: 0 }, 9 | visible: { 10 | opacity: 1, 11 | transition: { 12 | staggerChildren: 0.3, 13 | delayChildren: 0.2, 14 | } 15 | } 16 | }; 17 | 18 | const itemVariants = { 19 | hidden: { y: 30, opacity: 0 }, 20 | visible: { 21 | y: 0, 22 | opacity: 1, 23 | transition: { 24 | duration: 0.8, 25 | ease: [0.25, 0.46, 0.45, 0.94], // Custom easing 26 | } 27 | } 28 | }; 29 | 30 | const fadeInLeftVariants = { 31 | hidden: { x: -50, opacity: 0 }, 32 | visible: { 33 | x: 0, 34 | opacity: 1, 35 | transition: { 36 | duration: 0.8, 37 | ease: [0.25, 0.46, 0.45, 0.94], 38 | } 39 | } 40 | }; 41 | 42 | const imageVariants = { 43 | hidden: { scale: 0.8, opacity: 0, rotateY: 20 }, 44 | visible: { 45 | scale: 1, 46 | opacity: 1, 47 | rotateY: 0, 48 | transition: { 49 | duration: 1, 50 | ease: "easeOut", 51 | } 52 | } 53 | }; 54 | 55 | function Hero() { 56 | const [isDownloading, setIsDownloading] = useState(false); 57 | const [nameText, setNameText] = useState(''); 58 | const [titleText, setTitleText] = useState(''); 59 | const [showCursor, setShowCursor] = useState(true); 60 | const [currentPhase, setCurrentPhase] = useState('name'); // 'name', 'title', 'erasing' 61 | 62 | const { scrollY } = useScroll(); 63 | const y = useTransform(scrollY, [0, 500], [0, 150]); 64 | const opacity = useTransform(scrollY, [0, 300], [1, 0.5]); 65 | 66 | const fullName = "Dilshan De Silva"; 67 | const titles = [ 68 | "Full Stack Developer", 69 | "Mobile App Developer", 70 | "Software Engineer", 71 | "Web Developer" 72 | ]; 73 | 74 | const [currentTitleIndex, setCurrentTitleIndex] = useState(0); 75 | const fullTitle = titles[currentTitleIndex]; 76 | 77 | useEffect(() => { 78 | let timeoutId; 79 | 80 | if (currentPhase === 'name') { 81 | if (nameText.length < fullName.length) { 82 | timeoutId = setTimeout(() => { 83 | setNameText(fullName.slice(0, nameText.length + 1)); 84 | }, 100); // Speed of typing 85 | } else { 86 | // Name complete, start title after a pause 87 | timeoutId = setTimeout(() => { 88 | setCurrentPhase('title'); 89 | }, 500); 90 | } 91 | } else if (currentPhase === 'title') { 92 | if (titleText.length < fullTitle.length) { 93 | timeoutId = setTimeout(() => { 94 | setTitleText(fullTitle.slice(0, titleText.length + 1)); 95 | }, 80); // Slightly faster for title 96 | } else { 97 | // Title complete, wait then start erasing 98 | timeoutId = setTimeout(() => { 99 | setCurrentPhase('erasing'); 100 | }, 2000); // Wait 2 seconds before erasing 101 | } 102 | } else if (currentPhase === 'erasing') { 103 | if (titleText.length > 0) { 104 | timeoutId = setTimeout(() => { 105 | setTitleText(titleText.slice(0, -1)); 106 | }, 50); // Faster erasing 107 | } else { 108 | // Move to next title 109 | setCurrentTitleIndex((prev) => (prev + 1) % titles.length); 110 | setCurrentPhase('title'); 111 | } 112 | } 113 | 114 | return () => clearTimeout(timeoutId); 115 | }, [nameText, titleText, currentPhase, fullName, fullTitle, titles.length]); 116 | 117 | // Cursor blinking effect 118 | useEffect(() => { 119 | const cursorInterval = setInterval(() => { 120 | setShowCursor(prev => !prev); 121 | }, 530); // Cursor blink speed 122 | 123 | return () => clearInterval(cursorInterval); 124 | }, []); 125 | 126 | // Google Drive download link - replace with your actual Google Drive file ID 127 | const handleDownload = async () => { 128 | setIsDownloading(true); 129 | 130 | // Your Google Drive CV file ID 131 | const googleDriveFileId = '14ypoha_i2Mpi95mbHHHlGg9cAQdWrIxQ'; 132 | const downloadUrl = `https://drive.google.com/uc?export=download&id=${googleDriveFileId}`; 133 | 134 | try { 135 | // Create a temporary link and trigger download 136 | const link = document.createElement('a'); 137 | link.href = downloadUrl; 138 | link.download = 'Dilshan_De_Silva_CV.pdf'; 139 | document.body.appendChild(link); 140 | link.click(); 141 | document.body.removeChild(link); 142 | } catch (error) { 143 | console.error('Download failed:', error); 144 | // Fallback: open in new tab 145 | window.open(downloadUrl, '_blank'); 146 | } finally { 147 | setTimeout(() => setIsDownloading(false), 2000); 148 | } 149 | }; 150 | 151 | return ( 152 |
153 | {/* Animated Background Elements */} 154 |
155 | 159 | 163 |
164 | 165 | 172 |
173 | 174 | {/* Greeting */} 175 | 179 | 180 | Hello, I'm 181 | 182 | 183 | {/* Name with typewriter effect */} 184 | 188 | {nameText} 189 | {currentPhase === 'name' && showCursor && ( 190 | | 191 | )} 192 | 193 | 194 | {/* Enhanced title with typing effect */} 195 | 199 | 200 | {titleText} 201 | 202 | {(currentPhase === 'title' || currentPhase === 'erasing' || showCursor) && ( 203 | | 204 | )} 205 | 206 | 207 | {/* Description with better typography */} 208 | 212 | {HERO_CONTENT} 213 | 214 | 215 | {/* Enhanced CTA Section */} 216 | 217 | {/* Download Button */} 218 | 225 |
226 |
227 | {isDownloading ? ( 228 | <> 229 |
230 | Downloading... 231 | 232 | ) : ( 233 | <> 234 | 235 | Download CV 236 | 237 | )} 238 |
239 | 240 | 241 | {/* Contact Button */} 242 | 248 | 249 | Get In Touch 250 | 251 | 252 | 253 | 254 | 255 | 256 | {/* Enhanced Image Section */} 257 | 261 | 267 | {/* Multiple Background Effects */} 268 |
269 |
270 | 271 | {/* Border Animation */} 272 |
273 |
274 |
275 | 276 | {/* Main Image */} 277 | 283 |
284 |
285 |
286 | 287 |
288 | ); 289 | } 290 | 291 | export default Hero; -------------------------------------------------------------------------------- /src/components/Contact.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import emailjs from "@emailjs/browser"; 3 | import { 4 | Mail, 5 | Send, 6 | MessageSquare, 7 | User, 8 | AtSign, 9 | Phone, 10 | MapPin, 11 | Sparkles, 12 | ArrowRight, 13 | CheckCircle, 14 | } from "lucide-react"; 15 | import { CONTACT } from "../assets/constants/index"; 16 | import { motion, AnimatePresence } from "framer-motion"; 17 | 18 | export default function ContactForm() { 19 | const [isLoading, setIsLoading] = useState(false); 20 | const [isSuccess, setIsSuccess] = useState(false); 21 | const [formData, setFormData] = useState({ 22 | from_name: "", 23 | from_email: "", 24 | message: "", 25 | }); 26 | 27 | const handleChange = (e) => { 28 | const { name, value } = e.target; 29 | setFormData({ ...formData, [name]: value }); 30 | }; 31 | 32 | async function onSubmit(event) { 33 | event.preventDefault(); 34 | setIsLoading(true); 35 | 36 | try { 37 | await emailjs.send( 38 | "service_zvn9fo2", 39 | "template_dlf2j2q", 40 | { 41 | from_name: formData.from_name, 42 | from_email: formData.from_email, 43 | message: formData.message, 44 | }, 45 | "J_zrKa24x-Oneu1iw" 46 | ); 47 | setIsSuccess(true); 48 | setTimeout(() => setIsSuccess(false), 3000); 49 | } catch (error) { 50 | console.error("Failed to send message:", error); 51 | alert("Failed to send message. Please try again."); 52 | } finally { 53 | setIsLoading(false); 54 | setFormData({ from_name: "", from_email: "", message: "" }); 55 | } 56 | } 57 | 58 | const containerVariants = { 59 | hidden: { opacity: 0 }, 60 | visible: { 61 | opacity: 1, 62 | transition: { 63 | staggerChildren: 0.1, 64 | delayChildren: 0.2, 65 | }, 66 | }, 67 | }; 68 | 69 | const itemVariants = { 70 | hidden: { y: 50, opacity: 0 }, 71 | visible: { 72 | y: 0, 73 | opacity: 1, 74 | transition: { 75 | type: "spring", 76 | stiffness: 100, 77 | damping: 12, 78 | }, 79 | }, 80 | }; 81 | 82 | return ( 83 |
84 | {/* Animated Background Elements */} 85 |
86 |
87 |
88 |
89 |
90 | 91 | 98 | {/* Left Side - Contact Info */} 99 | 100 |
101 | 113 | 114 | 118 | 119 |

120 | Let's Connect 121 |

122 |
123 | 124 | 128 | Ready to bring your ideas to life? 129 | 130 | 134 | Drop me a message and let's create something amazing together. 135 | 136 |
137 | 138 | 139 | {[ 140 | { icon: Mail, label: "Email", value: CONTACT.email, href: `mailto:${CONTACT.email}` }, 141 | { icon: Phone, label: "Phone", value: CONTACT.phoneNo, href: `tel:${CONTACT.phoneNo}` }, 142 | { icon: MapPin, label: "Location", value: CONTACT.address, href: "#" }, 143 | ].map((item, index) => ( 144 | 152 |
153 | 154 |
155 |
156 |

{item.label}

157 |

{item.value}

158 |
159 | 160 |
161 | ))} 162 |
163 |
164 | 165 | {/* Right Side - Contact Form */} 166 | 167 | {/* Animated Border */} 168 |
169 | 170 |
171 |
172 |
173 |

174 | Send Message 175 |

176 |
177 | 178 |
179 | {[ 180 | { icon: User, name: "from_name", placeholder: "Your Name", type: "text" }, 181 | { icon: AtSign, name: "from_email", placeholder: "your@email.com", type: "email" }, 182 | ].map((field, index) => ( 183 | 188 | 189 | 198 | 199 | ))} 200 | 201 | 202 | 203 |