Skip to content

Public like counts on every card (#95 part B) - #105

Merged
Muawiya-contact merged 9 commits into
developfrom
feat/public-like-counts
Sep 5, 2026
Merged

Public like counts on every card (#95 part B)#105
Muawiya-contact merged 9 commits into
developfrom
feat/public-like-counts

Conversation

@Muawiya-contact

Copy link
Copy Markdown
Member

Part B of #95 — turn Like into a public like count ("how many people liked this card"), shown wherever a card appears, hidden at zero, and instant. Builds on the responsiveness fix in #104 (part A).

Data model — no new table

Likes are already stored per-user in concept_interactions.liked_at. The public count is just an aggregate; migration 0009 adds a by-concept partial index so it's fast (the existing index is keyed by user).

Design that keeps it responsive

The backend returns the count of other users' likes (excludes the viewer); the client adds the viewer's own like on top:

displayed = othersCount + (youLiked ? 1 : 0)

So a like/unlike is an instant +1 / −1 with no round trip, and it reconciles on the next load — no baseline bookkeeping.

Backend

  • 0009 index on concept_interactions (concept_id) where liked_at is not null.
  • like_count (others') added to /v1/daily, and to the learned and saved lists on /v1/me/state.
  • New test: the count excludes the viewer, counts another user, and rides the state lists. 89 tests pass.

Mobile

  • likeCount flows through Concept, LearnedRecord, SavedConcept.
  • New LikeCount badge (🔥 N), rendered on the Today card (next to the flame), History rows, and Saved rows.
  • Shown only when the total is ≥ 1 (hidden at 0), per your decision.
  • The count updates instantly on tap (uses Instant optimistic feedback for Like/Save/etc. (#95 part A) #104's immediate-optimistic machinery for the viewer's own like).

Decisions applied

  • Show at 1+ (hide only 0).
  • Everywhere a card shows (Today, History, Saved).
  • Not realtime — reflects everyone's likes as of the last load; refreshes on reload.

Ships as

Backend is additive (safe to deploy before the app; old apps ignore like_count). Mobile is JS-only (no native module) — ships over the air.

Verification

pytest → 89 passed. npx tsc --noEmit → clean.

Counting likes per concept needs an index keyed by concept_id (the existing one
is keyed by user_id). Partial on liked_at is not null so it only covers likes.
Return the count of likes by OTHER users on the day's concept; the client adds
the viewer's own like on top, so a like/unlike is an instant +/-1.
The like number is shown wherever a card appears (Today, History, Saved), so the
learned and saved rows now include the same others'-likes count.
Parse the server's others'-likes count into Concept.likeCount and into the
learned/saved records, so every surface can render it.
Add a small flame+number badge, and show it in the concept action bar next to
the like button: others' likes plus the viewer's own (optimistic), hidden at
zero. Tapping like ticks it +/-1 instantly.
The count appears wherever a card is shown, per the issue: each row adds the
viewer's own like to the server's others'-count and hides it at zero.
Match the codebase's memoisation pattern (cf. learnedIds in ProgressContext) so
the liked-set isn't rebuilt on every render.

@Muawiya-contact Muawiya-contact left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant