feat: Phase 4 — Wetter-Widget, Wiederkehrende Aufgaben, Kanban-Ansicht, PWA

- server/routes/weather.js: OpenWeatherMap-Proxy (aktuelles Wetter + 3-Tage-Forecast,
  30-min-Cache, graceful fallback wenn kein API-Key gesetzt)
- public/pages/dashboard.js: Weather-Widget parallel mit Dashboard-Daten laden
- public/styles/dashboard.css: Weather-Widget-Styles (Gradient, Forecast-Strip)
- server/services/recurrence.js: RRULE-Parser (FREQ=DAILY/WEEKLY/MONTHLY, BYDAY,
  INTERVAL, UNTIL) + nextOccurrence()-Funktion
- server/routes/tasks.js: Bei PATCH /:id/status = done → nächste Instanz
  wiederkehrender Aufgaben automatisch anlegen
- public/pages/tasks.js: Kanban-Ansicht (3 Spalten: Offen/In Bearbeitung/Erledigt)
  mit HTML5 Drag & Drop, View-Toggle (Liste/Kanban)
- public/styles/tasks.css: Kanban-Board-Styles (Spalten, Cards, Drag-over-Highlight)
- public/sw.js: Cache-Version auf v2, alle Modul-CSS-Dateien im APP_SHELL-Cache

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ulsklyc
2026-03-24 21:32:22 +01:00
parent 74b6e5f078
commit 450ae37f42
8 changed files with 669 additions and 26 deletions
+23 -3
View File
@@ -6,9 +6,10 @@
'use strict';
const express = require('express');
const router = express.Router();
const db = require('../db');
const express = require('express');
const router = express.Router();
const db = require('../db');
const { nextOccurrence } = require('../services/recurrence');
// --------------------------------------------------------
// Konstanten
@@ -253,6 +254,25 @@ router.patch('/:id/status', (req, res) => {
if (result.changes === 0)
return res.status(404).json({ error: 'Aufgabe nicht gefunden.', code: 404 });
// Wiederkehrende Aufgabe: nächste Instanz erstellen wenn erledigt
if (status === 'done') {
const task = db.get().prepare('SELECT * FROM tasks WHERE id = ?').get(req.params.id);
if (task?.is_recurring && task.recurrence_rule && !task.parent_task_id) {
const nextDate = nextOccurrence(task.due_date, task.recurrence_rule);
if (nextDate) {
db.get().prepare(`
INSERT INTO tasks (title, description, category, priority, status,
due_date, due_time, assigned_to, created_by, is_recurring, recurrence_rule)
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, 1, ?)
`).run(
task.title, task.description, task.category, task.priority,
nextDate, task.due_time, task.assigned_to, task.created_by,
task.recurrence_rule
);
}
}
}
res.json({ data: { id: Number(req.params.id), status } });
} catch (err) {
console.error('[Tasks] PATCH /:id/status Fehler:', err);