Skip to content

[Feature] Create a Next Task component #246

Open
0 of 2 issues completed
Open

Description

@goodbounties-nanoclaw-agent

Feature summary

Add a reusable "Next Task" component to GoodWidget that restores the post-UBI-claim
feedback loop lost when goodwallet was rebuilt (never existed in gooddapp either):
after a user completes an action (initially claim), show a modal/bottom-sheet with a
single, dynamically-managed CTA (title, copy, image sourced externally) pointing the
user at a next task — voting, a community highlight, etc.

Problem or opportunity

The old goodwallet showed a feedback-loop modal after claiming UBI, nudging users
toward a next action (protocol/community highlight). That flow didn't carry over to
the new goodwallet and was never built in gooddapp. We want it back, but built as a
reusable primitive from the start — attachable to any widget's user action, not
hardcoded to claim — with easy, dynamic management of which CTA shows, and analytics
to measure whether it works.

Proposed solution

  1. Component: a NextTaskModal/NextTaskCard composition in packages/ui,
    built from existing primitives (Drawer/Dialog, Card/GlowCard, Button) —
    no existing CTA-card component to extend, this is new (same pattern as [Feature]: Add Data Table component #146 Data
    Table / [Feature] Scorecard: add subtitle prop #223 Scorecard: composition of existing primitives, full prop contract
    documented in the Plan sub-issue).
  2. Trigger: a shared hook (e.g. useNextTaskTrigger, home TBD — likely
    packages/core) any widget calls after a user action succeeds. Today the only
    precedent is narrow, single-widget callbacks on CitizenClaimWidget
    (onClaimSuccess/onClaimError) — this generalizes that pattern instead of adding
    another one-off callback.
  3. Content fetch: CTA title/copy/image come from an external, dynamically-updatable
    source; everything else (badge text, headline, dismiss copy) stays as in-app
    defaults per the design reference. Open decision: what that external source is.
    GoodWidget itself has no existing remote-config/CMS mechanism — confirmed absent.
    Need Laurence to confirm whether there's existing GoodDollar-level infra to reuse
    before we pick something net-new (constraint from Oliseh: prefer free/simple,
    supports dynamic updates).
  4. Navigation: if the CTA's target maps to a widget already available in the
    same app/page, load it in-app; otherwise fall back to an external link, on both
    web and native. GoodWidget has no shared cross-widget navigation abstraction
    today, so "in-app" likely means the host app passes a canHandle/navigateTo
    callback into the component. For native, Linking.openURL is already used
    elsewhere (packages/governance-widget/src/hooks/useGovernanceMembership.ts) and
    can be reused directly for the external-link fallback.
  5. Analytics: no existing tracking convention anywhere in GoodWidget — confirmed
    absent repo-wide. Proposing the component emit simple lifecycle events (shown,
    CTA clicked, dismissed) via callback props, so the host app wires them to whatever
    GoodDollar already uses at the org level. Open decision: pending Laurence —
    does that org-level tool exist, or is this greenfield too?
  6. Open scope question: PR Citizen-claim-widget: contract-sourced how-it-works copy (invite rewards) #191 flagged "native-app redirect handling for the
    claim widget" as a separate, still-open research item. Need Laurence to confirm
    whether that overlaps with this bounty's native external-link fallback, or is
    unrelated and should stay out of scope.

Required states, flows, and behaviors

  • Trigger fires after a watched action succeeds (e.g. claim) → fetch external CTA content.
  • Fetch succeeds → show modal: status indicator (host-provided, e.g. "Claim completed"),
    default headline/supporting copy, CTA card (badge, image, title, description from the
    external source, primary button), dismiss ("Skip for now").
  • Fetch fails or returns no CTA → modal does not show (no broken/empty state) — flagged
    as an assumption, to confirm with the Bounty Lead.
  • Primary CTA tap, target widget available in-app → navigate to it in-app, no full reload.
  • Primary CTA tap, no matching in-app widget → open external link (new tab on web,
    Linking.openURL on native).
  • Dismiss/close (X) → closes modal, no navigation, fires a dismiss tracking event.
  • Same trigger/component reusable after any widget's user action, not hardcoded to claim.

Acceptance criteria

  • Reusable Next Task component built once in packages/ui, not duplicated per widget.
  • CTA content (title, copy, image) sourced from an externally-managed, dynamically
    updatable source (mechanism per the architecture decision above).
  • Trigger mechanism works from more than one widget (claim is the first consumer, not
    the only one).
  • In-app navigation works when the CTA target widget is present on the same page.
  • External-link fallback works on both web and native when no in-app target exists.
  • Dismiss action closes the modal with no side effects.
  • Shown / clicked / dismissed events are emitted for analytics wiring.
  • Claim flow is wired as the first live consumer, restoring the original feedback loop.
  • No broken/empty UI when CTA content is unavailable.

Additional context

Bounty Lead: Oliseh Genesis (GitHub: olisehgenesis), approved by Laurence. Notion spec:
"Goodbounties: Next task in the widget" (GoodDollar DX workspace). Design reference:
post-claim bottom-sheet mock (badge → headline → externally-sourced CTA card → dismiss).

Open items pending Laurence before this can be fully finalized:

Create the plan

Based on the above description create an execution plan in a new sub-issue and preserve the original issue content unchanged.
Do not execute the plan until given instructions to do so.

Sub-issue requirements:

  • Title format: [DRAFT][PLAN] <what issue is being planned>
  • Type: Task
  • Description must start with: <sub-issue title>
  • Link the sub-issue back to this parent issue.

Instructions when creating the plan:

  • Map relevant files that are too be used as reference from all repos mentioned
  • import existing @GoodDollar packages
  • Map new components that should be created. Assess when a new component should be created in the new savings widget package or made part of the reusable packages/ui

Plan specification required sections:

  • Required states, flows, and behaviors
  • Execution plan
  • acceptance criteria
  • human-reviewer checklist

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions