Untitled
unknown
plain_text
10 months ago
4.8 kB
8
Indexable
// app/api/comments/route.ts
import { NextResponse } from "next/server";
// Interface for comment structure
interface Comment {
id: string;
photoId: string;
name: string;
rating: number;
text: string;
createdAt: string;
}
// Interface for comment index
interface CommentIndex {
[photoId: string]: number; // photoId -> comment count
}
// Helper to get R2 paths
const getR2Path = (clientId: string, path: string) => {
return `${clientId}/comments/${path}`;
};
// Helper to fetch JSON from R2
async function fetchJsonFromR2(key: string): Promise<any> {
try {
// Use R2 public URL if available
const publicUrl = `${process.env.NEXT_PUBLIC_R2_PUBLIC_URL}/${key}`;
const response = await fetch(publicUrl, {
cache: 'no-store',
headers: {
'Cache-Control': 'no-cache'
}
});
if (!response.ok) {
if (response.status === 404) {
return null; // File doesn't exist
}
throw new Error(`Failed to fetch from R2: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`Error fetching from R2: ${key}`, error);
return null;
}
}
// Helper to upload JSON to R2
async function uploadJsonToR2(key: string, data: any): Promise<boolean> {
try {
// Use the R2 proxy endpoint (create this endpoint next)
const uploadUrl = `/api/r2-upload?key=${encodeURIComponent(key)}`;
const response = await fetch(uploadUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Failed to upload to R2: ${response.status}`);
}
return true;
} catch (error) {
console.error(`Error uploading to R2: ${key}`, error);
return false;
}
}
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const photoId = searchParams.get("photoId");
const clientId = searchParams.get("clientId");
const getIndex = searchParams.get("index") === "true";
if (!clientId) {
return NextResponse.json(
{ error: "Client ID is required" },
{ status: 400 }
);
}
// If requesting the index
if (getIndex) {
const indexPath = getR2Path(clientId, 'index.json');
const index = await fetchJsonFromR2(indexPath);
return NextResponse.json(index || {});
}
// If requesting comments for a specific photo
if (!photoId) {
return NextResponse.json(
{ error: "Photo ID is required" },
{ status: 400 }
);
}
const commentsPath = getR2Path(clientId, `${photoId}.json`);
const comments = await fetchJsonFromR2(commentsPath);
return NextResponse.json(comments || []);
} catch (error) {
console.error("Error fetching comments:", error);
return NextResponse.json(
{ error: "Failed to fetch comments" },
{ status: 500 }
);
}
}
export async function POST(request: Request) {
try {
const body = await request.json();
const { photoId, clientId, name, rating, text } = body;
if (!photoId || !text || !clientId) {
return NextResponse.json(
{ error: "Photo ID, Client ID, and text are required" },
{ status: 400 }
);
}
// Create paths for R2 storage
const commentsPath = getR2Path(clientId, `${photoId}.json`);
const indexPath = getR2Path(clientId, 'index.json');
// Fetch existing comments or create empty array
let comments: Comment[] = await fetchJsonFromR2(commentsPath) || [];
// Create new comment
const newComment: Comment = {
id: Date.now().toString(),
photoId,
name: name || "Anonym",
rating: rating || 0,
text,
createdAt: new Date().toISOString()
};
// Add comment to beginning of array
comments.unshift(newComment);
// Upload comments to R2
const commentUploadSuccess = await uploadJsonToR2(commentsPath, comments);
if (!commentUploadSuccess) {
throw new Error("Failed to upload comments to R2");
}
// Update index in R2
const index: CommentIndex = await fetchJsonFromR2(indexPath) || {};
index[photoId] = comments.length;
const indexUploadSuccess = await uploadJsonToR2(indexPath, index);
if (!indexUploadSuccess) {
console.warn("Failed to update comment index in R2");
}
return NextResponse.json(newComment);
} catch (error) {
console.error("Error creating comment:", error);
return NextResponse.json(
{ error: "Failed to create comment" },
{ status: 500 }
);
}
}Editor is loading...
Leave a Comment