Admin: city comms, report chat composer, verification flow, jurisdiction and queue cleanups (shared 0.53.0) - #31
Conversation
…cleanup pin matches the token
…eeds-verification facet
… email, checks keep evidence
|
| verdict.mutate( | ||
| { id: report.id, verdict: "approved" }, | ||
| { | ||
| onSuccess: () => { | ||
| setApprovedLocally(true) | ||
| routeToJurisdiction(note) | ||
| }, |
There was a problem hiding this comment.
Keep approval and routing together
“Verify and send” persists approval before it starts the separate routing request. If routing fails, the report stays approved even though no jurisdiction received it, which can advance the reporter’s verification progress and remove the report from the state requiring routing. Make this one atomic server operation, or compensate by reversing approval when routing cannot complete. This must be addressed before merging.
Artifacts
Approval and routing failure harness
- The authored harness reproduces the page’s approval-then-route request sequence against the shared API client, showing the two operations are independent.
Successful approval and routing output
- The successful baseline records verdict then route and ends with the report approved and routed.
Routing failure after approval output
- The forced route failure records HTTP 503 while the report remains approved and unrouted, with no compensating request.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/src/features/reports/reports-page.tsx
Line: 609-615
Comment:
**Keep approval and routing together**
“Verify and send” persists approval before it starts the separate routing request. If routing fails, the report stays approved even though no jurisdiction received it, which can advance the reporter’s verification progress and remove the report from the state requiring routing. Make this one atomic server operation, or compensate by reversing approval when routing cannot complete. This must be addressed before merging.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| export function useReportChatHistory(id: string | null) { | ||
| return useQuery<ChatHistoryResponse>({ | ||
| queryKey: queryKeys.reports.chat(id ?? ""), | ||
| queryFn: () => api.reportMessages({ id: id as string, limit: REPORT_CHAT_LIMIT }), | ||
| queryFn: () => api.adminReportMessages({ id: id as string, limit: REPORT_CHAT_LIMIT }), |
There was a problem hiding this comment.
This request loads only the newest 50 messages and does not use the returned cursor. The discussion view offers no way to load older messages and presents the loaded-window length as the chat count, so operators cannot inspect or moderate earlier discussion on active reports. This is non-blocking, but it makes moderation incomplete and the displayed count misleading.
Artifacts
- The authored Vitest test simulates a 70-message cursor-paginated chat response and asserts the client request and discussion UI behavior, with the takeaway that only the first 50-message page is accessible.
- Captured output from running the narrow Vitest client/UI test in the admin workspace; it reports the simulated 70-message conversation receives and counts only 50 with no older-page control, confirming the finding.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/src/features/reports/use-reports.ts
Line: 123-126
Comment:
**Load older chat messages**
This request loads only the newest 50 messages and does not use the returned cursor. The discussion view offers no way to load older messages and presents the loaded-window length as the chat count, so operators cannot inspect or moderate earlier discussion on active reports. This is non-blocking, but it makes moderation incomplete and the displayed count misleading.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| <span className="meta" title={LOADED_TITLE}> | ||
| {loadedCount(activeCount, !!activeListQuery.hasNextPage)} | ||
| </span> | ||
| <span className="meta">{activeCount}</span> |
There was a problem hiding this comment.
The header displays the number of loaded mail rows as a bare total while “Load more” remains available. Operators can read that partial page length as the full queue size. This is non-blocking, but it gives an inaccurate view of outstanding mail; retain a “+” or “loaded so far” treatment, or show a server-provided total.
Artifacts
Mail pagination browser fixture
- The authored browser fixture simulates a paginated Mail response and captures the count before and after the second page loads.
Mail pagination browser output
- The rendered-state output shows count 2 with Load more available, then count 3 after the final page loads.
▶ Mail count before loading another page
- The recording shows a bare count of 2 while another Mail page remains available.
▶ Mail count after loading another page
- The recording shows the count changing to 3 after the remaining Mail page loads.
Mail pagination fixture server output
- The server output records the local rendered fixture used for the paginated Mail interaction.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/src/features/mail/mail-page.tsx
Line: 708
Comment:
**Clarify loaded mail count**
The header displays the number of loaded mail rows as a bare total while “Load more” remains available. Operators can read that partial page length as the full queue size. This is non-blocking, but it gives an inaccurate view of outstanding mail; retain a “+” or “loaded so far” treatment, or show a server-provided total.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| }, | ||
| "dependencies": { | ||
| "@civfix/shared": "^0.52.0", | ||
| "@civfix/shared": "^0.53.0", |
There was a problem hiding this comment.
This directly changes the @civfix/shared version range and refreshes the lockfile without adding a changeset. The repository directive requires dependency version changes to use the changeset workflow. This repository requirement must be satisfied before merging.
Rule Used: # civfix review rules civfix is a live civic-tech platform that will hold government contracts. Review every PR for correctness, security and performance. Flag real defects with evidence; skip style nits that lint already covers. ## Repos - **... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/package.json
Line: 18
Comment:
**Use the changeset workflow**
This directly changes the `@civfix/shared` version range and refreshes the lockfile without adding a changeset. The repository directive requires dependency version changes to use the changeset workflow. This repository requirement must be satisfied before merging.
**Rule Used:** # civfix review rules civfix is a live civic-tech platform that will hold government contracts. Review every PR for **correctness, security and performance**. Flag real defects with evidence; skip style nits that lint already covers. ## Repos - **... ([source](https://app.greptile.com/civfix/-/custom-context?memory=39a53925-3d93-4c82-980e-27b67393717d))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| /** | ||
| * The moderation tile leads with the server-side queue total when the summary carries one. When the | ||
| * field is absent (an older API) it leads with a plain label instead of the length of the two-row | ||
| * preview, which is not a count of anything. | ||
| */ |
There was a problem hiding this comment.
Remove new explanatory comments
This change adds a new explanatory block comment. The repository directive says new code must not add comments; the same new-comment pattern also appears in the government-claim presentation helpers and on SectionSummary.lead. Keep the implementation self-explanatory and remove the new comments. This repository requirement must be satisfied before merging.
Rule Used: # civfix review rules civfix is a live civic-tech platform that will hold government contracts. Review every PR for correctness, security and performance. Flag real defects with evidence; skip style nits that lint already covers. ## Repos - **... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/src/features/home/home-preview-presentation.ts
Line: 8-12
Comment:
**Remove new explanatory comments**
This change adds a new explanatory block comment. The repository directive says new code must not add comments; the same new-comment pattern also appears in the government-claim presentation helpers and on `SectionSummary.lead`. Keep the implementation self-explanatory and remove the new comments. This repository requirement must be satisfied before merging.
**Rule Used:** # civfix review rules civfix is a live civic-tech platform that will hold government contracts. Review every PR for **correctness, security and performance**. Flag real defects with evidence; skip style nits that lint already covers. ## Repos - **... ([source](https://app.greptile.com/civfix/-/custom-context?memory=39a53925-3d93-4c82-980e-27b67393717d))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| --cat-trash: #776C60; | ||
| --cat-recycling: #63A45A; | ||
| --cat-graffiti: #9B7ED9; | ||
| --cat-hazard: #E4574A; | ||
| --cat-encampment: #3E9E8E; | ||
| --cat-water: #74A9D8; | ||
| --cat-other: #8D8577; | ||
| --cat-cleanup: #D9A21B; |
There was a problem hiding this comment.
This change replaces the cleanup category token reference with a raw hex value while retaining a literal category palette for changed presentation. The frontend styling directive requires design tokens and prohibits new raw hex colors. Source the category colors from the shared category-color mechanism or existing semantic variables. This repository requirement must be satisfied before merging.
Rule Used: # civfix review rules civfix is a live civic-tech platform that will hold government contracts. Review every PR for correctness, security and performance. Flag real defects with evidence; skip style nits that lint already covers. ## Repos - **... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/src/styles/colors-and-type.css
Line: 93-100
Comment:
**Use category color tokens**
This change replaces the cleanup category token reference with a raw hex value while retaining a literal category palette for changed presentation. The frontend styling directive requires design tokens and prohibits new raw hex colors. Source the category colors from the shared category-color mechanism or existing semantic variables. This repository requirement must be satisfied before merging.
**Rule Used:** # civfix review rules civfix is a live civic-tech platform that will hold government contracts. Review every PR for **correctness, security and performance**. Flag real defects with evidence; skip style nits that lint already covers. ## Repos - **... ([source](https://app.greptile.com/civfix/-/custom-context?memory=39a53925-3d93-4c82-980e-27b67393717d))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Comments Outside DiffThese findings sit on lines the diff does not cover, so they could not be posted inline. Each one leaves this list once its file changes.
|
What changed
Operators can now talk to a report's neighbours from the admin dashboard: the report's "Chat" panel loads for real and has a box to post into it. The verification buttons on a report tell the truth about what they do and an "Approve" button is back for reports that cannot be sent to a city. The Jurisdictions detail's "Save & route" now keeps the operator note and the "@handle" it used to throw away, the Reports / Moderation / Users queue chips now count and filter on the server, and the dashboard's "Moderation" and "Mail" tiles lead with real totals. Admin only — nothing changes on web or mobile.
Before you start
Verify
[Admin]
Regression
Working the reports queue — [Admin]
One report end to end — [Admin]
Jurisdictions detail — [Admin]
Moderation queue and gov claims — [Admin]
Mail — [Admin]
Users — [Admin]
Dashboard — [Admin]
Not covered