Skip to content

feat: Add user profile bottom sheet with activity heatmap#122

Merged
RedBlueBird merged 14 commits into
mainfrom
claude/add-user-profile-bottom-sheet-011CUvTsFqJiH69tNAtrzHER
Nov 8, 2025
Merged

feat: Add user profile bottom sheet with activity heatmap#122
RedBlueBird merged 14 commits into
mainfrom
claude/add-user-profile-bottom-sheet-011CUvTsFqJiH69tNAtrzHER

Conversation

@RedBlueBird
Copy link
Copy Markdown
Collaborator

Overview

  • Created ActivityHeatmapView: GitHub-style heatmap with orange theme (#f54900) showing 30-day rolling window of user activity with point-based intensity
  • Created UserProfileViewModel: Data management layer for fetching user profiles, mission results, and badge collections with parallel async fetching
  • Created UserProfileBottomSheetView: Main profile view displaying username, avatar badge, activity heatmap with tooltips, and 4-column badge grid
  • Extended UserSupabase: Added getUserProfile function to fetch any user's data
  • Extended BadgeSupabase: Added fetchUserBadges and fetchBadgesByIds methods for fetching user badge collections
  • Updated NationalRankingView: Added tap handlers to ranking rows and podium positions to open user profiles in bottom sheet
  • Updated TeamRankingView: Added same tap functionality for team rankings
  • All components use UserAvatarView for consistent badge/avatar display
  • Bottom sheet supports .medium and .large detents with swipe-to-dismiss
  • Includes loading states, error handling, and empty state views

Related Issue

N/A

Changes

How to Test

Build & Run

Screenshots/Videos

Points for Review

- Created ActivityHeatmapView: GitHub-style heatmap with orange theme (#f54900)
  showing 30-day rolling window of user activity with point-based intensity
- Created UserProfileViewModel: Data management layer for fetching user profiles,
  mission results, and badge collections with parallel async fetching
- Created UserProfileBottomSheetView: Main profile view displaying username,
  avatar badge, activity heatmap with tooltips, and 4-column badge grid
- Extended UserSupabase: Added getUserProfile function to fetch any user's data
- Extended BadgeSupabase: Added fetchUserBadges and fetchBadgesByIds methods
  for fetching user badge collections
- Updated NationalRankingView: Added tap handlers to ranking rows and podium
  positions to open user profiles in bottom sheet
- Updated TeamRankingView: Added same tap functionality for team rankings
- All components use UserAvatarView for consistent badge/avatar display
- Bottom sheet supports .medium and .large detents with swipe-to-dismiss
- Includes loading states, error handling, and empty state views
- Remove unnecessary optional unwrapping for entry.userId (not optional)
- Replace NavigationView with NavigationStack for iOS 16+ compatibility
- Fix conditional binding errors in ranking tap handlers
- Convert Int64? finalPoints to Int for daily points aggregation
- Change shelterBadgeId to profileBadgeId (correct User model field)
- Rename getShelterBadge() to getProfileBadge() for clarity
- Handle optional finalPoints with nil coalescing
… positioning

- Add weekday labels (Mon-Sun) at the top of heatmap columns
- Align grid cells to correct weekdays using padding cells
- Fix tooltip positioning to appear directly above clicked cell
- Use offset-based positioning instead of absolute position for tooltip
- Add smooth animation for tooltip show/hide
- Increase tooltip display duration to 2.5 seconds
@RedBlueBird RedBlueBird force-pushed the claude/add-user-profile-bottom-sheet-011CUvTsFqJiH69tNAtrzHER branch from 5eb244c to 8b3f71a Compare November 8, 2025 14:56
Changed weekday labels from HStack to LazyVGrid to ensure perfect
alignment with the heatmap grid columns below.
When users tap on a member row in the group details view, it now opens
a bottom sheet showing the user's profile with activity heatmap and
badge collection. Includes haptic feedback on tap.
@RedBlueBird RedBlueBird force-pushed the claude/add-user-profile-bottom-sheet-011CUvTsFqJiH69tNAtrzHER branch 2 times, most recently from d8c0291 to d437e1b Compare November 8, 2025 15:26
@RedBlueBird RedBlueBird force-pushed the claude/add-user-profile-bottom-sheet-011CUvTsFqJiH69tNAtrzHER branch from edf84a3 to d8c0291 Compare November 8, 2025 16:02
RedBlueBird and others added 6 commits November 9, 2025 01:10
Fixed blank sheet issue on first open by starting isLoading as true.
This prevents the "User Not Found" empty state from flashing before
the async fetch begins in the .task modifier.
Changed from .sheet(isPresented:) with optional unwrapping to
.sheet(item:) which properly handles the optional UUID binding.
This prevents the blank sheet issue on first open by ensuring the
sheet content is only created when selectedUserId has a value.

- Removed showUserProfile state variable (no longer needed)
- Updated handleUserTap to only set selectedUserId
- Applied fix to both NationalRankingView and TeamRankingView
Added UUID extension to conform to Identifiable protocol, which is
required by the .sheet(item:) modifier. UUID's id is itself.
UUID already conforms to Identifiable in Foundation, so the custom
extensions were causing redeclaration errors. Removed both extensions.
Created IdentifiableUUID wrapper struct to make UUID work with
.sheet(item:) modifier. UUID's Identifiable conformance may not
be available in the current Swift/iOS version, so this wrapper
provides the necessary conformance.
@RedBlueBird RedBlueBird merged commit 92ada14 into main Nov 8, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants