feat: upload/recipe/job API routes + Klarbild visual identity

- api: /uploads (multipart, HEIC, 25MB guard, S3), /recipes (GET/POST),
  /jobs (create+snapshot+enqueue, list), /jobs/:id (status+items),
  /jobs/:id/:action (pause/resume/cancel/retry-failed), /items/:id/retry
- design: adopt Till mockup identity — Space Grotesk + Space Mono (self-hosted,
  no google/US), blue accent, paper/card, registration-mark motif; OKLCH tokens
- verified: astro build passes
This commit is contained in:
till committed 2026-07-23 11:47:27 +00:00
1 parent 577b13f680
commit c12d55368c
10 files changed
+285 -46

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
import type { APIRoute } from 'astro';
import { one, query } from '../../../../lib/db';
import { enqueue } from '../../../../lib/queue';
export const prerender = false;
const json = (b: unknown, s = 200) =>
new Response(JSON.stringify(b), { status: s, headers: { 'Content-Type': 'application/json' } });
export const POST: APIRoute = async ({ params, locals }) => {
if (!locals.user) return new Response('Unauthorized', { status: 401 });
const item = await one<{ id: string; job_id: string }>(
'SELECT id, job_id FROM items WHERE id=$1', [params.id]);
if (!item) return json({ error: 'Nicht gefunden.' }, 404);
await query(`UPDATE items SET status='queued', error_message=NULL WHERE id=$1`, [item.id]);
await query(`UPDATE jobs SET status='queued' WHERE id=$1 AND status IN ('done','paused')`, [item.job_id]);
await enqueue({ itemId: item.id, jobId: item.job_id });
return json({ ok: true });
};