Skip to content

Commit c7bcb09

Browse files
committed
feat: add recommendations page
1 parent cf2dba9 commit c7bcb09

File tree

7 files changed

+171
-2
lines changed

7 files changed

+171
-2
lines changed

src/app/recommendations/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { RecommendationsPage } from '@/domains/recommendations';
2+
3+
export { metadata } from '@/domains/recommendations';
4+
export default RecommendationsPage;

src/data/recommendations.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ROUTES } from "@/shared/constants";
2+
13
export interface RecommendationItem {
24
id: number;
35
url: string;
@@ -9,6 +11,15 @@ export interface RecommendationItem {
911
imageURL: string | null;
1012
}
1113

14+
export const RECOMMENDATION_PAGE_DATA = {
15+
title: 'Recommendations',
16+
description:
17+
'I have had the pleasure of working with many talented individuals throughout my career. Here are some of the recommendations I have received from my colleagues and managers.',
18+
footer: 'If you would like to know more about me, feel free to reach out.',
19+
footerActionLabel: 'Contact Me',
20+
footerActionURL: ROUTES.CONTACT_ME,
21+
} as const;
22+
1223
export const RECOMMENDATIONS: RecommendationItem[] = [
1324
{
1425
id: 17,

src/domains/projects/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function ProjectsPage() {
4141

4242
<div
4343
className={clsx(
44-
'bo mt-10 flex flex-col items-center justify-center gap-3 border-t border-dashed pt-5',
44+
'mt-10 flex flex-col items-center justify-center gap-3 pt-4',
4545
animator({ name: 'fadeInUp', delay: '1s' })
4646
)}
4747
>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import Image from 'next/image';
2+
import Link from 'next/link';
3+
4+
import { sendGTMEvent } from '@next/third-parties/google';
5+
import { clsx } from 'clsx';
6+
7+
import type { RecommendationItem } from '@/data';
8+
import { GTM_EVENTS } from '@/shared/constants';
9+
import { titleFont } from '@/app/fonts';
10+
11+
import styles from './recommendation-card.module.scss';
12+
13+
export function RecommendationCard({
14+
data,
15+
animationDelay = '0s'
16+
}: {
17+
data: RecommendationItem;
18+
animationDelay?: string;
19+
}) {
20+
const { url, text, date, title, caption, fullName, imageURL } = data;
21+
22+
const sendEvent = () => sendGTMEvent(GTM_EVENTS.LINKEDIN_RECOMMENDATION(fullName));
23+
24+
return (
25+
<div
26+
style={{ animationDelay }}
27+
className={clsx(
28+
'w-full flex flex-col items-start gap-2 border bg-white p-4 dark:bg-black',
29+
styles['recommendation-card']
30+
)}
31+
>
32+
<div
33+
className={clsx(
34+
'mb-2 flex w-full gap-3 border-b pb-4 text-left duration-500',
35+
styles['recommendation-card__header']
36+
)}
37+
>
38+
{imageURL && (
39+
<Link onClick={sendEvent} href={url} target="_blank" rel="noopener noreferrer">
40+
<Image
41+
width={100}
42+
height={100}
43+
alt={fullName}
44+
src={imageURL}
45+
loading="lazy"
46+
className={clsx(
47+
'rounded-md grayscale duration-500',
48+
styles['recommendation-card__profile-image']
49+
)}
50+
/>
51+
</Link>
52+
)}
53+
<div className="flex w-full flex-col gap-1 text-left">
54+
<Link
55+
href={url}
56+
target="_blank"
57+
onClick={sendEvent}
58+
rel="noopener noreferrer"
59+
className={clsx(titleFont.className, 'text-xl font-bold text-amber-500')}
60+
>
61+
{fullName.toUpperCase()}
62+
</Link>
63+
<p>{title}</p>
64+
<div className="flex flex-wrap items-center gap-2">
65+
<span>{caption}</span>
66+
<span>( {date} )</span>
67+
</div>
68+
</div>
69+
</div>
70+
71+
<p className="w-full text-left" dangerouslySetInnerHTML={{ __html: text }} />
72+
73+
<Link
74+
href={url}
75+
target="_blank"
76+
onClick={sendEvent}
77+
rel="noopener noreferrer"
78+
className="text-amber-500"
79+
>
80+
LinkedIn
81+
</Link>
82+
</div>
83+
);
84+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.recommendation-card {
2+
&:hover & {
3+
&__header {
4+
border-color: var(--primary);
5+
}
6+
7+
&__profile-image {
8+
filter: grayscale(0);
9+
}
10+
}
11+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { clsx } from 'clsx';
2+
import Link from 'next/link';
3+
import { Metadata } from 'next';
4+
5+
import { RECOMMENDATION_PAGE_DATA, RECOMMENDATIONS, type RecommendationItem } from '@/data';
6+
import { ContentContainer } from '@/layout/components/content-container';
7+
import { animator } from '@/shared/helpers';
8+
import { titleFont } from '@/app/fonts';
9+
10+
import { RecommendationCard } from './components/RecommendationCard';
11+
12+
export const metadata: Metadata = {
13+
title: 'Recommendations'
14+
};
15+
16+
export async function RecommendationsPage() {
17+
return (
18+
<ContentContainer>
19+
<h1
20+
className={clsx(
21+
'select-none text-center text-3xl font-bold',
22+
titleFont.className,
23+
animator({ name: 'fadeInUp' })
24+
)}
25+
dangerouslySetInnerHTML={{ __html: RECOMMENDATION_PAGE_DATA.title }}
26+
/>
27+
<p
28+
className={clsx(
29+
titleFont.className,
30+
'mt-4 select-none text-center text-xl',
31+
animator({ name: 'fadeIn', delay: '1s' })
32+
)}
33+
dangerouslySetInnerHTML={{ __html: RECOMMENDATION_PAGE_DATA.description }}
34+
/>
35+
36+
<div className="mt-8 flex flex-col gap-4 overflow-hidden">
37+
{RECOMMENDATIONS.map((item: RecommendationItem, index: number) => (
38+
<RecommendationCard key={item.id} data={item} animationDelay={`${(index + 1) * 0.3}s`} />
39+
))}
40+
</div>
41+
42+
<div
43+
className={clsx(
44+
'mt-10 flex flex-col items-center justify-center gap-3 pt-4',
45+
animator({ name: 'fadeInUp', delay: '1s' })
46+
)}
47+
>
48+
<p>{RECOMMENDATION_PAGE_DATA.footer}</p>
49+
<Link
50+
href={RECOMMENDATION_PAGE_DATA.footerActionURL}
51+
className="border-b border-orange-500 px-5 pb-1 duration-200 hover:px-8 hover:text-orange-500"
52+
>
53+
{RECOMMENDATION_PAGE_DATA.footerActionLabel}
54+
</Link>
55+
</div>
56+
</ContentContainer>
57+
);
58+
}

src/shared/constants/routes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export const ROUTES = {
44
JOURNEY: '/journey/',
55
PROJECTS: '/projects/',
66
ABOUT_ME: '/about-me/',
7-
CONTACT_ME: '/contact-me/'
7+
CONTACT_ME: '/contact-me/',
8+
RECOMMENDATIONS: '/recommendations/',
89
} as const;
910

1011
export const MENU_ITEM_ROUTES = [

0 commit comments

Comments
 (0)