Skip to content

Commit ba48c2f

Browse files
committed
add ui alert box
1 parent ebcd290 commit ba48c2f

File tree

2 files changed

+177
-20
lines changed

2 files changed

+177
-20
lines changed

public/js/alerts.js

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,93 @@
22
* Global alert utilities for the application
33
*/
44

5-
// Global alert function for login page
5+
// Container for dynamic alerts
6+
let alertContainer;
7+
8+
// Initialize the alert container
9+
function initAlertContainer() {
10+
// Check if container already exists
11+
if (document.getElementById('global-alert-container')) {
12+
return document.getElementById('global-alert-container');
13+
}
14+
15+
// Create a container for alerts if it doesn't exist
16+
alertContainer = document.createElement('div');
17+
alertContainer.id = 'global-alert-container';
18+
alertContainer.style.position = 'fixed';
19+
alertContainer.style.top = '20px';
20+
alertContainer.style.left = '50%';
21+
alertContainer.style.transform = 'translateX(-50%)';
22+
alertContainer.style.zIndex = '9999';
23+
alertContainer.style.width = '80%';
24+
alertContainer.style.maxWidth = '500px';
25+
document.body.appendChild(alertContainer);
26+
27+
return alertContainer;
28+
}
29+
30+
// Global function to show a floating alert
31+
window.showFloatingAlert = function(message, type = 'error', duration = 5000) {
32+
// Initialize container if needed
33+
const container = initAlertContainer();
34+
35+
// Create alert element
36+
const alertElement = document.createElement('div');
37+
alertElement.className = `alert alert-${type}`;
38+
alertElement.style.marginBottom = '10px';
39+
alertElement.style.boxShadow = 'var(--shadow-md)';
40+
alertElement.style.opacity = '0';
41+
alertElement.style.transition = 'opacity 0.3s ease-in-out';
42+
43+
// Add message
44+
alertElement.textContent = message;
45+
46+
// Add to container
47+
container.appendChild(alertElement);
48+
49+
// Fade in
50+
setTimeout(() => {
51+
alertElement.style.opacity = '1';
52+
}, 10);
53+
54+
// Auto-dismiss after duration
55+
setTimeout(() => {
56+
alertElement.style.opacity = '0';
57+
setTimeout(() => {
58+
container.removeChild(alertElement);
59+
}, 300);
60+
}, duration);
61+
62+
return alertElement;
63+
};
64+
65+
// Function to handle API errors
66+
window.handleApiError = function(error, defaultMessage = 'An error occurred') {
67+
console.error('API Error:', error);
68+
69+
let errorMessage = defaultMessage;
70+
71+
// Extract error message from different error formats
72+
if (error && error.message) {
73+
errorMessage = error.message;
74+
} else if (error && error.error) {
75+
errorMessage = error.error;
76+
} else if (error && error.data && error.data.error) {
77+
errorMessage = error.data.error;
78+
} else if (typeof error === 'string') {
79+
errorMessage = error;
80+
}
81+
82+
// Show the error alert
83+
showFloatingAlert(errorMessage, 'error');
84+
};
85+
86+
// Function to show success message
87+
window.showSuccess = function(message) {
88+
showFloatingAlert(message, 'success');
89+
};
90+
91+
// Global alert function for login page (preserved for backward compatibility)
692
window.showLoginAlert = function(message, type = 'error') {
793
// Try to find the alert element
894
const alertElement = document.getElementById('login-alert');
@@ -20,13 +106,12 @@ window.showLoginAlert = function(message, type = 'error') {
20106
}, 5000);
21107
}
22108
} else {
23-
// Fallback to standard browser alert if element doesn't exist
24-
console.log(`Alert (${type}): ${message}`);
25-
alert(message);
109+
// Fallback to floating alert
110+
showFloatingAlert(message, type);
26111
}
27112
};
28113

29-
// Function to show any type of alert by ID
114+
// Function to show any type of alert by ID (preserved for backward compatibility)
30115
window.showAlert = function(elementId, message, type = 'error') {
31116
const alertElement = document.getElementById(elementId);
32117

@@ -41,8 +126,7 @@ window.showAlert = function(elementId, message, type = 'error') {
41126
}, 5000);
42127
}
43128
} else {
44-
// Fallback to console + alert
45-
console.log(`Alert (${type}): ${message}`);
46-
alert(message);
129+
// Fallback to floating alert
130+
showFloatingAlert(message, type);
47131
}
48132
};

public/js/api-client.js

