ProjectR Docs
Screen MapDashboard

Loyalty

Dashboard: every screen, state and flow in Loyalty.

15 screens and overlays, 60 states, 1 flows. Frames show a real screenshot where one was captured and a wireframe card where the state needs data or conditions a device run cannot produce.

Flows

Loyalty campaign setup and operation

Step 1
Loyalty Dashboard (Web)
Loyalty dashboard with cards and recent activity
New Campaign
Step 2
Wireframe

Create Campaign

Edge

Draft autosave

Draft restored from localStorage with an info toast

Not captured yet

Create form autosaves a draft in localStorage
Submit
Step 3
Campaigns (Web)
Campaigns list
View
Step 4
Campaign detail (Web)
Campaign detail tabs
View all users
Step 5
User Management (Web)
Loyalty users table
Award stamps
Step 6
Wireframe

Award Bonus Stamps

Edge

Writes to Shopify

A reward or special position creates a real voucher and a live Shopify discount code

Not captured yet

Award dialog; may mint a Shopify code (do not submit)

Branches and edge cases

Errorfrom step 2
Wireframe

Create Campaign

Error

Tier probabilities

Tiers must total 100% and be VOUCHER or MISS

Not captured yet

Tiers do not sum to 100 percent
Edgefrom step 2
Wireframe

Create Campaign

Edge

Bad draft cleared

Previous draft contained errors and was cleared

Needs data: Needs specific backend rows, a role, or a submitted write on a disposable record

Draft restored
Edgefrom step 3
Wireframe

Delete Campaign

Edge

Admin downgraded

Campaign deactivated (permanent delete requires super admin)

Needs data: Needs specific backend rows, a role, or a submitted write on a disposable record

Delete as admin: deactivate only
Errorfrom step 3
Wireframe

Delete Campaign

Error

Participants block hard delete

Cannot delete: N user(s) have participated in this campaign

Needs data: Needs specific backend rows, a role, or a submitted write on a disposable record

Delete as super admin with participants
Successfrom step 3
Wireframe

Delete Campaign

Edge

Single sends hardDelete true

Bulk delete sends false, so it only deactivates

Needs data: Needs specific backend rows, a role, or a submitted write on a disposable record

Delete, no participants: hard delete
Gatefrom step 5
Reset User Progress, Campaign picked first (Web)
Reset progress deletes stamp history
Edgefrom step 5
User loyalty profile (Web)
Open a user profile
Gatefrom step 5
Wireframe

Delete Voucher

Edge

Writes to Shopify

Cancels the voucher and deletes its discount code from Shopify when it was active

Needs data: Needs specific backend rows, a role, or a submitted write on a disposable record

Delete voucher removes the Shopify code
Gatefrom step 3
Audit & Compliance, audit:view admin (Web)
Audit log, admin only
Flow diagram

Screens and states

Loyalty Dashboard

Loyalty Dashboard (Web)
Screen/dashboard/loyalty

Loyalty Dashboard

Loyalty hub with stats, quick actions, audit and realtime tabs.

src/app/dashboard/loyalty/page.tsx

Entry

  • Sidebar Loyalty

Exits

  • Campaigns → /loyalty/campaigns
  • New Campaign → /campaigns/new
  • Quick actions → users, audit, pools
  • Audit tab → /loyalty/audit
  • Export → Export dialog

States · 4

Loading
Per-card loading · Skeletons per card plus loading.tsxsrc/app/dashboard/loyalty/loading.tsx
Empty
No campaigns · No campaigns found. Get started by creating your first loyalty campaignsrc/features/loyalty/components/views/loyalty-dashboard-view.tsx:271
Empty
No recent audit activity · Audit tab emptysrc/features/loyalty/components/views/loyalty-dashboard-view.tsx
Edge
Export not role gated · Export button is not admin gated here, unlike other screenssrc/features/loyalty/components/views/loyalty-dashboard-view.tsx:534

Campaigns

Campaigns (Web)
Screen/dashboard/loyalty/campaigns

Campaigns

List stamp campaigns with bulk actions.

src/app/dashboard/loyalty/campaigns/page.tsx

Entry

  • Sidebar
  • Loyalty dashboard

Exits

  • New Campaign → /campaigns/new
  • View → /campaigns/[id]
  • Edit → /campaigns/[id]/edit
  • Pause or Activate
  • Delete → confirm dialog
  • Bulk Activate, Pause, Delete

