Schedule an Event Story - Implementation Audit
Schedule an Event Story - Implementation Audit
Section titled “Schedule an Event Story - Implementation Audit”Story: Schedule an Event
Date: 2025-01-27
Status: ⚠️ PARTIALLY IMPLEMENTED - UI Complete, Backend Integration Missing
Executive Summary
Section titled “Executive Summary”The Schedule an Event story has a complete UI implementation with all required form fields and validation. However, events are not persisted to the data layer after creation. The form submission shows success but doesn’t actually save the event, similar to the add_venue issue that was recently fixed.
Acceptance Criteria Review
Section titled “Acceptance Criteria Review”✅ 1. I must provide a Title (Name) for the event
Section titled “✅ 1. I must provide a Title (Name) for the event”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 158-164
- Details:
- TextInput with label “Event Name *”
- Required field validation
- Placeholder: “e.g., Halloween Party 2025”
- Error handling implemented
✅ 2. I must provide a Date for the event
Section titled “✅ 2. I must provide a Date for the event”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 187-195
- Details:
- DateTimePicker with label “Date *”
- Required field validation
- Minimum date validation (prevents past dates)
- Date format validation
✅ 3. I can optionally provide a Start Time and End Time
Section titled “✅ 3. I can optionally provide a Start Time and End Time”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 197-219
- Details:
- Two DateTimePicker components (Start Time and End Time)
- Optional fields (no required validation)
- Time format validation (HH:MM)
- End time validation (must be after start time)
- Side-by-side layout for better UX
✅ 4. I can optionally provide a Description
Section titled “✅ 4. I can optionally provide a Description”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 166-174
- Details:
- TextInput with multiline support
- Optional field
- Placeholder: “Tell us about your event…”
✅ 5. I can optionally provide a Theme
Section titled “✅ 5. I can optionally provide a Theme”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 246-252
- Details:
- Picker component with theme options
- Options loaded from
getThemePickerOptions() - Optional field
✅ 6. I can optionally provide the Venue
Section titled “✅ 6. I can optionally provide the Venue”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 238-244
- Details:
- Picker component with venue options
- Options loaded from
getVenuePickerOptions() - Now includes newly created venues (after recent fix)
- Optional field
✅ 7. I can optionally provide an initial Expected Guest Count
Section titled “✅ 7. I can optionally provide an initial Expected Guest Count”Status: ✅ COMPLETE
- Implementation:
shaker/components/EventForm.tsx - Location: Lines 229-236
- Details:
- TextInput with numeric keyboard
- Optional field
- Validation: must be a number, must be at least 1
- Placeholder: “Number of guests”
⚠️ 8. After creation, the event should be saved in the system
Section titled “⚠️ 8. After creation, the event should be saved in the system”Status: ⚠️ NOT FULLY IMPLEMENTED
-
Issue: Events are not persisted to the data layer, only stored in component state
-
Current State:
Path 1: Add Event Screen (
add-event.tsx)- Form submission creates event object in memory
- Shows success toast and navigates away
- Event is NOT saved anywhere (completely lost)
- Event disappears and cannot be viewed later
Path 2: Inline Form in Events List (
events/index.tsx)- Form submission updates local component state (
setEvents) - Event appears in the list temporarily
- Event is NOT saved to
allEventsarray in data layer - Event is lost on page refresh/navigation
- Event cannot be viewed from event detail screen (doesn’t exist in data layer)
-
Evidence - Add Event Screen:
const handleFormSubmit = useCallback(async (formData: EventFormData) => {setIsLoading(true);try {// Simulate API callawait new Promise(resolve => setTimeout(resolve, 1000));const newEvent: Event = {id: Date.now().toString(),name: formData.name,description: formData.description,date: formData.date,startTime: formData.startTime,endTime: formData.endTime,expectedGuestCount: formData.expectedGuestCount ? parseInt(formData.expectedGuestCount, 10) : undefined,status: 'planned',venue: formData.venueId ? {id: formData.venueId,name: formData.venueId === 'home' ? 'Home Bar' :formData.venueId === 'patio' ? 'Backyard Patio' :formData.venueId === 'living-room' ? 'Living Room' :formData.venueId === 'lime-factory' ? 'LIME Factory' : 'Rooftop Terrace',venueType: formData.venueId === 'lime-factory' ? 'other' : 'residential',capacity: formData.venueId === 'lime-factory' ? 50 : 30,} : undefined,theme: formData.themeId ? {id: formData.themeId,name: formData.themeId === 'tiki' ? 'Tiki Night' :formData.themeId === 'speakeasy' ? 'Speakeasy' :formData.themeId === 'halloween' ? 'Halloween' :formData.themeId === 'dxd-halloween' ? 'DxD Halloween' :formData.themeId === 'thanksgiving' ? 'Thanksgiving' :formData.themeId === 'valentines' ? "Valentine's Day" : 'Fiesta',colorScheme: formData.themeId === 'dxd-halloween' ? 'purple' : 'blue',} : undefined,createdAt: new Date().toISOString(),updatedAt: new Date().toISOString(),};// TODO: Save to backend/state managementsetToast({visible: true,message: 'Event created successfully!',variant: 'success',});// Navigate back to origin screen after toastsetTimeout(() => {if (returnTo) {router.push(returnTo as any);} else {router.back();}}, 1500);} catch (error) {setToast({visible: true,message: 'Failed to save event. Please try again.',variant: 'error',});} finally {setIsLoading(false);}}, [returnTo]); -
Evidence - Events List Screen (Inline Form):
const handleFormSubmit = useCallback(async (formData: EventFormData) => {setIsLoading(true);try {// Simulate API callawait new Promise(resolve => setTimeout(resolve, 1000));const newEvent: Event = {id: editingEvent?.id || Date.now().toString(),name: formData.name,// ... event data ...};if (editingEvent) {setEvents(prevEvents =>prevEvents.map(e => e.id === editingEvent.id ? newEvent : e));} else {setEvents(prevEvents => [newEvent, ...prevEvents]); // Only updates component state}// ... success toast ...} catch (error) {// ... error handling ...} finally {setIsLoading(false);}}, [editingEvent]); -
Missing:
- No
createEventfunction inshaker/data/events/index.ts - No
updateEventfunction inshaker/data/events/index.ts - Events not added to
allEventsarray (data layer) - Events only stored in component-level state
- Events lost on page refresh
- No
-
Impact:
- Events created via
add-event.tsxroute: Completely lost, never appear in list - Events created via inline form: Appear temporarily but lost on refresh
- Events cannot be viewed from event detail screen (don’t exist in data layer)
- Cannot edit events after creation (they don’t persist)
- Breaks the entire event workflow
- Events created via
⚠️ 9. I should be able to view and edit the event details later
Section titled “⚠️ 9. I should be able to view and edit the event details later”Status: ⚠️ PARTIALLY COMPLETE
-
Viewing: ✅ Complete (for existing mock data)
- Event detail screen exists (
shaker/app/(tabs)/events/[id].tsx) - Event list screen exists (
shaker/app/(tabs)/events/index.tsx) - Navigation works correctly
- Can view existing events from mock data
- ⚠️ Cannot view newly created events (they’re not in data layer)
- Event detail screen exists (
-
Editing: ⚠️ Partially Complete
- Edit event screen exists (
shaker/app/(tabs)/events/edit-event.tsx) - Form pre-populates with existing event data
- Form submission shows success but doesn’t persist changes
- No
updateEventfunction in data layer - Changes lost on refresh
- Edit event screen exists (
-
Issues:
- Newly created events cannot be viewed (don’t exist in data layer)
- Edit screen tries to load event via
getEventById()which won’t find newly created events - Even if editing existing events, changes aren’t persisted to data layer
Implementation Details
Section titled “Implementation Details”Files Involved
Section titled “Files Involved”-
UI Components:
- ✅
shaker/components/EventForm.tsx- Complete form implementation - ✅
shaker/app/(tabs)/events/add-event.tsx- Add event screen (doesn’t persist) - ✅
shaker/app/(tabs)/events/edit-event.tsx- Edit event screen (doesn’t persist) - ✅
shaker/app/(tabs)/events/[id].tsx- Event detail screen - ✅
shaker/app/(tabs)/events/index.tsx- Events list screen
- ✅
-
GraphQL Mutation:
- ✅
shaker/graphql/mutations/CreateEvent.graphql- Exists but not used
- ✅
-
Data Layer:
- ❌
shaker/data/events/index.ts- MissingcreateEventfunction - ❌ Missing
updateEventfunction - ✅ Has
getEventByIdfunction - ✅ Has
allEventsmock data array
- ❌
Form Features
Section titled “Form Features”The EventForm includes:
-
Basic Information Card:
- Event Name (required, validated)
- Description (optional, multiline)
-
Date & Time Card:
- Date (required, DateTimePicker with minimum date)
- Start Time (optional, DateTimePicker)
- End Time (optional, DateTimePicker with validation)
-
Event Details Card:
- Expected Guest Count (optional, numeric validation)
- Venue (optional, picker)
- Theme (optional, picker)
Validation
Section titled “Validation”Comprehensive validation implemented:
- ✅ Required fields: Name, Date
- ✅ Time format validation (HH:MM)
- ✅ End time after start time validation
- ✅ Guest count numeric validation
- ✅ Guest count minimum value (>= 1)
- ✅ Date minimum value (prevents past dates)
Data Structure Issues
Section titled “Data Structure Issues”Venue Mapping: The current implementation uses hardcoded venue name mapping:
venue: formData.venueId ? { id: formData.venueId, name: formData.venueId === 'home' ? 'Home Bar' : formData.venueId === 'patio' ? 'Backyard Patio' : formData.venueId === 'living-room' ? 'Living Room' : formData.venueId === 'lime-factory' ? 'LIME Factory' : 'Rooftop Terrace', venueType: formData.venueId === 'lime-factory' ? 'other' : 'residential', capacity: formData.venueId === 'lime-factory' ? 50 : 30,} : undefined,Problem: New venues created via add-venue won’t be properly mapped. Should use getVenueById() to get full venue data.
Theme Mapping: Similar hardcoded theme mapping exists:
theme: formData.themeId ? { id: formData.themeId, name: formData.themeId === 'tiki' ? 'Tiki Night' : formData.themeId === 'speakeasy' ? 'Speakeasy' : formData.themeId === 'halloween' ? 'Halloween' : formData.themeId === 'dxd-halloween' ? 'DxD Halloween' : formData.themeId === 'thanksgiving' ? 'Thanksgiving' : formData.themeId === 'valentines' ? "Valentine's Day" : 'Fiesta', colorScheme: formData.themeId === 'dxd-halloween' ? 'purple' : 'blue',} : undefined,Problem: Should use getThemeById() to get full theme data.
Missing Implementation
Section titled “Missing Implementation”1. Data Layer Function
Section titled “1. Data Layer Function”File: shaker/data/events/index.ts
Required:
/** * Create a new event * Note: This updates mock data. Replace with GraphQL mutation when backend is ready. */export function createEvent(event: Omit<Event, 'id' | 'createdAt' | 'updatedAt'>): Event { const newId = Date.now().toString(); const now = new Date().toISOString();
const newEvent: Event = { ...event, id: newId, createdAt: now, updatedAt: now, };
allEvents.push(newEvent); console.log('✅ Created new event:', newEvent); return newEvent;}2. Update Event Function
Section titled “2. Update Event Function”File: shaker/data/events/index.ts
Required:
/** * Update an existing event * Note: This updates mock data. Replace with GraphQL mutation when backend is ready. */export function updateEvent(eventId: string, updates: Partial<Omit<Event, 'id' | 'createdAt'>>): Event | undefined { const event = allEvents.find((e) => e.id === eventId); if (!event) { return undefined; }
Object.assign(event, updates, { updatedAt: new Date().toISOString(), });
return event;}3. GraphQL Mutation Integration
Section titled “3. GraphQL Mutation Integration”File: shaker/app/(tabs)/events/add-event.tsx
Required Changes:
- Import
useMutationfrom@apollo/client - Import
CreateEventMutationfrom GraphQL file - Import
createEventfrom data layer - Set up mutation hook
- Call mutation in
handleFormSubmit - Add event to mock data as fallback
- Handle success/error states
4. Fix Venue/Theme Mapping
Section titled “4. Fix Venue/Theme Mapping”Files: shaker/app/(tabs)/events/add-event.tsx, shaker/app/(tabs)/events/index.tsx
Current Issue: Hardcoded venue/theme name mapping doesn’t work with newly created venues/themes.
Fix: Use data layer functions to get full venue/theme objects:
getVenueById(formData.venueId)instead of hardcoded mapping (function exists)getThemeById(formData.themeId)instead of hardcoded mapping (function exists ✅)
Note: Both getVenueById() and getThemeById() functions exist in the data layer. The hardcoded mapping should be replaced to support dynamically created venues and themes.
5. Update Edit Event Screen
Section titled “5. Update Edit Event Screen”File: shaker/app/(tabs)/events/edit-event.tsx
Required:
- Import and use
updateEventfunction - Persist changes to data layer
- Update local state if needed
Recommendations
Section titled “Recommendations”Priority 1: Complete Backend Integration
Section titled “Priority 1: Complete Backend Integration”- Add
createEventfunction to data layer - Add
updateEventfunction to data layer - Integrate GraphQL mutation call (optional, fallback to mock data)
- Update form to persist event data
- Fix venue/theme mapping to use data layer functions
Priority 2: Error Handling
Section titled “Priority 2: Error Handling”- Add proper error handling for GraphQL mutation failures
- Show user-friendly error messages
- Handle network errors gracefully
Priority 3: Data Consistency
Section titled “Priority 3: Data Consistency”- Ensure venue data comes from
getVenueById() - Ensure theme data comes from
getThemeById() - Validate venue and theme exist before saving
Related Commands Status
Section titled “Related Commands Status”- ⚠️
ScheduleEvent(C1) - GraphQL mutation exists but not integrated - ✅
DefineEventTheme(C2) - Themes can be selected, theme creation separate story
Conclusion
Section titled “Conclusion”The Schedule an Event story has excellent UI implementation with comprehensive validation and all required fields. The main gap is backend integration - events are not actually saved when created. This prevents the story from being functional, as created events cannot be viewed, edited, or used in the application.
Estimated Effort to Complete: 3-4 hours
- Add data layer functions: 30 minutes
- Fix venue/theme mapping: 30 minutes
- Integrate GraphQL mutation: 1 hour
- Update edit functionality: 1 hour
- Testing and edge cases: 1 hour
Similar to: This issue is identical to the add_venue story that was recently fixed. The same pattern should be applied here.