Photo Wall — House of Legends
Documented: 2026-05-11
Overview
Guests can submit photos during their visit. Photos appear on the live "wall" display and other guests can like them. Winning photos are featured.
Photo Submission Flow
Guest at Table
│
▼
Open Photo Wall in App
│
▼
Take Photo or Select from Gallery
│
▼
Add Caption (optional)
│
▼
Submit → Upload to R2
│
▼
Photo appears on Wall DisplayTables
photoSubmissions: defineTable({
profileId: v.id("guestProfiles"),
orderId: v.id("orders"),
tableId: v.id("tables"),
imageUrl: v.string(),
caption: v.optional(v.string()),
likeCount: v.number(),
status: v.union(v.literal("ACTIVE"), v.literal("HIDDEN")),
winner: v.boolean(),
showDate: v.string(),
createdAt: v.number(),
})
.index("by_show_date", ["showDate"])
.index("by_profile", ["profileId"])
.index("by_status", ["status"])
.index("by_likes", ["likeCount", "status"]);
photoLikes: defineTable({
submissionId: v.id("photoSubmissions"),
profileId: v.id("guestProfiles"),
createdAt: v.number(),
})
.index("by_submission", ["submissionId"])
.index("by_profile_submission", ["profileId", "submissionId"]);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"]);Components
| Component | Purpose |
|---|---|
photo-submission-form.tsx | Upload form with camera/gallery |
photo-card.tsx | Individual photo with likes |
photo-wall-grid.tsx | Masonry grid of photos |
photo-likes.tsx | Like button + count |
wall-display.tsx | Full-screen wall for venue display |
Like Flow
- Guest taps heart on photo
photoLikesrecord createdphotoSubmissions.likeCountincremented- Heart fills in UI
Winner Selection
Admin selects winning photos:
- Set
winner: trueon selected photos - Winners featured at top of wall
- Winners eligible for prize (comp items, discounts)
Backend Functions
| Function | Purpose |
|---|---|
minigames.submitPhoto | Upload + create submission |
minigames.likePhoto | Add like |
minigames.getWallPhotos | Get photos for date |
minigames.selectWinner | Mark photo as winner |