Skip to content

Add tier trial UI components and activation flow - #2506

Merged
MusabShakeel576 merged 1 commit into
masterfrom
claude/admin-dashboard-profile-page-uuvq4r
Sep 10, 2026
Merged

Add tier trial UI components and activation flow#2506
MusabShakeel576 merged 1 commit into
masterfrom
claude/admin-dashboard-profile-page-uuvq4r

Conversation

@MusabShakeel576

Copy link
Copy Markdown
Contributor

Summary

Implements the complete UI and logic for tier trials (admin gifts and welcome offers), including opt-in popups, activation, countdown displays, and upgrade celebrations.

Key Changes

New Components

  • TierPopup: Reusable card component for tier-related popups (upgrades, offers, celebrations) featuring a tier star, benefits stats, and action buttons
  • TierTrialOfferPopup: Opt-in popup for pending tier trials with activation logic
  • TierTrialBanner: Wallet screen card showing trial status (pending offer or active countdown)
  • TierTrialPill: Countdown badge under tier name on rewards screen with expiry details modal
  • TierTrialSlot: Container managing trial visibility, auto-opening offer popup on first view, and state coordination

Copy and Logic

  • tierTrialCopy.ts: Centralized copy generation for all trial-related UI states:
    • trialOfferCopy(): Generates text for pending trials (admin gifts vs. welcome offers)
    • upgradeCelebrationCopy(): Generates celebration text based on upgrade source (trial, points, FUSE)
    • tierPopupStats(): Extracts tier benefits for display
    • Countdown utilities: trialRemainingLabel(), trialDaysRemaining(), durationLabel()

API and State Management

  • activateTierTrial(): New API endpoint to start a pending trial
  • useActivateTierTrial(): React Query mutation hook for activation with automatic cache update
  • useTierTrialStore: Zustand store tracking which trial offer popups have auto-opened (prevents re-showing on every launch)

Type Definitions

  • TierTrial: New type for trial data including id, tier, source, status, duration, expiry, and countdown hours
  • TierTrialSource: Union type for 'admin_gift' | 'promotion'
  • TierTrialStatus: Union type for trial lifecycle states
  • GiftableTier: Type restricting trials to PRIME and ULTRA tiers
  • Extended RewardsUserData with pendingTierTrial and activeTierTrial fields

Refactoring

  • Moved getTierDisplayName() from constants/rewards.ts to new lib/tierNames.ts to reduce circular dependencies
  • Replaced old RewardsUpgradeFeedback celebration logic with new TierPopup-based implementation
  • Removed getConfirmedUpgradeBenefits() in favor of tier-benefits endpoint data

Integration Points

  • RewardsScreenNew: Added TierTrialPill to show countdown under tier name
  • HomeScreenNew: Added TierTrialSlot to wallet screen for trial banner and popup
  • PointsHeadline: Added optional trialCountdown prop for trial display
  • RewardsUpgradeFeedback: Refactored to use new popup component and copy generation

Notable Implementation Details

  • Trial offer popup auto-opens once per trial (tracked in persistent store) but can be reopened via banner
  • "Maybe later" dismisses popup without losing the offer—it remains claimable via banner
  • Activation is idempotent server-side; double-tap shows running trial instead of restarting clock
  • Countdown uses backend's hoursRemaining rather than expiresAt to prevent pill/backend disagreement
  • Celebration copy adapts based on upgrade source: trial duration, FUSE balance, or points milestone
  • All three upgrade routes (trial activation, points milestone, FUSE unlock) show identical celebration card with different text

https://claude.ai/code/session_01TkJ3tWhLMMe8ifA3VGQx1Z

The app side of the admin gift. A trial the user has been given shows up as a
card on the wallet screen — "You've received a gift", with the admin's own
message when they wrote one — and the popup behind it opens once by itself so a
gift is not left sitting unnoticed. Activating it is required and is the only
thing that starts the clock, which is what makes "Maybe later" a real answer
rather than a way of losing the gift: the offer stays on the account and the
card is still there to tap. That is also why the card has no ✕, unlike the
card-funnel banners it sits with — a dismissal would leave a live gift with
nothing in the app pointing at it.

Once it is running the card reads "You're on Prime", and the rewards screen
grows the countdown the design puts between the tier name and the points.
Tapping it answers the question a temporary tier actually raises — what happens
at the end — with the expiry and the plain fact that the tier then goes back to
being whatever the points and FUSE balance earn.

The upgrade celebration is rebuilt to the design and is now genuinely shared:
one card, mounted on the protected layout, that a points milestone, a confirmed
FUSE balance and a just-activated trial all arrive at through the same tier
change. Only the words differ, and a trial gets the extra line saying how long
it runs. Nothing has to open it: activation writes the new tier into the rewards
cache and the existing upgrade watcher takes it from there.

Its three headline stats come from the tier-benefits endpoint rather than the
user's own payload, because a gift is usually a tier they do not hold yet —
their own numbers are Core's zeroes, and a per-cardholder cashback override is
not what "Welcome to Prime" is announcing. That retires
getConfirmedUpgradeBenefits, which built the old list from those numbers.

Two small extractions keep this testable: the subscription rate is now served
as a number alongside the prose it already had, and getTierDisplayName moved to
lib/tierNames so the copy module can name a tier without pulling in the asset
registry. constants/rewards re-exports it, so no call site changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TkJ3tWhLMMe8ifA3VGQx1Z
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
solid-app Ignored Ignored Sep 10, 2026 12:04pm UTC
solid-app-staging Ignored Ignored Sep 10, 2026 12:04pm UTC

Request Review

@claude

claude Bot commented Sep 10, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.


🤖 Generated with Claude Code

@MusabShakeel576
MusabShakeel576 merged commit 7c56832 into master Sep 10, 2026
5 checks passed
@MusabShakeel576
MusabShakeel576 deleted the claude/admin-dashboard-profile-page-uuvq4r branch September 10, 2026 12:16
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.

2 participants