fix: map Drizzle camelCase fields to frontend snake_case fields in reports API
This commit is contained in:
@@ -4,6 +4,22 @@ import { db, reports } from '@project-e/db';
|
|||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
function mapReport(report: Record<string, any>) {
|
||||||
|
return {
|
||||||
|
id: report.id,
|
||||||
|
title: report.title,
|
||||||
|
content: report.content || '',
|
||||||
|
report_type: report.reportType || report.report_type || 'custom',
|
||||||
|
date_range_start: report.dateRangeStart?.toISOString?.() || report.date_range_start || null,
|
||||||
|
date_range_end: report.dateRangeEnd?.toISOString?.() || report.date_range_end || null,
|
||||||
|
domain: report.domain || 'personal',
|
||||||
|
is_draft: report.isDraft ?? report.is_draft ?? false,
|
||||||
|
created: report.createdAt?.toISOString?.() || report.created || new Date().toISOString(),
|
||||||
|
updated: report.updatedAt?.toISOString?.() || report.updated || new Date().toISOString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const updateReportSchema = z.object({
|
const updateReportSchema = z.object({
|
||||||
title: z.string().min(1, 'Title is required').optional(),
|
title: z.string().min(1, 'Title is required').optional(),
|
||||||
content: z.string().optional(),
|
content: z.string().optional(),
|
||||||
@@ -29,7 +45,7 @@ export const GET = withAuth<RouteContext>(async (request: NextRequest, _user, co
|
|||||||
return createErrorResponse('NOT_FOUND', 'Report not found', 404);
|
return createErrorResponse('NOT_FOUND', 'Report not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json(report);
|
return NextResponse.json(mapReport(report));
|
||||||
});
|
});
|
||||||
|
|
||||||
// PATCH /api/reports/[id] — Update a report
|
// PATCH /api/reports/[id] — Update a report
|
||||||
@@ -58,7 +74,7 @@ export const PATCH = withAuth<RouteContext>(async (request: NextRequest, _user,
|
|||||||
return createErrorResponse('NOT_FOUND', 'Report not found', 404);
|
return createErrorResponse('NOT_FOUND', 'Report not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json(report);
|
return NextResponse.json(mapReport(report));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
return createErrorResponse('VALIDATION_ERROR', 'Invalid input', 400, error.issues);
|
return createErrorResponse('VALIDATION_ERROR', 'Invalid input', 400, error.issues);
|
||||||
|
|||||||
@@ -4,6 +4,23 @@ import { db, reports } from '@project-e/db';
|
|||||||
import { and, asc, desc, eq, ilike, or, sql } from 'drizzle-orm';
|
import { and, asc, desc, eq, ilike, or, sql } from 'drizzle-orm';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
// Map Drizzle DB fields to frontend-expected field names
|
||||||
|
function mapReport(report: Record<string, any>) {
|
||||||
|
return {
|
||||||
|
id: report.id,
|
||||||
|
title: report.title,
|
||||||
|
content: report.content || '',
|
||||||
|
report_type: report.reportType || report.report_type || 'custom',
|
||||||
|
date_range_start: report.dateRangeStart?.toISOString?.() || report.date_range_start || null,
|
||||||
|
date_range_end: report.dateRangeEnd?.toISOString?.() || report.date_range_end || null,
|
||||||
|
domain: report.domain || 'personal',
|
||||||
|
is_draft: report.isDraft ?? report.is_draft ?? false,
|
||||||
|
created: report.createdAt?.toISOString?.() || report.created || new Date().toISOString(),
|
||||||
|
updated: report.updatedAt?.toISOString?.() || report.updated || new Date().toISOString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const createReportSchema = z.object({
|
const createReportSchema = z.object({
|
||||||
title: z.string().min(1, 'Title is required').default('Untitled report'),
|
title: z.string().min(1, 'Title is required').default('Untitled report'),
|
||||||
content: z.string().optional().default(''),
|
content: z.string().optional().default(''),
|
||||||
@@ -60,7 +77,7 @@ export const GET = withAuth(async (request: NextRequest, _user) => {
|
|||||||
const totalItems = Number(countResult[0]?.count || 0);
|
const totalItems = Number(countResult[0]?.count || 0);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
items,
|
items: items.map(mapReport),
|
||||||
totalItems,
|
totalItems,
|
||||||
totalPages: Math.ceil(totalItems / perPage),
|
totalPages: Math.ceil(totalItems / perPage),
|
||||||
page,
|
page,
|
||||||
@@ -85,7 +102,7 @@ export const POST = withAuth(async (request: NextRequest, _user) => {
|
|||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
return NextResponse.json(report, { status: 201 });
|
return NextResponse.json(mapReport(report), { status: 201 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
return createErrorResponse('VALIDATION_ERROR', 'Invalid input', 400, error.issues);
|
return createErrorResponse('VALIDATION_ERROR', 'Invalid input', 400, error.issues);
|
||||||
|
|||||||
Reference in New Issue
Block a user