Skip to content

Commit 363dfb4

Browse files
committed
build update
1 parent 744263c commit 363dfb4

8 files changed

Lines changed: 1658 additions & 2197 deletions

File tree

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"clsx": "^2.1.0",
1919
"fast-glob": "^3.2.11",
2020
"feed": "^4.2.2",
21-
"html2pdf.js": "^0.13.0",
2221
"next": "^14.0.4",
2322
"next-themes": "^0.2.1",
2423
"react": "^18.2.0",

src/app/contact/page.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
PhoneIcon,
66
LocationIcon,
77
TelegramIcon,
8+
FacebookMessengerIcon,
89
} from '@/components/SocialIcons'
910
import { SimpleLayout } from '@/components/SimpleLayout'
1011
import { personal } from '@/data/personal'
@@ -99,6 +100,13 @@ export default function Contact() {
99100
href={personal.social.telegram.url}
100101
external
101102
/>
103+
<ContactCard
104+
icon={FacebookMessengerIcon}
105+
label="Messenger"
106+
value="Chat with me"
107+
href={personal.social.messenger.url}
108+
external
109+
/>
102110
<ContactCard
103111
icon={LocationIcon}
104112
label="Location"

src/app/resume/page.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const metadata = {
2323
export default function Resume() {
2424
return (
2525
<Container className="mt-16 sm:mt-32">
26-
<div className="mb-6 flex items-end justify-end gap-4">
26+
<div className="mb-6 flex items-end justify-end gap-4 print:hidden">
2727
<div className="flex-shrink-0">
2828
<DownloadPdfButton />
2929
</div>

src/components/DownloadPdfButton.jsx

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,16 @@
11
'use client'
22

3-
import { useState } from 'react'
4-
53
export function DownloadPdfButton() {
6-
const [isGenerating, setIsGenerating] = useState(false)
7-
8-
const handleDownload = async () => {
9-
setIsGenerating(true)
10-
try {
11-
// Dynamically import html2pdf to avoid SSR issues
12-
const html2pdf = (await import('html2pdf.js')).default
13-
14-
const element = document.getElementById('resume-content')
15-
16-
const opt = {
17-
margin: [0.5, 0.5, 0.5, 0.5],
18-
filename: 'Wem_Senior_Software_Engineer_Resume.pdf',
19-
image: { type: 'jpeg', quality: 1 },
20-
jsPDF: {
21-
unit: 'in',
22-
format: 'letter',
23-
orientation: 'portrait',
24-
},
25-
pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
26-
}
27-
28-
await html2pdf().set(opt).from(element).save()
29-
} catch (error) {
30-
console.error('Error generating PDF:', error)
31-
alert('Failed to generate PDF. Please try again.')
32-
} finally {
33-
setIsGenerating(false)
34-
}
4+
const handleDownload = () => {
5+
// Use the browser's native print dialog which produces pixel-perfect PDF
6+
// The @media print styles in tailwind.css handle the layout
7+
window.print()
358
}
369

3710
return (
3811
<button
3912
onClick={handleDownload}
40-
disabled={isGenerating}
41-
className="group inline-flex items-center gap-2 rounded-full bg-zinc-800 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-zinc-800/5 transition hover:bg-zinc-700 disabled:opacity-50 disabled:cursor-not-allowed dark:bg-zinc-700 dark:hover:bg-zinc-600"
13+
className="print:hidden group inline-flex items-center gap-2 rounded-full bg-zinc-800 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-zinc-800/5 transition hover:bg-zinc-700 dark:bg-zinc-700 dark:hover:bg-zinc-600"
4214
>
4315
<svg
4416
viewBox="0 0 24 24"
@@ -53,7 +25,7 @@ export function DownloadPdfButton() {
5325
stroke="currentColor"
5426
/>
5527
</svg>
56-
{isGenerating ? 'Generating PDF...' : 'Download PDF'}
28+
Download PDF
5729
</button>
5830
)
5931
}

src/components/SocialIcons.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,11 @@ export function TelegramIcon(props) {
7676
</svg>
7777
)
7878
}
79+
80+
export function FacebookMessengerIcon(props) {
81+
return (
82+
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
83+
<path d="M12 2C6.36 2 2 6.13 2 11.7c0 2.91 1.2 5.42 3.15 7.18.16.15.26.36.27.58l.05 1.82c.02.63.66 1.04 1.24.79l2.03-.8c.17-.07.36-.09.55-.05.93.26 1.93.4 2.96.4 5.64 0 10.25-4.13 10.25-9.7S17.64 2 12 2zm6.12 7.55l-3 4.63c-.47.73-1.46.91-2.15.38l-2.38-1.79a.6.6 0 00-.72 0l-3.21 2.44c-.43.33-.99-.22-.7-.68l3-4.63c.47-.73 1.46-.91 2.15-.38l2.38 1.79a.6.6 0 00.72 0l3.21-2.44c.43-.33.99.22.7.68z" />
84+
</svg>
85+
)
86+
}

src/data/personal.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@ export const personal = {
2828
url: 'https://t.me/huynhdeveloper',
2929
label: 'Follow on Telegram',
3030
},
31+
messenger: {
32+
url: 'https://m.me/huynhdung18041993',
33+
label: 'Message on Messenger',
34+
},
3135
},
3236

3337
contact: {
3438
title: 'Contact me.',
3539
intro:
36-
"Feel free to contact me via LinkedIn, Telegtam, or email. I'll respond when free time. If you have an interesting project or collaboration opportunity, I'd love to hear from you.",
40+
"Feel free to contact me via LinkedIn, Telegram, Messenger, or email. I'll respond when free time. If you have an interesting project or collaboration opportunity, I'd love to hear from you.",
3741
},
3842

3943
copyright: {

src/styles/tailwind.css

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,151 @@
22
@import 'tailwindcss/components';
33
@import './prism.css';
44
@import 'tailwindcss/utilities';
5+
6+
@media print {
7+
/* Force light mode colors for print */
8+
html {
9+
color-scheme: light !important;
10+
}
11+
12+
body {
13+
background: white !important;
14+
color: black !important;
15+
-webkit-print-color-adjust: exact !important;
16+
print-color-adjust: exact !important;
17+
}
18+
19+
/* Remove dark mode backgrounds */
20+
.dark\:bg-black,
21+
.dark\:bg-zinc-900,
22+
.dark\:bg-zinc-800 {
23+
background-color: transparent !important;
24+
}
25+
26+
/* Hide non-resume elements */
27+
header,
28+
footer,
29+
nav {
30+
display: none !important;
31+
}
32+
33+
/* Hide the fixed background decoration */
34+
.fixed.inset-0 {
35+
display: none !important;
36+
}
37+
38+
/* Remove top margin for print */
39+
.mt-16.sm\:mt-32,
40+
.mt-16 {
41+
margin-top: 0 !important;
42+
}
43+
44+
/* Reset container max-width for print to use full page */
45+
#resume-content {
46+
max-width: 100% !important;
47+
padding: 0 !important;
48+
margin: 0 !important;
49+
}
50+
51+
/* Ensure proper bullet point rendering */
52+
ul.list-disc,
53+
.list-disc {
54+
list-style-type: disc !important;
55+
padding-left: 1.5em !important;
56+
}
57+
58+
ul.list-inside,
59+
.list-inside {
60+
list-style-position: inside !important;
61+
}
62+
63+
.list-disc li {
64+
display: list-item !important;
65+
list-style-type: disc !important;
66+
}
67+
68+
.list-disc li::marker {
69+
font-size: inherit !important;
70+
color: inherit !important;
71+
}
72+
73+
/* Ensure borders are visible */
74+
.border,
75+
.border-zinc-200,
76+
.border-b-2,
77+
.divide-y > * + * {
78+
border-color: #e4e4e7 !important;
79+
}
80+
81+
/* Force text colors for print */
82+
.text-zinc-900,
83+
.dark\:text-zinc-100 {
84+
color: #18181b !important;
85+
}
86+
87+
.text-zinc-700,
88+
.dark\:text-zinc-300 {
89+
color: #3f3f46 !important;
90+
}
91+
92+
.text-zinc-600,
93+
.dark\:text-zinc-400 {
94+
color: #52525b !important;
95+
}
96+
97+
.text-zinc-500 {
98+
color: #71717a !important;
99+
}
100+
101+
.text-blue-500,
102+
.dark\:text-blue-400 {
103+
color: #3b82f6 !important;
104+
}
105+
106+
/* Ensure backgrounds for skill badges */
107+
.bg-zinc-100,
108+
.dark\:bg-zinc-800 {
109+
background-color: #f4f4f5 !important;
110+
}
111+
112+
/* Shadows for logo containers */
113+
.shadow-md {
114+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1) !important;
115+
}
116+
117+
/* Ring borders for logo containers */
118+
.ring-1.ring-zinc-900\/5 {
119+
box-shadow: 0 0 0 1px rgb(24 24 27 / 0.05) !important;
120+
}
121+
122+
/* SVG icon fills for print */
123+
.fill-zinc-500,
124+
.dark\:fill-zinc-400 {
125+
fill: #71717a !important;
126+
}
127+
128+
.stroke-zinc-400,
129+
.dark\:stroke-zinc-500 {
130+
stroke: #a1a1aa !important;
131+
}
132+
133+
/* Page break control */
134+
section {
135+
break-inside: avoid;
136+
}
137+
138+
li {
139+
break-inside: avoid;
140+
}
141+
142+
h2 {
143+
break-after: avoid;
144+
}
145+
146+
/* Print page settings */
147+
@page {
148+
size: letter;
149+
margin: 0.5in;
150+
}
151+
}
152+

0 commit comments

Comments
 (0)