diff --git a/public/pages/budget.js b/public/pages/budget.js index 176d052..81765a6 100644 --- a/public/pages/budget.js +++ b/public/pages/budget.js @@ -54,13 +54,21 @@ function addMonths(ym, n) { // -------------------------------------------------------- async function loadMonth(month) { - const [entriesRes, summaryRes] = await Promise.all([ - api.get(`/budget?month=${month}`), - api.get(`/budget/summary?month=${month}`), - ]); - state.month = month; - state.entries = entriesRes.data; - state.summary = summaryRes.data; + try { + const [entriesRes, summaryRes] = await Promise.all([ + api.get(`/budget?month=${month}`), + api.get(`/budget/summary?month=${month}`), + ]); + state.month = month; + state.entries = entriesRes.data; + state.summary = summaryRes.data; + } catch (err) { + console.error('[Budget] loadMonth Fehler:', err); + state.month = month; + state.entries = []; + state.summary = { income: 0, expenses: 0, balance: 0, by_category: [] }; + window.oikos?.showToast('Budget konnte nicht geladen werden.', 'danger'); + } } // -------------------------------------------------------- diff --git a/public/pages/calendar.js b/public/pages/calendar.js index 526fd55..e8eceba 100644 --- a/public/pages/calendar.js +++ b/public/pages/calendar.js @@ -124,8 +124,14 @@ function eventsOnDay(dateStr) { // -------------------------------------------------------- async function loadRange(from, to) { - const res = await api.get(`/calendar?from=${from}&to=${to}`); - state.events = res.data; + try { + const res = await api.get(`/calendar?from=${from}&to=${to}`); + state.events = res.data; + } catch (err) { + console.error('[Calendar] loadRange Fehler:', err); + state.events = []; + window.oikos?.showToast('Termine konnten nicht geladen werden.', 'danger'); + } state.rangeFrom = from; state.rangeTo = to; } diff --git a/public/pages/meals.js b/public/pages/meals.js index b58d703..560606b 100644 --- a/public/pages/meals.js +++ b/public/pages/meals.js @@ -74,9 +74,16 @@ function formatDayDate(dateStr) { // -------------------------------------------------------- async function loadWeek(week) { - const res = await api.get(`/meals?week=${week}`); - state.meals = res.data; - state.currentWeek = getMondayOf(week); + try { + const res = await api.get(`/meals?week=${week}`); + state.meals = res.data; + state.currentWeek = getMondayOf(week); + } catch (err) { + console.error('[Meals] loadWeek Fehler:', err); + state.meals = []; + state.currentWeek = getMondayOf(week); + window.oikos?.showToast('Essensplan konnte nicht geladen werden.', 'danger'); + } } async function loadLists() { diff --git a/public/pages/notes.js b/public/pages/notes.js index ebbd079..09ca433 100644 --- a/public/pages/notes.js +++ b/public/pages/notes.js @@ -58,8 +58,14 @@ export async function render(container, { user }) { if (window.lucide) lucide.createIcons(); - const res = await api.get('/notes'); - state.notes = res.data; + try { + const res = await api.get('/notes'); + state.notes = res.data; + } catch (err) { + console.error('[Notes] Laden fehlgeschlagen:', err); + state.notes = []; + window.oikos?.showToast('Notizen konnten nicht geladen werden.', 'danger'); + } renderGrid(); _container.querySelector('#notes-add-btn').addEventListener('click', () => openModal({ mode: 'create' })); diff --git a/public/pages/shopping.js b/public/pages/shopping.js index 6e30a29..c81636e 100644 --- a/public/pages/shopping.js +++ b/public/pages/shopping.js @@ -351,8 +351,14 @@ function updateListCounter(listId, totalDelta, checkedDelta) { // -------------------------------------------------------- async function loadLists() { - const data = await api.get('/shopping'); - state.lists = data.data ?? []; + try { + const data = await api.get('/shopping'); + state.lists = data.data ?? []; + } catch (err) { + console.error('[Shopping] loadLists Fehler:', err); + state.lists = []; + window.oikos?.showToast('Listen konnten nicht geladen werden.', 'danger'); + } } async function loadItems(listId) { @@ -366,9 +372,11 @@ async function switchList(listId, container) { renderTabs(container); try { await loadItems(listId); - } catch { + } catch (err) { + console.error('[Shopping] loadItems Fehler:', err); state.items = []; state.activeList = state.lists.find((l) => l.id === listId) ?? null; + window.oikos?.showToast('Artikel konnten nicht geladen werden.', 'danger'); } renderListContent(container); wireListContentEvents(container); diff --git a/server/index.js b/server/index.js index ec1b3f9..3e4798b 100644 --- a/server/index.js +++ b/server/index.js @@ -67,6 +67,17 @@ app.set('trust proxy', 1); app.use(express.json({ limit: '1mb' })); app.use(express.urlencoded({ extended: true, limit: '1mb' })); +// JSON-Parse-Fehler abfangen (gibt sonst HTML zurück) +app.use((err, req, res, next) => { + if (err.type === 'entity.parse.failed') { + return res.status(400).json({ error: 'Ungültiges JSON im Request-Body.', code: 400 }); + } + if (err.type === 'entity.too.large') { + return res.status(413).json({ error: 'Request-Body zu groß (max. 1 MB).', code: 413 }); + } + next(err); +}); + // -------------------------------------------------------- // Sessions // -------------------------------------------------------- diff --git a/server/routes/contacts.js b/server/routes/contacts.js index ff45016..1f0a27c 100644 --- a/server/routes/contacts.js +++ b/server/routes/contacts.js @@ -151,8 +151,13 @@ router.delete('/:id', (req, res) => { * Kategorien-Liste für Dropdowns. * Response: { data: { categories } } */ -router.get('/meta', (req, res) => { - res.json({ data: { categories: VALID_CATEGORIES } }); +router.get('/meta', (_req, res) => { + try { + res.json({ data: { categories: VALID_CATEGORIES } }); + } catch (err) { + console.error('[contacts/GET /meta]', err); + res.status(500).json({ error: 'Interner Fehler', code: 500 }); + } }); module.exports = router; diff --git a/server/routes/dashboard.js b/server/routes/dashboard.js index 980f8ba..5dabcf3 100644 --- a/server/routes/dashboard.js +++ b/server/routes/dashboard.js @@ -25,6 +25,7 @@ const db = require('../db'); * } */ router.get('/', (req, res) => { + try { const d = db.get(); const result = {}; @@ -116,6 +117,10 @@ router.get('/', (req, res) => { } res.json(result); + } catch (err) { + console.error('[Dashboard] Kritischer Fehler:', err.message); + res.status(500).json({ error: 'Dashboard konnte nicht geladen werden.', code: 500 }); + } }); module.exports = router;