${{ formatPrice(berth.Price) }}
-
- {{ getInterestedCount(berth) }} interested
-
+
+
+
+ {{ getInterestedCount(berth) }} interested
+
+
+
+
Interested Parties:
+
+ {{ party['Full Name'] }}
+
+
+
diff --git a/plugins/01.auth-refresh.client.ts b/plugins/01.auth-refresh.client.ts
index 33a9f3b..4f81503 100644
--- a/plugins/01.auth-refresh.client.ts
+++ b/plugins/01.auth-refresh.client.ts
@@ -14,8 +14,8 @@ export default defineNuxtPlugin(() => {
refreshTimer = null
}
- // Calculate time until refresh (refresh 5 minutes before expiry)
- const refreshBuffer = 5 * 60 * 1000 // 5 minutes in milliseconds
+ // Calculate time until refresh (refresh 10 minutes before expiry for better safety margin)
+ const refreshBuffer = 10 * 60 * 1000 // 10 minutes in milliseconds (increased from 5)
const timeUntilRefresh = expiresAt - Date.now() - refreshBuffer
console.log('[AUTH_REFRESH] Scheduling token refresh in:', Math.max(0, timeUntilRefresh), 'ms')
diff --git a/server/api/expenses/generate-pdf.ts b/server/api/expenses/generate-pdf.ts
index 3c9e93e..187f2cb 100644
--- a/server/api/expenses/generate-pdf.ts
+++ b/server/api/expenses/generate-pdf.ts
@@ -748,56 +748,22 @@ async function fetchReceiptImage(receipt: any): Promise
{
console.log('[expenses/generate-pdf] Detected S3 URL, fetching directly...');
try {
- // Ensure URL is properly encoded
- let encodedUrl = rawPath;
- try {
- // Parse and reconstruct URL to ensure proper encoding
- const url = new URL(rawPath);
- // Re-encode the pathname to handle special characters
- url.pathname = url.pathname.split('/').map(segment => encodeURIComponent(decodeURIComponent(segment))).join('/');
- encodedUrl = url.toString();
- console.log('[expenses/generate-pdf] URL encoded:', encodedUrl);
- } catch (urlError) {
- console.log('[expenses/generate-pdf] Using original URL (encoding failed):', rawPath);
- encodedUrl = rawPath;
- }
+ // Use the signed URL directly without modification to preserve AWS signature
+ console.log('[expenses/generate-pdf] Fetching from S3 URL (preserving signature):', rawPath);
- // Fetch image directly from S3 URL with proper headers
- const response = await fetch(encodedUrl, {
+ // Fetch image directly from S3 URL with minimal headers to avoid signature issues
+ const response = await fetch(rawPath, {
method: 'GET',
headers: {
- 'Accept': 'image/*',
- 'User-Agent': 'PortNimara-Client-Portal/1.0',
- 'Cache-Control': 'no-cache'
+ 'Accept': 'image/*'
},
// Add timeout to prevent hanging
- signal: AbortSignal.timeout(45000) // 45 second timeout
+ signal: AbortSignal.timeout(30000) // 30 second timeout
});
if (!response.ok) {
console.error(`[expenses/generate-pdf] Failed to fetch image from S3: ${response.status} ${response.statusText}`);
console.error('[expenses/generate-pdf] Response headers:', Object.fromEntries(response.headers.entries()));
-
- // Try with the original URL if encoding failed
- if (encodedUrl !== rawPath) {
- console.log('[expenses/generate-pdf] Retrying with original URL...');
- const originalResponse = await fetch(rawPath, {
- method: 'GET',
- headers: {
- 'Accept': 'image/*',
- 'User-Agent': 'PortNimara-Client-Portal/1.0'
- },
- signal: AbortSignal.timeout(30000)
- });
-
- if (originalResponse.ok) {
- const arrayBuffer = await originalResponse.arrayBuffer();
- const imageBuffer = Buffer.from(arrayBuffer);
- console.log('[expenses/generate-pdf] Successfully fetched with original URL, Size:', imageBuffer.length);
- return imageBuffer;
- }
- }
-
return null;
}
@@ -810,27 +776,13 @@ async function fetchReceiptImage(receipt: any): Promise {
} catch (fetchError: any) {
console.error('[expenses/generate-pdf] Error fetching from S3 URL:', fetchError.message);
+ console.error('[expenses/generate-pdf] Error details:', {
+ name: fetchError.name,
+ code: fetchError.code,
+ message: fetchError.message
+ });
- // If it's a timeout or network error, try one more time with simpler approach
- if (fetchError.name === 'TimeoutError' || fetchError.name === 'AbortError' || fetchError.code === 'ECONNRESET') {
- console.log('[expenses/generate-pdf] Network error, trying simplified approach...');
- try {
- const simpleResponse = await fetch(rawPath, {
- method: 'GET',
- signal: AbortSignal.timeout(90000) // Extended timeout for final attempt
- });
-
- if (simpleResponse.ok) {
- const arrayBuffer = await simpleResponse.arrayBuffer();
- const imageBuffer = Buffer.from(arrayBuffer);
- console.log('[expenses/generate-pdf] Successfully fetched image with simplified approach, Size:', imageBuffer.length);
- return imageBuffer;
- }
- } catch (finalError) {
- console.error('[expenses/generate-pdf] Final attempt also failed:', finalError);
- }
- }
-
+ // Don't try multiple attempts for signed URLs as they may expire
return null;
}
}