States · 6

Loading
Table skeleton · DataTableSkeleton while loadingsrc/features/loyalty/components/views/campaign-management-view.tsx
Empty
No campaigns · DataTable default plus Total 0 stat stripsrc/features/loyalty/components/views/campaign-management-view.tsx
Edge
Window label is informational · Nd left, Ends today, Expired; only isActive is storedsrc/features/loyalty/components/campaigns/campaign-columns.tsx:204
Error
reset_collections unsupported · Confirming shows reset_collections is not yet supportedsrc/features/loyalty/components/campaigns/campaign-table.tsx:107
Gate
Auth expired · Authentication required. Please sign in again.src/features/loyalty/components/campaigns/campaign-table.tsx
Edge
Delete button visible to all · Non-super-admin hard delete is downgraded to deactivatepackages/backend/convex/gamificationLoyalty/mutations.ts

Delete Campaign

Delete Campaign (Web)
DialogLoyaltyCampaignDeleteDialog

Delete Campaign

Confirm deleting one or many campaigns.

src/features/loyalty/components/campaigns/campaign-table.tsx

Entry

  • Row menu Delete
  • Bulk bar Delete

Exits

  • Confirm → delete or deactivate
  • Cancel → closes

States · 3

Edge
Single sends hardDelete true · Bulk delete sends false, so it only deactivatessrc/features/loyalty/components/campaigns/campaign-table.tsx:95
Edge
Admin downgraded · Campaign deactivated (permanent delete requires super admin)packages/backend/convex/gamificationLoyalty/mutations.ts
Error
Participants block hard delete · Cannot delete: N user(s) have participated in this campaignpackages/backend/convex/gamificationLoyalty/mutations.ts

Create Campaign

Create Campaign (Web)
Screen/dashboard/loyalty/campaigns/new

Create Campaign

Set up a new loyalty stamp campaign.

src/app/dashboard/loyalty/campaigns/new/page.tsx

Entry

  • New Campaign buttons
  • Template Use in Campaign

Exits

  • Back or Cancel → unsaved dialog
  • Submit → /loyalty/campaigns

States · 10

Edge
Draft autosave · Draft restored from localStorage with an info toastsrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:505
Edge
Bad draft cleared · Previous draft contained errors and was clearedsrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:505
Error
Network retry loop · Retrying... (n/max) toast, Retry button on error alertsrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:237
Error
Special position checks · Positions 1..totalStamps, each with tiers, rewardType, no duplicatessrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:342
Error
Tier probabilities · Tiers must total 100% and be VOUCHER or MISSpackages/backend/convex/gamificationLoyalty/mutations.ts:55
Success
Perfect 100% · Perfect! All reward tiers total exactly 100%src/features/loyalty/components/campaigns/forms/special-positions-manager.tsx
Error
Max 24 stamps · Maximum 24 stamps per cardsrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:66
Error
Position invalid · Position must be between 1 and N; Position N already configuredsrc/features/loyalty/components/campaigns/forms/special-positions-manager.tsx
Edge
Template param does nothing · loadTemplate is a stub; no voucher template field existssrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:304
Success
Campaign created · Toast then redirect to list after 1 secondsrc/features/loyalty/components/campaigns/forms/campaign-form.tsx:430

Campaign detail

Campaign detail (Web)
Screen/dashboard/loyalty/campaigns/[id]

Campaign detail

Campaign detail with analytics, rewards and realtime tabs.

src/app/dashboard/loyalty/campaigns/[id]/page.tsx

Entry

  • List View
  • Users page campaign filter

Exits

  • Back to campaigns
  • Edit → /[id]/edit
  • View all → /loyalty/users?campaign=
  • Export → Export dialog (admin)

States · 6

Loading
Detail skeleton · CampaignDetailSkeletonsrc/app/dashboard/loyalty/campaigns/[id]/campaign-detail-client.tsx
Error
Campaign not found · Error card with no back buttonsrc/app/dashboard/loyalty/campaigns/[id]/campaign-detail-client.tsx:108
Edge
Invalid tab falls back · Unknown ?tab= falls back to collectionssrc/app/dashboard/loyalty/campaigns/[id]/campaign-detail-client.tsx
Empty
No stamps collected yet · Analytics tab emptysrc/app/dashboard/loyalty/campaigns/[id]/campaign-detail-client.tsx
Empty
No special positions · Shows a configure linksrc/app/dashboard/loyalty/campaigns/[id]/campaign-detail-client.tsx
Edge
Participants capped at 50 · List shows first 50; analytics reads all rowssrc/app/dashboard/loyalty/campaigns/[id]/campaign-detail-client.tsx

