Skip to content

Manage Guests for Event Story - Implementation Audit

Manage Guests for Event Story - Implementation Audit

Section titled “Manage Guests for Event Story - Implementation Audit”

Story: Manage Guests for an Event
Date: 2025-01-27
Status: ⚠️ PARTIALLY IMPLEMENTED (~70%) - Core Features Complete, Critical Gaps Exist

The Manage Guests for Event story has good UI implementation with most core features working. However, there are critical gaps that prevent full functionality:

  1. Add Guest functionality is not implemented - shows alert but doesn’t actually add guests
  2. AttendanceEstimate is NOT automatically updated on the event when RSVP status changes
  3. Guest preferences cannot be edited via UI - only displayed, no add/edit interface
  4. Data layer uses in-memory storage - data lost on refresh (separate from mock data)

✅ 1. For a specific event, I can create a guest list

Section titled “✅ 1. For a specific event, I can create a guest list”

Status:COMPLETE

  • Implementation: shaker/data/guests/guestData.ts

  • Location: Lines 95-108

  • Details:

    • createGuestList(eventId) function exists
    • Automatically creates guest list when adding first guest
    • Guest list structure properly defined
    • Mock data exists for demonstration
  • Note: Guest lists are created automatically when needed, but also exist in mock data for existing events

⚠️ 2. I can add guests to the list by name

Section titled “⚠️ 2. I can add guests to the list by name”

Status: ⚠️ NOT IMPLEMENTED (UI exists but doesn’t save)

  • Issue: Add Guest modal shows success alert but doesn’t actually add the guest

  • Current State:

    • Modal UI exists with name and email inputs
    • Form validation exists (name required)
    • Success alert shown
    • Guest is NOT saved to data layer
  • Evidence:

    const handleAddGuest = () => {
    if (!newGuestName.trim()) {
    Alert.alert("Error", "Please enter a guest name");
    return;
    }
    // In real app, this would call a mutation
    Alert.alert("Success", `${newGuestName} has been added to the guest list!`);
    setNewGuestName("");
    setShowAddModal(false);
    };
  • Missing Implementation:

    // Should call:
    import { createGuest, addGuestToEvent } from '@/data/guests';
    const handleAddGuest = () => {
    if (!newGuestName.trim()) {
    Alert.alert("Error", "Please enter a guest name");
    return;
    }
    const newGuest = createGuest({
    name: newGuestName.trim(),
    email: newGuestEmail.trim() || undefined,
    rsvpStatus: 'pending',
    });
    addGuestToEvent(eventId, newGuest);
    setNewGuestName("");
    setNewGuestEmail("");
    setShowAddModal(false);
    };
  • Impact: Users cannot actually add guests - functionality is broken

✅ 3. I can update the RSVP status for each guest

Section titled “✅ 3. I can update the RSVP status for each guest”

Status:COMPLETE

  • Implementation: shaker/app/(tabs)/events/guests.tsx and shaker/data/guests/guestData.ts

  • Location:

    • UI: Lines 76-79, 136-162 (GuestCard with RSVP buttons)
    • Data layer: Lines 162-168 (updateRSVPStatus function)
  • Details:

    • GuestCard component displays RSVP status badges
    • Quick action buttons for Confirmed, Maybe, Declined
    • Status updates persist to data layer
    • Visual feedback with badges and colors
    • All four statuses supported: confirmed, declined, maybe, pending
  • UI Features:

    • Color-coded badges (green=confirmed, yellow=maybe, red=declined, gray=pending)
    • Quick action buttons on each guest card
    • Filter buttons to view guests by RSVP status

❌ 4. The system must update the event’s AttendanceEstimate based on the number of confirmed guests

Section titled “❌ 4. The system must update the event’s AttendanceEstimate based on the number of confirmed guests”

