Fix Todo module: ID mismatches, overdue filter, Discord webhook settings
Deploy HouseHub / deploy (push) Successful in 2s

- Rewrite todo.php with correct element IDs matching todo.js
- Fix sidebar: fully dynamic rendering (no more static nav items)
- Fix quick-add: list selector added, Enter key works correctly
- Fix modals: todo-form-*, list-form-name, list-icon-opts IDs
- Fix overdue filter missing from API (list_id=overdue)
- Add settings modal (⚙️) with Discord webhook URL field
- Add settings action in API (GET/PUT via pf_notes table)
- Discord webhook: notify on task create and task done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
perco
2026-05-12 14:46:32 +02:00
co-authored by Claude Sonnet 4.6
parent b97cba6e75
commit 7790375c01
3 changed files with 187 additions and 124 deletions
+44 -4
View File
@@ -19,6 +19,17 @@ function tOk($d) { echo json_encode(['ok' => true, 'data' => $d], JSON_UNESCAPE
function tErr($m, $c = 400) { http_response_code($c); echo json_encode(['ok' => false, 'error' => $m]); exit; }
function tBody() { return json_decode(file_get_contents('php://input'), true) ?? []; }
function discordNotify(PDO $pdo, string $msg): void {
$s = $pdo->prepare("SELECT content FROM pf_notes WHERE note_type='todo_settings' AND reference_id='webhook_discord'");
$s->execute(); $url = $s->fetchColumn();
if (!$url) return;
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>4,
CURLOPT_HTTPHEADER=>['Content-Type: application/json'],
CURLOPT_POSTFIELDS=>json_encode(['username'=>'HouseHub Todo','content'=>$msg])]);
curl_exec($ch); curl_close($ch);
}
// ── LISTS ──────────────────────────────────────────────────────────────────────
if ($action === 'lists') {
if ($method === 'GET') {
@@ -71,14 +82,17 @@ if ($action === 'todos') {
} elseif ($list_id === 'upcoming') {
$where[] = 't.due_date >= CURDATE()';
$where[] = 't.done = 0';
} elseif ($list_id === 'overdue') {
$where[] = 't.due_date < CURDATE()';
$where[] = 't.done = 0';
} elseif ($list_id === 'done') {
$where[] = 't.done = 1';
} else {
$where[] = 't.list_id = ?'; $params[] = $list_id;
}
if (!$show_done && $list_id !== 'done') {
if (!$show_done && !in_array($list_id, ['done', 'overdue'])) {
$where[] = 't.done = 0';
} elseif ($list_id === 'done') {
$where[] = 't.done = 1';
}
if ($priority) { $where[] = 't.priority = ?'; $params[] = $priority; }
@@ -105,7 +119,10 @@ if ($action === 'todos') {
]);
$id = (int)$pdo->lastInsertId();
$new = $pdo->prepare("SELECT t.*, l.name as list_name, l.color as list_color, l.icon as list_icon FROM pf_todos t LEFT JOIN pf_todo_lists l ON l.id = t.list_id WHERE t.id=?");
$new->execute([$id]); tOk($new->fetch());
$new->execute([$id]);
$row = $new->fetch();
discordNotify($pdo, "📋 **Nouvelle tâche** : " . $title . ($row['list_name'] ? " _(". $row['list_name'] .")_" : ""));
tOk($row);
}
if ($method === 'PUT') {
@@ -117,6 +134,11 @@ if ($action === 'todos') {
$done = $d['done'] ? 1 : 0;
$pdo->prepare("UPDATE pf_todos SET done=?, done_at=?, updated_at=NOW() WHERE id=?")
->execute([$done, $done ? date('Y-m-d H:i:s') : null, $id]);
if ($done) {
$t = $pdo->prepare("SELECT title FROM pf_todos WHERE id=?"); $t->execute([$id]);
$row = $t->fetch();
if ($row) discordNotify($pdo, "✅ **Tâche terminée** : " . $row['title']);
}
tOk(['done' => $done]);
}
@@ -145,4 +167,22 @@ if ($action === 'stats') {
]);
}
// ── SETTINGS ───────────────────────────────────────────────────────────────────
if ($action === 'settings') {
if ($method === 'GET') {
$rows = $pdo->query("SELECT reference_id, content FROM pf_notes WHERE note_type='todo_settings'")->fetchAll();
$s = [];
foreach ($rows as $r) $s[$r['reference_id']] = $r['content'];
tOk($s);
}
if ($method === 'PUT') {
$d = tBody();
foreach ($d as $key => $val) {
$pdo->prepare("INSERT INTO pf_notes (note_type, reference_id, content) VALUES ('todo_settings',?,?) ON DUPLICATE KEY UPDATE content=?")
->execute([$key, $val ?? '', $val ?? '']);
}
tOk(['updated' => true]);
}
}
tErr('Action inconnue', 404);