This commit is contained in:
Omar Najjar 2025-04-02 22:22:26 +11:00
parent 9e8260d1cb
commit 626e635bee

View file

@ -444,7 +444,7 @@ function getMediaURL(path) {
try { try {
console.log("Creating user:", user); console.log("Creating user:", user);
const data = await fetch(`${API_BASE_URL}/users`, { const data = await safeFetch(`${API_BASE_URL}/users`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -561,38 +561,81 @@ function getMediaURL(path) {
}, 3000); }, 3000);
} }
async function fetch(url, options = {}) { // Improved fetch implementation
async function safeFetch(url, options = {}) {
try { try {
// Add mode: 'cors' explicitly to ensure CORS is respected // Ensure URL is a string
const response = await fetch(url, { const requestUrl = typeof url === 'string' ? url : url.toString();
...options,
// Default options
const defaultOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
// Add any additional default headers
},
mode: 'cors', mode: 'cors',
credentials: 'same-origin' credentials: 'same-origin'
};
// Merge provided options with defaults
const fetchOptions = {
...defaultOptions,
...options,
headers: {
...defaultOptions.headers,
...(options.headers || {})
}
};
// Log fetch details for debugging
console.log('Fetch Request:', {
url: requestUrl,
method: fetchOptions.method,
headers: Object.keys(fetchOptions.headers)
}); });
// Perform fetch with timeout
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
fetchOptions.signal = controller.signal;
const response = await window.fetch(requestUrl, fetchOptions);
clearTimeout(timeoutId);
// Check for successful response
if (!response.ok) { if (!response.ok) {
// Try to parse error message from response const errorBody = await response.text();
let errorData; console.error('Fetch Error Response:', {
try { status: response.status,
errorData = await response.json(); statusText: response.statusText,
} catch (e) { body: errorBody
errorData = { error: `HTTP error: ${response.status} ${response.statusText}` }; });
}
throw new Error( throw new Error(`HTTP error! status: ${response.status}, message: ${errorBody}`);
errorData.error ||
errorData.message ||
`Request failed with status ${response.status}`
);
} }
return await response.json(); return await response.json();
} catch (error) { } catch (error) {
console.error(`Fetch error for ${url}:`, error); console.error('Fetch Error:', {
message: error.message,
name: error.name,
stack: error.stack
});
// Handle specific error types
if (error.name === 'AbortError') {
throw new Error('Request timed out');
}
throw error; throw error;
} }
} }
// Fetch proposals from API // Fetch proposals from API
async function fetchProposals() { async function fetchProposals() {
try { try {
@ -602,7 +645,7 @@ function getMediaURL(path) {
const sortSelect = document.getElementById('sort-select'); const sortSelect = document.getElementById('sort-select');
const sortBy = sortSelect ? sortSelect.value : 'newest'; const sortBy = sortSelect ? sortSelect.value : 'newest';
const data = await fetch( const data = await safeFetch(
`${API_BASE_URL}/proposals?sortBy=${sortBy}&userId=${currentUser.id}` `${API_BASE_URL}/proposals?sortBy=${sortBy}&userId=${currentUser.id}`
); );
@ -807,7 +850,7 @@ async function submitVoteToServer(proposalId, voteType, isPetition = false, peti
voteData.petitionDetails = petitionDetails; voteData.petitionDetails = petitionDetails;
} }
const response = await fetch(`${API_BASE_URL}/votes`, { const response = await safeFetch(`${API_BASE_URL}/votes`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -1164,7 +1207,7 @@ uploadIcon.style.marginRight = '8px';
const trending = Math.random() > 0.8; // Randomly mark some as trending const trending = Math.random() > 0.8; // Randomly mark some as trending
// Create the proposal first // Create the proposal first
const createResponse = await fetch(`${API_BASE_URL}/proposals`, { const createResponse = await safeFetch(`${API_BASE_URL}/proposals`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -1513,7 +1556,7 @@ uploadIcon.style.marginRight = '8px';
showToastMessage('Loading petition...', '#11cc77'); showToastMessage('Loading petition...', '#11cc77');
// Fetch the specific proposal // Fetch the specific proposal
const response = await fetch(`${API_BASE_URL}/proposals?userId=${currentUser.id}`); const response = await safeFetch(`${API_BASE_URL}/proposals?userId=${currentUser.id}`);
if (!response.ok) { if (!response.ok) {
throw new Error('Failed to fetch proposal'); throw new Error('Failed to fetch proposal');
@ -1808,7 +1851,7 @@ async function loadModalComments(proposalId) {
try { try {
// Include the current user ID to get their votes // Include the current user ID to get their votes
const response = await fetch(`${API_BASE_URL}/comments?proposalId=${proposalId}&userId=${currentUser.id}`); const response = await safeFetch(`${API_BASE_URL}/comments?proposalId=${proposalId}&userId=${currentUser.id}`);
if (!response.ok) { if (!response.ok) {
throw new Error('Failed to fetch comments'); throw new Error('Failed to fetch comments');
@ -1927,7 +1970,7 @@ async function handleCommentVote(commentId, voteType) {
// Submit vote to server // Submit vote to server
try { try {
const response = await fetch(`${API_BASE_URL}/comment-votes`, { const response = await safeFetch(`${API_BASE_URL}/comment-votes`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -1985,7 +2028,7 @@ async function loadComments(proposalId) {
try { try {
// Include the current user ID to get their votes // Include the current user ID to get their votes
const response = await fetch(`${API_BASE_URL}/comments?proposalId=${proposalId}&userId=${currentUser.id}`); const response = await safeFetch(`${API_BASE_URL}/comments?proposalId=${proposalId}&userId=${currentUser.id}`);
if (!response.ok) { if (!response.ok) {
throw new Error('Failed to fetch comments'); throw new Error('Failed to fetch comments');
@ -2075,7 +2118,7 @@ async function submitComment(proposalId, form) {
submitButton.disabled = true; submitButton.disabled = true;
try { try {
const response = await fetch(`${API_BASE_URL}/comments`, { const response = await safeFetch(`${API_BASE_URL}/comments`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -2389,7 +2432,7 @@ function updateCommentCount(proposalId) {
const commentsToggle = document.getElementById(`comments-toggle-${proposalId}`); const commentsToggle = document.getElementById(`comments-toggle-${proposalId}`);
if (!commentsToggle) return; if (!commentsToggle) return;
fetch(`${API_BASE_URL}/comments?proposalId=${proposalId}`) safeFetch(`${API_BASE_URL}/comments?proposalId=${proposalId}`)
.then(response => response.json()) .then(response => response.json())
.then(comments => { .then(comments => {
const commentCount = comments.length; const commentCount = comments.length;
@ -2407,7 +2450,7 @@ function loadComments(proposalId) {
commentsList.innerHTML = '<div class="comments-loading">Loading comments...</div>'; commentsList.innerHTML = '<div class="comments-loading">Loading comments...</div>';
fetch(`${API_BASE_URL}/comments?proposalId=${proposalId}`) safeFetch(`${API_BASE_URL}/comments?proposalId=${proposalId}`)
.then(response => response.json()) .then(response => response.json())
.then(comments => { .then(comments => {
if (comments.length === 0) { if (comments.length === 0) {
@ -2436,7 +2479,7 @@ function loadComments(proposalId) {
// Update submitComment function to handle promises // Update submitComment function to handle promises
function submitComment(proposalId, commentText) { function submitComment(proposalId, commentText) {
return fetch(`${API_BASE_URL}/comments`, { return safeFetch(`${API_BASE_URL}/comments`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'