CRM Product Spec · crm-v1.4

Loyalty Program Designer

Product spec for the Loyalty Program Designer — a visual, template-driven CRM tool that lets club operators design their loyalty program from scratch. Templates to start fast, full configurability to customise every detail, and a live member preview so operators see exactly what members will experience before going live.

Planning4 program models4 templates8 screens16 config options

Program Models

Supported Program Types (4)

The designer supports four distinct loyalty mechanics. The chosen model determines which templates are available and which configuration options are shown.

Points-Basedsupports tiers

Earn points, redeem rewards.

Members earn points on every qualifying action (bookings, POS spend, program enrollments). Points accumulate in a spendable balance. Staff redeem points against a rewards catalogue at the front desk.

Example Mechanic

Book 1 hour → earn 10 pts. Accumulate 200 pts → redeem for 1 free court hour.

Best for: Clubs that want a flexible, long-term loyalty economy. Most versatile model.

Cashback

Spend money, earn credit back.

Members earn club credit (not abstract points) as a percentage of their spend. Credit automatically applies to their next booking or POS purchase. Simple and immediately tangible.

Example Mechanic

Book ฿1,400 court → earn ฿70 credit (5% back). Credit applied on next booking.

Best for: High-frequency clubs where spend is the primary driver. Members love seeing 'you saved ฿X'.

Punch Card

Book N times, get one free.

Classic loyalty mechanic. Every completed booking punches a card. After reaching the target count, the member earns a free session. Resets automatically after each redemption.

Example Mechanic

Book 10 courts, get the 11th free (฿1,400 value).

Best for: Simple operations that want minimal configuration. Easy to explain to members.

Tier-Only (Status)supports tiers

Reach a tier, unlock perks.

No points currency. Members progress through tiers based on their lifetime booking count or spend. Each tier unlocks standing perks (court discounts, priority booking, free racket rental) that apply automatically.

Example Mechanic

Book 20+ sessions → Silver tier → 5% off all future bookings applied at checkout.

Best for: Clubs that want to reward loyal members with automatic discounts without managing a points economy.

Templates

Starting Templates (4)

Templates pre-fill the designer canvas with sensible defaults. Every field remains fully editable after selection — templates are a starting point, not a constraint.

★
Simple Pointspoints-based

Easy to understand, easy to explain.

The classic earn-and-redeem template. Members earn a flat number of points per booking. Points redeem for court credit or discounts. No tiers — just a simple balance and rewards catalogue. Perfect starting point for clubs launching their first loyalty program.

Pre-filled Config

Program Name

Club Rewards

Points Name

pts

Earn Rules
  • 10 pts per booking
  • POS: off
  • Programs: off
Expiry

Points never expire

Sample Rewards

  • 100 pts → Free court credit (฿500)
  • 200 pts → Free court hour
  • 50 pts → 10% discount on one booking

Best for: Clubs launching their first program. Minimal setup, immediate member value.

🏆
Tiered Clubpoints-based

Status + rewards. The full loyalty experience.

Points plus a four-tier status ladder. Members earn points per hour played, progress through Bronze → Silver → Gold → Platinum, and unlock escalating perks at each level. Spending points doesn't drop your tier — lifetime points determine status. Best-in-class loyalty design used by major sports and hospitality brands.

Pre-filled Config

Program Name

Club Rewards

Points Name

pts

Earn Rules
  • 10 pts per hour on court
  • 5 pts per ฿100 at the shop
  • 50 pts per program enrollment
Expiry

Points expire after 365 days of inactivity

Tier Ladder

Bronze0 pts (all members)

Welcome to the program

Silver500 pts

5% off all bookings

Gold1,500 pts

10% off + priority booking

Platinum5,000 pts

15% off + exclusive events

Sample Rewards

  • 200 pts → Free court hour
  • 150 pts → 20% discount on one booking
  • 300 pts → Club merchandise

Best for: Clubs that want a premium, full-featured program. Creates aspiration and loyalty over time.

💵
Cashbackcashback

Spend money, earn credit back automatically.

Members earn a percentage of their court spend back as club credit. Credit is applied automatically to their account balance and deducted on the next booking. No points to track — just visible savings. Simple, transparent, and immediately rewarding.

Pre-filled Config

Program Name

Cashback Rewards

