added menubar and experience section
This commit is contained in:
64
frontend/package-lock.json
generated
64
frontend/package-lock.json
generated
@ -11,7 +11,8 @@
|
|||||||
"lucide-react": "^0.469.0",
|
"lucide-react": "^0.469.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-icons": "^5.3.0"
|
"react-icons": "^5.3.0",
|
||||||
|
"react-router-dom": "^7.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.9.0",
|
"@eslint/js": "^9.9.0",
|
||||||
@ -1241,6 +1242,11 @@
|
|||||||
"@babel/types": "^7.20.7"
|
"@babel/types": "^7.20.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
@ -1843,6 +1849,14 @@
|
|||||||
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
@ -3293,6 +3307,44 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-router": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/cookie": "^0.6.0",
|
||||||
|
"cookie": "^1.0.1",
|
||||||
|
"set-cookie-parser": "^2.6.0",
|
||||||
|
"turbo-stream": "2.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router-dom": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-vSrQHWlJ5DCfyrhgo0k6zViOe9ToK8uT5XGSmnuC2R3/g261IdIMpZVqfjD6vWSXdnf5Czs4VA/V60oVR6/jnA==",
|
||||||
|
"dependencies": {
|
||||||
|
"react-router": "7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/read-cache": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
@ -3425,6 +3477,11 @@
|
|||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/set-cookie-parser": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="
|
||||||
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
@ -3718,6 +3775,11 @@
|
|||||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/turbo-stream": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g=="
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
|
|||||||
@ -13,7 +13,8 @@
|
|||||||
"lucide-react": "^0.469.0",
|
"lucide-react": "^0.469.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-icons": "^5.3.0"
|
"react-icons": "^5.3.0",
|
||||||
|
"react-router-dom": "^7.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.9.0",
|
"@eslint/js": "^9.9.0",
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
|
import { Routes, Route } from 'react-router-dom';
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
import Home from './pages/Home'
|
||||||
import Navbar from './components/Navbar'
|
import Navbar from './components/Navbar'
|
||||||
import Introduction from './components/Introduction'
|
|
||||||
import Skills from './components/Skills'
|
|
||||||
import Footer from './components/Footer'
|
import Footer from './components/Footer'
|
||||||
|
import Experience from './pages/Experience';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [darkMode, setDarkMode] = useState(true)
|
const [darkMode, setDarkMode] = useState(true)
|
||||||
@ -14,12 +16,16 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={darkMode ? "dark" : ""}>
|
<div className={darkMode ? "dark" : ""}>
|
||||||
<main className="bg-white px-10 dark:bg-gray-900">
|
<main className="bg-amber-50 px-10 dark:bg-gray-900">
|
||||||
<section className="min-h-screen">
|
<section className="min-h-screen">
|
||||||
<Navbar toggleDarkMode={toggleDarkMode} darkMode={darkMode}/>
|
<Navbar toggleDarkMode={toggleDarkMode} darkMode={darkMode}/>
|
||||||
<Introduction></Introduction>
|
<Router>
|
||||||
<Skills></Skills>
|
<Routes>
|
||||||
<Footer></Footer>
|
<Route path='/' element={<Home/>} />
|
||||||
|
<Route path='/experience' element={<Experience/>} />
|
||||||
|
</Routes>
|
||||||
|
</Router>
|
||||||
|
<Footer />
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,7 +4,7 @@ const Footer = () => {
|
|||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="mt-12 py-6 border-t border-gray-200 dark:border-gray-800">
|
<footer className="mt-16 py-6 border-t border-gray-200 dark:border-gray-800">
|
||||||
<div className="max-w-4xl mx-auto px-4">
|
<div className="max-w-4xl mx-auto px-4">
|
||||||
<div className="flex flex-col items-center gap-4 text-gray-600 dark:text-gray-400 text-sm">
|
<div className="flex flex-col items-center gap-4 text-gray-600 dark:text-gray-400 text-sm">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@ -1,35 +1,106 @@
|
|||||||
import React from "react"
|
import React, { useState, useRef } from 'react';
|
||||||
import { Sun, Moon, FileText } from "lucide-react"
|
import { Menu, Sun, Moon, FileText, Mail, Check, Copy } from "lucide-react";
|
||||||
|
|
||||||
interface NavProps {
|
interface NavProps {
|
||||||
darkMode: boolean
|
darkMode: boolean;
|
||||||
toggleDarkMode: () => void
|
toggleDarkMode: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Navbar: React.FC<NavProps> = ({toggleDarkMode, darkMode}) => {
|
const Navbar: React.FC<NavProps> = ({toggleDarkMode, darkMode}) => {
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
|
const email = "taqitahmid@gmail.com";
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleCopyEmail = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(email);
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 2000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to copy email');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const menuItem = [
|
||||||
|
{title: 'Home', href: '/'},
|
||||||
|
{title: 'Experience', href: '/experience'},
|
||||||
|
{title: 'Projects', href: '/projects'},
|
||||||
|
{title: 'Interests', href: '/interests'},
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full flex justify-center">
|
<div className="w-full flex justify-center">
|
||||||
<nav className="py-5 mb-12 flex justify-between dark:text-white w-full max-w-5xl px-4">
|
<nav className="py-5 mb-12 flex justify-between dark:text-white w-full max-w-5xl px-4">
|
||||||
<h1>taqitahmid@gmail.com</h1>
|
<button
|
||||||
|
onClick={handleCopyEmail}
|
||||||
|
className="flex items-center space-x-2 hover:bg-gray-100 dark:hover:bg-gray-800 px-3 py-2 rounded-lg transition-colors duration-200 group relative"
|
||||||
|
>
|
||||||
|
<Mail size={20} className="text-blue-500" />
|
||||||
|
<span className="hidden sm:inline">{email}</span>
|
||||||
|
<span className="sm:hidden">Email</span>
|
||||||
|
{copied ? (
|
||||||
|
<Check size={16} className="text-green-500" />
|
||||||
|
) : (
|
||||||
|
<Copy size={16} className="opacity-0 group-hover:opacity-100 transition-opacity duration-200" />
|
||||||
|
)}
|
||||||
|
<span className="pointer-events-none absolute -bottom-8 left-1/2 -translate-x-1/2 whitespace-nowrap rounded bg-slate-800 px-2 py-1 text-xs text-slate-100 opacity-0 transition before:absolute before:left-1/2 before:top-full before:-translate-x-1/2 before:border-4 before:border-transparent before:border-t-slate-800 before:content-[''] group-hover:opacity-100">
|
||||||
|
{copied ? 'Copied!' : 'Click to copy'}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<ul className="flex items-center">
|
<ul className="flex items-center">
|
||||||
<li className="transition ease-in-out delay-100 hover:scale-110 duration-300 cursor-pointer"
|
<li className="transition ease-in-out delay-50 duration-100 cursor-pointer"
|
||||||
onClick={toggleDarkMode}>
|
onClick={toggleDarkMode}>
|
||||||
<div className="bg-blue-900 hover:bg-blue-1000 dark:bg-blue-500 dark:hover:bg-blue-600 text-white p-2 rounded-lg ml-8 shadow-sm">
|
<div className="bg-blue-900 hover:bg-blue-1000 dark:bg-blue-500 dark:hover:bg-blue-600 text-white p-2 rounded-lg ml-8 shadow-sm group relative">
|
||||||
{darkMode ? <Sun size={24} /> : <Moon size={24} />}
|
{darkMode ? <Sun size={24} /> : <Moon size={24} />}
|
||||||
|
<span className="pointer-events-none absolute -bottom-8 left-1/2 -translate-x-1/2 whitespace-nowrap rounded bg-slate-800 px-2 py-1 text-xs text-slate-100 opacity-0 transition before:absolute before:left-1/2 before:top-full before:-translate-x-1/2 before:border-4 before:border-transparent before:border-t-slate-800 before:content-[''] group-hover:opacity-100">
|
||||||
|
{darkMode ? "Light Mode": "Dark Mode"}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li className="transition ease-in-out delay-150 hover:scale-110 duration-300">
|
<li className="transition ease-in-out delay-50 duration-100">
|
||||||
|
<div className="group relative">
|
||||||
<a className="bg-blue-900 hover:bg-blue-1000 dark:bg-blue-500 dark:hover:bg-blue-600 text-white p-2 rounded-lg ml-8 shadow-sm inline-flex"
|
<a className="bg-blue-900 hover:bg-blue-1000 dark:bg-blue-500 dark:hover:bg-blue-600 text-white p-2 rounded-lg ml-8 shadow-sm inline-flex"
|
||||||
href="https://www.linkedin.com/in/taqi-tahmid/overlay/1635520467350/single-media-viewer/?profileId=ACoAACDU_GsBCgKtvw2bmzbVwTy2WixBG6-e3JM"
|
href="https://www.linkedin.com/in/taqi-tahmid/details/featured/1735981754176/single-media-viewer/?profileId=ACoAACDU_GsBCgKtvw2bmzbVwTy2WixBG6-e3JM"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer">
|
rel="noreferrer">
|
||||||
<FileText size={24} />
|
<FileText size={24} />
|
||||||
</a>
|
</a>
|
||||||
|
<span className="pointer-events-none absolute -bottom-8 left-1/2 -translate-x-1/2 whitespace-nowrap rounded bg-slate-800 px-2 py-1 text-xs text-slate-100 opacity-0 transition before:absolute before:left-1/2 before:top-full before:-translate-x-1/2 before:border-4 before:border-transparent before:border-t-slate-800 before:content-[''] group-hover:opacity-100">
|
||||||
|
Resume
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li className="p-2 ml-5 cursor-pointer">
|
||||||
|
<div ref={menuRef} className="group relative">
|
||||||
|
<button onClick={() => setIsMenuOpen(!isMenuOpen)} className='focus:outline-none'>
|
||||||
|
<Menu size={24}/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Dropdown Menu */}
|
||||||
|
{isMenuOpen && (
|
||||||
|
<div className="absolute right-0 mt-3 w-36 rounded-md shadow-lg bg-amber-50 dark:bg-gray-800 ring-1 ring-black ring-opacity-5">
|
||||||
|
<div className="py-1" role="menu" aria-orientation="vertical">
|
||||||
|
{menuItem.map((item) => (
|
||||||
|
<a
|
||||||
|
key={item.title}
|
||||||
|
href={item.href}
|
||||||
|
className="block px-4 py-2 text-sm text-gray-00 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-150"
|
||||||
|
role='menuitem'
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Navbar
|
export default Navbar;
|
||||||
153
frontend/src/pages/Experience.tsx
Normal file
153
frontend/src/pages/Experience.tsx
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import { Building2, Calendar, GraduationCap, MapPin, Microscope, Wrench } from 'lucide-react';
|
||||||
|
|
||||||
|
const Experience = () => {
|
||||||
|
const BoldStyle = "text-blue-900 dark:text-blue-400 font-semibold";
|
||||||
|
|
||||||
|
const experiences = [
|
||||||
|
{
|
||||||
|
title: "Experienced Developer (DevOps)",
|
||||||
|
company: "Ericsson",
|
||||||
|
location: "Jorvas, Finland",
|
||||||
|
period: "November-2022 - Present",
|
||||||
|
responsibilities: [
|
||||||
|
"Managing and optimizing Kubernetes clusters in production environments",
|
||||||
|
"Designing and implementing CI/CD pipelines for end to end product development flow using Jenkins",
|
||||||
|
"Automating infrastructure deployment using Terraform and Ansible",
|
||||||
|
"Develop and maintain monitoring solutions of various resources for greater observability and troubleshooting",
|
||||||
|
"Actively support development teams regarding product development flow and infrastructure issues",
|
||||||
|
"Develop and perform automated end-to-end product testing with Python, Robot Framework, Jenkins, Bash, etc.",
|
||||||
|
],
|
||||||
|
tools: "Kubernetes, Docker, KVM, Openstack, Ansible, Terraform, Prometheus, Grafana"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Test Engineer",
|
||||||
|
company: "Nokia",
|
||||||
|
location: "Espoo, Finland",
|
||||||
|
period: "June-2021 - October-2022",
|
||||||
|
responsibilities: [
|
||||||
|
"Develop and maintain Cloud RAN E2E test setup for vCU and vDU application testing on top of RedHat Openshift",
|
||||||
|
"Develop automation and CI/CD flow for Cloud RAN testing using Python, Robot Framework, Bash, Jenkins etc.",
|
||||||
|
"Develop and perform automated testing to validate the functionality of Nokia Cloud RAN base stations",
|
||||||
|
"Integrate new hardware and software into the test setup",
|
||||||
|
"Perform hands on debugging and log analysis to nd root cause and solve any software or hardware issues",
|
||||||
|
],
|
||||||
|
tools: "Keysight Nemo Outdoor, Nemo Analyze, Qualcomm PCAT, QCAT, QXDM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Testing and Prototyping Intern",
|
||||||
|
company: "GE Healthcare",
|
||||||
|
location: "Helsinki, Finland",
|
||||||
|
period: "Jan-2019 - May-2021",
|
||||||
|
responsibilities: [
|
||||||
|
"Planning, writing, and performing manual and automated tests of different prototype wireless medical devices",
|
||||||
|
"Designing driver and PCB circuits in Altium Designer to test the performance of the Digital Sensor Interface",
|
||||||
|
"Ensuring the PCB componets used in the devices are EU RoHS and REACH compliant",
|
||||||
|
],
|
||||||
|
tools: "LTSpice, Altium Designer, HP-ALM, Vector Network Analyzer, Spectrum Analyzer, Climate Chamber"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const education = [
|
||||||
|
{
|
||||||
|
degree: "Master's in Wireless Communication & RF Systems",
|
||||||
|
institution: "Tampere University",
|
||||||
|
location: "Tampere, Finland",
|
||||||
|
period: "2018 - 2020",
|
||||||
|
thesis: "5G Reference Signals and their Possibility to be for 5G Based Positioning"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
degree: "Bachelor's in Electrical & Electronic Engineering",
|
||||||
|
institution: "Khulna University of Engineering & Technology",
|
||||||
|
location: "Khulna, Bangladesh",
|
||||||
|
period: "2013 - 2017",
|
||||||
|
thesis: "Density-based smart traffic control system using Canny edge detection technique using Digital Image Processing"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-4 max-w-4xl mx-auto">
|
||||||
|
<h2 className="text-3xl text-blue-900 dark:text-blue-400 py-4 font-medium font-burtons text-center">
|
||||||
|
Experience
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-8">
|
||||||
|
{experiences.map((exp, index) => (
|
||||||
|
<div key={index} className="border-l-4 border-blue-900 dark:border-blue-400 pl-4 space-y-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Building2 className="text-blue-900 dark:text-blue-400" size={24} />
|
||||||
|
<h3 className={`text-xl ${BoldStyle}`}>{exp.title}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col md:flex-row md:items-center gap-2 md:gap-6 text-gray-600 dark:text-gray-400">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Building2 size={16} />
|
||||||
|
<span>{exp.company}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<MapPin size={16} />
|
||||||
|
<span>{exp.location}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Calendar size={16} />
|
||||||
|
<span>{exp.period}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-gray-800 dark:text-gray-300 space-y-1">
|
||||||
|
{exp.responsibilities.map((resp, idx) => (
|
||||||
|
<p key={idx} className="flex items-start">
|
||||||
|
<span className="mr-2 mt-2 ml-4">•</span>
|
||||||
|
<span>{resp}</span>
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="text-gray-800 dark:text-gray-300 space-y-1 flex items-start">
|
||||||
|
<div className='flex items-center gap-2'>
|
||||||
|
<Wrench size={20}/>
|
||||||
|
<span>{exp.tools}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-3xl text-blue-900 dark:text-blue-400 py-4 mt-8 font-medium font-burtons text-center">
|
||||||
|
Education
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
{education.map((edu, index) => (
|
||||||
|
<div key={index} className="border-l-4 border-blue-900 dark:border-blue-400 pl-4 space-y-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<GraduationCap className="text-blue-900 dark:text-blue-400" size={24} />
|
||||||
|
<h3 className={`text-xl ${BoldStyle}`}>{edu.degree}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col md:flex-row md:items-center gap-2 md:gap-6 text-gray-600 dark:text-gray-400">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Building2 size={16} />
|
||||||
|
<span>{edu.institution}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<MapPin size={16} />
|
||||||
|
<span>{edu.location}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Calendar size={16} />
|
||||||
|
<span>{edu.period}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-gray-600 dark:text-gray-400 space-y-1 flex items-start">
|
||||||
|
<div className='flex items-center gap-1'>
|
||||||
|
<Microscope />
|
||||||
|
<span>{edu.thesis}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Experience;
|
||||||
13
frontend/src/pages/Home.tsx
Normal file
13
frontend/src/pages/Home.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Introduction from '../components/Introduction'
|
||||||
|
import Skills from '../components/Skills'
|
||||||
|
|
||||||
|
function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Introduction />
|
||||||
|
<Skills />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home
|
||||||
Reference in New Issue
Block a user