Untitled

 avatar
unknown
plain_text
2 months ago
4.8 kB
3
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