Skip to content

Commit a89a9d1

Browse files
authored
Merge pull request #4 from kashvigarg/frontend-test
Untested Changes
2 parents a743512 + 696938e commit a89a9d1

File tree

10 files changed

+234
-99
lines changed

10 files changed

+234
-99
lines changed

web2/app/api/[...path]/route.ts

Lines changed: 75 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -8,80 +8,81 @@ export async function GET(request: NextRequest, { params }: { params: { path: st
88
const token = searchParams.get("token") || request.headers.get("Authorization")?.split(" ")[1];
99

1010
// Check if this is an SSE endpoint
11-
const isSSE = path === "timeline" || path === "notifications" || path.includes("/comments");
12-
13-
if (isSSE) {
14-
try {
15-
// Try SSE first
16-
const response = await fetch(`${process.env.API_URL}/api/${path}`, {
17-
headers: {
18-
Authorization: `Bearer ${token}`,
19-
Accept: "text/event-stream",
20-
},
21-
});
22-
23-
const text = await response.text();
24-
25-
if (response.ok && text.trim()) {
26-
try {
27-
const data = JSON.parse(text);
28-
29-
// Set up SSE response
30-
const encoder = new TextEncoder();
31-
const stream = new ReadableStream({
32-
async start(controller) {
33-
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
34-
35-
// Keep the connection open
36-
const interval = setInterval(() => {
37-
controller.enqueue(encoder.encode(": keepalive\n\n"));
38-
}, 30000);
39-
40-
// Clean up on close
41-
request.signal.addEventListener("abort", () => {
42-
clearInterval(interval);
43-
controller.close();
44-
});
45-
},
46-
});
47-
48-
return new NextResponse(stream, {
49-
headers: {
50-
"Content-Type": "text/event-stream",
51-
"Cache-Control": "no-cache",
52-
Connection: "keep-alive",
53-
},
54-
});
55-
} catch (jsonError) {
56-
console.error("SSE JSON parse error:", jsonError);
57-
return NextResponse.json({ error: "Invalid JSON response from SSE" }, { status: 502 });
58-
}
59-
} else {
60-
console.log("SSE response empty, falling back to basic fetch...");
61-
62-
const fallbackResponse = await fetch(`${process.env.API_URL}/api/${path}`, {
63-
headers: { Authorization: `Bearer ${token}` },
64-
});
65-
66-
const fallbackText = await fallbackResponse.text();
67-
68-
if (!fallbackText.trim()) {
69-
return NextResponse.json({ error: "Empty response from server" }, { status: 502 });
70-
}
71-
72-
try {
73-
return NextResponse.json(JSON.parse(fallbackText), { status: fallbackResponse.status });
74-
} catch {
75-
return NextResponse.json({ error: "Invalid JSON from fallback" }, { status: 502 });
76-
}
77-
}
78-
} catch (error: any) {
79-
console.error("SSE error:", error);
80-
if (error.code !== "UND_ERR_HEADERS_TIMEOUT") {
81-
return NextResponse.json({ error: "Failed to connect to SSE" }, { status: 500 });
82-
}
83-
}
84-
}
11+
// const isSSE = path === "timeline" || path === "notifications" ||path.includes("/comments");
12+
13+
// if (isSSE) {
14+
// try {
15+
// // Try SSE first
16+
// const response = await fetch(`${process.env.API_URL}/api/${path}`, {
17+
// headers: {
18+
// Authorization: `Bearer ${token}`,
19+
// Accept: "text/event-stream",
20+
// },
21+
// });
22+
// console.log(response)
23+
24+
// const text = await response.text();
25+
26+
// if (response.ok && !text.trim()) {
27+
// try {
28+
// const data = JSON.parse(text);
29+
30+
// // Set up SSE response
31+
// const encoder = new TextEncoder();
32+
// const stream = new ReadableStream({
33+
// async start(controller) {
34+
// controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));
35+
36+
// // Keep the connection open
37+
// const interval = setInterval(() => {
38+
// controller.enqueue(encoder.encode(": keepalive\n\n"));
39+
// }, 30000);
40+
41+
// // Clean up on close
42+
// request.signal.addEventListener("abort", () => {
43+
// clearInterval(interval);
44+
// controller.close();
45+
// });
46+
// },
47+
// });
48+
49+
// return new NextResponse(stream, {
50+
// headers: {
51+
// "Content-Type": "text/event-stream",
52+
// "Cache-Control": "no-cache",
53+
// Connection: "keep-alive",
54+
// },
55+
// });
56+
// } catch (jsonError) {
57+
// console.error("SSE JSON parse error:", jsonError);
58+
// return NextResponse.json({ error: "Invalid JSON response from SSE" }, { status: 502 });
59+
// }
60+
// } else {
61+
// console.log("SSE response empty, falling back to basic fetch...");
62+
63+
// const fallbackResponse = await fetch(`${process.env.API_URL}/api/${path}`, {
64+
// headers: { Authorization: `Bearer ${token}` },
65+
// });
66+
67+
// const fallbackText = await fallbackResponse.text();
68+
69+
// if (!fallbackText.trim()) {
70+
// return NextResponse.json({ error: "Empty response from server" }, { status: 502 });
71+
// }
72+
73+
// try {
74+
// return NextResponse.json(JSON.parse(fallbackText), { status: fallbackResponse.status });
75+
// } catch {
76+
// return NextResponse.json({ error: "Invalid JSON from fallback" }, { status: 502 });
77+
// }
78+
// }
79+
// } catch (error: any) {
80+
// console.error("SSE error:", error);
81+
// if (error.code !== "UND_ERR_HEADERS_TIMEOUT") {
82+
// return NextResponse.json({ error: "Failed to connect to SSE" }, { status: 500 });
83+
// }
84+
// }
85+
// }
8586

8687
// Regular API request
8788
try {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// app/api/sse/[...path]/route.ts
2+
import { type NextRequest } from "next/server";
3+
4+
export async function GET(request: NextRequest) {
5+
const url = new URL(request.url);
6+
const path = url.pathname.replace("/api/sse/", ""); // e.g., "timeline" or "comments/123"
7+
const token =
8+
url.searchParams.get("token") ||
9+
request.headers.get("Authorization")?.split(" ")[1];
10+
11+
try {
12+
const backendResponse = await fetch(
13+
`${process.env.API_URL}/api/${path}?${url.searchParams.toString()}`,
14+
{
15+
method: "GET",
16+
headers: {
17+
Authorization: token ? `Bearer ${token}` : "",
18+
Accept: "text/event-stream",
19+
},
20+
}
21+
);
22+
23+
// Proxy the backend SSE stream directly to the client
24+
return new Response(backendResponse.body, {
25+
status: 200,
26+
headers: {
27+
"Content-Type": "text/event-stream",
28+
"Cache-Control": "no-cache",
29+
Connection: "keep-alive",
30+
// Optional headers for CORS (if needed):
31+
// "Access-Control-Allow-Origin": "*",
32+
},
33+
});
34+
} catch (error) {
35+
console.error("SSE proxy error:", error);
36+
return new Response("Failed to connect to SSE", { status: 502 });
37+
}
38+
}

web2/app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { redirect } from "next/navigation"
22
import { cookies } from "next/headers"
3-
import { Timeline } from "@/components/timeline"
43
import { MainLayout } from "@/components/main-layout"
4+
import TimelinePage from "./timeline/page"
55

66
export default async function Home() {
77
const cookieStore = await cookies()
@@ -13,7 +13,7 @@ export default async function Home() {
1313

1414
return (
1515
<MainLayout>
16-
<Timeline />
16+
<TimelinePage />
1717
</MainLayout>
1818
)
1919
}

web2/app/timeline/page.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Timeline } from "@/components/timeline";
2+
import React from "react";
3+
4+
export default function TimelinePage(){
5+
return (
6+
<div>
7+
<Timeline/>
8+
</div>
9+
)
10+
}

web2/components/comments-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function CommentsList({ proseId }: { proseId: string }) {
3434
const { toast } = useToast()
3535

3636
// Try to use SSE for comments, fall back to regular fetch
37-
const { data, error: sseError } = useSSE<Comment[]>(`/api/${proseId}/comments`, token, {
37+
const { data, error: sseError } = useSSE<Comment[]>(`/api/sse/${proseId}/comments`, token, "comment", {
3838
onMessage: (data) => {
3939
if (data) {
4040
console.log("SSE CHECK FOR COMMENTS")

web2/components/notification-indicator.tsx

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function NotificationIndicator({ className = "" }: NotificationIndicatorP
1313
const { token } = useAuth()
1414

1515
// Use SSE to check for unread notifications
16-
const { data } = useSSE<{ has_unread: boolean }>("/api/notifications", token, {
16+
const { data } = useSSE<{ has_unread: boolean }>("/api/sse/notifications", token, "notification", {
1717
onMessage: (data) => {
1818
if (data && Array.isArray(data)) {
1919
setHasUnread(data.some((notification) => !notification.read))
@@ -38,13 +38,14 @@ export function NotificationIndicator({ className = "" }: NotificationIndicatorP
3838

3939
if (response.ok) {
4040
const text = await response.text()
41-
const data = JSON.parse(text)
41+
if (text.trim()){
42+
const data = JSON.parse(text)
4243
if (data!=null){
4344
setHasUnread(data.some((notification: any) => !notification.read))
44-
} else {
45+
}
46+
}
47+
else {
4548
setHasUnread(false)
46-
console.log("EMPTY")
47-
console.log(data)
4849
}
4950
}
5051
} catch (err) {
@@ -60,3 +61,49 @@ export function NotificationIndicator({ className = "" }: NotificationIndicatorP
6061
return <div className={`h-2 w-2 rounded-full bg-red-500 ${className}`} />
6162
}
6263

64+
// "use client";
65+
66+
// import { useState, useEffect } from "react";
67+
// import { useAuth } from "@/lib/auth-hooks";
68+
69+
// type NotificationIndicatorProps = {
70+
// className?: string;
71+
// };
72+
73+
// export function NotificationIndicator({ className = "" }: NotificationIndicatorProps) {
74+
// const [hasUnread, setHasUnread] = useState(false);
75+
// const { token } = useAuth();
76+
77+
// // Fallback: check for unread notifications on mount (SSE disabled)
78+
// useEffect(() => {
79+
// const checkUnread = async () => {
80+
// try {
81+
// const response = await fetch("/api/notifications", {
82+
// headers: {
83+
// Authorization: `Bearer ${token}`,
84+
// },
85+
// });
86+
87+
// if (response.ok) {
88+
// const text = await response.text();
89+
// if (text.trim()) {
90+
// const data = JSON.parse(text);
91+
// if (data != null) {
92+
// setHasUnread(data.some((notification: any) => !notification.read));
93+
// }
94+
// } else {
95+
// setHasUnread(false);
96+
// }
97+
// }
98+
// } catch (err) {
99+
// console.error("Failed to check unread notifications", err);
100+
// }
101+
// };
102+
103+
// checkUnread();
104+
// }, [token]);
105+
106+
// if (!hasUnread) return null;
107+
108+
// return <div className={`h-2 w-2 rounded-full bg-red-500 ${className}`} />;
109+
// }

web2/components/notifications-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function NotificationsList() {
2828
const { toast } = useToast()
2929

3030
// Try to use SSE for notifications, fall back to regular fetch
31-
const { data, error: sseError } = useSSE<Notification[]>("/api/notifications", token, {
31+
const { data, error: sseError } = useSSE<Notification[]>("/api/sse/notifications", token, "notification", {
3232
onMessage: (data) => {
3333
if (data) {
3434
console.log("SSE CHECK FOR NOTIFS")

web2/components/timeline.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function Timeline() {
3434
const { toast } = useToast();
3535

3636
// Use SSE to get timeline updates
37-
const { data, error: sseError } = useSSE<TimelineItem[]>("/api/timeline", token, {
37+
const { data, error: sseError } = useSSE<TimelineItem[]>("/api/sse/timeline", token, "timeline",{
3838
onMessage: (data) => {
3939
if (data) {
4040
console.log("SSE CHECK FOR TL")
@@ -192,3 +192,6 @@ export function Timeline() {
192192
</div>
193193
);
194194
}
195+
196+
197+

web2/components/users-list.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export function UsersList() {
8585
);
8686
}
8787

88+
// console.log(filteredUsers)
8889
return (
8990
<div className="space-y-4">
9091
<h2 className="text-2xl font-serif font-bold">Find Users to Follow</h2>

0 commit comments

Comments
 (0)