Skip to main content

Mobile Address Management System

Overview

This document outlines the comprehensive address management system implemented for the ADHD medication management app. The solution provides unified address handling for both patient settings and order delivery addresses with offline-first architecture and automatic sync.

Architecture Components

1. Unified Type System (lib/types/Address.ts)

  • BaseAddress: Core address fields shared across all address types
  • LocalAddress: Extends BaseAddress with sync tracking for local storage
  • PatientAddress: Database representation with audit fields
  • OrderDeliveryAddress: Specialized for order delivery with additional fields

2. Local Storage Service (lib/services/LocalAddressService.ts)

Key Features:
  • CRUD operations for patient addresses
  • Automatic default address management (only one default per patient)
  • Sync status tracking (pending, synced, error)
  • Local UID generation for offline creation
  • Data persistence using AsyncStorage
Main Methods:
  • getAddresses(): Load all addresses
  • createAddress(): Create new address
  • updateAddress(): Update existing address
  • deleteAddress(): Delete address
  • setDefaultAddress(): Set address as default
  • getAddressesNeedingSync(): Get addresses pending sync

3. Database Schema

patient_addresses Table:
  • Full address information with audit trails
  • Foreign key to patients table
  • RLS policies for patient and doctor access
  • Triggers for default address enforcement
  • Automatic timestamp updates
Security Features:
  • Patients can only access their own addresses
  • Doctors can read addresses for their clinic’s patients
  • Automatic enforcement of single default address per patient

4. Sync Integration (lib/services/SyncService.ts)

Enhanced Sync Process:
  1. Prepare address sync payload from pending local changes
  2. Send to Edge Function with medication sync
  3. Process address CRUD operations on server
  4. Return updated address list
  5. Update local storage with synced data
Sync Payload Structure:
  • addresses_to_create: New addresses to insert
  • addresses_to_update: Existing addresses to update
  • addresses_to_delete: Address IDs to remove

5. Edge Function Updates (packages/supabase/functions/mobile-application-patient-sync/index.ts)

New Functionality:
  • Process address sync operations before data fetch
  • Handle address creation, updates, and deletion
  • Maintain data integrity with patient ownership checks
  • Return complete address list with sync response

6. React Hook (hooks/usePatientAddresses.ts)

Comprehensive Address Management:
  • Load addresses from local storage
  • Create, update, delete operations with automatic sync
  • Default address management
  • Error handling and loading states
  • Sync status tracking
  • Event-driven updates from sync service

Integration Points

1. Settings Page Integration

Replace the existing mock data in app/delivery-addresses.tsx:
import { usePatientAddresses } from '@/hooks/usePatientAddresses';

export default function DeliveryAddressesScreen() {
  const { 
    addresses, 
    isLoading, 
    createAddress, 
    updateAddress, 
    deleteAddress, 
    setDefaultAddress 
  } = usePatientAddresses();

  // Use real addresses instead of mock data
  // Implement CRUD operations using the hook methods
}

2. Order Flow Integration

Update app/reorder/delivery-address.tsx:
import { usePatientAddresses } from '@/hooks/usePatientAddresses';
import { useOrderContext } from '@/lib/contexts/OrderContext';

export default function DeliveryAddressScreen() {
  const { addresses, createAddress } = usePatientAddresses();
  const { updateDeliveryAddress } = useOrderContext();

  // Load real addresses instead of hardcoded ones
  // Allow selection from existing addresses
  // Convert selected address to OrderDeliveryAddress format
}

3. Order Context Integration

The existing OrderContext already supports delivery addresses:
// Already implemented in lib/contexts/OrderContext.tsx
const updateDeliveryAddress = async (address: OrderDeliveryAddress) => {
  // Updates draft order with selected delivery address
};

Data Flow

1. Address Creation Flow

User Creates Address → LocalAddressService.createAddress() → 
AsyncStorage → usePatientAddresses Hook → Auto Sync → 
Edge Function → Database → Sync Response → Local Update

2. Order Address Selection Flow

User Selects Address → Convert to OrderDeliveryAddress → 
OrderContext.updateDeliveryAddress() → LocalOrderService → 
Draft Order Storage → Order Completion → Final Sync

3. Sync Flow

SyncService.performSync() → Prepare Address Payload → 
Edge Function → Address CRUD Operations → 
Return Updated Data → Update Local Storage → Notify Hooks

Benefits

1. Unified Management

  • Single source of truth for all address types
  • Consistent data structure across settings and orders
  • Shared validation and business logic

2. Offline-First

  • Addresses work without internet connection
  • Automatic sync when connection restored
  • Conflict resolution through server-side validation

3. User Experience

  • Seamless address reuse between settings and orders
  • Default address selection
  • Real-time sync status indicators

4. Data Integrity

  • Single default address enforcement
  • Patient data isolation
  • Audit trail for all changes

5. Scalability

  • Easy to extend with additional address types
  • Supports multiple addresses per patient
  • Ready for future features (address validation, geolocation, etc.)

Implementation Status

Completed:
  • Type system and interfaces
  • Local storage service
  • Database schema and migrations
  • Sync service integration
  • Edge function updates
  • React hook implementation
🔄 Next Steps:
  1. Update settings page to use real addresses
  2. Update order flow to load existing addresses
  3. Test sync functionality with database
  4. Add address validation (optional)
  5. Implement address search/autocomplete (optional)

Testing

To test the address system:
  1. Database Setup:
    cd packages/supabase
    supabase db reset
    supabase migration up
    
  2. Create Test Addresses:
    const { createAddress } = usePatientAddresses();
    await createAddress({
      name: "Home",
      address_line_1: "123 Main St",
      city: "London",
      postal_code: "SW1A 1AA",
      country: "United Kingdom",
      type: "home",
      is_default: true
    });
    
  3. Verify Sync:
    • Check local storage for address data
    • Verify database insertion after sync
    • Test offline/online scenarios
This solution provides a robust, scalable address management system that seamlessly integrates with your existing offline-first architecture while maintaining data consistency and user experience.