Week 2: Validating, Learning, and Fixing Things Up
Validating the approach, polishing the first PR, and what testing thoroughly turned up along the way.
Week 2: Validating, Learning, and Fixing Things Up
Validating the approach, polishing the first PR, and what testing thoroughly turned up along the way.
Week 1 ended with a draft PR going up and a quiet hope that the approach would hold. Week 2 was about earning that confidence the honest way: by trying to poke holes in my own work.
If Week 1 was about getting the first row of real data on screen, Week 2 was about asking further questions.

Validating the approach
The whole point of putting up a draft PR early was to validate the direction before building more on top of it. So this week I spent real time with the dashboard the way a reviewer or an actual admin user would: filtering, paging, expanding rows, switching entity types, and watching what the backend actually returned at each step.
That kind of testing is slower and less glamorous than writing new features, but it is where the real information lives. A clean happy-path demo tells you almost nothing. The interesting findings only turn up once you start combining filters and walking through pages.
The good news is that the core approach held up well. The useAuditLogs SWR hook, the pure table component, the permission gate, and the server-side filter contract all behaved the way I had designed them to. Nothing structural needed to be torn out, which was a relief and a small vote of confidence in the plan the mentors and I had agreed on.
Polishing the first PR
With the structure validated, I used the rest of the week to tighten up the code so the first proper review would be about substance rather than rough edges. A few of the changes I am happiest with:
Simplified the error handling. The first version surfaced API errors through a toast notification, which needed a useRef and a dedicated useEffect just to avoid re-firing on every SWR revalidation. It worked, but it was a lot of machinery for what is really a display concern. I removed all of it in favour of a single inline notification that already lives in the render path. The component lost a good chunk of code and got easier to reason about in the process.
Typed the errors properly. While I was in there, I replaced an any cast on the fetch error with the framework's own FetchError type, so the 404 "module not installed" branch is now type-checked rather than guessed at.
Fixed how empty values render in the diff panel. The old/new value cells were using value || '—', which quietly replaced any falsy value with a placeholder. That is wrong for a value like 0 or an intentionally empty field that actually changed. I switched it to only show the placeholder when the value is genuinely an empty string, so the diff now tells the truth about what changed.
Kept the route and the breadcrumb in sync. The breadcrumb path was hardcoded, separately from the base path constant the rest of the app uses. I pointed it at the same constant so the two can never drift apart if the route ever changes.
Small correctness and cleanup. A pluralization fix so the count reads “1 item” instead of “1 items,” removing an unused import, and dropping the now-dead translation strings that the old toast had left behind.
None of these are headline features. They are the kind of changes that make a reviewer’s job easier, and that is exactly what I wanted the PR to feel like before the first real round of feedback.
Validating, and what it surfaced
Here is the find I am most glad I caught this week, because it is exactly the sort of thing a quick demo would sail right past.
While testing the dashboard thoroughly, I noticed that pagination does not work past the first page. When there are more results than fit on one page, page 1 looks perfect, but every page after it comes up empty. The frustrating part is that the pager still confidently says there is more to see, for example “Page 2 of 2.” So the table just looks like the data quietly disappeared. And if you also apply an entity type filter, page 2 onwards is always empty.
That mismatch is what makes it sneaky. The total count is correct, so the UI promises more pages, and then renders nothing. If you were only clicking around the first page during a demo, you would never see it.
Digging into the module source, the cause looks like the page offset being applied twice. The per-entity database query already skips page * size rows, and then the combined results get sliced by page * size a second time in memory. So for any page beyond the first, the second slice starts past the end of what the first step returned, and you get an empty list even though the count was calculated correctly further upstream.
What is next
While the Audit Log Dashboard PR is awaiting review, I do not want to sit idle. The backend endpoint for patient-specific audit log filtering is already in place, which means the groundwork exists for the next piece of the project: a patient-specific history tab.
So my plan for the coming days is to start researching that tab in earnest. How it should fit into the patient chart, what the existing patterns are for similar tabs, and how to reuse as much of the dashboard’s filtering and diff work as possible rather than reinventing it. Starting with research rather than code feels like the right move, especially given how much this week reinforced that understanding the problem well is most of the battle.
Thank you to Oliver and Manoj for the guidance so far.
Thanks for reading this💖 Regards Raj
메타데이터
- post_id
- c3d20fe06cf2
- slug
- week-2-validating-learning-and-fixing-things-up-c3d20fe06cf2
- url
- https://medium.com/@rjnt452/week-2-validating-learning-and-fixing-things-up-c3d20fe06cf2
- canonical_url
- https://medium.com/@rjnt452/week-2-validating-learning-and-fixing-things-up-c3d20fe06cf2
- author_url
- https://medium.com/@rjnt452
- status
- ok
- fetched_at
- 2026-06-17 08:20:12