Skip to content

Commit 5b000c4

Browse files
committed
feat: added timeline feature to Experiences section & updated ExperienceTile
1 parent c1bf7d6 commit 5b000c4

File tree

3 files changed

+65
-24
lines changed

3 files changed

+65
-24
lines changed

src/components/Experiences.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use client'
2+
13
import { useState, useEffect } from 'react'
24
import { ExperienceTileProps, ExperienceTile } from './Tiles/ExperienceTile'
35

@@ -11,9 +13,12 @@ export function Experiences({ arr }: ExperiencesProps) {
1113
<section id="experience" className="mb-12">
1214
<h2 className="text-2xl font-bold mb-4">Experience</h2>
1315
{experiences && experiences.length > 0 ? (
14-
<div className="space-y-6">
16+
<div className="relative space-y-6">
17+
<div
18+
className="z-1 absolute md:left-20 top-0 bottom-0 w-1 md:bg-emerald-500 md:dark:bg-emerald-200 bg-pink-500 dark:bg-red-300 rounded-full"
19+
></div>
1520
{experiences.map((experience, index) => (
16-
<ExperienceTile key={index} {...experience} />
21+
<ExperienceTile key={index} {...experience} />
1722
))}
1823
</div>
1924
) : (
Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Briefcase } from 'lucide-react'
2+
import { useMediaQuery } from '@/hooks/useMediaQuery'
13
import Image from 'next/image'
24

35
export type ExperienceTileProps = {
@@ -8,31 +10,46 @@ export type ExperienceTileProps = {
810
responsibilities: string[]
911
}
1012

13+
14+
1115
export function ExperienceTile({ companyLogo, companyName, position, period, responsibilities }: ExperienceTileProps) {
16+
const isDesktop = useMediaQuery('(min-width: 768px)')
1217
return (
13-
<div className="bg-sushi-200 dark:bg-sushi-900 p-6 rounded-lg shadow-md">
14-
<div className="flex flex-col sm:flex-row items-center sm:items-start mb-4">
15-
<div className="mb-4 sm:mb-0 sm:mr-4 flex-shrink-0">
16-
<img
17-
src={companyLogo}
18-
alt={`${companyName} logo`}
19-
width={150}
20-
height={75}
21-
className="rounded-lg"
22-
/>
23-
</div>
24-
<div className="sm:text-left">
25-
<h3 className="text-xl font-semibold mb-2">{position}</h3>
26-
<p className="text-gray-600 dark:text-gray-400">{companyName} | {period}</p>
18+
<div className="mb-8 flex items-center">
19+
<div className="relative flex-grow md:pl-28">
20+
{isDesktop ? (
21+
<div className="bg-white absolute left-[5px] top-3 p-1 rounded-full">
22+
{/* // center the bullet : `top-1/2 transform -translate-y-1/2` */}
23+
<img
24+
src={companyLogo}
25+
alt={`${companyName} logo`}
26+
width={150}
27+
height={75}
28+
className="rounded-md"
29+
/>
30+
</div>
31+
) : (
32+
<div className="absolute left-[-10px] top-5">
33+
<Briefcase className="bg-neutral-100 dark:bg-neutral-950 rounded-md w-6 h-6"/>
34+
</div>
35+
)}
36+
<div className="pl-8 md:pl-16 py-3">
37+
<div className="flex flex-col md:items-center sm:flex-row mb-4">
38+
<div>
39+
<h2 className="text-xl font-bold">{position}</h2>
40+
<h3 className="text-lg font-semibold">{companyName}</h3>
41+
<h3 className="text-gray-600 italic dark:text-gray-400">{period}</h3>
42+
</div>
43+
</div>
44+
<div className="mt-4">
45+
<ul className="list-inside text-gray-700 dark:text-gray-300 space-y-1">
46+
{responsibilities.map((responsibility, index) => (
47+
<li key={index}>- {responsibility}</li>
48+
))}
49+
</ul>
50+
</div>
51+
</div>
2752
</div>
28-
</div>
29-
<div className="mt-4">
30-
<ul className="list-disc list-inside text-gray-700 dark:text-gray-300 space-y-1">
31-
{responsibilities.map((responsibility, index) => (
32-
<li key={index}>{responsibility}</li>
33-
))}
34-
</ul>
35-
</div>
3653
</div>
3754
)
3855
}

src/hooks/useMediaQuery.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use client'
2+
3+
import { useState, useEffect } from 'react'
4+
5+
export function useMediaQuery(query: string): boolean {
6+
const [matches, setMatches] = useState(false)
7+
8+
useEffect(() => {
9+
const media = window.matchMedia(query)
10+
if (media.matches !== matches) {
11+
setMatches(media.matches)
12+
}
13+
const listener = () => setMatches(media.matches)
14+
window.addEventListener('resize', listener)
15+
return () => window.removeEventListener('resize', listener)
16+
}, [matches, query])
17+
18+
return matches
19+
}

0 commit comments

Comments
 (0)