Skip to main content

Catalog / Earn / Today Restructure — Design Spec

Date: 2026-07-21 Status: Draft for owner review Branch target: feat/mvp1-personas-authz (or a fresh feature branch)

Goal

Make the earning experience personal and actionable for each member, make Today a family dashboard for parents, and give admins a single Manage surface for every catalog type plus a badged review queue for kids' submitted suggestions.

This is mostly reassembly of existing pieces (claim/join, submit-completion, member-request-for-4-types, editor sheets, DsSegmented tabs all already exist) plus four genuine gaps. No new SDK domain verbs are required for the core flows.

Confirmed decisions (owner)

  1. Earn + Rewards stay separate member tabs (not merged into one tabbed page).
  2. Everything on Earn/Rewards is tied to the specific user — the member-switcher is kept but defaults to self.
  3. The one tabbed page is the Admin Manage surface — tabs for Rewards · Activities · Chores · Bounties (4 tabs, no dedicated Recommendations tab) — and it replaces today's separate "Manage Rewards" / "Manage Activities" admin rows.
  4. Recommendations = member-submitted ChoreRequests (kids can already propose any of the 4 types). Submit moves onto the Earn (chore/bounty) and Rewards (activity/reward) tabs as a "provide feedback / suggest" affordance → the suggestion section is removed from Household. Review is inline: pending suggestions of a type render at the top of that type's Manage list (approve/reject there). A badge on the Manage row in the More tab shows when anything is pending. (This is NOT the AI recommend sheet — that stays as-is.)
  5. Today is a role-personalized high-level dashboard (not the do-it screen):
    • admin / owner / parent (any "manager") → the whole family (all members' rows) — confirmed 2026-07-22
    • plain member (non-admin, non-parent, incl. kids) → their own + family goals Earn/Rewards are the action-oriented member pages; the Today/Earn check-off overlap is intentional (two entry points, same action).

Global constraints

  • FVM only (fvm flutter/fvm dart); one data path (Bloc → Repository → Client facade → Service → Adapter); presentation never imports supabase/drift.
  • Tabs use the existing DsSegmented<T> atom (no Flutter TabBar); cards reuse CatalogItemCard/EarnChoreCard/reward cards; admin pages follow the RewardsManagementPage scaffold.
  • Suite baselines must not drop (app 757 / SDK 1163 / DS 287 at spec time).
  • No brand strings in package/class names; all copy via Strings.

Architecture — reuse map (from codebase exploration)

Reuse as-is:

  • CatalogBloc already loads all four types + eligibility + wallet + claim state; both Earn and Rewards tabs instantiate it.
  • Interaction seams wired: CatalogBountyClaimed (join/claim), CatalogRewardRedeemRequested, CatalogActivityRedeemRequested, submitCompletion (Today), requestChore (member submit, 4 types), approveChoreRequest / rejectChoreRequest (admin resolution).
  • Models: Chore.assignedMemberIds/assignedMemberIdsUnion (assignment), ChoreKind.expectation/bounty, claimedByMemberIds/canClaimBounty()/hasJoined()/isMultiClaimFull() (claim state), ChoreRequest.itemType (chore/bounty/activity/reward discriminator).
  • Admin scaffold: RewardsManagementPage/ActivitiesManagementPage (list + editor sheet); _AdminRow hub pattern.

Genuine gaps to build:

  1. "Assigned to me / To-Do" projectionCatalogState has no assignedToMe getter (pure filter on chores by assignedMemberIdsUnion + selected member). No SDK change.
  2. Submit from EarnCatalogBloc has no completion-submit event; logic lives in TodayChoresBloc._onCompletionSubmitted. Add a CatalogChoreCompletionSubmitted event reusing ChoresRepository.submitCompletion.
  3. Nav / section badge — no badge mechanism exists; DsNavDestination carries none. Need a pending-recommendations count propagated to the admin surface (and optionally the nav).
  4. Chores & Bounties admin list page — none exists (chore CRUD is only the ChoreEditorRoute via FAB/per-row). Build a management page mirroring RewardsManagementPage, reusing the existing chore editor sheet/route.
  5. Manage tabs are cross-bloc today — Rewards uses RewardsBloc, Activities uses ActivitiesBloc, chores use CatalogBloc/ChoreEditorBloc. The tabbed Manage page hosts these under one scaffold with a DsSegmented type selector.
  6. Recommendations queue is on the Household tab today (ChoreRequestsSection, MembersBloc page-scoped). Move/surface a variant into Manage; needs a shell- or page-scoped requests source.

Surface designs

1. Today — role-personalized high-level dashboard

Today is the centralized overview, scoped by the viewer's role (NOT the action surface — that's Earn/Rewards):

  • manager (admin role OR owner OR parent/co-parent): the whole family — all members' rows, reusing the existing grouping (#190). Admins/parents see everyone.
  • plain member (non-admin, non-parent, incl. kids): their own items + family goals (shared household goals, GoalScope.family).
  • Single rule: "if the viewer is a manager (admin/owner/parental) or unknown → show the full roster; else → the viewer's own row + family goals." Implemented bloc-side in TodayChoresBloc (_deriveViewerScope), leaving the widget a pure renderer and _tailor() untouched.
  • Done-states already correct per the shipped local-day reset fix. Reuse the existing selected-member submit/approve flow for a parent acting on a child's row.