Status:NOT IMPLEMENTED

  • Issue: Attendance estimate is calculated but NOT updated on the event object

  • Current State:

    • getGuestStats() calculates confirmed guests and plus-ones
    • getExpectedAttendance() returns total expected attendance
    • Stats are displayed in UI (Attendance Summary card)
    • Event’s expectedGuestCount is NOT automatically updated
  • Evidence:

    export function getGuestStats(eventId: string): {
    total: number;
    confirmed: number;
    declined: number;
    maybe: number;
    pending: number;
    totalWithPlusOnes: number;
    } {
    const guestList = mockGuestLists[eventId];
    if (!guestList) {
    return { total: 0, confirmed: 0, declined: 0, maybe: 0, pending: 0, totalWithPlusOnes: 0 };
    }
    const stats = {
    total: guestList.guests.length,
    confirmed: 0,
    declined: 0,
    maybe: 0,
    pending: 0,
    totalWithPlusOnes: 0,
    };
    guestList.guests.forEach((guest) => {
    stats[guest.rsvpStatus]++;
    if (guest.rsvpStatus === 'confirmed') {
    stats.totalWithPlusOnes++;
    if (guest.plusOne) {
    stats.totalWithPlusOnes++;
    }
    }
    });
    return stats;
    }
  • What’s Missing:

    • No function to update event’s expectedGuestCount
    • No automatic sync when RSVP status changes
    • No updateEvent function in events data layer (from schedule_an_event audit)
    • Stats are displayed but not used to update event
  • Expected Behavior: When a guest’s RSVP status changes to “confirmed” or is updated:

    1. Calculate total expected attendance (confirmed guests + plus ones)
    2. Update event’s expectedGuestCount field
    3. Trigger any dependent calculations (shopping list, ingredient quantities, etc.)
  • Impact:

    • Event’s expected guest count remains manual/manually set
    • Shopping list generation and ingredient calculations use outdated counts
    • System cannot automatically adjust quantities based on actual RSVPs

⚠️ 5. I can optionally record guest preferences

Section titled “⚠️ 5. I can optionally record guest preferences”

Status: ⚠️ PARTIALLY COMPLETE

  • Data Layer: ✅ Complete

    • GuestPreference interface exists with types: ‘likes’, ‘dislikes’, ‘allergy’
    • addGuestPreference() function exists
    • removeGuestPreference() function exists
    • Preferences stored in guest object
    • Preferences displayed in GuestCard component
  • UI: ⚠️ Incomplete

    • Preferences are displayed in GuestCard (lines 110-125)
    • Preferences are NOT editable via UI
    • No form to add/edit preferences
    • Only “notes” field exists in edit-guest screen (can be used as workaround)
  • Evidence - Display:

    {guest.preferences && guest.preferences.length > 0 && (
    <View className={preferences()}>
    <View className="flex-row flex-wrap">
    {guest.preferences.map((pref, index) => (
    <View key={index} className={preferenceTag()}>
    <Icon
    name={pref.type === 'allergy' ? 'triangle-exclamation' : pref.type === 'likes' ? 'heart' : 'ban'}
    size="sm"
    color={pref.type === 'allergy' ? 'red' : pref.type === 'likes' ? 'primary' : 'gray'}
    />
    <Text className={preferenceText()}>{pref.description}</Text>
    </View>
    ))}
    </View>
    </View>
    )}
  • Evidence - No Edit UI:

    const handleSave = () => {
    // ... validation ...
    const updatedGuest = updateGuest(eventId, guestId, {
    name: guestName.trim(),
    email: guestEmail.trim() || undefined,
    phone: guestPhone.trim() || undefined,
    notes: guestNotes.trim() || undefined, // Only notes, no preferences
    plusOne: guestPlusOne,
    plusOneName: guestPlusOne ? guestPlusOneName.trim() || undefined : undefined,
    });
    // ...
    };
  • Missing UI Features:

    • Add preference button/form in edit-guest screen
    • Preference type selector (likes/dislikes/allergy)
    • Preference description input
    • List of existing preferences with delete option
    • Preference validation
  • Workaround: Users can currently use the “notes” field, but this doesn’t use the structured preference system

  1. UI Components:

    • shaker/app/(tabs)/events/guests.tsx - Guest list screen
    • shaker/app/(tabs)/events/edit-guest.tsx - Edit guest screen (missing preferences)
    • shaker/components/GuestCard.tsx - Guest display card (shows preferences)
  2. Data Layer:

    • shaker/data/guests/index.ts - Type definitions and mock data
    • shaker/data/guests/guestData.ts - CRUD operations (complete)
    • ✅ Comprehensive test suite exists
  3. Integration:

    • ⚠️ shaker/data/events/index.ts - Missing updateEvent function
    • ⚠️ No automatic sync between guest stats and event

