file uploaded path correction
This commit is contained in:
+35
-18
@@ -1,4 +1,6 @@
|
||||
import { API_BASE } from '../lib/apiBase';
|
||||
import { uploadLocal } from '../lib/localFileStore';
|
||||
import { notifyContentUpdated } from '../context/ContentContext';
|
||||
|
||||
/** Frontend-only fallback when the Node API is not reachable on the host. */
|
||||
const STATIC_USER = 'admin';
|
||||
@@ -45,7 +47,9 @@ async function apiFetch(path, options = {}) {
|
||||
: res.status === 502
|
||||
? 'API server unreachable. Start Node on the host (port 3001).'
|
||||
: 'Request failed';
|
||||
throw new Error(data.error || fallback);
|
||||
const err = new Error(data.error || fallback);
|
||||
err.status = res.status;
|
||||
throw err;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -65,7 +69,17 @@ export const adminApi = {
|
||||
|
||||
me: async () => {
|
||||
if (isStaticSession()) {
|
||||
return { username: STATIC_USER, mode: 'static' };
|
||||
// If server is now running, clear the stale static token so real login is used
|
||||
try {
|
||||
await apiFetch('/api/auth/me');
|
||||
// Server responded — clear static token so user re-authenticates properly
|
||||
clearToken();
|
||||
throw new Error('Session expired, please log in again');
|
||||
} catch (err) {
|
||||
if (err.status) throw err; // server is up but rejected — force re-login
|
||||
// Server unreachable — static session is fine
|
||||
return { username: STATIC_USER, mode: 'static' };
|
||||
}
|
||||
}
|
||||
return apiFetch('/api/auth/me');
|
||||
},
|
||||
@@ -82,14 +96,28 @@ export const adminApi = {
|
||||
},
|
||||
|
||||
updateSection: async (section, data) => {
|
||||
try {
|
||||
return await apiFetch(`/api/content/${section}`, { method: 'PUT', body: JSON.stringify(data) });
|
||||
} catch {
|
||||
// Skip API entirely for static sessions
|
||||
if (isStaticSession()) {
|
||||
const saved = localStorage.getItem('static_content');
|
||||
const { default: seed } = await import('../../server/seed/default-content.json');
|
||||
const current = saved ? JSON.parse(saved) : seed;
|
||||
const updated = { ...current, [section]: data, _updatedAt: new Date().toISOString() };
|
||||
localStorage.setItem('static_content', JSON.stringify(updated));
|
||||
notifyContentUpdated();
|
||||
return { message: `${section} updated (local)`, updatedAt: updated._updatedAt };
|
||||
}
|
||||
try {
|
||||
const result = await apiFetch(`/api/content/${section}`, { method: 'PUT', body: JSON.stringify(data) });
|
||||
notifyContentUpdated();
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (err.status === 401) clearToken();
|
||||
const saved = localStorage.getItem('static_content');
|
||||
const { default: seed } = await import('../../server/seed/default-content.json');
|
||||
const current = saved ? JSON.parse(saved) : seed;
|
||||
const updated = { ...current, [section]: data, _updatedAt: new Date().toISOString() };
|
||||
localStorage.setItem('static_content', JSON.stringify(updated));
|
||||
notifyContentUpdated();
|
||||
return { message: `${section} updated (local)`, updatedAt: updated._updatedAt };
|
||||
}
|
||||
},
|
||||
@@ -103,18 +131,7 @@ export const adminApi = {
|
||||
},
|
||||
|
||||
upload: async (file) => {
|
||||
// Try Node API first; fall back to local data URL when server is unavailable.
|
||||
try {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
return await apiFetch('/api/upload', { method: 'POST', body: form });
|
||||
} catch {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve({ url: reader.result, filename: file.name });
|
||||
reader.onerror = () => reject(new Error('Failed to read file'));
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
// Store file locally in IndexedDB — no server needed
|
||||
return uploadLocal(file);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ export function ImageUpload({ value, onChange, label = 'Image' }) {
|
||||
const { url } = await adminApi.upload(file);
|
||||
onChange(url);
|
||||
} catch (err) {
|
||||
alert(err.message);
|
||||
alert('Upload failed: ' + err.message);
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
|
||||
+9
-5
@@ -2,9 +2,13 @@ import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import './admin.css';
|
||||
import App from './App.jsx';
|
||||
import { restoreAllBlobUrls } from '../lib/localFileStore';
|
||||
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>
|
||||
);
|
||||
// Restore IndexedDB-stored file blob URLs before rendering
|
||||
restoreAllBlobUrls().then(() => {
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user