Edit Campaign

Edit Campaign (Web)
Screen/dashboard/loyalty/campaigns/[id]/edit

Edit Campaign

Modify campaign settings.

src/app/dashboard/loyalty/campaigns/[id]/edit/page.tsx

Entry

  • Edit links

Exits

  • Back or Cancel → unsaved dialog
  • Save Changes → /loyalty/campaigns

States · 3

Loading
Form skeleton · Skeleton while campaign loadssrc/features/loyalty/components/campaigns/forms/campaign-form.tsx
Edge
No not-found branch · Missing campaign has no explicit statesrc/features/loyalty/components/campaigns/forms/campaign-form.tsx
Edge
No draft autosave · Draft autosave is create onlysrc/features/loyalty/components/campaigns/forms/campaign-form.tsx

User Management

User Management (Web)
Screen/dashboard/loyalty/users

User Management

Per-user stamp progress, manual awards and resets.

src/app/dashboard/loyalty/users/page.tsx

Entry

  • Sidebar
  • Dashboard quick actions
  • Campaign View all

Exits

  • View user → /users/[userId]
  • Award stamps → dialog
  • Reset progress → dialog
  • View history
  • Export data

States · 4

Loading
Combined loading · campaignsLoading or usersLoading or statsLoadingsrc/features/loyalty/components/views/user-management-view.tsx
Empty
No users · No users match your search or No users yetsrc/features/loyalty/components/views/user-management-view.tsx:505
Edge
URL state · q, campaign, page size, sort field and direction live in the URLsrc/features/loyalty/components/views/user-management-view.tsx
Edge
Award limits disagree · Dialog max 10, popover max 5, backend 1 to 100src/features/loyalty/components/views/user-management-view.tsx:859

Award Bonus Stamps

Award Bonus Stamps (Web)
DialogAwardBonusStampsDialog

Award Bonus Stamps

Award stamps to a user through the real collect-stamp path.

src/features/loyalty/components/views/user-management-view.tsx

Entry

  • Row menu Award stamps

Exits

  • Award → toast with positions
  • Cancel → closes

States · 4

Error
Required fields missing · Please fill in all required fieldssrc/features/loyalty/components/views/user-management-view.tsx
Success
Award result toast · Lists previous to current position, special, shake, cycle completedsrc/features/loyalty/components/views/user-management-view.tsx
Edge
Writes to Shopify · A reward or special position creates a real voucher and a live Shopify discount codepackages/backend/convex/gamificationLoyalty/mutations.ts:294
Edge
No Shopify banner · ShopifyWriteBanner is missing on this dialogsrc/features/loyalty/components/views/user-management-view.tsx

Award stamps popover

Award stamps popover (Web)
DialogTestStampAwardPopover

Award stamps popover

Quick award of 1 to 5 stamps for the selected campaign.

src/features/loyalty/components/views/test-stamp-award-popover.tsx

Entry

  • Row actions menu when a campaign is selected

Exits

  • Award → toast
  • Close

States · 2

Edge
Writes to Shopify · Crossing a reward position mints a real voucher and Shopify codesrc/features/loyalty/components/views/test-stamp-award-popover.tsx:205
Edge
Max 5 stamps · Popover limit differs from dialog (10) and backend (100)src/features/loyalty/components/views/test-stamp-award-popover.tsx:205

Reset User Progress

Reset User Progress (Web)
DialogResetUserProgressDialog

Reset User Progress

Delete a user's stamp history for a campaign.

src/features/loyalty/components/views/user-management-view.tsx

Entry

  • Row menu Reset progress

Exits

  • Reset → toast
  • Cancel → closes

States · 3

Edge
Campaign picked first · With no campaign selected it first asks for onesrc/features/loyalty/components/views/user-management-view.tsx
Success
Progress reset · Reset progress for <name>packages/backend/convex/gamificationLoyalty/mutations.ts:2080
Error
No progress found · No progress found for this user and campaignpackages/backend/convex/gamificationLoyalty/mutations.ts:2080

