Light Lantern Flows โ
This document maps out the two distinct user flows for lighting a lantern in the Lantern app. Both flows use shared logic via the useLightLantern hook and converge to the same success screen.
Architecture Overview โ
Shared Hook: useLightLantern
- Handles Firebase lantern creation
- Manages loading and error states
- Triggers success/error callbacks
Shared Success Screen: ActiveLanternView
- Displays lit lantern details
- Shows mood, interest, time remaining
- Allows extinguish action
- Used by both Flow 1 and Flow 2
Flow 1: Light Lantern from Venue Detail โ
Entry point: User taps "Light My Lantern" button on a venue detail page
Screenshots: docs/screenshots/light_lantern_flows/flow_1_from_place/
Steps โ
Venue Detail (
step1_from_venue_light_lantern.png)- User views venue details
- Taps "Light My Lantern" button
- Code:
VenueViewcomponent in Dashboard.jsx - Handler:
handleLightLantern()โ setsview='form'
Enter Lantern Details (
step2_enter_lantern_details.png)- User selects mood (Conversation, Quiet Company, Activity/Game)
- User enters interest text (140 char max)
- Taps "Light My Lantern" button
- Code:
LightLanternFormcomponent in LightLanternForm.jsx - Handler:
confirmLantern()โ usesuseLightLanternhook โ setsview='active'
Success & Lantern Details (
step3_lit_lantern_success_and_details.png)- Shows lit lantern with celebration animation
- Displays mood, interest, time remaining
- Shows other active lanterns at venue
- User can extinguish or wave to others
- Code:
ActiveLanternViewcomponent in Dashboard.jsx
Key Functions โ
handleLightLantern()- Entry point, sets view to formconfirmLantern(data)- UsesuseLightLanternhook to light lantern, navigates to active viewuseLightLantern()- Shared hook in useLightLantern.js
Flow 2: Light Lantern from Fire Icon (Global) โ
Entry point: User taps fire icon in Lantern Hub menu
Screenshots: docs/screenshots/light_lantern_flows/flow_2_from_fire_icon/
Steps โ
Choose Light Lantern (
step1_choose_light_lantern.png)- User opens Lantern Hub
- Taps fire icon to light a lantern
- Code:
LanternHubcomponent in Dashboard.jsx - Handler:
handleLanternHubLightLantern()โ setsshowLightLanternModal=true
Choose Venue (
step2_choose_venue.png)- Modal shows nearby venues (map + list view)
- User selects a venue
- Code:
VenuePickercomponent in VenuePicker.jsx - State:
LightLanternModalmanages flow,step='venue' - Handler:
handleSelectVenue(venue)โ setsselectedVenue, advances tostep='form'
Enter Lantern Details (
step3_enter_lantern_details.png)- User selects mood (Conversation, Quiet Company, Activity/Game)
- User enters interest text (140 char max)
- Taps "Light My Lantern" button
- Code:
LightLanternFormcomponent embedded in modal - Handler:
handleFormConfirm(data)โ usesuseLightLanternhook โ closes modal
Success Screen (
step4_lit_lantern_success_and_details.png)- Modal closes, returns to Dashboard
- Dashboard shows
ActiveLanternViewwith celebration animation - Displays mood, interest, status
- Same view as Flow 1
- Code:
ActiveLanternViewcomponent in Dashboard.jsx - Flow: Modal's
onLanternLit()callback โ Dashboard setsview='active'
Key Functions โ
handleLanternHubLightLantern()- Entry point, opens modalLightLanternModalcomponent - Manages 2-step flow (venue โ form), then closeshandleFormConfirm(data)- UsesuseLightLanternhook to light lantern and close modal- Modal's
onLanternLit()callback - Triggers Dashboard to showActiveLanternView useLightLantern()- Shared hook in useLightLantern.jshandleSuccessClose()- Closes modal and passes lantern data to DashboardonLanternLit(lanternData)- Dashboard callback, navigates toActiveLanternView
Component Architecture โ
Component Architecture โ
Shared Components โ
useLightLantern (useLightLantern.js)
- Custom hook that centralizes Firebase lighting logic
- Used by both flows
- Handles loading, error states, and success/error callbacks
LightLanternForm (LightLanternForm.jsx)
- Reusable form for mood + interest input
- Used in both flows
- Props:
venue,onCancel,onConfirm,loading
VenuePicker (VenuePicker.jsx)
- Map/list view of nearby venues
- Only used in Flow 2
- Shows distance, category, active lantern count
ActiveLanternView (Dashboard.jsx)
- Final "success" view showing lit lantern
- Used by both flows as the success screen
- Shows lantern details, time remaining, other lanterns at venue
- Allows user to extinguish or wave
Flow-Specific Components โ
- Flow 1: Uses
viewstate in Dashboard to navigate (venue โ form โ active) - Flow 2: Uses
LightLanternModal(LightLanternModal.jsx) with internalstepstate (venue โ form, then closes and triggers Dashboard's active view)
State Management โ
Flow 1 State (Dashboard.jsx) โ
const [view, setView] = useState('home') // 'home' | 'venue' | 'form' | 'active'
const [selectedVenue, setSelectedVenue] = useState(null)
// Computed from real-time listener
const myLantern = activeLanterns.length > 0 ? {
...activeLanterns[0],
timeRemaining: formatTimeRemaining(activeLanterns[0])
} : nullFlow 2 State (LightLanternModal.jsx) โ
const [selectedVenue, setSelectedVenue] = useState(null)
const [lighting, setLighting] = useState(false)
const [userLocation, setUserLocation] = useState(null)
// Derived state - only 2 steps now
const step = selectedVenue ? 'form' : 'venue'Shared Hook: useLightLantern โ
import { useLightLantern } from '../../hooks/useLightLantern'
const { lightLanternFlow, loading, error } = useLightLantern()
// Usage
await lightLanternFlow({
userId: currentUser.uid,
venueId: venue.id,
location: { lat, lng },
formData: { mood, interest },
onSuccess: (lantern) => { ... },
onError: (error) => { ... }
})The hook:
- Calls
lightLantern()from lanternService.js - Manages loading and error states
- Invokes callbacks on success/error
- Used identically by both flows
Refactor Summary (2026-01-07) โ
Changes Made โ
Created
useLightLanternhook (useLightLantern.js)- Centralizes Firebase lighting logic
- Eliminates duplicate code between flows
- Single source of truth for lantern creation
Refactored Flow 1 (Dashboard.jsx)
confirmLantern()now usesuseLightLanternhook- Removed duplicate Firebase call logic
Refactored Flow 2 (LightLanternModal.jsx)
handleFormConfirm()now usesuseLightLanternhook- Removed success step from modal - modal just closes
- Dashboard's
onLanternLitcallback showsActiveLanternView - Simplified from 3 steps (venue โ form โ success) to 2 steps (venue โ form)
Fixed bugs
- Removed intermediate success screen from Flow 1
- Fixed blank screen when viewing lantern details from fire icon
- Both flows now properly navigate to
ActiveLanternView
Benefits โ
โ
Single source of truth - Both flows use same hook
โ
Code reduction - ~60 lines of duplication eliminated
โ
Converged UX - Both flows end at same success screen
โ
Easier to maintain - Change lighting logic once, affects both flows
โ
Simpler modal - No success screen state management in modal
โ
Bugs fixed - Blank screen and duplicate success screens resolved
Testing โ
To test flows:
Flow 1:
- Navigate to venue detail from map
- Tap "Light My Lantern"
- Fill form and submit
- Should see
ActiveLanternViewimmediately
Flow 2:
- Tap fire icon in Lantern Hub
- Select venue from picker
- Fill form and submit
- Should see success screen in modal
- Tap "Got it!" to close and see
ActiveLanternView
See VENUE_TESTING_GUIDE.md for venue testing setup.