Points Name

credit

Earn Rules
  • 5% cashback on every court booking
  • 2% cashback on POS purchases
Expiry

Credit expires after 90 days

Best for: High-frequency players who book regularly. Cashback feels tangible and immediate.

✓
Punch Cardpunch-card

Book 10, get the 11th free.

The simplest loyalty mechanic. Every completed booking adds one punch to the card. Reach the target (e.g. 10 bookings) and earn a free session. The card resets automatically. No points, no tiers — just a visible countdown that members love.

Pre-filled Config

Program Name

Court Punch Card

Points Name

punches

Earn Rules
  • 1 punch per completed court booking
  • 10 punches = 1 free court session
Expiry

Punches never expire

Best for: Casual clubs that want a loyalty program without the complexity of points or tiers.

UX Screens

Designer Screens & Mockups (8)

Every screen in the loyalty designer, with ASCII mockups showing exact layout, components, and interactions.

Template Picker/crm/loyalty/new

The entry point. Shown only on first-time program creation. Presents 4 template cards plus a 'Start from scratch' option. Selecting a template pre-fills the designer canvas with sensible defaults. Users can change everything after.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  CRM  /  Loyalty  /  New Program                                     │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Choose a starting template                                          │
│  Pick a template to pre-fill your program. You can change            │
│  everything after — templates are just a starting point.             │
│                                                                      │
│  ┌──────────────────────┐   ┌──────────────────────┐                │
│  │  ★  Simple Points    │   │  🏆  Tiered Club      │                │
│  │                      │   │                      │                │
│  │  Earn pts per booking│   │  Bronze → Silver      │                │
│  │  Spend on rewards    │   │  → Gold → Platinum   │                │
│  │                      │   │                      │                │
│  │  Best for clubs      │   │  Best for clubs       │                │
│  │  launching their     │   │  wanting status and   │                │
│  │  first program       │   │  escalating rewards  │                │
│  │                      │   │                      │                │
│  │  [ Use template ]    │   │  [ Use template ]    │                │
│  └──────────────────────┘   └──────────────────────┘                │
│                                                                      │
│  ┌──────────────────────┐   ┌──────────────────────┐                │
│  │  💵  Cashback         │   │  ✓  Punch Card        │                │
│  │                      │   │                      │                │
│  │  Earn % back as      │   │  Book 10 courts,      │                │
│  │  club credit on      │   │  get the 11th free   │                │
│  │  every booking       │   │                      │                │
│  │                      │   │  Best for simple      │                │
│  │  Best for high-      │   │  operations with     │                │
│  │  frequency clubs     │   │  minimal setup       │                │
│  │                      │   │                      │                │
│  │  [ Use template ]    │   │  [ Use template ]    │                │
│  └──────────────────────┘   └──────────────────────┘                │
│                                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  [ Start from scratch — blank canvas ]                               │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

Components

  • 4 template cards — name, icon, tagline, 3-line description, best-for label
  • Each card: [ Use template ] button → loads canvas with pre-filled defaults
  • Cards highlight on hover (amber border + subtle glow)
  • Selected card: filled amber border, checkmark icon
  • [ Start from scratch ] — text link at bottom, opens blank canvas
  • Back navigation: ← Back to Loyalty (if returning to existing program)

Notes & Edge Cases

  • Template picker only appears when no program exists for the facility
  • Returning to settings after program creation goes straight to the designer canvas
  • All 4 templates map to program models: Simple Points + Tiered Club = points-based; Cashback = cashback; Punch Card = punch-card
  • Template selection is not persisted — it just pre-populates the form
Designer Canvas/crm/loyalty/settings

