feat(api): admin all-users filtered CSV export
This commit is contained in:
@@ -5,6 +5,7 @@ import { db } from '../db/client';
|
||||
import { activities, user, workSessions } from '../db/schema';
|
||||
import { getSessionUser, isAdmin } from '../lib/require-user';
|
||||
import { toWorkSession } from '../lib/work-session';
|
||||
import { buildSessionsCsv } from '../lib/csv';
|
||||
|
||||
function computeDuration(startMs: number, endMs: number, paused: number): number {
|
||||
return Math.max(0, Math.round((endMs - startMs) / 1000) - paused);
|
||||
@@ -230,6 +231,41 @@ adminRoutes.get('/api/admin/report', async (c) => {
|
||||
});
|
||||
});
|
||||
|
||||
adminRoutes.get('/api/admin/export', async (c) => {
|
||||
const q = parseReportQuery(c);
|
||||
if (!q) return c.json({ error: 'Invalid query' }, 400);
|
||||
|
||||
const rows = await db
|
||||
.select(baseSelect)
|
||||
.from(workSessions)
|
||||
.leftJoin(activities, eq(workSessions.activityId, activities.id))
|
||||
.leftJoin(user, eq(workSessions.userId, user.id))
|
||||
.where(and(...buildSessionFilters(q)))
|
||||
.orderBy(asc(workSessions.startTime));
|
||||
|
||||
const csv = buildSessionsCsv(
|
||||
rows.map((r) => ({
|
||||
id: r.session.id,
|
||||
activityName: r.activityName,
|
||||
userName: r.userName,
|
||||
insoleType: r.session.insoleType,
|
||||
pairCount: r.session.pairCount,
|
||||
startTime: r.session.startTime,
|
||||
endTime: r.session.endTime,
|
||||
durationSeconds: r.session.durationSeconds,
|
||||
pausedSeconds: r.session.pausedSeconds,
|
||||
})),
|
||||
{ includeWorker: true },
|
||||
);
|
||||
|
||||
const fromDate = q.from.toISOString().slice(0, 10);
|
||||
const toDate = q.to.toISOString().slice(0, 10);
|
||||
return c.body(csv, 200, {
|
||||
'Content-Type': 'text/csv; charset=utf-8',
|
||||
'Content-Disposition': `attachment; filename="solelog-report_${fromDate}_${toDate}.csv"`,
|
||||
});
|
||||
});
|
||||
|
||||
// Manual create → always completed, source='manual', duration derived server-side.
|
||||
adminRoutes.post('/api/admin/sessions', async (c) => {
|
||||
const parsed = CreateManualSessionInput.safeParse(await c.req.json().catch(() => null));
|
||||
|
||||
Reference in New Issue
Block a user