Skip to content

Commit 2e0a980

Browse files
committed
Refactor: Extract reusable author logic and component
- Moved author image logic to a utility function `getAuthorImage` - Created `AuthorSection` component to reduce repetition - Simplified the blog rendering logic for better maintainability
1 parent 424380b commit 2e0a980

File tree

4 files changed

+136
-175
lines changed

4 files changed

+136
-175
lines changed

components/AuthorSection.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export function AuthorSection(
2+
{ author, date, authorImage }: {
3+
author: string;
4+
date: Date;
5+
authorImage: string;
6+
},
7+
) {
8+
return (
9+
<div class="flex flex-row items-center mt-auto pt-4">
10+
<div>
11+
<img
12+
class="mr-4 rounded-full w-10 h-10 object-cover"
13+
src={authorImage}
14+
alt={`${author}'s profile`}
15+
/>
16+
</div>
17+
<div>
18+
<p class="m-0 font-black">{author}</p>
19+
<p class="m-0 text-gray-500 text-sm">
20+
{new Intl.DateTimeFormat("en-US", {
21+
month: "long",
22+
day: "numeric",
23+
year: "numeric",
24+
}).format(date)}
25+
</p>
26+
</div>
27+
</div>
28+
);
29+
}

lib/getAuthorsImage.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function getAuthorImage(
2+
author: string,
3+
authorsWithImage: string[],
4+
): string {
5+
const firstName = author.split(" ")[0].toLowerCase();
6+
const isAuthorImageAvailable = authorsWithImage.includes(firstName);
7+
return isAuthorImageAvailable
8+
? `/assets/img/authors/${firstName}.jpg`
9+
: "/assets/fs-logo-no-text.svg";
10+
}

routes/blog-index-route.tsx

Lines changed: 51 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { useBlog } from "../blog/blog.ts";
2+
import { AuthorSection } from "../components/AuthorSection.tsx";
3+
import { getAuthorImage } from "../lib/getAuthorsImage.ts";
24
import { useAppHtml } from "./app.html.tsx";
35

