feat(scheduling): persist notifications, batch notify flow, dedup protection

- Add tab_scheduling_notifications table with bootstrap via ensureSchedulingTables()
- Notify endpoint rewritten: dedup by (suggestion_id, candidate_plate), history list, PATCH /:id for execute/cancel lifecycle
- Batch notify endpoint returns success/skipped/failed counts
- Suggestions response now carries notificationId + notificationStatus per candidate (joined from active-notification map)
- UI: select mode with checkboxes, floating action bar, confirmation modal listing each swap; already-notified items are dimmed and skipped
- Detail view badges show sent/executed state, preventing duplicate notify

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-16 23:43:21 +08:00
parent 31716c6547
commit 3ef0d4edfa
12 changed files with 614 additions and 33 deletions

View File

@@ -6,6 +6,7 @@ import dotenv from 'dotenv';
import vehiclesRouter from './routes/vehicles.js';
import mileageRouter from './routes/mileage/index.js';
import schedulingRouter from './routes/scheduling/index.js';
import { ensureSchedulingTables } from './routes/scheduling/db-schema.js';
import authRouter from './auth/login.js';
import { authMiddleware } from './auth/middleware.js';
@@ -34,6 +35,7 @@ app.use('/*', serveStatic({ root: './dist', path: 'index.html' }));
const port = Number(process.env.SERVER_PORT) || 3001;
console.log(`Server starting on port ${port}...`);
ensureSchedulingTables().catch(e => console.error('scheduling bootstrap error:', e));
serve({ fetch: app.fetch, port }, () => {
console.log(`Server running at http://localhost:${port}`);
});