feat/real-profile-stats

Summary

Profile screens previously showed “0 Follower” and “0 Seguiti” for every user because UserStats() was hardcoded with zeros throughout the codebase. This feature wires follower/following/events-attended counts to real Supabase queries.

Problem

Every location that mapped a Supabase profile row to a User model called stats: UserStats() — the zero-default constructor. The profile screen displayed these zeros as the user’s social stats.

Solution

user_api_service.dart

Added _fetchUserStats(String userId) — runs three parallel queries via Future.wait:

  1. SELECT * FROM user_follows WHERE following_id = userId → follower count
  2. SELECT * FROM user_follows WHERE follower_id = userId → following count
  3. SELECT * FROM event_attendees WHERE user_id = userId AND status = 'going' → events attended

The three queries run concurrently so total latency is ~1 round-trip extra.

Why not PostgREST embedded counts? The user_follows FKs reference auth.users(id), not profiles(id). PostgREST can’t traverse this indirect relationship for embedded counts from the profiles table.

Updated getCurrentUser() and getUserById() to run profile fetch + stats fetch in parallel, then copyWith(stats: stats).

List-context methods (searchUsers, getSuggestedUsers, getUserFollowers, getUserFollowing) intentionally keep UserStats() — stats aren’t shown in list tiles and fetching them for 20 users would be 60 extra queries.

auth_notifier.dartrefreshUser() now re-fetches from DB

Previously refreshUser() returned the in-memory cached user (always zero stats). Now it calls UserApiService().getCurrentUser() which includes real stats. Called by profile_screen.dart on init.

auth_service.dart — profile fetch at login now includes stats

_fetchUserProfile(userId) now delegates to UserApiService().getUserById(userId) instead of a bare profiles.select(). This means the user object stored at login already has accurate stats.

After updateProfile(), stats are preserved by re-fetching the full user with getUserById() before saving to local storage.

Affected UI

  • profile_screen.dart — “Follower” / “Seguiti” / “Amici” stat columns
  • public_profile_screen.dart — same columns on other users’ profiles
  • Any screen using user.followersCount or user.followingCount