fix: Error Handling in Backend und Frontend verbessern (Phase 5, Schritt 31)
- Backend: JSON-Parse-Error + Payload-Too-Large Middleware in index.js - Backend: Dashboard äußerer try/catch für db.get()-Fehler - Backend: contacts/meta Route mit try/catch - Frontend: try/catch + Toast-Fallback in loadMonth (budget), loadRange (calendar), loadWeek (meals), loadLists/switchList (shopping), initiales Laden (notes) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,7 @@ function addMonths(ym, n) {
|
|||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
async function loadMonth(month) {
|
async function loadMonth(month) {
|
||||||
|
try {
|
||||||
const [entriesRes, summaryRes] = await Promise.all([
|
const [entriesRes, summaryRes] = await Promise.all([
|
||||||
api.get(`/budget?month=${month}`),
|
api.get(`/budget?month=${month}`),
|
||||||
api.get(`/budget/summary?month=${month}`),
|
api.get(`/budget/summary?month=${month}`),
|
||||||
@@ -61,6 +62,13 @@ async function loadMonth(month) {
|
|||||||
state.month = month;
|
state.month = month;
|
||||||
state.entries = entriesRes.data;
|
state.entries = entriesRes.data;
|
||||||
state.summary = summaryRes.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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|||||||
@@ -124,8 +124,14 @@ function eventsOnDay(dateStr) {
|
|||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
async function loadRange(from, to) {
|
async function loadRange(from, to) {
|
||||||
|
try {
|
||||||
const res = await api.get(`/calendar?from=${from}&to=${to}`);
|
const res = await api.get(`/calendar?from=${from}&to=${to}`);
|
||||||
state.events = res.data;
|
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.rangeFrom = from;
|
||||||
state.rangeTo = to;
|
state.rangeTo = to;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,9 +74,16 @@ function formatDayDate(dateStr) {
|
|||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
async function loadWeek(week) {
|
async function loadWeek(week) {
|
||||||
|
try {
|
||||||
const res = await api.get(`/meals?week=${week}`);
|
const res = await api.get(`/meals?week=${week}`);
|
||||||
state.meals = res.data;
|
state.meals = res.data;
|
||||||
state.currentWeek = getMondayOf(week);
|
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() {
|
async function loadLists() {
|
||||||
|
|||||||
@@ -58,8 +58,14 @@ export async function render(container, { user }) {
|
|||||||
|
|
||||||
if (window.lucide) lucide.createIcons();
|
if (window.lucide) lucide.createIcons();
|
||||||
|
|
||||||
|
try {
|
||||||
const res = await api.get('/notes');
|
const res = await api.get('/notes');
|
||||||
state.notes = res.data;
|
state.notes = res.data;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[Notes] Laden fehlgeschlagen:', err);
|
||||||
|
state.notes = [];
|
||||||
|
window.oikos?.showToast('Notizen konnten nicht geladen werden.', 'danger');
|
||||||
|
}
|
||||||
renderGrid();
|
renderGrid();
|
||||||
|
|
||||||
_container.querySelector('#notes-add-btn').addEventListener('click', () => openModal({ mode: 'create' }));
|
_container.querySelector('#notes-add-btn').addEventListener('click', () => openModal({ mode: 'create' }));
|
||||||
|
|||||||
@@ -351,8 +351,14 @@ function updateListCounter(listId, totalDelta, checkedDelta) {
|
|||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
async function loadLists() {
|
async function loadLists() {
|
||||||
|
try {
|
||||||
const data = await api.get('/shopping');
|
const data = await api.get('/shopping');
|
||||||
state.lists = data.data ?? [];
|
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) {
|
async function loadItems(listId) {
|
||||||
@@ -366,9 +372,11 @@ async function switchList(listId, container) {
|
|||||||
renderTabs(container);
|
renderTabs(container);
|
||||||
try {
|
try {
|
||||||
await loadItems(listId);
|
await loadItems(listId);
|
||||||
} catch {
|
} catch (err) {
|
||||||
|
console.error('[Shopping] loadItems Fehler:', err);
|
||||||
state.items = [];
|
state.items = [];
|
||||||
state.activeList = state.lists.find((l) => l.id === listId) ?? null;
|
state.activeList = state.lists.find((l) => l.id === listId) ?? null;
|
||||||
|
window.oikos?.showToast('Artikel konnten nicht geladen werden.', 'danger');
|
||||||
}
|
}
|
||||||
renderListContent(container);
|
renderListContent(container);
|
||||||
wireListContentEvents(container);
|
wireListContentEvents(container);
|
||||||
|
|||||||
@@ -67,6 +67,17 @@ app.set('trust proxy', 1);
|
|||||||
app.use(express.json({ limit: '1mb' }));
|
app.use(express.json({ limit: '1mb' }));
|
||||||
app.use(express.urlencoded({ extended: true, 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
|
// Sessions
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|||||||
@@ -151,8 +151,13 @@ router.delete('/:id', (req, res) => {
|
|||||||
* Kategorien-Liste für Dropdowns.
|
* Kategorien-Liste für Dropdowns.
|
||||||
* Response: { data: { categories } }
|
* Response: { data: { categories } }
|
||||||
*/
|
*/
|
||||||
router.get('/meta', (req, res) => {
|
router.get('/meta', (_req, res) => {
|
||||||
|
try {
|
||||||
res.json({ data: { categories: VALID_CATEGORIES } });
|
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;
|
module.exports = router;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const db = require('../db');
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
router.get('/', (req, res) => {
|
router.get('/', (req, res) => {
|
||||||
|
try {
|
||||||
const d = db.get();
|
const d = db.get();
|
||||||
const result = {};
|
const result = {};
|
||||||
|
|
||||||
@@ -116,6 +117,10 @@ router.get('/', (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res.json(result);
|
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;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user