Web app ready

This commit is contained in:
2026-06-06 17:08:04 +02:00
parent ff187a5bd4
commit 3e127afbae
39 changed files with 2622 additions and 123 deletions
+18
View File
@@ -0,0 +1,18 @@
import { NextResponse } from 'next/server';
import db from '@/lib/db';
export const dynamic = 'force-dynamic';
type Params = { params: Promise<{ id: string }> };
export async function POST(_req: Request, { params }: Params) {
const { id } = await params;
const tx = db.transaction(() => {
const row = db.prepare('UPDATE counters SET value = value - 1 WHERE id = ? AND value > 0 RETURNING *').get(Number(id));
if (row) db.prepare('INSERT INTO events (counter_id, delta, created_at) VALUES (?, -1, ?)').run(Number(id), Date.now());
return row;
});
const result = tx();
if (!result) return NextResponse.json({ error: 'Not found' }, { status: 404 });
return NextResponse.json(result);
}
+31
View File
@@ -0,0 +1,31 @@
import { NextResponse } from 'next/server';
import db from '@/lib/db';
export const dynamic = 'force-dynamic';
type Params = { params: Promise<{ id: string }> };
export async function GET(_req: Request, { params }: Params) {
const { id } = await params;
const counter = db.prepare('SELECT * FROM counters WHERE id = ?').get(Number(id));
if (!counter) return NextResponse.json({ error: 'Not found' }, { status: 404 });
const cutoff = Date.now() - 365 * 24 * 60 * 60 * 1000;
const dailyActivity = db.prepare(`
SELECT
date(created_at / 1000, 'unixepoch', 'localtime') AS date,
SUM(delta) AS value
FROM events
WHERE counter_id = ? AND created_at >= ?
GROUP BY date
HAVING SUM(delta) > 0
ORDER BY date ASC
`).all(Number(id), cutoff);
const allTimeTotal = (db.prepare(
'SELECT COALESCE(SUM(delta), 0) AS total FROM events WHERE counter_id = ?'
).get(Number(id)) as { total: number }).total;
return NextResponse.json({ counter, dailyActivity, allTimeTotal });
}
+18
View File
@@ -0,0 +1,18 @@
import { NextResponse } from 'next/server';
import db from '@/lib/db';
export const dynamic = 'force-dynamic';
type Params = { params: Promise<{ id: string }> };
export async function POST(_req: Request, { params }: Params) {
const { id } = await params;
const tx = db.transaction(() => {
const row = db.prepare('UPDATE counters SET value = value + 1 WHERE id = ? RETURNING *').get(Number(id));
if (row) db.prepare('INSERT INTO events (counter_id, delta, created_at) VALUES (?, 1, ?)').run(Number(id), Date.now());
return row;
});
const result = tx();
if (!result) return NextResponse.json({ error: 'Not found' }, { status: 404 });
return NextResponse.json(result);
}
+49
View File
@@ -0,0 +1,49 @@
import { NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
import db, { UPLOADS_DIR } from '@/lib/db';
export const dynamic = 'force-dynamic';
type Params = { params: Promise<{ id: string }> };
export async function GET(_req: Request, { params }: Params) {
const { id } = await params;
const counter = db.prepare('SELECT * FROM counters WHERE id = ?').get(Number(id));
if (!counter) return NextResponse.json({ error: 'Not found' }, { status: 404 });
return NextResponse.json(counter);
}
export async function PUT(request: Request, { params }: Params) {
const { id } = await params;
const body = await request.json();
const existing = db.prepare('SELECT * FROM counters WHERE id = ?').get(Number(id)) as Record<string, unknown> | undefined;
if (!existing) return NextResponse.json({ error: 'Not found' }, { status: 404 });
const name = body.name?.trim() ?? existing.name;
const value = body.value !== undefined ? body.value : existing.value;
const group_id = body.group_id !== undefined ? body.group_id : existing.group_id;
const image_path = body.image_path !== undefined ? body.image_path : existing.image_path;
db.prepare(
'UPDATE counters SET name = ?, value = ?, group_id = ?, image_path = ? WHERE id = ?'
).run(name, value, group_id, image_path, Number(id));
const updated = db.prepare('SELECT * FROM counters WHERE id = ?').get(Number(id));
return NextResponse.json(updated);
}
export async function DELETE(_req: Request, { params }: Params) {
const { id } = await params;
const existing = db.prepare('SELECT * FROM counters WHERE id = ?').get(Number(id)) as Record<string, unknown> | undefined;
if (!existing) return NextResponse.json({ error: 'Not found' }, { status: 404 });
// Remove associated image if present
if (existing.image_path) {
const imgFile = path.join(UPLOADS_DIR, path.basename(existing.image_path as string));
try { fs.unlinkSync(imgFile); } catch { /* ignore missing file */ }
}
db.prepare('DELETE FROM counters WHERE id = ?').run(Number(id));
return new NextResponse(null, { status: 204 });
}