Complete CRUD Operations:

  • createGuest() - Create guest object
  • createGuestList() - Create guest list for event
  • addGuestToEvent() - Add guest to event’s guest list
  • getGuestListByEventId() - Retrieve guest list
  • getGuestById() - Get single guest
  • updateGuest() - Update guest information
  • updateRSVPStatus() - Update RSVP status
  • removeGuestFromEvent() - Remove guest
  • getGuestStats() - Calculate statistics
  • getExpectedAttendance() - Get total expected attendance
  • addGuestPreference() - Add preference (data layer only)
  • removeGuestPreference() - Remove preference (data layer only)
  • getGuestsByStatus() - Filter by RSVP status
  • getGuestsWithAllergies() - Filter guests with allergies

Guest List Screen (guests.tsx):

  • ✅ Display all guests for event
  • ✅ Attendance summary card with statistics
  • ✅ Filter buttons (All, Confirmed, Maybe, Pending, Declined)
  • ✅ Guest cards with RSVP status badges
  • ✅ Quick RSVP status update buttons
  • ✅ Add guest button and modal
  • ⚠️ Add guest modal doesn’t save (bug)
  • ✅ Navigate to edit guest screen
  • ✅ Display guest preferences (read-only)
  • ✅ Display plus-one information

Edit Guest Screen (edit-guest.tsx):

  • ✅ Name, email, phone inputs
  • ✅ Notes field (multiline)
  • ✅ Plus-one toggle and name field
  • ✅ Save and cancel buttons
  • ✅ Form validation
  • No preferences management UI

GuestCard Component:

  • ✅ Display guest name and contact info
  • ✅ RSVP status badge with colors
  • ✅ Edit button
  • ✅ Quick RSVP update buttons
  • ✅ Display preferences with icons
  • ✅ Display plus-one information

Two Separate Storage Systems:

  1. Mock Data (mockGuestLists):

    • Located in shaker/data/guests/index.ts
    • Hardcoded data for demo events
    • Persists across sessions (in source code)
  2. In-Memory Data (guestLists):

    • Located in shaker/data/guests/guestData.ts
    • Runtime data created via createGuestList() and addGuestToEvent()
    • Lost on app refresh/reload
    • Not persisted to any storage

Problem: The UI reads from mockGuestLists but new guests would be added to guestLists (if the add function worked). This creates inconsistency.

Evidence:

export function getGuestListByEventId(eventId: string): GuestList | undefined {
return mockGuestLists[eventId]; // Only reads from mock data
}
export function addGuestToEvent(eventId: string, guest: Guest): GuestList | undefined {
let guestList = guestLists[eventId]; // Uses in-memory storage
// ...
}

File: shaker/app/(tabs)/events/guests.tsx

Required:

import { createGuest, addGuestToEvent } from '@/data/guests';
const handleAddGuest = () => {
if (!newGuestName.trim()) {
Alert.alert("Error", "Please enter a guest name");
return;
}
if (!eventId) {
Alert.alert("Error", "Missing event information");
return;
}
const newGuest = createGuest({
name: newGuestName.trim(),
email: newGuestEmail.trim() || undefined,
rsvpStatus: 'pending',
});
const updatedGuestList = addGuestToEvent(eventId, newGuest);
if (updatedGuestList) {
setNewGuestName("");
setNewGuestEmail("");
setShowAddModal(false);
// Refresh guest list (may need state management)
} else {
Alert.alert("Error", "Failed to add guest. Please try again.");
}
};

Files: shaker/data/guests/index.ts, shaker/data/guests/guestData.ts

Issue: Two separate storage systems create inconsistency.

Options:

  • Option A: Merge guestLists into mockGuestLists (use mock data as runtime storage)
  • Option B: Use only in-memory guestLists and initialize from mock data on startup
  • Option C: Add persistence layer (AsyncStorage, database, etc.)

Recommended: Option A for now (quickest fix), migrate to Option C later for production.

3. Implement AttendanceEstimate Auto-Update

Section titled “3. Implement AttendanceEstimate Auto-Update”

