Skip to content

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 โ€‹

  1. Venue Detail (step1_from_venue_light_lantern.png)

    • User views venue details
    • Taps "Light My Lantern" button
    • Code: VenueView component in Dashboard.jsx
    • Handler: handleLightLantern() โ†’ sets view='form'
  2. 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: LightLanternForm component in LightLanternForm.jsx
    • Handler: confirmLantern() โ†’ uses useLightLantern hook โ†’ sets view='active'
  3. 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: ActiveLanternView component in Dashboard.jsx

Key Functions โ€‹

  • handleLightLantern() - Entry point, sets view to form
  • confirmLantern(data) - Uses useLightLantern hook to light lantern, navigates to active view
  • useLightLantern() - 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 โ€‹

  1. Choose Light Lantern (step1_choose_light_lantern.png)

    • User opens Lantern Hub
    • Taps fire icon to light a lantern
    • Code: LanternHub component in Dashboard.jsx
    • Handler: handleLanternHubLightLantern() โ†’ sets showLightLanternModal=true
  2. Choose Venue (step2_choose_venue.png)

    • Modal shows nearby venues (map + list view)
    • User selects a venue
    • Code: VenuePicker component in VenuePicker.jsx
    • State: LightLanternModal manages flow, step='venue'
    • Handler: handleSelectVenue(venue) โ†’ sets selectedVenue, advances to step='form'
  3. 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: LightLanternForm component embedded in modal
    • Handler: handleFormConfirm(data) โ†’ uses useLightLantern hook โ†’ closes modal
  4. Success Screen (step4_lit_lantern_success_and_details.png)

    • Modal closes, returns to Dashboard
    • Dashboard shows ActiveLanternView with celebration animation
    • Displays mood, interest, status
    • Same view as Flow 1
    • Code: ActiveLanternView component in Dashboard.jsx
    • Flow: Modal's onLanternLit() callback โ†’ Dashboard sets view='active'

Key Functions โ€‹

  • handleLanternHubLightLantern() - Entry point, opens modal
  • LightLanternModal component - Manages 2-step flow (venue โ†’ form), then closes
  • handleFormConfirm(data) - Uses useLightLantern hook to light lantern and close modal
  • Modal's onLanternLit() callback - Triggers Dashboard to show ActiveLanternView
  • useLightLantern() - Shared hook in useLightLantern.js
  • handleSuccessClose() - Closes modal and passes lantern data to Dashboard
  • onLanternLit(lanternData) - Dashboard callback, navigates to ActiveLanternView

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 view state in Dashboard to navigate (venue โ†’ form โ†’ active)
  • Flow 2: Uses LightLanternModal (LightLanternModal.jsx) with internal step state (venue โ†’ form, then closes and triggers Dashboard's active view)

State Management โ€‹

Flow 1 State (Dashboard.jsx) โ€‹

javascript
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])
} : null

Flow 2 State (LightLanternModal.jsx) โ€‹

javascript
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 โ€‹

javascript
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 โ€‹

  1. Created useLightLantern hook (useLightLantern.js)

    • Centralizes Firebase lighting logic
    • Eliminates duplicate code between flows
    • Single source of truth for lantern creation
  2. Refactored Flow 1 (Dashboard.jsx)

    • confirmLantern() now uses useLightLantern hook
    • Removed duplicate Firebase call logic
  3. Refactored Flow 2 (LightLanternModal.jsx)

    • handleFormConfirm() now uses useLightLantern hook
    • Removed success step from modal - modal just closes
    • Dashboard's onLanternLit callback shows ActiveLanternView
    • Simplified from 3 steps (venue โ†’ form โ†’ success) to 2 steps (venue โ†’ form)
  4. 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:

  1. Flow 1:

    • Navigate to venue detail from map
    • Tap "Light My Lantern"
    • Fill form and submit
    • Should see ActiveLanternView immediately
  2. 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.

Built with VitePress