Skip to content

Commit 762d845

Browse files
committed
Refactor code structure for improved readability and maintainability
1 parent 8e7eafe commit 762d845

8 files changed

Lines changed: 127 additions & 107 deletions

File tree

43.2 KB
Loading

src/components/MyLink.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ const { href, text, className } = Astro.props;
55
<a href={href} class={`relative group ${className}`}>
66
{text}
77
<span
8-
class="absolute bottom-0 left-0 w-full h-0.5 bg-primary origin-left transform scale-x-0 transition-transform duration-300 ease-out group-hover:scale-x-100"
8+
class="absolute bottom-0 left-0 h-0.5 w-full origin-left bg-primary scale-x-0 transition-transform duration-300 ease-out group-hover:scale-x-100"
99
></span>
1010
</a>

src/data/projects.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
[
2+
{
3+
"title": "DevTools",
4+
"image": "/images/projects/devtools.webp",
5+
"link": "https://devtools.klpod221.com/",
6+
"description": "A collection of tools for developers. Includes a Code compiler, Image Tools, Web Tools, and more."
7+
},
8+
{
9+
"title": "Finance Tracker",
10+
"image": "/images/projects/finance-tracker.png",
11+
"link": "https://finance.klpod221.com/",
12+
"description": "A finance tracker that helps you manage your income and expenses."
13+
},
214
{
315
"title": "Web Base SSH Client",
416
"image": "/images/projects/ssh-client.webp",
517
"link": "https://github.com/klpod221/ssh-client",
618
"description": "A web-based SSH client that allows you to connect to your server from your browser."
719
},
8-
{
9-
"title": "DevToolkit",
10-
"image": "/images/projects/devtoolkit.webp",
11-
"link": "https://devtools.klpod221.com/",
12-
"description": "A collection of tools for developers. Includes a Code compiler, Image Tools, Web Tools, and more."
13-
},
1420
{
1521
"title": "Calculator",
1622
"image": "/images/projects/calculator.webp",

src/layouts/BaseLayout.astro

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const { title } = Astro.props;
1212
---
1313

1414
<!doctype html>
15-
<html lang="en">
15+
<html lang="en" class="scroll-smooth">
1616
<head>
1717
<meta charset="UTF-8" />
1818
<meta name="description" content="klpod221 Portfolio" />
@@ -21,15 +21,13 @@ const { title } = Astro.props;
2121
<meta name="generator" content={Astro.generator} />
2222
<title>{title}</title>
2323
</head>
24-
<body
25-
class="bg-background text-primary mx-auto my-0 px-4 font-sans text-base"
26-
>
24+
<body class="bg-background text-primary font-sans">
2725
<Header />
2826

29-
<main class="max-w-[50rem] mx-auto mt-32 overflow-x-hidden">
27+
<main class="max-w-[50rem] mx-auto mt-32 px-4">
3028
<slot />
3129
</main>
3230

3331
<Footer />
3432
</body>
35-
</html>
33+
</html>

src/layouts/partials/Footer.astro

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,25 @@ const currentYear = new Date().getFullYear();
88
<footer
99
class="max-w-[60rem] mx-auto my-8 pt-8 border-t border-tertiary text-center"
1010
>
11-
<p class="flex justify-center items-center">
12-
© {currentYear} klpod221. All rights reserved.
11+
<p class="flex justify-center items-center gap-1 flex-wrap text-sm">
12+
<span{currentYear}</span>
13+
<MyLink
14+
href="/"
15+
text="klpod221."
16+
className="text-secondary"
17+
/>
18+
<span>All rights reserved.</span>
1319
</p>
1420

1521
<p class="flex justify-center items-center flex-wrap gap-1 text-xs mt-1">
1622
<span>Build with</span>
1723
<Icon name="mdi:heart" class="w-4 h-4 text-red-500" />
1824
<span>using</span>
19-
<MyLink href="https://astro.build" text="Astro." className="text-secondary" />
25+
<MyLink
26+
href="https://astro.build"
27+
text="Astro."
28+
className="text-secondary"
29+
/>
2030
<span>Hosted on</span>
2131
<MyLink
2232
href="https://pages.github.com/"

src/layouts/partials/Header.astro

Lines changed: 75 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,29 @@ import { Icon } from "astro-icon/components";
44
import MyLink from "../../components/MyLink.astro";
55
---
66

7-
<header class="fixed top-0 left-0 z-50 bg-background w-full">
7+
<header class="fixed top-0 left-0 z-50 w-full bg-background">
88
<nav
9-
class="flex justify-between items-center mx-auto max-w-7xl px-4 font-mono"
9+
class="flex items-center justify-between max-w-7xl mx-auto px-4 font-mono"
1010
>
11-
<a class="text-xl font-bold py-4" href="/">#-klpod221</a>
11+
<a class="py-4 text-xl font-bold" href="/">#-klpod221</a>
1212

1313
<ul
14-
class="hidden md:flex m-0 p-0 fixed z-40 top-16 left-0 bg-background w-full md:w-auto md:static md:flex-row md:space-x-4 md:items-center md:justify-center"
14+
class="hidden md:flex md:items-center md:space-x-4 fixed md:static z-40 top-16 left-0 w-full md:w-auto bg-background"
1515
>
1616
<li class="p-4 text-center">
1717
<MyLink href="#about" text="About" className="inline-block" />
1818
</li>
1919
<li class="p-4 text-center">
20-
<MyLink href="#experience" text="Experience" className="inline-block">
21-
</li>
22-
<li class="p-4 text-center">
23-
<MyLink href="#projects" text="Projects" className="inline-block" />
24-
</li>
25-
<li class="p-4 text-center">
26-
<MyLink href="#contact" text="Contact" className="inline-block" />
20+
<MyLink href="#experience" text="Experience" className="inline-block" />
21+
<li class="p-4 text-center">
22+
<MyLink href="#projects" text="Projects" className="inline-block" />
23+
</li>
24+
<li class="p-4 text-center">
25+
<MyLink href="#contact" text="Contact" className="inline-block" />
26+
</li>
2727
</li>
2828
</ul>
29-
29+
3030
<div class="flex items-center space-x-4">
3131
<a
3232
href="https://github.com/klpod221"
@@ -42,81 +42,81 @@ import MyLink from "../../components/MyLink.astro";
4242
</button>
4343
</div>
4444
</nav>
45-
</header>
4645

47-
<script>
48-
const activeHeaderItem = (item) => {
49-
// Get all navigation items
50-
const navItems = document.querySelectorAll("nav ul li a");
46+
<script>
47+
const activeHeaderItem = (item) => {
48+
// Get all navigation items
49+
const navItems = document.querySelectorAll("nav ul li a");
5150

52-
// Remove active class from all items
53-
navItems.forEach((navItem) => {
54-
navItem.classList.remove("text-primary");
55-
navItem.querySelector("span")?.classList.remove("scale-x-100");
56-
});
51+
// Remove active class from all items
52+
navItems.forEach((navItem) => {
53+
navItem.classList.remove("text-primary");
54+
navItem.querySelector("span")?.classList.remove("scale-x-100");
55+
});
5756

58-
// Add active class to clicked item
59-
item.classList.add("text-primary");
60-
item.querySelector("span")?.classList.add("scale-x-100");
57+
// Add active class to clicked item
58+
item.classList.add("text-primary");
59+
item.querySelector("span")?.classList.add("scale-x-100");
6160

62-
const target = item.getAttribute("href");
61+
const target = item.getAttribute("href");
6362

64-
// Handle navigation properly
65-
if (target === "#about") {
66-
// Scroll to top since there's no explicit about section
67-
window.scrollTo({
68-
top: 0,
69-
behavior: "smooth",
70-
});
71-
} else {
72-
const targetElement = document.querySelector(target);
73-
if (targetElement) {
74-
// Add proper offset for header height
63+
// Handle navigation properly
64+
if (target === "#about") {
65+
// Scroll to top since there's no explicit about section
7566
window.scrollTo({
76-
top: targetElement.offsetTop - 80,
67+
top: 0,
7768
behavior: "smooth",
7869
});
70+
} else {
71+
const targetElement = document.querySelector(target);
72+
if (targetElement) {
73+
// Add proper offset for header height
74+
window.scrollTo({
75+
top: targetElement.offsetTop - 80,
76+
behavior: "smooth",
77+
});
78+
}
79+
}
80+
};
81+
82+
const toggleMobileMenu = () => {
83+
document.querySelector("nav ul")?.classList.toggle("hidden");
84+
};
85+
86+
// When DOM is loaded
87+
document.addEventListener("DOMContentLoaded", () => {
88+
// Activate the first item by default
89+
const firstNavItem = document.querySelector("nav ul li a");
90+
if (firstNavItem) {
91+
activeHeaderItem(firstNavItem);
7992
}
80-
}
81-
};
82-
83-
const toggleMobileMenu = () => {
84-
document.querySelector("nav ul")?.classList.toggle("hidden");
85-
};
86-
87-
// When DOM is loaded
88-
document.addEventListener("DOMContentLoaded", () => {
89-
// Activate the first item by default
90-
const firstNavItem = document.querySelector("nav ul li a");
91-
if (firstNavItem) {
92-
activeHeaderItem(firstNavItem);
93-
}
9493

95-
// Add event listener to all navigation items
96-
document.querySelectorAll("nav ul li a").forEach((item) => {
97-
item.addEventListener("click", function (e) {
98-
e.preventDefault();
99-
activeHeaderItem(this);
94+
// Add event listener to all navigation items
95+
document.querySelectorAll("nav ul li a").forEach((item) => {
96+
item.addEventListener("click", function (e) {
97+
e.preventDefault();
98+
activeHeaderItem(this);
10099

101-
// Only hide on mobile devices
102-
if (window.innerWidth < 768) {
103-
document.querySelector("nav ul")?.classList.add("hidden");
104-
}
100+
// Only hide on mobile devices
101+
if (window.innerWidth < 768) {
102+
document.querySelector("nav ul")?.classList.add("hidden");
103+
}
104+
});
105105
});
106-
});
107106

108-
// Add event listener to mobile menu button
109-
document
110-
.querySelector("header button")
111-
?.addEventListener("click", toggleMobileMenu);
112-
});
113-
</script>
107+
// Add event listener to mobile menu button
108+
document
109+
.querySelector("header button")
110+
?.addEventListener("click", toggleMobileMenu);
111+
});
112+
</script>
114113

115-
<style>
116-
@media (max-width: 767px) {
117-
nav ul {
118-
transition: all 0.3s ease;
119-
border-bottom: 1px solid #27272a;
114+
<style>
115+
@media (max-width: 767px) {
116+
nav ul {
117+
transition: all 0.3s ease;
118+
border-bottom: 1px solid #27272a;
119+
}
120120
}
121-
}
122-
</style>
121+
</style>
122+
</header>

src/pages/index.astro

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import ProjectList from "../components/ProjectList.astro";
1111
const calculateYearsOfExperience = (startDate) => {
1212
const start = new Date(startDate);
1313
const today = new Date();
14-
14+
1515
// Tính số milliseconds giữa hai ngày
1616
const diffMs = today.getTime() - start.getTime();
17-
17+
1818
// Chuyển đổi thành năm (chia cho số milliseconds trong một năm)
1919
const years = diffMs / (1000 * 60 * 60 * 24 * 365.25);
20-
20+
2121
// Làm tròn đến 1 số thập phân
2222
return years.toFixed(1);
2323
};
@@ -27,22 +27,22 @@ const yearOfExperience = calculateYearsOfExperience("2021-12-01");
2727

2828
<BaseLayout title="klpod221's Portfolio">
2929
<MyCard>
30-
<div class="flex justify-between w-full flex-col sm:flex-row" id="about">
30+
<div class="flex w-full flex-col justify-between sm:flex-row" id="about">
3131
<div class="flex flex-col">
32-
<h1 class="font-bold text-3xl">Bùi Thanh Xuân</h1>
33-
<p class="text-secondary flex items-center">
34-
<Icon name="mdi:location" class="w-4 h-4 inline-block" />
32+
<h1 class="text-3xl font-bold">Bùi Thanh Xuân</h1>
33+
<p class="flex items-center text-secondary">
34+
<Icon name="mdi:location" class="inline-block h-4 w-4" />
3535
Hà Nội, Việt Nam
3636
</p>
3737
</div>
3838

39-
<div class="flex items-baseline space-x-4 mt-2">
39+
<div class="mt-2 flex items-baseline space-x-4">
4040
<a
4141
href="mailto:klpod221@gmail.com"
42-
class="p-2 border border-tertiary rounded-lg hover:bg-tertiary"
42+
class="rounded-lg border border-tertiary p-2 hover:bg-tertiary"
4343
aria-label="Email"
4444
>
45-
<Icon name="mdi:email" class="w-5 h-5 sm:w-6 sm:h-6" />
45+
<Icon name="mdi:email" class="h-5 w-5 sm:h-6 sm:w-6" />
4646
</a>
4747

4848
<a
@@ -145,7 +145,9 @@ const yearOfExperience = calculateYearsOfExperience("2021-12-01");
145145
/>
146146
</div>
147147

148-
<h2 class="font-bold text-2xl md:text-3xl mt-6" id="experience">Work Experience</h2>
148+
<h2 class="font-bold text-2xl md:text-3xl mt-6" id="experience">
149+
Work Experience
150+
</h2>
149151
<div class="w-full pl-2">
150152
<div class="flex flex-col">
151153
<ExperienceItem
@@ -179,7 +181,7 @@ const yearOfExperience = calculateYearsOfExperience("2021-12-01");
179181
descriptions={[
180182
"Developed custom web applications for clients using modern technologies",
181183
"Contributed to open-source projects on GitHub",
182-
"Led small development teams for project delivery"
184+
"Led small development teams for project delivery",
183185
]}
184186
/>
185187

@@ -195,20 +197,24 @@ const yearOfExperience = calculateYearsOfExperience("2021-12-01");
195197
</div>
196198
</div>
197199

198-
<h2 class="font-bold text-2xl md:text-3xl my-6" id="projects">My Personal Projects</h2>
200+
<h2 class="font-bold text-2xl md:text-3xl my-6" id="projects">
201+
My Personal Projects
202+
</h2>
199203

200204
<ProjectList />
201205

202-
<h2 class="font-bold text-2xl md:text-3xl my-6" id="contact">Like what you see?</h2>
206+
<h2 class="font-bold text-2xl md:text-3xl my-6" id="contact">
207+
Like what you see?
208+
</h2>
203209

204210
<MyCard>
205-
<h3 class="font-bold text-2xl">Contact me</h3>
211+
<h3 class="text-2xl font-bold">Contact me</h3>
206212
<p class="mt-2">
207213
If you want to work with me, please contact me via email or social
208214
media. I'm always open to new opportunities.
209215
</p>
210216

211-
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mt-4">
217+
<div class="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-3">
212218
<a
213219
class="flex flex-col items-center group"
214220
href="mailto:klpod221@gmail.com"

0 commit comments

Comments
 (0)