fix(frontend): resolve published blog detail 404
Some checks failed
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled

This commit is contained in:
2026-06-08 22:36:27 +03:30
parent 37b123838f
commit 8b1fc942cf
4 changed files with 21 additions and 13 deletions

View File

@@ -12,6 +12,8 @@ import { formatJalali } from "@/lib/utils";
type Params = Promise<{ slug: string }>;
export const dynamic = "force-dynamic";
function cleanText(value?: string | null) {
if (!value) return "";
return value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();

View File

@@ -422,7 +422,7 @@ class ApiClient {
}
async getPost(slug: string) {
return this.request<Types.PostDetailSchema>(`/api/blog/posts/${slug}`);
return this.request<Types.PostDetailSchema>(`/api/blog/posts/${encodeURIComponent(slug)}`);
}
async createPost(data: Types.PostCreateSchema) {
@@ -511,7 +511,7 @@ class ApiClient {
}
async deletePost(slug: string) {
return this.request<Types.MessageSchema>(`/api/blog/posts/${slug}`, {
return this.request<Types.MessageSchema>(`/api/blog/posts/${encodeURIComponent(slug)}`, {
method: 'DELETE',
});
}
@@ -528,11 +528,11 @@ class ApiClient {
// Comments
async getComments(slug: string) {
return this.request<Types.CommentSchema[]>(`/api/blog/posts/${slug}/comments`);
return this.request<Types.CommentSchema[]>(`/api/blog/posts/${encodeURIComponent(slug)}/comments`);
}
async createComment(slug: string, data: Types.CommentCreateSchema) {
return this.request<Types.CommentSchema>(`/api/blog/posts/${slug}/comments`, {
return this.request<Types.CommentSchema>(`/api/blog/posts/${encodeURIComponent(slug)}/comments`, {
method: 'POST',
body: JSON.stringify(data),
});
@@ -557,23 +557,23 @@ class ApiClient {
// Likes
async toggleLike(slug: string) {
return this.request<Types.BlogInteractionSchema>(`/api/blog/posts/${slug}/like`, {
return this.request<Types.BlogInteractionSchema>(`/api/blog/posts/${encodeURIComponent(slug)}/like`, {
method: 'POST',
});
}
async toggleSave(slug: string) {
return this.request<Types.BlogInteractionSchema>(`/api/blog/posts/${slug}/save`, {
return this.request<Types.BlogInteractionSchema>(`/api/blog/posts/${encodeURIComponent(slug)}/save`, {
method: 'POST',
});
}
async getBlogInteraction(slug: string) {
return this.request<Types.BlogInteractionSchema>(`/api/blog/posts/${slug}/interaction`);
return this.request<Types.BlogInteractionSchema>(`/api/blog/posts/${encodeURIComponent(slug)}/interaction`);
}
async getLikesCount(slug: string) {
return this.request<Types.MessageSchema>(`/api/blog/posts/${slug}/likes`);
return this.request<Types.MessageSchema>(`/api/blog/posts/${encodeURIComponent(slug)}/likes`);
}
async getMyBlogActivity() {

View File

@@ -54,11 +54,15 @@ async function requestJson<T>(
options?: {
params?: Record<string, QueryValue>;
revalidate?: number;
cache?: RequestCache;
},
) {
const response = await fetch(buildUrl(path, options?.params), {
next: { revalidate: options?.revalidate ?? DEFAULT_REVALIDATE_SECONDS },
});
const response = await fetch(
buildUrl(path, options?.params),
options?.cache
? { cache: options.cache }
: { next: { revalidate: options?.revalidate ?? DEFAULT_REVALIDATE_SECONDS } },
);
if (!response.ok) {
throw new PublicApiError(path, response.status);
@@ -80,7 +84,9 @@ export async function getPublicPosts(options?: { search?: string; limit?: number
}
export async function getPublicPost(slug: string) {
return requestJson<Types.PostDetailSchema>(`/api/blog/posts/${encodeURIComponent(slug)}`);
return requestJson<Types.PostDetailSchema>(`/api/blog/posts/${encodeURIComponent(slug)}`, {
cache: "no-store",
});
}
export async function getPublicEvents(options?: { search?: string; limit?: number }) {

View File

@@ -80,7 +80,7 @@ export default function Blog({
) : (
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{posts.map((post) => (
<Link key={post.id} to={`/blog/${post.slug}`}>
<Link key={post.id} to={`/blog/${encodeURIComponent(post.slug)}`}>
<Card className="h-full hover:shadow-lg transition-shadow">
<CardHeader>
<CardTitle className="line-clamp-2">{post.title}</CardTitle>