The main design workspace. Two-panel layout: configuration sidebar on the left, live member preview on the right. As the operator changes settings, the preview updates in real time so they see exactly what members experience before going live.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  CRM  /  Loyalty  /  Settings                                        │
├─────────────────────────────────┬────────────────────────────────────┤
│  CONFIGURE                      │  MEMBER PREVIEW                    │
│                                 │                                    │
│  Program Name                   │  ┌──────────────────────────────┐  │
│  ┌───────────────────────────┐  │  │  🥉  BRONZE MEMBER            │  │
│  │ Pad Thai Padel Rewards    │  │  │  Sarah K.  ·  Member         │  │
│  └───────────────────────────┘  │  │                              │  │
│                                 │  │    450  pts                  │  │
│  Points Name                    │  │  Lifetime  450 pts           │  │
│  ○ pts   ○ stars   ● tokens     │  │                              │  │
│                                 │  │  ─────────────────────────── │  │
│  ─────────────────────────────  │  │  Progress to Silver          │  │
│  Earn Rules                  ▸  │  │  ████████████░░  90%         │  │
│  Tier Ladder                 ▸  │  │  50 pts to Silver            │  │
│  Rewards Catalogue           ▸  │  │                              │  │
│  Expiry Policy               ▸  │  └──────────────────────────────┘  │
│                                 │                                    │
│  ─────────────────────────────  │  How members earn tokens:          │
│  Program Status                 │  • 10 tokens / hour on court       │
│  ○ Inactive   ● Active          │  • 5 tokens per ฿100 at shop       │
│                                 │                                    │
│  ─────────────────────────────  │  Available Rewards                 │
│  [ Save Changes ]               │  ┌──────────────────────────────┐  │
│                                 │  │  Free Court Hour   200 tokens │  │
│  Last saved: 2 mins ago         │  │  20% Booking Disc  150 tokens │  │
│                                 │  │  Club T-Shirt      300 tokens │  │
└─────────────────────────────────┤  └──────────────────────────────┘  │
                                  │                                    │
                                  │  Redeem at the front desk →        │
                                  └────────────────────────────────────┘

Components

  • Left panel: sticky config sidebar with all settings sections
  • Program Name — text input, live updates preview header
  • Points Name — radio group (pts / stars / tokens) or custom text input
  • Earn Rules ▸ — chevron link opens earn rules panel (slide-in or expand)
  • Tier Ladder ▸ — chevron link opens tier config panel
  • Rewards Catalogue ▸ — chevron link opens rewards panel
  • Expiry Policy ▸ — chevron link opens expiry panel
  • Program Status — Active / Inactive toggle (disabled programs still configurable)
  • [ Save Changes ] — disabled when no unsaved changes
  • Last saved timestamp — auto-refreshes after save
  • Right panel: live member preview (updates as operator types)
  • Preview: tier badge (bronze/silver/gold/platinum with color), member name, points balance
  • Preview: progress bar to next tier with percentage and pts remaining
  • Preview: earn summary list (how points are earned)
  • Preview: rewards catalogue cards (name + point cost)
  • Preview: 'Redeem at the front desk' note for v1.4

Notes & Edge Cases

  • Preview uses a simulated member (Sarah K., 450 pts, Bronze) so the preview always shows a realistic state
  • Preview tier updates live as the operator changes tier thresholds
  • Progress bar fills/empties as the operator adjusts tier thresholds around the simulated 450-pt member
  • Right panel is non-interactive — operators configure on the left, preview updates on the right
  • On mobile: single panel with preview collapsible at the bottom
Earn Rules Panel/crm/loyalty/settings (earn rules section)