46
export function blogIndexRoute() {
@@ -28,13 +30,13 @@ export function blogIndexRoute() {
2830
"jorge",
2931
"paul",
3032
];
31-
const firstName = latest.author.split(" ")[0].toLowerCase();
32-
const isAuthorImageAvailable = authorsWithImage.includes(
33-
firstName,
34-
);
35-
const authorImage = isAuthorImageAvailable
36-
? `/assets/img/authors/${firstName}.jpg`
37-
: "/assets/fs-logo-no-text.svg";
33+
// const firstName = latest.author.split(" ")[0].toLowerCase();
34+
// const isAuthorImageAvailable = authorsWithImage.includes(
35+
// firstName,
36+
// );
37+
// const authorImage = isAuthorImageAvailable
38+
// ? `/assets/img/authors/${firstName}.jpg`
39+
// : "/assets/fs-logo-no-text.svg";
3840

3941
return (
4042
<App>
@@ -59,25 +61,11 @@ export function blogIndexRoute() {
5961
<h3 class="font-black text-3xl">{latest.title}</h3>
6062
<p class="max-w-prose font-normal">{latest.description}</p>
6163
<strong>&rarr; Read Article</strong>
62-
<div class="flex flex-row items-center pt-2">
63-
<div>
64-
<img
65-
class="mr-4 rounded-full w-10 h-10 object-cover"
66-
src={authorImage}
67-
alt={`${latest.author}'s profile`}
68-
/>
69-
</div>
70-
<div>
71-
<p class="m-0 font-black">{latest.author}</p>
72-
<p class="m-0 text-gray-500 text-sm">
73-
{new Intl.DateTimeFormat("en-US", {
74-
month: "long",
75-
day: "numeric",
76-
year: "numeric",
77-
}).format(latest.date)}
78-
</p>
79-
</div>
80-
</div>
64+
<AuthorSection
65+
author={latest.author}
66+
date={latest.date}
67+
authorImage={getAuthorImage(latest.author, authorsWithImage)}
68+
/>
8169
</div>
8270
</a>
8371
</section>
@@ -124,25 +112,14 @@ export function blogIndexRoute() {
124112
<strong>&rarr; Read Article</strong>
125113
</div>
126114
{/* Author Info */}
127-
<div class="flex flex-row items-center mt-auto pt-4">
128-
<div>
129-
<img
130-
class="mr-4 rounded-full w-10 h-10 object-cover"
131-
src={authorImage}
132-
alt={`${post.author}'s profile`}
133-
/>
134-
</div>
135-
<div>
136-
<p class="m-0 font-black">{post.author}</p>
137-
<p class="m-0 text-gray-500 text-sm">
138-
{new Intl.DateTimeFormat("en-US", {
139-
month: "long",
140-
day: "numeric",
141-
year: "numeric",
142-
}).format(post.date)}
143-
</p>
144-
</div>
145-
</div>
115+
<AuthorSection
116+
author={post.author}
117+
date={post.date}
118+
authorImage={getAuthorImage(
119+
post.author,
120+
authorsWithImage,
121+
)}
122+
/>
146123
</a>
147124
</li>
148125
);
@@ -152,71 +129,35 @@ export function blogIndexRoute() {
152129
<section>
153130
<h2>All</h2>
154131
<ol class="md:gap-6 lg:gap-11 space-y-10 md:space-y-0 md:grid md:grid-cols-2 lg:grid-cols-3 mx-auto p-4 max-w-7xl">
155-
{blog.getPosts().map((post) => {
156-
const authorsWithImage = [
157-
"charles",
158-
"elrick",
159-
"taras",
160-
"jacob",
161-
"min",
162-
"jeffrey",
163-
"jorge",
164-
"paul",
165-
];
166-
const firstName = post.author.split(" ")[0].toLowerCase();
167-
const isAuthorImageAvailable = authorsWithImage.includes(
168-
firstName,
169-
);
170-
const authorImage = isAuthorImageAvailable
171-
? `/assets/img/authors/${firstName}.jpg`
172-
: "/assets/fs-logo-no-text.svg";
173-
174-
return (
175-
<li class="flex flex-col md:mt-0 p-2 md:p-4 border h-full prose">
176-
<a
177-
class="flex flex-col h-full no-underline"
178-
href={`/blog/${post.id}`}
179-
>
180-
{/* Blog Image */}
181-
<img
182-
class="flex-shrink-0 rounded-lg md:w-[500px] md:h-[200px] object-cover"
183-
src={post.image
184-
? `blog/${post.id}/${post.image}`
185-
: "/assets/fs-logo-no-text.svg"}
186-
alt="Blog image"
187-
/>
188-
{/* Main Content */}
189-
<div class="flex-grow">
190-
<h3 class="font-black text-2xl">{post.title}</h3>
191-
<p class="max-w-prose font-normal">
192-
{post.description}
193-
</p>
194-
<strong>&rarr; Read Article</strong>
195-
</div>
196-
{/* Author Section */}
197-
<div class="flex flex-row items-center mt-auto pt-4">
198-
<div>
199-
<img
200-
class="mr-4 rounded-full w-10 h-10 object-cover"
201-
src={authorImage}
202-
alt={`${post.author}'s profile`}
203-
/>
204-
</div>
205-
<div>
206-
<p class="m-0 font-black">{post.author}</p>
207-
<p class="m-0 text-gray-500 text-sm">
208-
{new Intl.DateTimeFormat("en-US", {
209-
month: "long",
210-
day: "numeric",
211-
year: "numeric",
212-
}).format(post.date)}
213-
</p>
214-
</div>
215-
</div>
216-
</a>
217-
</li>
218-
);
219-
})}
132+
{blog.getPosts().map((post) => (
133+
<li class="flex flex-col md:mt-0 p-2 md:p-4 border h-full prose">
134+
<a
135+
class="flex flex-col h-full no-underline"
136+
href={`/blog/${post.id}`}
137+
>
138+
<img
139+
class="flex-shrink-0 rounded-lg md:w-[500px] md:h-[200px] object-cover"
140+
src={post.image
141+
? `blog/${post.id}/${post.image}`
142+
: "/assets/fs-logo-no-text.svg"}
143+
alt="Blog image"
144+
/>
145+
<div class="flex-grow">
146+
<h3 class="font-black text-2xl">{post.title}</h3>
147+
<p class="max-w-prose font-normal">{post.description}</p>
148+
<strong>&rarr; Read Article</strong>
149+
</div>
150+
<AuthorSection
151+
author={post.author}
152+
date={post.date}
153+
authorImage={getAuthorImage(
154+
post.author,
155+
authorsWithImage,
156+
)}
157+
/>
158+
</a>
159+
</li>
160+
))}
220161
</ol>
221162
</section>
222163
</div>

routes/blog-tag-route.tsx

Lines changed: 46 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { useParams } from "revolution";
22
import { useBlog } from "../blog/blog.ts";
33
import { useAppHtml } from "./app.html.tsx";
4+
import { AuthorSection } from "../components/AuthorSection.tsx";
5+
import { getAuthorImage } from "../lib/getAuthorsImage.ts";
46

57
export function blogTagRoute() {
68
return function* () {
@@ -19,77 +21,56 @@ export function blogTagRoute() {
1921
twitterXImage: "/assets/index-meta-home-cloud-native.png",
2022
});
2123

24+
const authorsWithImage = [
25+
"charles",
26+
"elrick",
27+
"taras",
28+
"jacob",
29+
"min",
30+
"jeffrey",
31+
"jorge",
32+
"paul",
33+
];
34+
2235
return (
2336
<App>
2437
<div class="flex flex-col justify-self-center !max-w-none prose prose">
2538
<section>
2639
<h2>Tag: {tag}</h2>
2740
<ol class="md:gap-6 lg:gap-11 space-y-10 md:space-y-0 md:grid md:grid-cols-2 lg:grid-cols-3 mx-auto p-4 max-w-7xl">
28-
{posts.map((post) => {
29-
const authorsWithImage = [
30-
"charles",
31-
"elrick",
32-
"taras",
33-
"jacob",
34-
"min",
35-
"jeffrey",
36-
"jorge",
37-
"paul",
38-
];
39-
const firstName = post.author.split(" ")[0].toLowerCase();
40-
const isAuthorImageAvailable = authorsWithImage.includes(
41-
firstName,
42-
);
43-
const authorImage = isAuthorImageAvailable
44-
? `/assets/img/authors/${firstName}.jpg`
45-
: "/assets/fs-logo-no-text.svg";
46-
47-
return (
48-
<li class="flex flex-col md:mt-0 p-2 md:p-4 border rounded h-full prose">
49-
<a
50-
class="flex flex-col h-full no-underline"
51-
href={`/blog/${post.id}`}
52-
>
53-
<img
54-
class="flex-shrink-0 rounded-lg md:w-[500px] md:h-[200px] object-cover"
55-
src={post.image
56-
? `/blog/${post.id}/${post.image}`
57-
: "/assets/fs-logo-no-text.svg"}
58-
alt="blog image"
59-
/>
60-
<div class="flex-grow">
61-
<h3 class="min-h-[90px] font-black text-2xl">
62-
{post.title}
63-
</h3>
64-
<p class="max-w-prose font-normal">
65-
{post.description}
66-
</p>
67-
<strong>&rarr; Read Article</strong>
68-
</div>
69-
<div class="flex flex-row items-center pt-4">
70-
<div>
71-
<img
72-
class="mr-4 rounded-full w-10 h-10 object-cover"
73-
src={authorImage}
74-
alt={`${post.author}'s profile`}
75-
/>
76-
</div>
77-
<div>
78-
{/* author */}
79-
<p class="m-0 font-black">{post.author}</p>
80-
<p class="m-0 text-gray-500 text-sm">
81-
{new Intl.DateTimeFormat("en-US", {
82-
month: "long",
83-
day: "numeric",
84-
year: "numeric",
85-
}).format(post.date)}
86-
</p>
87-
</div>
88-
</div>
89-
</a>
90-
</li>
91-
);
92-
})}
41+
{posts.map((post) => (
42+
<li class="flex flex-col md:mt-0 p-2 md:p-4 border rounded h-full prose">
43+
<a
44+
class="flex flex-col h-full no-underline"
45+
href={`/blog/${post.id}`}
46+
>
47+
<img
48+
class="flex-shrink-0 rounded-lg md:w-[500px] md:h-[200px] object-cover"
49+
src={post.image
50+
? `/blog/${post.id}/${post.image}`
51+
: "/assets/fs-logo-no-text.svg"}
52+
alt="blog image"
53+
/>
54+
<div class="flex-grow">
55+
<h3 class="min-h-[90px] font-black text-2xl">
56+
{post.title}
57+
</h3>
58+
<p class="max-w-prose font-normal">
59+
{post.description}
60+
</p>
61+
<strong>&rarr; Read Article</strong>
62+
</div>
63+
<AuthorSection
64+
author={post.author}
65+
date={post.date}
66+
authorImage={getAuthorImage(
67+
post.author,
68+
authorsWithImage,
69+
)}
70+
/>
71+
</a>
72+
</li>
73+
))}
9374
</ol>
9475
</section>
9576
</div>

0 commit comments

Comments
 (0)