Skip to content

Commit 199da7f

Browse files
authored
Refactor with zulstand and components (#3)
* refactor with zustand and components * fix speech bubbles in layout plan
1 parent a5e536c commit 199da7f

27 files changed

+2682
-2004
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
"pino": "9.9.5",
2222
"pino-pretty": "13.1.1",
2323
"react": "19.1.1",
24-
"react-dom": "19.1.1"
24+
"react-dom": "19.1.1",
25+
"zustand": "5.0.8"
2526
},
2627
"devDependencies": {
2728
"@biomejs/biome": "2.2.4",
2829
"@tailwindcss/postcss": "4.1.13",
29-
"@types/node": "24.4.0",
30+
"@types/node": "24.5.0",
3031
"@types/react": "19.1.13",
3132
"@types/react-dom": "19.1.9",
3233
"knip": "5.63.1",

pnpm-lock.yaml

Lines changed: 38 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/api/reddit/route.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { type NextRequest, NextResponse } from "next/server";
2+
3+
interface RedditPost {
4+
title: string;
5+
selftext: string;
6+
author: string;
7+
subreddit: string;
8+
url: string;
9+
permalink: string;
10+
}
11+
12+
interface RedditApiResponse {
13+
data: {
14+
children: Array<{
15+
data: RedditPost;
16+
}>;
17+
};
18+
}
19+
20+
interface RedditPostContent {
21+
title: string;
22+
body: string;
23+
author: string;
24+
subreddit: string;
25+
url: string;
26+
}
27+
28+
export async function GET(request: NextRequest) {
29+
try {
30+
const { searchParams } = new URL(request.url);
31+
const redditPath = searchParams.get("path");
32+
33+
if (!redditPath) {
34+
return NextResponse.json(
35+
{ error: "Reddit path parameter is required" },
36+
{ status: 400 },
37+
);
38+
}
39+
40+
// Extract subreddit and post ID from path like /r/subreddit/comments/postid/title
41+
const pathMatch = redditPath.match(/^\/r\/([^/]+)\/comments\/([^/]+)/);
42+
if (!pathMatch) {
43+
return NextResponse.json(
44+
{ error: "Invalid Reddit URL format" },
45+
{ status: 400 },
46+
);
47+
}
48+
49+
const [, subreddit, postId] = pathMatch;
50+
const apiUrl = `https://www.reddit.com/r/${subreddit}/comments/${postId}.json`;
51+
52+
const response = await fetch(apiUrl, {
53+
headers: {
54+
"User-Agent": "story-to-manga/1.0",
55+
},
56+
});
57+
58+
if (!response.ok) {
59+
if (response.status === 404) {
60+
return NextResponse.json(
61+
{ error: "Reddit post not found" },
62+
{ status: 404 },
63+
);
64+
}
65+
if (response.status === 403) {
66+
return NextResponse.json(
67+
{ error: "Reddit post is private or restricted" },
68+
{ status: 403 },
69+
);
70+
}
71+
return NextResponse.json(
72+
{ error: `Failed to fetch Reddit post: ${response.status}` },
73+
{ status: response.status },
74+
);
75+
}
76+
77+
const data: RedditApiResponse[] = await response.json();
78+
79+
if (!data || !Array.isArray(data) || data.length === 0) {
80+
return NextResponse.json(
81+
{ error: "Invalid Reddit API response format" },
82+
{ status: 500 },
83+
);
84+
}
85+
86+
const postData = data[0]?.data?.children?.[0]?.data;
87+
if (!postData) {
88+
return NextResponse.json(
89+
{ error: "No post data found in Reddit response" },
90+
{ status: 500 },
91+
);
92+
}
93+
94+
const redditPostContent: RedditPostContent = {
95+
title: postData.title || "",
96+
body: postData.selftext || "",
97+
author: postData.author || "",
98+
subreddit: postData.subreddit || "",
99+
url: `https://www.reddit.com${postData.permalink}`,
100+
};
101+
102+
return NextResponse.json({
103+
success: true,
104+
post: redditPostContent,
105+
});
106+
} catch (error) {
107+
console.error("Reddit proxy error:", error);
108+
return NextResponse.json(
109+
{
110+
error: `Network error while fetching Reddit post: ${
111+
error instanceof Error ? error.message : "Unknown error"
112+
}`,
113+
},
114+
{ status: 500 },
115+
);
116+
}
117+
}

0 commit comments

Comments
 (0)