Skip to content

Commit 5070fea

Browse files
fix: address code review feedback for trail conditions feature
- Use c.req.valid('json') instead of c.req.json() in createReport handler - Add PUT /api/trail-conditions/:reportId endpoint for updates - Log errors in SubmitConditionReportForm catch block - Use @ts-expect-error instead of @ts-ignore in useSubmitTrailConditionReport - Validate date string in formatRelativeTime to handle Invalid Date Co-authored-by: andrew-bierman <94939237+andrew-bierman@users.noreply.github.com>
1 parent 3509c34 commit 5070fea

File tree

4 files changed

+89
-4
lines changed

4 files changed

+89
-4
lines changed

apps/expo/features/trail-conditions/components/SubmitConditionReportForm.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ export function SubmitConditionReportForm({
7878
});
7979
Alert.alert(t('common.success'), t('trailConditions.reportSubmitted'));
8080
onSuccess?.();
81-
} catch (_e) {
81+
} catch (e) {
82+
console.error('Failed to submit trail condition report:', e);
8283
Alert.alert(t('common.error'), t('errors.tryAgain'));
8384
} finally {
8485
setIsSubmitting(false);

apps/expo/features/trail-conditions/components/TrailConditionReportCard.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ function formatRelativeTime(dateStr?: string): string {
1212
if (!dateStr) return '';
1313
const now = new Date();
1414
const date = new Date(dateStr);
15+
if (Number.isNaN(date.getTime())) return '';
1516
const diffMs = now.getTime() - date.getTime();
1617
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
1718
if (diffDays === 0) return 'Today';

apps/expo/features/trail-conditions/hooks/useSubmitTrailConditionReport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function useSubmitTrailConditionReport() {
1616
localUpdatedAt: timestamp,
1717
};
1818

19-
// @ts-ignore: Safe because Legend-State uses Proxy
19+
// @ts-expect-error: Safe because Legend-State uses Proxy
2020
trailConditionReportsStore[id].set(newReport);
2121

2222
return id;

packages/api/src/routes/trailConditions/reports.ts

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ const createReportRoute = createRoute({
137137
trailConditionRoutes.openapi(createReportRoute, async (c) => {
138138
const auth = c.get('user');
139139
const db = createDb(c);
140-
const data = await c.req.json();
140+
const data = c.req.valid('json');
141141

142142
if (!data.id) return c.json({ error: 'Report ID is required' }, 400);
143143

@@ -173,7 +173,90 @@ trailConditionRoutes.openapi(createReportRoute, async (c) => {
173173
});
174174

175175
// ------------------------------
176-
// List My Reports Route
176+
// Update Report Route
177+
// ------------------------------
178+
const updateReportRoute = createRoute({
179+
method: 'put',
180+
path: '/{reportId}',
181+
tags: ['Trail Conditions'],
182+
summary: 'Update a trail condition report',
183+
security: [{ bearerAuth: [] }],
184+
request: {
185+
params: z.object({ reportId: z.string().openapi({ example: 'tcr_123456' }) }),
186+
body: {
187+
content: {
188+
'application/json': {
189+
schema: CreateReportRequestSchema.omit({ id: true, localCreatedAt: true }).partial(),
190+
},
191+
},
192+
required: true,
193+
},
194+
},
195+
responses: {
196+
200: {
197+
description: 'Report updated successfully',
198+
content: { 'application/json': { schema: TrailConditionReportSchema } },
199+
},
200+
403: {
201+
description: 'Forbidden',
202+
content: { 'application/json': { schema: ErrorResponseSchema } },
203+
},
204+
500: {
205+
description: 'Internal server error',
206+
content: { 'application/json': { schema: ErrorResponseSchema } },
207+
},
208+
},
209+
});
210+
211+
trailConditionRoutes.openapi(updateReportRoute, async (c) => {
212+
const auth = c.get('user');
213+
const db = createDb(c);
214+
const reportId = c.req.param('reportId');
215+
const data = c.req.valid('json');
216+
217+
try {
218+
const existing = await db.query.trailConditionReports.findFirst({
219+
where: and(
220+
eq(trailConditionReports.id, reportId),
221+
eq(trailConditionReports.userId, auth.userId),
222+
),
223+
});
224+
225+
if (!existing) return c.json({ error: 'Report not found or unauthorized' }, 403);
226+
227+
const updateData: Record<string, unknown> = { updatedAt: new Date() };
228+
if ('trailName' in data) updateData.trailName = data.trailName;
229+
if ('trailRegion' in data) updateData.trailRegion = data.trailRegion ?? null;
230+
if ('surface' in data) updateData.surface = data.surface;
231+
if ('overallCondition' in data) updateData.overallCondition = data.overallCondition;
232+
if ('hazards' in data) updateData.hazards = data.hazards ?? [];
233+
if ('waterCrossings' in data) updateData.waterCrossings = data.waterCrossings ?? 0;
234+
if ('waterCrossingDifficulty' in data)
235+
updateData.waterCrossingDifficulty = data.waterCrossingDifficulty ?? null;
236+
if ('notes' in data) updateData.notes = data.notes ?? null;
237+
if ('photos' in data) updateData.photos = data.photos ?? [];
238+
if ('localUpdatedAt' in data)
239+
updateData.localUpdatedAt = data.localUpdatedAt ? new Date(data.localUpdatedAt) : new Date();
240+
241+
await db
242+
.update(trailConditionReports)
243+
.set(updateData)
244+
.where(
245+
and(eq(trailConditionReports.id, reportId), eq(trailConditionReports.userId, auth.userId)),
246+
);
247+
248+
const updated = await db.query.trailConditionReports.findFirst({
249+
where: eq(trailConditionReports.id, reportId),
250+
});
251+
252+
return c.json(updated!, 200);
253+
} catch (error) {
254+
console.error('Error updating trail condition report:', error);
255+
return c.json({ error: 'Failed to update trail condition report' }, 500);
256+
}
257+
});
258+
259+
// ------------------------------
177260
// ------------------------------
178261
const listMyReportsRoute = createRoute({
179262
method: 'get',

0 commit comments

Comments
 (0)