Files: shaker/data/events/index.ts, shaker/data/guests/guestData.ts

Required Steps:

  1. Add updateEvent function to events data layer (if not exists from schedule_an_event fix)
  2. Add function to sync attendance estimate:
    export function syncAttendanceEstimate(eventId: string): void {
    const stats = getGuestStats(eventId);
    const expectedAttendance = stats.totalWithPlusOnes;
    // Update event's expectedGuestCount
    updateEvent(eventId, { expectedGuestCount: expectedAttendance });
    }
  3. Call syncAttendanceEstimate() after:
    • Adding a guest
    • Updating RSVP status
    • Removing a guest
    • Adding/removing plus-one

File: shaker/app/(tabs)/events/edit-guest.tsx

Required Features:

  • Display list of current preferences
  • Add preference button
  • Modal/form to add preference:
    • Type selector (likes/dislikes/allergy)
    • Description text input
  • Delete preference button for each preference
  • Validation (description required)

UI Mockup:

<View>
<Text className="mb-2 font-semibold text-black">Preferences</Text>
{guest.preferences?.map((pref, index) => (
<View key={index} className="flex-row items-center justify-between">
<View className="flex-row items-center">
<Icon name={getPreferenceIcon(pref.type)} />
<Text>{pref.description}</Text>
</View>
<Button title="Remove" onPress={() => handleRemovePreference(index)} />
</View>
))}
<Button title="Add Preference" onPress={() => setShowAddPreferenceModal(true)} />
</View>

Files: shaker/graphql/mutations/ (to be created)

Required Mutations:

  • CreateGuest (C24)
  • UpdateGuest
  • TrackGuestRSVP (C26)
  • SetGuestPreferences (C27)
  • SetAttendanceEstimate (C28)

Currently all operations use mock/in-memory data.

  1. Fix Add Guest functionality - Currently completely broken
  2. Fix data storage consistency - Two systems cause confusion
  3. Add state refresh after operations - UI doesn’t update after changes
  1. Implement AttendanceEstimate auto-update - Core requirement of story
  2. Add preferences management UI - Currently only displayed, not editable
  1. Add guest import functionality (mentioned in user guide but not implemented)
  2. Add guest tags/grouping (mentioned in user guide)
  3. Add guest communication features (email/message, mentioned in user guide)
  4. Add guest analytics (mentioned in user guide)
  1. Add data persistence (AsyncStorage or backend)
  2. GraphQL mutation integration
  3. Error handling improvements
  4. Loading states during operations
  • ⚠️ CreateGuestList (C23) - Function exists, not integrated with UI
  • ⚠️ AddGuest (C24) - Function exists, UI broken (doesn’t call function)
  • TrackGuestRSVP (C26) - Function exists and works via UI
  • SetAttendanceEstimate (C28) - Not implemented (attendance not auto-updated)
  • ⚠️ SetGuestPreferences (C27) - Function exists, no UI to use it

Data Layer Tests: ✅ Comprehensive test suite exists (shaker/data/guests/__tests__/guestData.test.ts)

  • Tests for all CRUD operations
  • Tests for RSVP status updates
  • Tests for preferences management
  • Tests for statistics calculation
  • Tests for filtering

UI Tests: ❌ Not found

  • No tests for guest list screen
  • No tests for edit guest screen
  • No integration tests for guest workflows

The Manage Guests for Event story has strong data layer implementation with comprehensive CRUD operations and good test coverage. The UI is well-designed with excellent UX features like filtering, quick actions, and visual feedback. However, there are critical gaps that prevent full functionality:

  1. Add Guest is broken - Shows success but doesn’t save (critical bug)
  2. AttendanceEstimate not auto-updated - Core requirement not met
  3. Preferences cannot be edited - Data layer supports it, UI doesn’t
  4. Data storage inconsistency - Two systems cause confusion

Estimated Effort to Complete: 4-6 hours

  • Fix add guest: 30 minutes
  • Fix data storage: 1 hour
  • Implement attendance sync: 1 hour
  • Add preferences UI: 2 hours
  • Testing and edge cases: 1 hour

Overall Completion: ~70%

  • Data layer: 95% complete
  • UI display: 90% complete
  • UI functionality: 60% complete
  • Integration: 40% complete