Review Challenge — House of Legends
Documented: 2026-05-11
Overview
Guests are encouraged to leave Google reviews in exchange for comp rewards. They submit a screenshot of their review, staff approves it, and the guest receives a reward.
Challenge Flow
Guest enjoys experience
│
▼
Open "Review Challenge" in app
│
▼
See challenge steps:
1. Go to Google Maps
2. Leave a review
3. Take screenshot
4. Submit screenshot
│
▼
Submit screenshot
│
▼
Staff reviews in admin dashboard
│
├──► APPROVED → Guest gets comp reward
└──► REJECTED → Guest notified, can resubmitTables
challengeSubmissions: defineTable({
profileId: v.id("guestProfiles"),
orderId: v.id("orders"),
tableId: v.id("tables"),
challengeType: v.literal("GOOGLE_REVIEW"),
screenshotUrl: v.string(),
status: v.union(
v.literal("PENDING"),
v.literal("APPROVED"),
v.literal("REJECTED"),
),
rewardMenuItemId: v.optional(v.id("menuItems")),
reviewedBy: v.optional(v.id("users")),
reviewedAt: v.optional(v.number()),
notes: v.optional(v.string()),
showDate: v.string(),
createdAt: v.number(),
})
.index("by_status", ["status"])
.index("by_show_date", ["showDate"])
.index("by_table_show", ["tableId", "showDate"]);Challenge Config
challengeConfig: defineTable({
challengeType: v.union(
v.literal("PHOTO_WALL"),
v.literal("LUCKY_SPIN"),
v.literal("GOOGLE_REVIEW"),
),
enabled: v.boolean(),
maxValue: v.optional(v.number()),
prizeDescription: v.optional(v.string()),
steps: v.array(
v.object({
order: v.number(),
text: v.string(),
imageUrl: v.optional(v.string()),
}),
),
activeForDates: v.array(v.string()),
createdAt: v.number(),
updatedAt: v.number(),
}).index("by_type", ["challengeType"]);Example steps for Google Review:
- "Search for House of Legends on Google Maps"
- "Tap 'Write a review'"
- "Add stars and your thoughts"
- "Take a screenshot of your review"
- "Submit it here"
Admin Review
Staff sees pending submissions in /dashboard/challenges:
- Guest name + profile
- Screenshot image
- Submitted at
- Approve / Reject buttons
On approve:
status→APPROVEDreviewedBy→ staff user IDreviewedAt→ timestamp- Comp item added to guest's order
Components
| Component | Purpose |
|---|---|
challenge-card.tsx | Display challenge info |
screenshot-upload.tsx | Upload review screenshot |
challenge-status.tsx | Show pending/approved/rejected |
challenge-steps.tsx | Step-by-step instructions |
Backend Functions
| Function | Purpose |
|---|---|
minigames.submitChallenge | Submit screenshot |
minigames.approveChallenge | Staff approval |
minigames.rejectChallenge | Staff rejection |
minigames.getChallengeStatus | Check submission status |