Render real homepage stats - #84
Open
VidurShah wants to merge 1 commit into
Open
Conversation
Replace the hardcoded placeholders in the home screen's stat grid (12 new messages, 10 of 12 checklists, 11 referrals) with the signed-in patient's own numbers, so the tiles stop showing figures unrelated to the account. - Wire the Chat, Checklists and Referrals tiles to StreamBuilders, following the shape _buildCalendarCard already used: Chat counts unread messages from staff, Checklists counts unchecked items across non-archived lists, and Referrals counts every non-deleted referral regardless of status. - Add ChatService.streamUnreadCount, filtering server-side on isRead only. That equality-only query is covered by the automatic single-field index, whereas also filtering senderId would need a new composite index, so the sender check is done client-side. - Add ChatService.markMessagesRead and call it when the message list renders, so opening the chat actually clears the count. firestore.rules already lets each side flip isRead on messages they did not send, so this needs no rules or backend change. The write reuses the docs the list already streamed, is best-effort, and sits behind the existing doc-count guard so it cannot re-trigger itself. Closes #72
VidurShah
force-pushed
the
vidur/home-dynamic-stats
branch
from
August 19, 2026 20:24
3ed17b4 to
9096fba
Compare
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.
Problem
The home screen's stat grid rendered hardcoded placeholders —
newMessageCount = 12,completedChecklists = 10 / 12,activeReferrals = 11. Only the Calendar tile was wired to real data, so a patient saw three numbers that had nothing to do with their account. Closes #72.The Checklists and Referrals tiles were straightforward:
ChecklistService.streamCurrentUserChecklistsandReferralService.streamCurrentUserReferralsalready existed and already scoped to the current user. Unread messages was the one that needed new plumbing, and it came with two constraints:isReadandsenderIdserver-side would need a new composite index.firestore.indexes.jsononly carriestimestampfield overrides for the messages subcollection.mobile/libhas ever writtenisRead— the web console is the only side implementing read receipts today, so an unread badge would have stuck at its first value forever.Changes
lib/services/chat_service.dart— addedstreamUnreadCount(chatId), which filters server-side onisReadonly. That equality-only query is covered by the automatic single-field index; thesenderIdcheck runs client-side to avoid needing a composite one.streamCurrentUserUnreadCount()wraps it for callers that don't have a chat id — the chat document id is the uid, so no lookup is needed and a chat that doesn't exist yet simply streams 0. Also addedmarkMessagesRead(docs), which batchesisRead: trueonto messages the current user didn't send.lib/pages/home_page.dart— dropped the hardcoded fields and added_buildChatCard,_buildChecklistCardand_buildReferralsCard, each following the shape_buildCalendarCardalready used (waiting→Loading..., error or null → a neutral fallback, else the value). Chat readsNo new messages/N new message(s); Checklists counts unchecked items across all non-archived lists and readsAll caught up/N item(s) left; Referrals counts every non-deleted referral regardless of status and readsNo referrals/N referral(s). The services are held asfinalfields alongside the existing_eventServiceso the streams are created once perHomePagerather than on every rebuild.lib/pages/chat_page.dart— one unawaitedmarkMessagesReadcall inside_MessagesListState.build, in the existingdocs.length != _lastDocCountblock that already handles the auto-scroll side effect. It reuses the docs the list has already streamed, so read receipts cost no extra reads, and it can't loop: flippingisReadchanges document contents but not the count, so the guard blocks a re-fire.firestore.rulesalready permits this write — each side may flipisReadtotrueon messages they did not send — so nothing underbackend/changed, and neither didfirestore.indexes.jsonorpubspec.yaml.Notes / follow-ups
markMessagesReadis debug-logged and swallowed rather than surfaced — the patient did nothing wrong, and the write retries on the next snapshot anyway.isRead. The web console only marks messages read wheresenderId !== user.uid, i.e. patient-to-staff; mobile now marks the reverse. The sets are disjoint, so the single shared flag works — but it is a single flag, and a third participant on a chat would break that assumption.completedmust not change the count while soft-deleting one does.