diff --git a/index.html b/index.html
index 54e7484..71cee80 100644
--- a/index.html
+++ b/index.html
@@ -640,8 +640,14 @@ async function safeFetch(url, options = {}) {
clearTimeout(timeoutId);
// Check for successful response
- if (!response.ok) {
- const errorText = await response.text();
+ if (response.status < 200 || response.status >= 300) {
+ let errorText;
+ try {
+ const errorData = await response.json();
+ errorText = errorData.error || JSON.stringify(errorData);
+ } catch (e) {
+ errorText = await response.text();
+ }
// Check if this is a Cloudflare error
if (errorText.includes('Cloudflare') || errorText.includes('cf-error')) {
@@ -663,7 +669,12 @@ async function safeFetch(url, options = {}) {
throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
}
- return await response.json();
+ try {
+ return await response.json();
+ } catch (jsonError) {
+ console.error('Error parsing JSON response:', jsonError);
+ throw new Error('Invalid response format from server');
+ }
} catch (error) {
console.error('Fetch Error:', {
message: error.message,
@@ -692,7 +703,7 @@ async function safeFetch(url, options = {}) {
const sortBy = sortSelect ? sortSelect.value : 'newest';
// Log the full request URL and parameters
- const requestUrl = `${API_BASE_URL}/proposals?sortBy=${sortBy}&userId=${currentUser.id}`;
+ const requestUrl = `${API_BASE_URL}/proposals?sortBy=${sortBy}&userId=${currentUser?.id || 'anonymous'}`;
console.log('Fetching proposals from:', requestUrl);
console.log('Current user:', currentUser);
@@ -711,13 +722,35 @@ async function safeFetch(url, options = {}) {
console.log('Response headers:', Object.fromEntries(response.headers.entries()));
if (!response.ok) {
- const errorText = await response.text();
- console.error('Error response:', errorText);
+ let errorText;
+ try {
+ const errorData = await response.json();
+ console.error('Error response JSON:', errorData);
+ errorText = errorData.error || errorData.details?.message || JSON.stringify(errorData);
+ } catch (e) {
+ errorText = await response.text();
+ console.error('Error response text:', errorText);
+ }
throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
}
- const data = await response.json();
- console.log('Proposals data:', data);
+ let data;
+ try {
+ data = await response.json();
+ } catch (jsonError) {
+ console.error('Error parsing JSON response:', jsonError);
+ throw new Error('Invalid JSON response from server');
+ }
+
+ console.log('Proposals data received:', {
+ count: data?.data?.length || 0,
+ pagination: data?.pagination
+ });
+
+ if (!data || !data.data || !Array.isArray(data.data)) {
+ console.error('Invalid data structure:', data);
+ throw new Error('Invalid data structure received from server');
+ }
renderProposals(data);
} catch (error) {
@@ -2259,34 +2292,49 @@ async function submitComment(proposalId, commentText) {
console.log(`Submitting comment for proposal ${proposalId}: ${commentText.substring(0, 20)}...`);
- return safeFetch(`${API_BASE_URL}/comments`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- proposalId: proposalId,
- userId: currentUser.id,
- commentText: commentText
- })
- })
- .then(response => {
- if (!response.ok) {
- throw new Error('Failed to post comment');
+ try {
+ const response = await fetch(`${API_BASE_URL}/comments`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ proposalId: proposalId,
+ userId: currentUser.id,
+ commentText: commentText
+ })
+ });
+
+ console.log("Comment submission response status:", response.status);
+
+ if (response.status >= 200 && response.status < 300) {
+ // Successfully created comment
+ const data = await response.json();
+ console.log("Comment created successfully:", data);
+
+ loadComments(proposalId);
+ updateCommentCount(proposalId);
+ showToastMessage('Comment posted!', '#11cc77');
+ return data;
+ } else {
+ // Server returned an error
+ let errorMessage;
+ try {
+ const errorData = await response.json();
+ errorMessage = errorData.error || 'Unknown server error';
+ } catch (e) {
+ errorMessage = await response.text() || 'Failed to post comment';
+ }
+
+ console.error('Error posting comment:', errorMessage);
+ showToastMessage('Failed to post comment', '#ff0099');
+ throw new Error(errorMessage);
}
- return response.json();
- })
- .then(data => {
- loadComments(proposalId);
- updateCommentCount(proposalId);
- showToastMessage('Comment posted!', '#11cc77');
- return data;
- })
- .catch(error => {
- console.error('Error posting comment:', error);
+ } catch (error) {
+ console.error('Network or processing error:', error);
showToastMessage('Failed to post comment', '#ff0099');
throw error;
- });
+ }
}
// Function to check if comment input is not empty
diff --git a/worker.js b/worker.js
index 96ca891..aa5eb8d 100644
--- a/worker.js
+++ b/worker.js
@@ -31,6 +31,8 @@ function createResponse(body, status = 200, cacheDuration = 60*60*24) {
headers['Cache-Control'] = 'no-store';
}
+ // Create a standard Response object
+ // This ensures properties like 'ok' are properly set based on status code
return new Response(JSON.stringify(body), {
status,
headers
@@ -1033,6 +1035,9 @@ async function getProposals(request, env) {
MAX_PAGE_SIZE
);
const offset = (page - 1) * limit;
+ const sortBy = url.searchParams.get('sortBy') || 'newest';
+
+ console.log(`Getting proposals with sorting: ${sortBy}`);
// Define the base query
let query = `
@@ -1045,26 +1050,44 @@ async function getProposals(request, env) {
(SELECT COUNT(DISTINCT pd.user_id) FROM petition_details pd WHERE pd.proposal_id = p.id AND pd.verified = 1) as verified_petitioners
FROM proposals p
JOIN users u ON p.author_id = u.id
- ORDER BY p.timestamp DESC
`;
+ // Add sorting
+ if (sortBy === 'newest') {
+ query += ` ORDER BY p.timestamp DESC`;
+ } else if (sortBy === 'oldest') {
+ query += ` ORDER BY p.timestamp ASC`;
+ } else if (sortBy === 'popular') {
+ query += ` ORDER BY upvotes DESC, p.timestamp DESC`;
+ } else if (sortBy === 'controversial') {
+ query += ` ORDER BY (upvotes + downvotes) DESC, ABS(upvotes - downvotes) ASC, p.timestamp DESC`;
+ } else {
+ // Default to newest
+ query += ` ORDER BY p.timestamp DESC`;
+ }
+
// Add pagination
query += ` LIMIT ? OFFSET ?`;
+ console.log(`Executing query with pagination: limit=${limit}, offset=${offset}`);
+
// Execute the query
const proposals = await env.DB.prepare(query).bind(limit, offset).all();
+ console.log(`Retrieved ${proposals.results?.length || 0} proposals`);
+
// Add pagination info to response
return createResponse({
data: proposals.results,
pagination: {
page,
limit,
- total: proposals.results.length,
- hasMore: proposals.results.length === limit
+ total: proposals.results?.length || 0,
+ hasMore: proposals.results?.length === limit
}
});
} catch (error) {
+ console.error('Error retrieving proposals:', error);
return createResponse({
error: 'Failed to retrieve proposals',
details: logError(error, { action: 'get_proposals' })