diff --git a/index.html b/index.html
index 71cee80..5150aad 100644
--- a/index.html
+++ b/index.html
@@ -2293,37 +2293,85 @@ async function submitComment(proposalId, commentText) {
console.log(`Submitting comment for proposal ${proposalId}: ${commentText.substring(0, 20)}...`);
try {
- const response = await fetch(`${API_BASE_URL}/comments`, {
+ console.log("Making POST request to comments endpoint");
+
+ // Log the full API URL and request details
+ const requestUrl = `${API_BASE_URL}/comments`;
+ const requestData = {
+ proposalId: proposalId,
+ userId: currentUser?.id || 'anonymous',
+ commentText: commentText
+ };
+
+ console.log("Request URL:", requestUrl);
+ console.log("Request data:", requestData);
+
+ // Ensure we have a user
+ if (!currentUser || !currentUser.id) {
+ console.error("No current user - creating anonymous");
+ showToastMessage('Please wait, initializing user...', '#ff0099');
+ await loadUserData(); // Reinitialize user
+ }
+
+ // Create a controller to manage request timeouts
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
+
+ const response = await fetch(requestUrl, {
method: 'POST',
headers: {
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json'
},
body: JSON.stringify({
proposalId: proposalId,
userId: currentUser.id,
commentText: commentText
- })
+ }),
+ mode: 'cors',
+ credentials: 'same-origin',
+ signal: controller.signal
});
- console.log("Comment submission response status:", response.status);
+ clearTimeout(timeoutId);
- if (response.status >= 200 && response.status < 300) {
+ console.log("Comment submission response status:", response.status);
+ console.log("Response headers:", Object.fromEntries(response.headers.entries()));
+
+ // Process response based on status code
+ if (response.status === 200 || response.status === 201) {
// Successfully created comment
- const data = await response.json();
- console.log("Comment created successfully:", data);
-
- loadComments(proposalId);
- updateCommentCount(proposalId);
- showToastMessage('Comment posted!', '#11cc77');
- return data;
+ try {
+ const data = await response.json();
+ console.log("Comment created successfully:", data);
+
+ loadComments(proposalId);
+ updateCommentCount(proposalId);
+ showToastMessage('Comment posted!', '#11cc77');
+ return data;
+ } catch (jsonError) {
+ console.warn("Could not parse success response as JSON:", jsonError);
+ // Still consider this a success if status code was good
+ loadComments(proposalId);
+ updateCommentCount(proposalId);
+ showToastMessage('Comment posted!', '#11cc77');
+ return { success: true };
+ }
} else {
// Server returned an error
let errorMessage;
try {
const errorData = await response.json();
+ console.error("Error response data:", errorData);
errorMessage = errorData.error || 'Unknown server error';
} catch (e) {
- errorMessage = await response.text() || 'Failed to post comment';
+ try {
+ errorMessage = await response.text() || 'Failed to post comment';
+ console.error("Error response text:", errorMessage);
+ } catch (textError) {
+ errorMessage = `HTTP error ${response.status}`;
+ console.error("Could not read error response:", textError);
+ }
}
console.error('Error posting comment:', errorMessage);
@@ -2331,8 +2379,13 @@ async function submitComment(proposalId, commentText) {
throw new Error(errorMessage);
}
} catch (error) {
- console.error('Network or processing error:', error);
- showToastMessage('Failed to post comment', '#ff0099');
+ if (error.name === 'AbortError') {
+ console.error('Comment request timed out');
+ showToastMessage('Comment request timed out', '#ff0099');
+ } else {
+ console.error('Network or processing error:', error);
+ showToastMessage('Failed to post comment', '#ff0099');
+ }
throw error;
}
}
diff --git a/worker.js b/worker.js
index aa5eb8d..e7c80da 100644
--- a/worker.js
+++ b/worker.js
@@ -2,7 +2,7 @@
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
- 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Accept',
'Access-Control-Max-Age': '86400'
};
@@ -19,6 +19,13 @@ function handleOptions() {
// Helper to create standardized responses
function createResponse(body, status = 200, cacheDuration = 60*60*24) {
+ // Don't allow null or undefined body
+ if (body === null || body === undefined) {
+ console.error('createResponse called with null or undefined body');
+ body = { error: 'Empty response body' };
+ status = 500;
+ }
+
const headers = {
'Content-Type': 'application/json',
...corsHeaders // Add CORS headers
@@ -31,6 +38,9 @@ function createResponse(body, status = 200, cacheDuration = 60*60*24) {
headers['Cache-Control'] = 'no-store';
}
+ // Log the response details for debugging
+ console.log(`Creating response: status=${status}, headers=${JSON.stringify(headers)}, body type=${typeof body}`);
+
// Create a standard Response object
// This ensures properties like 'ok' are properly set based on status code
return new Response(JSON.stringify(body), {
@@ -1028,6 +1038,10 @@ async function healthCheck(env) {
// Get proposals with optional sorting
async function getProposals(request, env) {
try {
+ // Define pagination constants locally to ensure they're in scope
+ const DEFAULT_PAGE_SIZE = 20;
+ const MAX_PAGE_SIZE = 100;
+
const url = new URL(request.url);
const page = parseInt(url.searchParams.get('page')) || 1;
const limit = Math.min(
@@ -1037,7 +1051,7 @@ async function getProposals(request, env) {
const offset = (page - 1) * limit;
const sortBy = url.searchParams.get('sortBy') || 'newest';
- console.log(`Getting proposals with sorting: ${sortBy}`);
+ console.log(`Getting proposals with sorting: ${sortBy}, page: ${page}, limit: ${limit}`);
// Define the base query
let query = `
@@ -1698,29 +1712,69 @@ async function getComments(request, env) {
// Function to create a new comment
async function createComment(request, env) {
+ console.log("========== BEGIN createComment ==========");
try {
- const data = await request.json();
+ // First check if request is properly formed
+ if (!request || !request.body) {
+ console.error("Invalid request object or missing body");
+ return createResponse({
+ error: 'Invalid request',
+ details: 'Request missing required properties'
+ }, 400);
+ }
+
+ // Attempt to parse JSON data
+ let data;
+ try {
+ data = await request.json();
+ console.log(`Parsed comment request data: ${JSON.stringify(data)}`);
+ } catch (jsonError) {
+ console.error("Failed to parse request JSON:", jsonError);
+ return createResponse({
+ error: 'Invalid JSON in request',
+ details: 'Could not parse request body as JSON'
+ }, 400);
+ }
+
const { proposalId, userId, commentText } = data;
- console.log(`Creating comment: ${JSON.stringify(data)}`);
+ console.log(`Creating comment: proposalId=${proposalId}, userId=${userId}, text length=${commentText?.length || 0}`);
if (!proposalId || !userId || !commentText) {
+ console.error("Missing required fields:", {
+ hasProposalId: !!proposalId,
+ hasUserId: !!userId,
+ hasCommentText: !!commentText
+ });
+
return createResponse({
error: 'Missing required fields',
- received: { proposalId, userId, commentText: commentText ? '[present]' : '[missing]' }
+ received: {
+ proposalId: proposalId || '[missing]',
+ userId: userId || '[missing]',
+ commentText: commentText ? '[present]' : '[missing]'
+ }
}, 400);
}
// Check if proposal exists
try {
+ console.log(`Checking if proposal exists: ${proposalId}`);
const proposalCheck = await env.DB.prepare(
`SELECT id FROM proposals WHERE id = ?`
).bind(proposalId).first();
if (!proposalCheck) {
- return createResponse({ error: 'Proposal does not exist', proposalId }, 404);
+ console.error(`Proposal not found: ${proposalId}`);
+ return createResponse({
+ error: 'Proposal does not exist',
+ proposalId
+ }, 404);
}
+
+ console.log(`Proposal found: ${proposalCheck.id}`);
} catch (checkError) {
+ console.error("Error checking proposal existence:", checkError);
return createResponse({
error: 'Error checking proposal existence',
details: logError(checkError, { action: 'check_proposal', proposalId })
@@ -1729,24 +1783,37 @@ async function createComment(request, env) {
// Check if user exists
try {
+ console.log(`Checking if user exists: ${userId}`);
const userCheck = await env.DB.prepare(
`SELECT id FROM users WHERE id = ?`
).bind(userId).first();
if (!userCheck) {
- return createResponse({ error: 'User does not exist', userId }, 404);
+ console.error(`User not found: ${userId}`);
+ return createResponse({
+ error: 'User does not exist',
+ userId
+ }, 404);
}
+
+ console.log(`User found: ${userCheck.id}`);
} catch (userError) {
+ console.error("Error checking user existence:", userError);
return createResponse({
error: 'Error checking user existence',
details: logError(userError, { action: 'check_user', userId })
}, 500);
}
+ // Generate a unique comment ID
const id = 'comment_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
const timestamp = Date.now();
+ console.log(`Generated comment ID: ${id}`);
+
+ // Insert the comment into the database
try {
+ console.log("Inserting comment into database");
await env.DB.prepare(`
INSERT INTO comments (id, proposal_id, user_id, comment_text, timestamp)
VALUES (?, ?, ?, ?, ?)
@@ -1755,19 +1822,32 @@ async function createComment(request, env) {
console.log(`Successfully created comment with ID: ${id}`);
// Get user name for response
+ console.log("Getting user name for response");
const userQuery = await env.DB.prepare(
`SELECT name FROM users WHERE id = ?`
).bind(userId).first();
- return createResponse({
+ if (!userQuery || !userQuery.name) {
+ console.warn(`Could not find name for user ${userId}, using 'Anonymous'`);
+ }
+
+ const responseData = {
id,
proposalId,
userId,
- userName: userQuery.name,
+ userName: userQuery?.name || 'Anonymous',
commentText,
- timestamp
- });
+ timestamp,
+ upvotes: 0,
+ downvotes: 0
+ };
+
+ console.log(`Creating successful response: ${JSON.stringify(responseData)}`);
+ console.log("========== END createComment ==========");
+
+ return createResponse(responseData, 201); // Use 201 Created for successful creation
} catch (dbError) {
+ console.error("Database error creating comment:", dbError);
return createResponse({
error: 'Failed to create comment in database',
details: logError(dbError, {
@@ -1777,6 +1857,8 @@ async function createComment(request, env) {
}, 500);
}
} catch (error) {
+ console.error("Unhandled error in createComment:", error);
+ console.log("========== END createComment (with error) ==========");
return createResponse({
error: 'Failed to process comment creation',
details: logError(error, { action: 'create_comment_outer' })