2. Earn tab — personal to-do + joinable

  • Reframe from "all chores greyed by eligibility" to "what's mine + what I can join."
  • My To-Do: chores assigned to the active member (assignedMemberIdsUnion.contains(memberId)), rendered as checkable/submittable rows — the actual submitCompletion happens here (new CatalogChoreCompletionSubmitted event), not only on Today. Applies to parents too (a parent checks off their own assigned chores here).
  • Joinable: open bounties / claimable chores the member hasn't joined (canClaimBounty / !hasJoined), each with a Join affordance (existing CatalogBountyClaimed).
  • Member-switcher retained, defaults to self.
  • Keep the existing DsSegmented filter (All / To-Do / Joinable / …) as the in-tab control.
  • Suggest affordance: a "provide feedback / suggest" entry to propose a chore or bounty (relocated requestChore flow) — replaces the Household suggestion section for these types.

3. Rewards tab — personal

  • Show the activities & rewards available/eligible to the active member, redeemable inline (existing redeem events). Personalized to the selected user (default self).
  • Suggest affordance: a "provide feedback / suggest" entry to propose an activity or reward (relocated requestChore flow) — replaces the Household suggestion section for these types.

4. Admin — unified Manage page

  • New page under /admin (AdminGuard + MustChangePasswordGuard) with a top DsSegmented selector: Rewards · Activities · Chores · Bounties (4 tabs; recommendations are inlined, not a tab).
  • Each type tab = [pending suggestions of this type at the TOP (approve/reject inline)] then the existing management list (add button + list + editor sheet). Rewards/Activities reuse RewardsBloc/ActivitiesBloc; Chores and Bounties get a new ChoresManagementPage-equivalent list (reusing the chore editor sheet/route; Bounties = ChoreKind.bounty filter).
  • Replaces the standalone "Manage Rewards" / "Manage Activities" hub rows with one "Manage catalog" row in More (the tabbed page). Keeps the existing management pages' logic; just re-hosts them under the tabbed shell. The Manage row carries a pending-suggestions badge.

5. Recommendations (member suggestions) — submit on Earn/Rewards, review inline in Manage, badge in More

  • Submit (member side): a "provide feedback / suggest" affordance on the Earn tab (propose a chore/bounty) and the Rewards tab (propose an activity/reward), reusing the existing requestChore flow (ChoreRequest.itemType). The current suggestion section on the Household tab is removed (its _RequestChoreDialog logic relocates to Earn/Rewards).
  • Review (admin side): pending ChoreRequests of a given type appear at the top of that type's Manage list, each with Approve / Reject (existing approveChoreRequest/rejectChoreRequest; approval routes to the right create verb by itemType). No separate Recommendations tab or page.
  • Badge: a pending-count badge on the Manage row in More (aggregate across all four types). Needs a pending-count source surfaced to the More/Manage surface (a small shell/page-scoped requests cubit, or extend an existing bloc) and a badge affordance on the _AdminRow widget (which currently has none).

Proposed phasing (plan will task-break)

  • Phase A — Today role-personalized dashboard: the single "own (+children if admin / +family goals if member)" rule; audience by role/participation. (Small, self-contained.)
  • Phase B — Earn personalization + submit + join: assignedToMe state, To-Do/Joinable sections, CatalogChoreCompletionSubmitted, switcher default-self. Rewards personalization.
  • Phase C — Admin Manage consolidation: tabbed page (4 tabs) hosting Rewards/Activities + new Chores/Bounties management; replace the two hub rows with one "Manage catalog" row in More.
  • Phase D — Recommendations relocation + inline review + badge: move requestChore submit onto Earn/Rewards + remove the Household suggestion section; render pending suggestions at the top of each Manage type list with approve/reject; pending-count badge on the More→Manage row (badge affordance added to _AdminRow).

Each phase is independently shippable and testable.

Testing

  • Bloc tests: assignedToMe projection; CatalogChoreCompletionSubmitted happy/blocked; join/claim eligibility; recommendations approve/reject routing per itemType; badge count.
  • Widget/flow tests: parent Today shows all members incl parents; kid Today personal; Earn To-Do check-off; Manage tab switching; badge appears on pending.
  • Reuse existing test doubles (MockClient, in-memory adapter, testAppBuilder).

Resolved (owner, 2026-07-21)

  1. Recommendations: NOT a dedicated tab — pending suggestions render at the top of each type's Manage list; badge on the More→Manage row. ✅
  2. Household requests section: moved entirely off Household (submit relocates to Earn/Rewards; review to Manage). ✅
  3. Badge scope: the More→Manage row only (no member-tab bottom-nav badge). ✅
  4. Earn ↔ Today overlap: intentional — check-off on both. ✅

Resolved (owner, 2026-07-22)

  • Today scope: managers (admin/owner/parent) see the whole family; only a plain non-admin non-parent member is narrowed to self + family goals. No oversight toggle. ✅