loadUserState method

Future<void> loadUserState()

Loads user-specific balances and basket from FirebaseFirestore.

Fetches the document at users/{uid} and populates local state. If the document doesn't exist, creates an empty scaffold via _persist. All category names are canonicalized via _canon.

Side effects:

  • Sets _balancesLoaded to true on completion
  • Calls notifyListeners to update UI
  • Creates Firestore document for first-time users

Implementation

Future<void> loadUserState() async {
  if (_uid == null) {
    _clear();
    notifyListeners();
    return;
  }

  try {
    final doc = await _db.collection('users').doc(_uid).get();
    final data = doc.data();

    if (data == null) {
      // First-time user: start empty; caps derive on demand
      _clear();
      await _persist(); // create doc scaffold
    } else {
      // balances
      final b = (data['balances'] as Map?) ?? {};
      balances = b.map((k, v) {
        final key = _canon(k.toString());
        final allowed = (v is Map && v['allowed'] is int)
            ? v['allowed'] as int
            : null;
        final used = (v is Map && v['used'] is int) ? v['used'] as int : 0;
        return MapEntry(key, {'allowed': allowed, 'used': used});
      });

      // basket
      final raw = (data['basket'] as List?) ?? [];
      basket
        ..clear()
        ..addAll(
          raw.whereType<Map>().map(
            (m) => {
              'upc': (m['upc'] ?? '').toString(),
              'name': (m['name'] ?? '').toString(),
              'category': _canon((m['category'] ?? '').toString()),
              'qty': (m['qty'] is int) ? m['qty'] as int : 1,
            },
          ),
        );
    }
  } finally {
    _balancesLoaded = true;
    notifyListeners();
  }
}