取代实体印花卡,用数码积分系统留住回头客、提升复购率
* Preview is for reference only. Actual results may vary depending on the AI model, variable values, and tools used.
You are a senior full-stack engineer proficient in Next.js 16, Tailwind CSS 4, and Supabase. Build a complete Customer Loyalty & Rewards System for {business_name} (a Malaysian {business_type}) to replace traditional physical stamp cards.
Tech stack: Next.js 16 (App Router) + TypeScript + Tailwind CSS 4 + shadcn/ui + Supabase (Postgres + Auth + RLS + Realtime)
## 1. Database Schema (Supabase Postgres)
### Tables
1. `members` — Customer profiles
- id (uuid, PK), phone (text, unique, +60 format), name (text), email (text, nullable)
- tier (enum: 'bronze','silver','gold'), total_spend (numeric), total_points_earned (int)
- current_points (int), birthday_month (int, 1-12), referral_code (text, unique)
- referred_by (uuid, FK → members.id, nullable), notes (text, nullable)
- joined_at (timestamptz), last_visit_at (timestamptz)
2. `transactions` — Spend records
- id (uuid, PK), member_id (uuid, FK → members.id)
- amount_myr (numeric), points_earned (int), multiplier (numeric, default 1.0)
- source (enum: 'purchase','referral','birthday','campaign','manual','welcome')
- description (text, nullable), created_at (timestamptz), created_by (uuid, nullable)
3. `rewards` — Rewards catalog
- id (uuid, PK), name_zh (text), name_en (text), description_zh (text), description_en (text)
- points_cost (int), category (text), image_url (text, nullable)
- min_tier (enum: 'bronze','silver','gold'), is_active (boolean), stock (int, nullable)
- valid_days (int, default 30), created_at (timestamptz)
4. `redemptions` — Redemption records
- id (uuid, PK), member_id (uuid, FK), reward_id (uuid, FK)
- points_spent (int), status (enum: 'pending','fulfilled','expired','cancelled')
- voucher_code (text, unique), expires_at (timestamptz)
- fulfilled_at (timestamptz, nullable), created_at (timestamptz)
5. `campaigns` — Marketing campaigns
- id (uuid, PK), name (text), type (enum: 'double_points','bonus_points','birthday','welcome')
- multiplier (numeric, nullable), bonus_points (int, nullable)
- start_date (date), end_date (date), is_active (boolean)
- conditions (jsonb), created_at (timestamptz)
6. `events` — Behavior tracking
- id (uuid, PK), member_id (uuid, nullable), event_type (text)
- metadata (jsonb), created_at (timestamptz)
### Indexes
- members: phone, referral_code, tier, birthday_month
- transactions: member_id, created_at, source
- redemptions: member_id, status, voucher_code
- campaigns: is_active, type, start_date, end_date
### RLS Policies
- Members can only view their own data (verified by phone)
- Public read access to rewards (is_active = true)
- Admin users (authenticated + admins allowlist) have full read/write access
- events table: anon INSERT allowed, admin-only SELECT
## 2. Points & Tier Business Logic
### Points Calculation
- Base rate: {points_per_rm} points earned per RM1 spent (rounded)
- Welcome bonus: {welcome_bonus} points on registration
- Referral bonus: 50 points each for referrer and referred member
- Birthday month: All purchases earn 2x points during member's birthday month
- Campaign multiplier: Stack with active campaign multipliers from campaigns table
- Manual adjustment: Admin can add/deduct points with a mandatory reason
### Tier System
- Bronze: Default tier, total spend RM0+
- Silver: Total spend reaches the silver threshold in {tier_thresholds}
- Gold: Total spend reaches the gold threshold in {tier_thresholds}
- Tier benefits: Silver earns 1.2x point multiplier, Gold earns 1.5x point multiplier
- Tier evaluation: Auto-evaluated on the 1st of each month; downgrade requires 3 consecutive months below threshold
### Reward Redemption Flow
1. Member browses reward catalog (filtered by eligible tier)
2. Selects reward → System checks current_points >= points_cost
3. Deduct points → Generate unique voucher_code (6-char alphanumeric)
4. Voucher validity = valid_days from redemption date
5. Staff scans/enters voucher_code → Mark as fulfilled
## 3. Customer-Facing Interface (Mobile-First PWA)
### Page Structure
1. **Home / Check-in** `/`
- Display {business_name} logo and brand color {primary_color}
- Two entry points: "Scan QR to Check In" and "Enter Phone Number"
- New user → Registration flow (name + phone in +60 format + birthday month)
- Returning user → Redirect to member dashboard
2. **Member Dashboard** `/member`
- Top card: Name, tier badge (Bronze/Silver/Gold), current points (large font)
- Progress bar: "RM XX more to reach [next tier]"
- Quick actions: "View Rewards", "Redemption History", "Refer a Friend"
- Recent transactions list (last 5)
3. **Rewards Catalog** `/rewards`
- Grid card layout, each card: reward name (ZH/EN), points cost, tier requirement
- Rewards beyond member's points shown greyed out but visible (motivation to spend)
- Tap → Reward detail → "Redeem Now" button
4. **History** `/history`
- Tabs: "Points History" and "Redemptions"
- Points: date, source, points change (+/-), running balance
- Redemptions: reward name, voucher code, status, expiry date
5. **Referral Page** `/referral`
- Display personal referral code and shareable link
- Share buttons (WhatsApp, copy link)
- Count of successful referrals and points earned
### UI/UX Design Specs
- Primary color: {primary_color}, paired with white background and dark gray text
- Typography: Inter (English) + Noto Sans SC (Chinese), Chinese displayed by default
- Points displayed in large bold numbers, tier badges as circular pills
- All monetary values prefixed with RM, use thousands separator
- Buttons: rounded-xl, cards with subtle shadow
- Loading states: Skeleton components, success feedback via Sonner toast
## 4. Admin Dashboard (Desktop-First)
### Dashboard `/admin`
- Four stat cards: Total Members, Active This Month, Points Issued Today, Points Redeemed Today
- Trend chart: New member registrations over the past 30 days (daily)
- Recent transactions list (real-time updates via Supabase Realtime)
### Member Management `/admin/members`
- Search bar: search by phone number or name
- Table: name, phone, tier, points balance, total spend, last visit
- Click row → Sheet sidebar: full profile, transaction history, manual point adjustment, add notes
- Filters: by tier, registration date range
### Rewards Management `/admin/rewards`
- Rewards list + "Add New Reward" button
- Edit form: ZH/EN names, points cost, minimum tier, stock count, validity days
- Toggle: enable/disable
### Campaign Management `/admin/campaigns`
- Campaign list: name, type, date range, status
- Create campaign: select type (double points / bonus points / birthday / welcome)
- Set conditions: date range, multiplier or bonus amount
### Redemption Verification `/admin/redeem`
- Input field: enter or scan voucher code
- Display: member name, reward details, expiry date
- "Confirm Redemption" button
### Analytics `/admin/analytics`
- Retention rate: 1-month and 3-month revisit rates
- Average visit frequency: weekly / monthly
- Redemption rate: points issued vs points redeemed ratio
- Loyalty member revenue vs non-member comparison (requires manual non-member input or estimation)
- Tier distribution pie chart: Bronze / Silver / Gold member counts
- Top redeemed rewards leaderboard
## 5. Sample Seed Data (Malaysian Bubble Tea Shop)
Initialize with the following sample data:
- Shop name: {business_name} (default: "Chadao Milk Tea 茶道奶茶")
- Rewards: Free Pearl Milk Tea = 50 pts, 10% Discount Voucher = 100 pts, Free Snack Platter = 150 pts, Gold-Exclusive Limited Edition Cup = 300 pts
- Members: 5 sample members (different tiers and point balances)
- Transactions: 3-5 historical purchases per member
- Campaigns: This weekend double points, new member {welcome_bonus} pts welcome bonus
## 6. Technical Requirements
- Prefer Server Components for all pages; use Client Components only for interactive elements
- Phone validation: Malaysian format starting with +60, 10-11 digits
- Points mutations MUST use database transactions for consistency
- QR code generation: Use `qrcode` library for store check-in QR codes
- PWA support (manifest.json + service worker) so customers can add to home screen
- Default language: Chinese, with English toggle in top-right corner
- Responsive design: customer-facing is mobile-first, admin is desktop-first
- Use Supabase Realtime for live admin dashboard updates