{{ message }}
Repository navigation
The Inquiries badge counts what nobody has opened - #71
Merged
Merged
Conversation
It counted everything unresolved -- New, Contacted and Pending -- so it lit up the moment an enquiry arrived and stayed lit for days while somebody waited on a callback. A number that is always on is a number nobody reads, and the morning it says 3 looks like every other morning. Read and resolved are different questions. Status says where an enquiry got to; viewed_at says whether anybody has seen it. The badge now asks the second, and opening an enquiry is what answers it -- the count clears itself the moment the detail opens, without waiting for a status change. The stamp is written once. Opening the same enquiry again does not move it, so "when was this first picked up" stays answerable, and it records who looked. In the list, an unopened enquiry gets a gold edge and an "Unread" pill, so the ones still needing a first look are findable and not only countable. Nothing is marked until the column exists: without the migration every viewed_at reads as null, which is indistinguishable from never opened, and the whole list would have claimed to be unread. The migration backfills everything already dealt with as seen. Without it the badge would light up with the entire history the first time the panel loads after the update -- exactly the noise this removes. The three helpers live in src/enquiry.php rather than in the endpoint, so they can be tested without a session or a router, and so the alerts endpoint can use the same count later. Tested: 18 browser checks and 17 server checks, plus the existing suites. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0128YzbhrfGdegUSc9RrARRf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

The badge counted everything unresolved — New, Contacted and Pending — so it lit up the moment an enquiry arrived and stayed lit for days while somebody waited on a callback. In the screenshot that prompted this, ENQ-2026-0004 had already been contacted and the sidebar still said 1. A number that is always on is a number nobody reads, and the morning it says 3 looks like every other morning.
Read and resolved are different questions. Status says where an enquiry got to;
viewed_atsays whether anybody has seen it. The badge now asks the second, and opening an enquiry is what answers it — the count clears the moment the detail opens, without waiting for a status change.What changed
enquiries.viewed_atandviewed_by, with the badge countingviewed_at IS NULLover the whole table — the list on screen is filtered, the badge is not.WHERE ... AND viewed_at IS NULLmeans opening the same enquiry again does not move it, so when was this first picked up stays answerable. It records who looked.getendpoint returns the new count alongside the enquiry, so the badge is right the moment the modal appears rather than after the list behind it refreshes.viewed_atreads as null, which is indistinguishable from never opened, and the whole list would have claimed to be unread — so the list response says whether the database tracks reading at all.src/enquiry.phprather than living in the endpoint, so they can be tested without a session or a router, and so the alerts endpoint can reuse the count later.One note on the guard:
getis a GET, so it uses the read guard, not the write one — passing the write guard would have demanded a POST and broken every enquiry detail. Marking it read is a side effect of reading it, the way opening a message marks it read, and the worst a forged request could do is clear a badge for somebody already signed in.Tested
One thing on your side
The database password is still in this repository's git history and has not been rotated. Change it in hPanel → Databases, then put the new one in
nitesha-config/config.phpabove the document root. Nothing in the panel will work between the two steps, so do them together.🤖 Generated with Claude Code
https://claude.ai/code/session_0128YzbhrfGdegUSc9RrARRf
Generated by Claude Code