Lines changed: 85 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ export class ApiClient {
55
// Flag to avoid logging token warning multiple times
66
static _tokenWarningLogged = false;
77

8+
/**
9+
* Show a success message using the alert system
10+
* @param {string} message - Success message to display
11+
* @private
12+
*/
13+
static _showSuccess(message) {
14+
if (window.showSuccess) {
15+
window.showSuccess(message);
16+
} else {
17+
console.log(`Success: ${message}`);
18+
}
19+
}
20+
821
/**
922
* Get a valid JWT token or null if none is available
1023
* @returns {string|null} - Valid JWT token or null
@@ -188,7 +201,12 @@ export class ApiClient {
188201

189202
if (!response.ok) {
190203
const errorData = await response.json();
191-
throw new Error(errorData.error || response.statusText);
204+
const errorMessage = errorData.error || response.statusText;
205+
// Use our new error handling system
206+
if (window.handleApiError) {
207+
window.handleApiError(errorData, errorMessage);
208+
}
209+
throw new Error(errorMessage);
192210
}
193211

194212
return await response.json();
@@ -235,10 +253,20 @@ export class ApiClient {
235253

236254
if (!response.ok) {
237255
const errorData = await response.json();
238-
throw new Error(errorData.error || 'Failed to create subscription');
256+
const errorMessage = errorData.error || 'Failed to create subscription';
257+
// Use our new error handling system
258+
if (window.handleApiError) {
259+
window.handleApiError(errorData, errorMessage);
260+
}
261+
throw new Error(errorMessage);
239262
}
240263

241-
return await response.json();
264+
const result = await response.json();
265+
266+
// Show success message
267+
this._showSuccess(`Subscription created successfully`);
268+
269+
return result;
242270
} catch (error) {
243271
console.error('Error creating subscription:', error);
244272
throw error;
@@ -267,7 +295,12 @@ export class ApiClient {
267295

268296
if (!response.ok) {
269297
const errorData = await response.json();
270-
throw new Error(errorData.error || response.statusText);
298+
const errorMessage = errorData.error || response.statusText;
299+
// Use our new error handling system
300+
if (window.handleApiError) {
301+
window.handleApiError(errorData, errorMessage);
302+
}
303+
throw new Error(errorMessage);
271304
}
272305

273306
return await response.json();
@@ -309,7 +342,12 @@ export class ApiClient {
309342

310343
if (!response.ok) {
311344
const errorData = await response.json();
312-
throw new Error(errorData.error || response.statusText);
345+
const errorMessage = errorData.error || response.statusText;
346+
// Use our new error handling system
347+
if (window.handleApiError) {
348+
window.handleApiError(errorData, errorMessage);
349+
}
350+
throw new Error(errorMessage);
313351
}
314352

315353
return await response.blob();
@@ -351,7 +389,12 @@ export class ApiClient {
351389

352390
if (!response.ok) {
353391
const errorData = await response.json();
354-
throw new Error(errorData.error || response.statusText);
392+
const errorMessage = errorData.error || response.statusText;
393+
// Use our new error handling system
394+
if (window.handleApiError) {
395+
window.handleApiError(errorData, errorMessage);
396+
}
397+
throw new Error(errorMessage);
355398
}
356399

357400
return await response.json();
@@ -409,10 +452,20 @@ export class ApiClient {
409452

410453
if (!response.ok) {
411454
const errorData = await response.json();
412-
throw new Error(errorData.error || response.statusText);
455+
const errorMessage = errorData.error || response.statusText;
456+
// Use our new error handling system
457+
if (window.handleApiError) {
458+
window.handleApiError(errorData, errorMessage);
459+
}
460+
throw new Error(errorMessage);
413461
}
414462

415-
return await response.json();
463+
const result = await response.json();
464+
465+
// Show success message
466+
this._showSuccess(`API key "${name}" created successfully`);
467+
468+
return result;
416469
}
417470

418471
/**
@@ -450,10 +503,20 @@ export class ApiClient {
450503

451504
if (!response.ok) {
452505
const errorData = await response.json();
453-
throw new Error(errorData.error || response.statusText);
506+
const errorMessage = errorData.error || response.statusText;
507+
// Use our new error handling system
508+
if (window.handleApiError) {
509+
window.handleApiError(errorData, errorMessage);
510+
}
511+
throw new Error(errorMessage);
454512
}
455513

456-
return await response.json();
514+
const result = await response.json();
515+
516+
// Show success message
517+
this._showSuccess(`API key updated successfully`);
518+
519+
return result;
457520
}
458521

459522
/**
@@ -492,10 +555,20 @@ export class ApiClient {
492555

493556
if (!response.ok) {
494557
const errorData = await response.json();
495-
throw new Error(errorData.error || response.statusText);
558+
const errorMessage = errorData.error || response.statusText;
559+
// Use our new error handling system
560+
if (window.handleApiError) {
561+
window.handleApiError(errorData, errorMessage);
562+
}
563+
throw new Error(errorMessage);
496564
}
497565

498-
return await response.json();
566+
const result = await response.json();
567+
568+
// Show success message
569+
this._showSuccess(`API key deleted successfully`);
570+
571+
return result;
499572
}
500573

501574
/**

0 commit comments

Comments
 (0)