Captured states

Reset User Progress, Campaign picked first (Web)
Campaign picked first

User loyalty profile

User loyalty profile (Web)
Screen/dashboard/loyalty/users/[id]

User loyalty profile

One user's loyalty profile with vouchers, history and campaigns.

src/app/dashboard/loyalty/users/[id]/page.tsx

Entry

  • Users table View

Exits

  • Tabs → overview, vouchers, history, campaigns
  • Copy voucher code
  • Delete voucher → confirm

States · 4

Loading
Profile skeleton · Loading skeletonsrc/app/dashboard/loyalty/users/[id]/user-detail-client.tsx
Error
Error Loading User · User not found cardsrc/app/dashboard/loyalty/users/[id]/user-detail-client.tsx:118
Edge
Lazy tabs · Vouchers and History fetch only when activesrc/app/dashboard/loyalty/users/[id]/user-detail-client.tsx:64
Empty
No campaign participation yet · Campaigns tab emptysrc/app/dashboard/loyalty/users/[id]/user-detail-client.tsx:625

Delete Voucher

Wireframe

Delete Voucher

Needs data: Needs a user holding a voucher

DialogDeleteUserVoucherDialog

Delete Voucher

Cancel a user's voucher and remove its code from Shopify.

src/app/dashboard/loyalty/users/[id]/user-detail-client.tsx

Entry

  • Voucher row Delete

Exits

  • Delete → toast
  • Cancel → closes

States · 4

Edge
Writes to Shopify · Cancels the voucher and deletes its discount code from Shopify when it was activepackages/backend/convex/gamificationLoyalty/mutations.ts:1908
Error
Used voucher refused · Cannot delete a used voucherpackages/backend/convex/gamificationLoyalty/mutations.ts:1908
Success
Voucher deleted · Toast Voucher deleted successfullysrc/app/dashboard/loyalty/users/[id]/user-detail-client.tsx:96
Edge
No Shopify banner · ShopifyWriteBanner is missing heresrc/app/dashboard/loyalty/users/[id]/user-detail-client.tsx

Audit & Compliance

Audit & Compliance (Web)
Screen/dashboard/loyalty/audit

Audit & Compliance

Stamp activity log and per-user summaries.

src/app/dashboard/loyalty/audit/page.tsx

Entry

  • Sidebar
  • Dashboard Audit tab

Exits

  • Export (admin) → Export dialog
  • Filters → sheet
  • Entry Details → row action
  • User links

States · 5

Gate
audit:view admin · Admin-only pagesrc/features/loyalty/components/audit/audit-combined-view.tsx
Loading
Table skeleton · DataTableSkeleton 4x10 per tab; charts load lazilysrc/features/loyalty/components/audit/audit-combined-view.tsx
Empty
No audit data found · Shown only when both tabs are emptysrc/features/loyalty/components/audit/audit-combined-view.tsx
Edge
Scan cap hit · A source table hit its N-row scan cap; rows may be missingsrc/features/loyalty/components/audit/audit-combined-view.tsx:333
Edge
Load more activity · Button when more entries existsrc/features/loyalty/components/audit/audit-combined-view.tsx

Captured states

Audit & Compliance, audit:view admin (Web)
audit:view admin

Audit filters

Audit filters (Web)
SheetAuditFiltersSheet

Audit filters

Filter by activity type, source, campaign and date range.

src/features/loyalty/components/audit/audit-filters.tsx

Entry

  • Filters button on audit

Exits

  • Apply
  • Clear

States · 1

Edge
Active count badge · Badge on the filter button shows active filterssrc/features/loyalty/components/audit/audit-filters.tsx

Legacy voucher templates

Legacy voucher templates (Web)
Redirect/dashboard/loyalty/voucher-templates

Legacy voucher templates

Four legacy routes redirect into /vouchers/templates.

src/app/dashboard/loyalty/voucher-templates/page.tsx

Entry

  • Old bookmarks

Exits

  • Redirect → /vouchers/templates (and /new, /[id], /[id]/edit)

States · 1

Edge
Old path in access map · access-control.ts still lists the old pathsrc/lib/access-control.ts:326

On this page