Skip to content

Commit 14e03ae

Browse files
committed
refactor: add markdown rendering component with sanitization and update author display logic
1 parent 30118a7 commit 14e03ae

File tree

14 files changed

+490
-214
lines changed

14 files changed

+490
-214
lines changed

app/authors/[author]/page.tsx

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type ArticleData = {
3636
label: string;
3737
slug: string;
3838
authorUID: string;
39+
publish: boolean; // Added publish field
3940
};
4041

4142
// Function to fetch author data
@@ -50,20 +51,53 @@ async function getAuthorData(slug: string) {
5051

5152
const authorData = authorSnapshot.docs[0].data() as AuthorData;
5253

53-
const articlesQuery = query(
54-
collection(db, "articles"),
55-
where("authorUID", "==", authorData.uid),
56-
orderBy("date", "desc")
57-
);
58-
const articlesSnapshot = await getDocs(articlesQuery);
59-
60-
const articles = articlesSnapshot.docs.map((doc) => ({
61-
uid: doc.id,
62-
...doc.data(),
63-
date: doc.data().date?.toDate() || new Date(),
64-
})) as ArticleData[];
65-
66-
return { author: authorData, articles };
54+
// Approach 1: Try with composite index (if you've created it in Firebase console)
55+
try {
56+
const articlesQuery = query(
57+
collection(db, "articles"),
58+
where("authorUID", "==", authorData.uid),
59+
where("publish", "==", true),
60+
orderBy("date", "desc")
61+
);
62+
const articlesSnapshot = await getDocs(articlesQuery);
63+
64+
const articles = articlesSnapshot.docs.map((doc) => ({
65+
uid: doc.id,
66+
...doc.data(),
67+
date: doc.data().date?.toDate() || new Date(),
68+
})) as ArticleData[];
69+
70+
return { author: authorData, articles };
71+
}
72+
// Fallback approach if composite index isn't available
73+
catch (error) {
74+
console.log("Using fallback approach for querying articles:", error);
75+
76+
// First get all articles by this author
77+
const articlesQuery = query(
78+
collection(db, "articles"),
79+
where("authorUID", "==", authorData.uid),
80+
orderBy("date", "desc")
81+
);
82+
const articlesSnapshot = await getDocs(articlesQuery);
83+
84+
// Then filter for published articles client-side
85+
const articles = articlesSnapshot.docs
86+
.map((doc) => {
87+
const data = doc.data();
88+
return {
89+
uid: doc.id,
90+
...data,
91+
date: data.date && typeof data.date.toDate === 'function'
92+
? data.date.toDate()
93+
: (data.date instanceof Date ? data.date : new Date()),
94+
publish: data.publish ?? false
95+
} as ArticleData;
96+
})
97+
.filter(article => article.publish === true);
98+
99+
return { author: authorData, articles };
100+
}
67101
} catch (error) {
68102
console.error("Error fetching author details:", error);
69103
return null;
@@ -83,14 +117,10 @@ const SOCIAL_ICONS: { [key: string]: any } = {
83117
discord: RiDiscordFill,
84118
};
85119

86-
// **Non-async page component**
87-
export default function Page({ params }: { params: { author: string } }) {
88-
return <AuthorPage authorSlug={params.author} />;
89-
}
90-
91-
// **Async server component**
92-
async function AuthorPage({ authorSlug }: { authorSlug: string }) {
93-
const data = await getAuthorData(authorSlug);
120+
// **Async page component**
121+
export default async function Page({ params }: { params: Promise<{ author: string }> }) {
122+
const { author } = await params; // Await the params object
123+
const data = await getAuthorData(author);
94124

95125
if (!data) {
96126
return <div className="p-8">Author not found</div>;
@@ -117,7 +147,7 @@ async function AuthorPage({ authorSlug }: { authorSlug: string }) {
117147
{/* **Author Profile Section** */}
118148
<div className="w-fit">
119149
<img
120-
src={authorData.avatar}
150+
src={authorData.avatar || "/default-avatar.png"}
121151
alt={authorData.imgAlt}
122152
className="w-full max-w-[300px] h-auto rounded-full"
123153
/>
@@ -140,20 +170,20 @@ async function AuthorPage({ authorSlug }: { authorSlug: string }) {
140170
{/* **Author Articles** */}
141171
<div className="pb-12 md:pb-48">
142172
<h2 className="text-blog-subheading mt-[9.5rem] pt-12 pb-12 md:pb-24">
143-
Articles by {authorData.name}
173+
Posts by {authorData.name}
144174
</h2>
145175
<AuthorArticles articles={articles} />
146176
</div>
147177
</main>
148178
);
149179
}
150180

151-
// **Component to Render Authors Articles**
181+
// **Component to Render Author's Articles**
152182
function AuthorArticles({ articles }: { articles: ArticleData[] }) {
153183
if (articles.length === 0) {
154184
return (
155185
<div className="p-8 text-center">
156-
<p>No articles found for this author</p>
186+
<p className="font-medium">No Posts found for this author</p>
157187
</div>
158188
);
159189
}

app/globals.css

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
@tailwind components;
33
@tailwind utilities;
44

5+
@import url("https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown-dark.min.css");
6+
57
@layer base {
68
:root {
79
--background: 0 0% 100%;
@@ -164,4 +166,99 @@
164166
*{
165167
scrollbar-width: 4px;
166168
scrollbar-color: #8a2be2 #121212;
167-
}
169+
}
170+
171+
.markdown-body {
172+
color: #c9d1d9 !important;
173+
/* padding: 20px !important; */
174+
}
175+
176+
/* Add specific styling for markdown elements */
177+
.markdown-body h1 {
178+
font-size: 2em !important;
179+
margin-bottom: 0.5em !important;
180+
color: #fff !important;
181+
border-bottom: 1px solid #30363d !important;
182+
padding-bottom: 0.3em !important;
183+
font-weight: 600 !important;
184+
}
185+
186+
.markdown-body h2 {
187+
font-size: 1.5em !important;
188+
margin-bottom: 0.5em !important;
189+
color: #fff !important;
190+
border-bottom: 1px solid #30363d !important;
191+
padding-bottom: 0.3em !important;
192+
}
193+
194+
.markdown-body h3 {
195+
font-size: 1.25em !important;
196+
margin-bottom: 0.5em !important;
197+
color: #fff !important;
198+
}
199+
200+
.markdown-body h4 {
201+
font-size: 1em !important;
202+
margin-bottom: 0.5em !important;
203+
color: #fff !important;
204+
}
205+
206+
.markdown-body ul,
207+
.markdown-body ol {
208+
padding-left: 2em !important;
209+
margin-bottom: 1em !important;
210+
}
211+
212+
.markdown-body li {
213+
margin: 0.25em 0 !important;
214+
list-style-type: disc !important;
215+
}
216+
217+
.markdown-body ol li {
218+
list-style-type: decimal !important;
219+
}
220+
221+
.markdown-body code {
222+
background-color: #161b22 !important;
223+
padding: 0.2em 0.4em !important;
224+
border-radius: 3px !important;
225+
font-family: monospace !important;
226+
}
227+
228+
.markdown-body pre {
229+
background-color: #161b22 !important;
230+
padding: 16px !important;
231+
border-radius: 6px !important;
232+
overflow: auto !important;
233+
margin-bottom: 1em !important;
234+
}
235+
236+
.markdown-body pre code {
237+
background-color: transparent !important;
238+
padding: 0 !important;
239+
}
240+
241+
.markdown-body blockquote {
242+
padding: 0 1em !important;
243+
color: #8b949e !important;
244+
border-left: 0.25em solid #30363d !important;
245+
margin-bottom: 1em !important;
246+
}
247+
248+
.markdown-body p {
249+
margin-bottom: 1em !important;
250+
}
251+
252+
iframe {
253+
width: 100% !important;
254+
height: 35rem !important;
255+
border: none !important;
256+
margin-bottom: 4rem;
257+
margin-top: 4rem;
258+
}
259+
@media (max-width: 768px) {
260+
iframe {
261+
262+
height: 14rem !important;
263+
}
264+
}

0 commit comments

Comments
 (0)