Configure how members earn points. Three earn sources — bookings, POS, and program enrollments — each independently toggled and rate-configured. A live calculation preview shows concrete examples ('A 2-hr booking = 20 pts').

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  ←  Earn Rules                                                       │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Court Bookings                                          [ ● ] ON   │
│  ─────────────────────────────────────────────────────────────────  │
│  Earn rate                                                           │
│  ● Per hour played   ○ Flat per booking                             │
│                                                                      │
│  Points per hour                                                     │
│  ┌────────────────┐                                                  │
│  │  10            │  pts / hour                                     │
│  └────────────────┘                                                  │
│                                                                      │
│  POS / Shop                                              [ ● ] ON   │
│  ─────────────────────────────────────────────────────────────────  │
│  Points per ฿100 spent                                              │
│  ┌────────────────┐                                                  │
│  │  5             │  pts per ฿100                                   │
│  └────────────────┘                                                  │
│                                                                      │
│  Program Enrollments                                     [ ○ ] OFF  │
│  ─────────────────────────────────────────────────────────────────  │
│  Points per enrollment                                               │
│  ┌────────────────┐                                                  │
│  │  50            │  pts flat  (toggled off — won't apply)          │
│  └────────────────┘                                                  │
│                                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  Earn Preview                                                        │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │  A 1-hr booking    →   10 pts                                │  │
│  │  A 2-hr booking    →   20 pts                                │  │
│  │  A 90-min booking  →   15 pts                                │  │
│  │  ฿500 shop order   →   25 pts                                │  │
│  │  Program enroll    →   — (source disabled)                   │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
│  [ Apply ]                                       [ Cancel ]         │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

Components

  • ← back navigation to designer canvas
  • Court Bookings section: ON/OFF toggle + earn rate radio (per hour / flat per booking) + points input
  • POS / Shop section: ON/OFF toggle + points-per-100 input + currency label from facility settings
  • Program Enrollments section: ON/OFF toggle + flat points input
  • Disabled source inputs are grayed out but retain their configured values
  • Earn Preview panel — live calculation box, updates as inputs change
  • Preview shows 5 concrete examples using current settings
  • Disabled sources show '— (source disabled)' in preview
  • [ Apply ] — saves earn rules back to designer canvas, updates live preview
  • [ Cancel ] — discards changes, returns to canvas

Notes & Edge Cases

  • Per-hour earn for bookings rewards longer sessions (90-min = 15 pts vs 60-min = 10 pts)
  • POS currency label auto-reads from facility settings (฿ for THB, $ for USD, etc.)
  • Points inputs are integers only (no decimal points)
  • Minimum value for all point inputs: 1
  • Changes not persisted until [ Apply ] is clicked (or [ Save Changes ] on canvas)
Tier Ladder Panel/crm/loyalty/settings (tier section)

Design the tier progression. Up to 6 tiers, each with a custom name, lifetime-points threshold, court discount %, POS discount %, and a freetext perks description. An inline tier preview shows the full ladder at a glance.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  ←  Tier Ladder                                                      │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Tiers are earned from lifetime points (total ever earned).          │
│  Spending points does NOT drop a member's tier.                      │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Tier 1  ┌─────────────┐  from  ┌──────────┐  pts             │ │
│  │          │ Bronze      │        │  0       │  (welcome tier)  │ │
│  │          └─────────────┘        └──────────┘                  │ │
│  │  Court discount  ┌──┐ %   POS discount  ┌──┐ %               │ │
│  │                  │ 0│                   │ 0│                  │ │
│  │                  └──┘                   └──┘                  │ │
│  │  Perks  ┌──────────────────────────────────────────────────┐  │ │
│  │         │ Welcome to Pad Thai Padel Rewards!               │  │ │
│  │         └──────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Tier 2  ┌─────────────┐  from  ┌──────────┐  pts             │ │
│  │          │ Silver      │        │  500     │                  │ │
│  │          └─────────────┘        └──────────┘                  │ │
│  │  Court discount  ┌──┐ %   POS discount  ┌──┐ %               │ │
│  │                  │ 5│                   │ 5│                  │ │
│  │                  └──┘                   └──┘                  │ │
│  │  Perks  ┌──────────────────────────────────────────────────┐  │ │
│  │         │ 5% off all bookings + priority court booking     │  │ │
│  │         └──────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Tier 3  ┌─────────────┐  from  ┌──────────┐  pts             │ │
│  │          │ Gold        │        │  1,500   │                  │ │
│  │          └─────────────┘        └──────────┘                  │ │
│  │  Court discount  ┌──┐ %   POS discount  ┌──┐ %               │ │
│  │                  │10│                   │10│                  │ │
│  │                  └──┘                   └──┘                  │ │
│  │  Perks  ┌──────────────────────────────────────────────────┐  │ │
│  │         │ 10% off + priority booking + free racket rental  │  │ │
│  │         └──────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Tier 4  ┌─────────────┐  from  ┌──────────┐  pts             │ │
│  │          │ Platinum    │        │  5,000   │                  │ │
│  │          └─────────────┘        └──────────┘                  │ │
│  │  Court discount  ┌──┐ %   POS discount  ┌──┐ %               │ │
│  │                  │15│                   │15│                  │ │
│  │                  └──┘                   └──┘                  │ │
│  │  Perks  ┌──────────────────────────────────────────────────┐  │ │
│  │         │ 15% off + exclusive events + VIP lounge access   │  │ │
│  │         └──────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  [ + Add Tier ]  (max 6)               [ − Remove last tier ]       │
│                                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  Tier Ladder Preview                                                 │
│  Bronze ─── 0      Silver ─── 500      Gold ─── 1,500    Pt ─ 5,000│
│  ●──────────────────●────────────────────●───────────────────────●  │
│                                                                      │
│  [ Apply ]                                       [ Cancel ]         │
└──────────────────────────────────────────────────────────────────────┘

Components

  • ← back navigation
  • Header note: 'Tier earned from lifetime points — spending doesn't drop tier'
  • Per-tier row: name input, from (threshold) input, court discount % input, POS discount % input, perks textarea
  • Tier 1 threshold locked at 0 (everyone starts here)
  • [ + Add Tier ] button — adds a new tier card at the bottom (max 6 tiers)
  • [ − Remove last tier ] button — removes the last tier (minimum 1 tier)
  • Tier Ladder Preview — horizontal progress bar showing all tier thresholds at a glance
  • [ Apply ] / [ Cancel ] at bottom

Notes & Edge Cases

  • Tier 1 threshold is always 0 and cannot be edited (welcome tier — all members qualify)
  • Thresholds must be ascending (each tier's threshold > previous). Validated on Apply.
  • Court and POS discount % are integers 0–50, validated on Apply
  • Tiers with higher discounts automatically apply to pricing at checkout via calculate_member_price()
  • The tier ladder preview dot-line shows how far apart tiers are — helps operators spot if Gold is unreachable
  • Discounts are cumulative by tier level — the highest applicable tier applies
Expiry Policy Panel/crm/loyalty/settings (expiry section)

Control how long earned points are valid. Operators choose between 90/180/365-day rolling windows or 'never expires'. When expiry is enabled, a nightly pg_cron job expires stale points and decrements the member's spendable balance.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  ←  Points Expiry                                                    │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Enable expiry                                           [ ● ] ON   │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                      │
│  Points expire after:                                                │
│  ○ 90 days     ○ 180 days     ● 365 days     ○ Never                │
│                                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  Example                                                             │
│  Points earned on Jan 1, 2026 expire on Jan 1, 2027.               │
│  Expiry check runs nightly at 02:00 (Asia/Bangkok time).            │
│                                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  ⚠  Members are not yet notified before expiry.                      │
│     Expiry email warnings are planned for v1.5.                      │
│                                                                      │
│  When expiry is off:                                                 │
│  Points earned today are valid forever. Simpler for members,        │
│  but no urgency to redeem. Recommended for programs just launching.  │
│                                                                      │
│  [ Apply ]                                       [ Cancel ]         │
└──────────────────────────────────────────────────────────────────────┘

Components

  • Enable Expiry toggle (ON/OFF)
  • When OFF: window options are grayed out, example text updates to 'points never expire'
  • When ON: 4 radio options (90 / 180 / 365 / Never days)
  • Example section — live text showing concrete expiry date based on current selection
  • Timezone note — uses facility's configured timezone (not UTC)
  • Warning banner — 'Members are not notified before expiry' (v1.5 scope)
  • Contextual help — when toggle is OFF, explains trade-off
  • [ Apply ] / [ Cancel ]

Notes & Edge Cases

  • Expiry runs per earned point batch, not per account. Points earned on date D expire on D + window_days.
  • Expiry only decrements spendable balance (not lifetime_points). Tier is preserved.
  • The pg_cron job runs at 02:00 in the facility's local timezone (not UTC)
  • Recommendation: start with 'never expires' to reduce member confusion on launch
  • v1.5 scope: expiry warning emails at 30-day and 7-day notice
Rewards Catalogue Panel/crm/loyalty/rewards

Define what members can redeem their points for. Each reward has a point cost, type (court credit, discount %, free session, merchandise, other), and a value payload. Staff redeem rewards at the front desk in v1.4 — members see the catalogue but cannot self-redeem.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  CRM  /  Loyalty  /  Rewards                    [ + New Reward ]    │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Free Court Hour                              ●  active       │ │
│  │  200 pts  ·  court credit  ·  1 hour = ฿1,400 credit         │ │
│  │                                    [ Edit ]  [ Disable ]      │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  20% Booking Discount                         ●  active       │ │
│  │  150 pts  ·  discount %  ·  20% off one booking              │ │
│  │                                    [ Edit ]  [ Disable ]      │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Club T-Shirt                                 ●  active       │ │
│  │  300 pts  ·  merchandise  ·  "Pad Thai Padel" branded tee     │ │
│  │                                    [ Edit ]  [ Disable ]      │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Free Racket Rental  [INACTIVE]               ○  inactive     │ │
│  │  100 pts  ·  free session  ·  60-min racket rental            │ │
│  │                                    [ Edit ]  [ Enable ]       │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  ℹ  Staff redeem rewards at the front desk. Members see this        │
│     catalogue on their account page but cannot self-redeem in v1.4.│
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

Components

  • [ + New Reward ] button (top-right) → opens create reward dialog
  • Reward card: name, point cost, reward type badge, value description
  • Active badge (green dot) / Inactive badge (gray dot)
  • [ Edit ] button → opens edit dialog (same form as create)
  • [ Disable ] on active rewards → sets is_active = false (soft delete)
  • [ Enable ] on inactive rewards → restores is_active = true
  • Inactive rewards shown below active rewards, dimmed
  • Info banner at bottom: v1.4 staff-only redemption note

Notes & Edge Cases

  • Reward types: court_credit, discount_pct, free_session, merchandise, other
  • court_credit reward_value: { amount: 140000 } (in facility currency's smallest unit, e.g. satang)
  • discount_pct reward_value: { pct: 20 } (applied to one booking)
  • free_session reward_value: { minutes: 60 } (free court time)
  • merchandise reward_value: { description: 'Branded tee, size M' }
  • Disabled rewards are hidden from member web app view
  • Cannot delete rewards with redemption history — only disable
  • Points cost displayed alongside facility's points_name (e.g. '200 pts' or '200 stars')
Live Member Preview/crm/loyalty/settings (right panel)

Embedded in the designer canvas. Shows the program exactly as a member would see it on the web app. Uses a simulated Bronze-tier member (450 pts) to demonstrate tier progression realistically. Updates in real time as the operator configures.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  MEMBER PREVIEW                              [ Change simulated tier]│
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  🥉  BRONZE                                                    │ │
│  │  Sarah K.  ·  Member since Jan 2025                           │ │
│  │                                                                │ │
│  │  Current Balance         Lifetime Points                       │ │
│  │  450 pts                 450 pts                               │ │
│  │                                                                │ │
│  │  ────────────────────────────────────────────────────────────  │ │
│  │  Progress to Silver                                            │ │
│  │  ████████████████████░░░░  450 / 500 pts   90%               │ │
│  │  50 pts to unlock Silver                                       │ │
│  │                                                                │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  How Sarah earns pts:                                                │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Court booking   →   10 pts per hour                           │ │
│  │  Shop purchase   →   5 pts per ฿100 spent                      │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  Available Rewards:                                                  │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Free Court Hour               200 pts                        │ │
│  │  20% Booking Discount          150 pts                        │ │
│  │  Club T-Shirt                  300 pts                        │ │
│  │                                                                │ │
│  │  Redeem at the front desk →                                    │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  Recent Activity:                                                    │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Mar 28  Booking — Court A, 2hr     +20 pts                   │ │
│  │  Mar 25  Shop — Grip tape            +5 pts                   │ │
│  │  Mar 20  Booking — Court B, 1hr     +10 pts                   │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  This is a preview — not a real member account                       │
└──────────────────────────────────────────────────────────────────────┘

Components

  • Preview header: 'MEMBER PREVIEW' label + [ Change simulated tier ] link
  • Member card: tier badge (bronze/silver/gold/platinum), simulated name, join date
  • Points balance (large) + lifetime points (smaller)
  • Progress bar to next tier: fills/empties as operator changes tier thresholds
  • Progress text: 'X pts to unlock [next tier name]'
  • Earn summary: list of enabled earn rules with rates (updates live)
  • Rewards catalogue preview: up to 5 active rewards with point costs
  • Recent activity (simulated): 3 sample transactions showing how the ledger looks
  • 'This is a preview' disclaimer at bottom

Notes & Edge Cases

  • Simulated member: Sarah K., 450 pts, Bronze tier — chosen to be near a tier threshold for a realistic preview
  • [ Change simulated tier ] lets the operator preview Gold or Platinum member experience
  • Points name in preview uses whatever the operator has set (pts, stars, tokens, etc.)
  • Earn rates in preview update in real time as the operator changes earn rules
  • Rewards in preview update as rewards are added/edited/disabled
  • Preview does not interact with any real member data
  • Right panel scrolls independently of the left config panel on long pages
Program Overview/crm/loyalty

The loyalty section landing page. Shows the program's live status, key metrics, earn rate summary, tier ladder visual, and a top earners leaderboard. The central dashboard for operators managing an active program.

Layout Mockup

┌──────────────────────────────────────────────────────────────────────┐
│  CRM  /  Loyalty                                                     │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Pad Thai Padel Rewards                             [ ● ] ACTIVE    │
│  crm-v1.4  ·  points-based  ·  4 tiers  ·  Smash Points            │
│                                                                      │
│  ┌───────────────────┐  ┌───────────────────┐  ┌──────────────────┐ │
│  │  Total Members    │  │  Points Issued     │  │  Redemptions     │ │
│  │  847              │  │  (this month)      │  │  (this month)    │ │
│  │  enrolled         │  │  12,430 pts        │  │  23              │ │
│  └───────────────────┘  └───────────────────┘  └──────────────────┘ │
│                                                                      │
│  Earn Rates                           Tier Ladder                    │
│  ┌──────────────────────┐  ┌──────────────────────────────────────┐ │
│  │  Court  10 pts/hr    │  │  Bronze ─── 0    Silver ─── 500      │ │
│  │  POS    5 pts/฿100   │  │  ●──────────────────●               │ │
│  │  Prog   off          │  │  Gold ─── 1,500  Platinum ─── 5,000 │ │
│  └──────────────────────┘  │            ●────────────────────────●│ │
│                             └──────────────────────────────────────┘ │
│                                                                      │
│  Tier Distribution                    Top Earners — March 2026       │
│  ┌──────────────────────┐  ┌──────────────────────────────────────┐ │
│  │  Bronze  584  (69%)  │  │  1.  Ahmad S.    Gold     2,840 pts  │ │
│  │  Silver  187  (22%)  │  │  2.  Maria C.   Silver    1,620 pts  │ │
│  │  Gold     63  (7%)   │  │  3.  James T.   Silver    1,580 pts  │ │
│  │  Platinum 13  (2%)   │  │  4.  Priya N.   Bronze      940 pts  │ │
│  └──────────────────────┘  │  5.  Tom W.     Bronze      880 pts  │ │
│                             └──────────────────────────────────────┘ │
│                                                                      │
│  [ Settings ]   [ Rewards ]   [ View Member Ledgers →  ]             │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

Components

  • Program name + status badge (Active/Inactive) + active toggle
  • Program meta line: version, model, tier count, points name
  • Stats row: total enrolled members, points issued this month, redemptions this month
  • Earn Rates card: summary of enabled earn sources with rates
  • Tier Ladder visual: horizontal dot-line showing all tier thresholds
  • Tier Distribution: count and % of members at each tier
  • Top Earners leaderboard: top 5 members by points earned this month (name, tier, pts)
  • [ Settings ] → designer canvas, [ Rewards ] → rewards page, [ View Member Ledgers ] → member CRM filter

Notes & Edge Cases

  • Accessed at /crm/loyalty — the main loyalty landing page
  • Active toggle here is a shortcut to the enable/disable toggle in Settings
  • Top earners: points earned in current calendar month (not lifetime)
  • Leaderboard pulls from /api/admin/crm/loyalty/leaderboard
  • If no program configured: shows empty state with [ Set Up Loyalty Program ] CTA

Config Reference

Configuration Options (16 fields)

Every configurable field in the designer — field name, input type, constraints, default value, and description.

name

Program Name

text

Displayed on the member web app account page and in all member communications.

Constraints: 1–60 characters. Required.Default: Club Rewards

points_name

Points Name

radio + custom text

What the club calls their currency. Shown everywhere: 'Earn 10 pts' vs 'Earn 10 stars'. Consistent singular form is used (not pluralised in the UI).

ptsstarstokenspunchescreditscustom
Constraints: 1–20 characters if custom. Required.Default: pts

earn_rules.booking.enabled

Court Booking Earn — Enabled

toggle

When OFF, completing a court booking awards zero points.

Constraints: Boolean.Default: true

earn_rules.booking.type

Court Booking Earn — Rate Type

radio

'Per hour' rewards longer sessions (90 min = 1.5x vs 60 min). 'Per booking' is flat regardless of duration.

per_hourper_booking
Constraints: Only relevant when booking earn is enabled.Default: per_hour

earn_rules.booking.points

Court Booking Earn — Points

number

Points awarded per hour (if per_hour) or per booking (if per_booking).

Constraints: Integer 1–1000.Default: 10

earn_rules.pos.enabled

POS Earn — Enabled

toggle

When OFF, POS orders award zero points.

Constraints: Boolean.Default: true

earn_rules.pos.points_per_100_units

POS Earn — Points per 100 currency units

number

Points per 100 units of the facility currency (e.g. ฿100 or $1.00). Currency label shown dynamically.

Constraints: Integer 1–100.Default: 5

earn_rules.program.enabled

Program Enrollment Earn — Enabled

toggle

When ON, enrolling in a paid or free program awards a flat point bonus.

Constraints: Boolean.Default: false

earn_rules.program.points_per_enrollment

Program Enrollment Earn — Points

number

Flat points awarded per program enrollment. Same value regardless of program price.

Constraints: Integer 1–1000.Default: 50

tiers[N].name

Tier Name

text

Displayed on the member's tier badge. Can be customised (e.g. 'Member', 'Regular', 'VIP', 'Elite').

Constraints: 1–30 characters. Required per tier.Default: Bronze / Silver / Gold / Platinum

tiers[N].lifetime_threshold

Tier Threshold (lifetime points)

number

Minimum lifetime points to reach this tier. Based on total ever earned — spending points cannot drop the tier.

Constraints: Integer ≥ 0. Must be ascending across tiers. Tier 1 = 0 (locked).Default: 0 / 500 / 1500 / 5000

tiers[N].court_discount_pct

Tier Court Discount %

number

Percentage discount applied to court booking price for members at this tier. Applied via calculate_member_price() at checkout.

Constraints: Integer 0–50.Default: 0 / 5 / 10 / 15

tiers[N].pos_discount_pct

Tier POS Discount %

number

Percentage discount applied to POS purchase total for members at this tier.

Constraints: Integer 0–50.Default: 0 / 5 / 10 / 15

tiers[N].perks

Tier Perks Description

textarea

Freetext description of what this tier unlocks. Displayed on the member web app account page.

Constraints: 0–200 characters. Optional.Default: Welcome tier / 5% off all bookings / 10% off + priority booking / 15% off + exclusive events

expiry_policy.enabled

Points Expiry — Enabled

toggle

When OFF, points never expire. Recommended for programs launching for the first time.

Constraints: Boolean.Default: false

expiry_policy.window_days

Expiry Window (days)

radio

Points earned today expire after this many days. Checked nightly at 02:00 (facility timezone).

90180365
Constraints: Only applies when expiry is enabled.Default: 365

Design Principles

Designer Principles (6)

1

Live preview eliminates guesswork

Operators should never have to imagine what the program looks like to members. The right panel mirrors the member web app exactly, updating in real time. If a threshold changes, the progress bar moves instantly. If a reward is added, it appears in the preview immediately.

2

Templates accelerate setup, not restrict

Templates pre-fill every field but lock nothing. An operator who picks 'Tiered Club' can immediately change 'Gold' to 'VIP' and reduce the threshold from 1,500 to 1,000 — no friction. Templates are a starting point, not a cage.

3

Destructive defaults are opt-in

Points expiry is OFF by default. Program status is Inactive by default. The operator must explicitly activate the program before it affects members. Nothing goes live accidentally.

4

Contextual guidance at decision points

Every configuration section includes a short rationale alongside the inputs. 'Per hour rewards longer sessions.' 'Spending points does not drop tier.' These micro-explanations reduce support questions and help operators make informed decisions.

5

Earn preview = confidence builder

The earn rules panel shows concrete examples before saving: 'A 2-hr booking = 20 pts'. Operators immediately understand the mechanics without math. Changes to rates update examples instantly.

6

Dark, minimal, amber-accented

Follows Setpoint CRM design system exactly: dark background, sharp edges, amber (#F59E0B) for primary accents and active states, muted gray for secondary information. Consistent with the rest of the CRM admin experience.