Skip to content

Commit d7c9387

Browse files
authored
Merge pull request #21 from jnnabugwu/dev
feat: profile pic download complete
2 parents 91d9c83 + 8e8d77e commit d7c9387

File tree

14 files changed

+347
-201
lines changed

14 files changed

+347
-201
lines changed

deploy.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash
2+
3+
# Exit on error
4+
set -e
5+
6+
echo "🚀 Starting deployment process for Athlete Alumni app..."
7+
8+
# Clean any previous builds
9+
echo "🧹 Cleaning previous builds..."
10+
flutter clean
11+
12+
# Get dependencies
13+
echo "📦 Getting dependencies..."
14+
flutter pub get
15+
16+
# Build the web app in release mode
17+
echo "🔨 Building web app in release mode..."
18+
flutter build web --release
19+
20+
# Verify the build
21+
if [ -d "build/web" ]; then
22+
echo "✅ Build completed successfully!"
23+
else
24+
echo "❌ Build failed. Directory build/web not found."
25+
exit 1
26+
fi
27+
28+
# Prompt for deployment
29+
read -p "Do you want to deploy to Firebase now? (y/n) " -n 1 -r
30+
echo
31+
if [[ $REPLY =~ ^[Yy]$ ]]; then
32+
echo "🔥 Deploying to Firebase..."
33+
firebase deploy --only hosting
34+
35+
echo "🎉 Deployment complete! Your app should be available shortly."
36+
echo "Visit https://athlete-alumni.web.app to see your deployed app."
37+
else
38+
echo "📋 Deployment skipped. You can manually deploy later with:"
39+
echo "firebase deploy --only hosting"
40+
fi
41+
42+
echo "Done! 🏁"

lib/core/di/injection.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:athlete_alumni/features/athletes/presentation/bloc/filter_athletes_bloc.dart';
2+
import 'package:athlete_alumni/features/profile/domain/usecases/get_profile_image_url_usecase.dart';
23
import 'package:get_it/get_it.dart';
34
import 'package:http/http.dart' as http;
45
import 'package:supabase_flutter/supabase_flutter.dart';
@@ -83,6 +84,7 @@ Future<void> _initProfile() async {
8384
getProfileUseCase: sl<GetProfileUseCase>(),
8485
updateProfileUseCase: sl<UpdateProfileUseCase>(),
8586
uploadProfileImageUseCase: sl<UploadProfileImageUseCase>(),
87+
getProfileImageUrlUseCase: sl<GetProfileImageUrlUseCase>(),
8688
));
8789

8890
sl.registerFactory(() => EditProfileBloc(
@@ -100,6 +102,7 @@ Future<void> _initProfile() async {
100102
sl.registerLazySingleton(() => GetProfileUseCase());
101103
sl.registerLazySingleton(() => UpdateProfileUseCase(sl<ProfileRepository>()));
102104
sl.registerLazySingleton(() => UploadProfileImageUseCase(sl<ProfileRepository>()));
105+
sl.registerLazySingleton(() => GetProfileImageUrlUseCase(sl<ProfileRepository>()));
103106

104107
// Repository
105108
sl.registerLazySingleton<ProfileRepository>(() => ProfileRepositoryImpl(

lib/core/router/app_router.dart

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:async';
22
import 'package:athlete_alumni/features/athletes/presentation/bloc/athlete_bloc.dart';
33
import 'package:athlete_alumni/features/athletes/presentation/bloc/filter_athletes_bloc.dart';
4+
import 'package:athlete_alumni/features/profile/domain/usecases/get_profile_image_url_usecase.dart';
45
import 'package:flutter/material.dart';
56
import 'package:flutter_bloc/flutter_bloc.dart';
67
import 'package:go_router/go_router.dart';
@@ -41,56 +42,44 @@ final appRouter = GoRouter(
4142

4243
// Redirect based on authentication state
4344
redirect: (context, state) {
44-
debugPrint("Router.redirect called for path: ${state.uri.path}");
45-
debugPrint("Router.redirect extra: ${state.extra}");
46-
4745
// Development bypass
4846
final bool isDevBypass = state.extra != null &&
4947
state.extra is Map &&
5048
(state.extra as Map).containsKey('devBypass') &&
5149
(state.extra as Map)['devBypass'] == true;
5250

5351
if (isDevBypass) {
54-
debugPrint("Router: Dev bypass detected, skipping auth checks");
5552
return null;
5653
}
5754

5855
// Get current auth state
5956
final authBloc = sl<AuthBloc>();
6057
final authState = authBloc.state;
6158
final authStatus = authState.status;
62-
debugPrint("Router: Current auth status = $authStatus");
6359

6460
// Don't redirect while we're waiting for the auth state
6561
if (authStatus == AuthStatus.initial || authStatus == AuthStatus.loading) {
66-
debugPrint("Router: Auth state is $authStatus, waiting for final state");
6762
return null;
6863
}
6964

7065
final isLoggedIn = authStatus == AuthStatus.authenticated;
71-
debugPrint("Router: isLoggedIn = $isLoggedIn");
7266

7367
// Check if the user is going to public routes that don't require authentication
7468
final isPublicRoute = state.uri.path == RouteConstants.login ||
7569
state.uri.path == RouteConstants.register ||
7670
state.uri.path == RouteConstants.passwordReset ||
7771
state.uri.path.startsWith('/password-reset/');
7872

79-
debugPrint("Router: isPublicRoute = $isPublicRoute for ${state.uri.path}");
80-
8173
// If not logged in and not going to a public route, redirect to login
8274
if (!isLoggedIn && !isPublicRoute) {
83-
debugPrint("Router: Not logged in and not going to a public route, redirecting to login");
8475
return RouteConstants.login;
8576
}
8677

8778
// If logged in and going to login/register, redirect to home
8879
if (isLoggedIn && (state.uri.path == RouteConstants.login || state.uri.path == RouteConstants.register)) {
89-
debugPrint("Router: Logged in and going to login/register, redirecting to home");
9080
return RouteConstants.home;
9181
}
9282

93-
debugPrint("Router: No redirect needed for ${state.uri.path}");
9483
return null;
9584
},
9685

@@ -144,8 +133,6 @@ final appRouter = GoRouter(
144133
// Check if this is a dev bypass
145134
final bool isDevBypass = state.extra != null && state.extra is Map && (state.extra as Map).containsKey('devBypass');
146135

147-
debugPrint("Profile Route: Building with id=$id, extras=${state.extra}");
148-
149136
// If dev bypass, we don't check if it's own profile since there's no real authentication
150137
final isOwnProfile = isDevBypass ? true : _isOwnProfile(id);
151138

@@ -154,6 +141,7 @@ final appRouter = GoRouter(
154141
getProfileUseCase: sl<GetProfileUseCase>(),
155142
updateProfileUseCase: sl<UpdateProfileUseCase>(),
156143
uploadProfileImageUseCase: sl<UploadProfileImageUseCase>(),
144+
getProfileImageUrlUseCase: sl<GetProfileImageUrlUseCase>(),
157145
),
158146
child: ProfileScreen(
159147
athleteId: id,
@@ -168,7 +156,6 @@ final appRouter = GoRouter(
168156
name: 'editProfile',
169157
builder: (context, state) {
170158
final id = state.pathParameters['id'] ?? '';
171-
debugPrint("Edit Profile Route: Building with id=$id");
172159

173160
// Check if this is a temporary user ID
174161
final bool isTemporaryId = id.startsWith('user-') ||
@@ -184,6 +171,7 @@ final appRouter = GoRouter(
184171
getProfileUseCase: sl<GetProfileUseCase>(),
185172
updateProfileUseCase: sl<UpdateProfileUseCase>(),
186173
uploadProfileImageUseCase: sl<UploadProfileImageUseCase>(),
174+
getProfileImageUrlUseCase: sl<GetProfileImageUrlUseCase>(),
187175
);
188176

189177
if (isTemporaryId) {
@@ -212,7 +200,6 @@ final appRouter = GoRouter(
212200
if (currentUser != null) {
213201
final userData = currentUser.userMetadata;
214202
if (userData != null) {
215-
debugPrint("Edit Profile Route: Found user metadata: $userData");
216203
fullName = userData['full_name'] as String?;
217204
username = userData['username'] as String?;
218205
college = userData['college'] as String?;
@@ -227,18 +214,15 @@ final appRouter = GoRouter(
227214
if (username == null) {
228215
// We can't use await here, so we'll just use any data we already have
229216
// and let the ProfileBloc handle fetching additional data
230-
debugPrint("Edit Profile Route: Could not get username from metadata, will attempt fetch in ProfileBloc");
231217
}
232218
}
233219
}
234220

235221
// Provide defaults for username if not found to avoid database errors
236222
if (username == null) {
237223
username = "user_${DateTime.now().millisecondsSinceEpoch.toString().substring(0, 8)}";
238-
debugPrint("Edit Profile Route: Generated default username: $username");
239224
}
240225

241-
debugPrint("Edit Profile Route: Initializing new profile for temporary ID: $id");
242226
profileBloc.add(InitializeNewProfileEvent(
243227
authUserId: id,
244228
email: email,
@@ -249,7 +233,6 @@ final appRouter = GoRouter(
249233
));
250234
} else {
251235
// For regular IDs, load the profile data
252-
debugPrint("Edit Profile Route: Loading profile data for ID: $id");
253236
profileBloc.add(GetProfileEvent(id));
254237
}
255238

@@ -281,7 +264,6 @@ final appRouter = GoRouter(
281264

282265
// Handle error state - initialize with default data for new users
283266
if (profileState is ProfileError && isTemporaryId) {
284-
debugPrint("Edit Profile Route: Creating default athlete data for temporary ID: $id");
285267

286268
// Create minimal athlete data for the form
287269
final authBloc = sl<AuthBloc>();
@@ -334,8 +316,6 @@ final appRouter = GoRouter(
334316
GoRoute(
335317
path: RouteConstants.myProfile,
336318
redirect: (context, state) {
337-
debugPrint("MyProfile.redirect called with extra: ${state.extra}");
338-
339319
// Check if this is a dev bypass
340320
final bool isDevBypass = state.extra != null &&
341321
state.extra is Map &&
@@ -344,7 +324,6 @@ final appRouter = GoRouter(
344324

345325
// For dev bypass, use a mock ID
346326
if (isDevBypass) {
347-
debugPrint("MyProfile Route: Dev bypass detected, using mock ID");
348327
return '/profile/mock-id-123';
349328
}
350329

@@ -354,31 +333,20 @@ final appRouter = GoRouter(
354333

355334
// We need to handle unauthenticated users
356335
if (authState.status == AuthStatus.unauthenticated) {
357-
debugPrint("MyProfile Route: User is not authenticated, redirecting to login");
358336
return RouteConstants.login;
359337
}
360338

361339
// If we have athlete data with an ID, use that ID
362340
if (authState.athlete != null && authState.athlete!.id.isNotEmpty) {
363341
final athleteId = authState.athlete!.id;
364-
debugPrint("MyProfile Route: User has athlete ID: $athleteId, redirecting");
365342
return '/profile/$athleteId';
366343
}
367344

368-
// // For authenticated users with no athlete data, generate a unique ID
369-
// if (authState.status == AuthStatus.authenticated && authState.athlete?.id == null) {
370-
// final uniqueId = 'user-${DateTime.now().millisecondsSinceEpoch}';
371-
// debugPrint("MyProfile Route: Generating unique ID for user: $uniqueId");
372-
// return '/profile/$uniqueId';
373-
// }
374-
375345
// Auth is still loading, use the builder to show loading screen
376-
debugPrint("MyProfile Route: Auth state is ${authState.status}, using loading screen");
377346
return state.uri.path; // Return current path to force using the builder
378347
},
379348
// Add a builder as a fallback to prevent it from being a redirect-only route
380349
builder: (context, state) {
381-
debugPrint("MyProfile Route: Builder called - this should only happen when loading auth state");
382350
// When auth is loading, show the ProfileLoadingScreen which will auto-navigate when auth is ready
383351
return const ProfileLoadingScreen();
384352
},
@@ -442,11 +410,9 @@ bool _isOwnProfile(String profileId) {
442410

443411
// For Google Sign-In users, we also need to check the email
444412
// Since the router can't do async operations, we'll check the database in the ProfileScreen
445-
debugPrint('Router: Checking profile ID: $profileId vs. current user: ${currentUser.id}');
446413

447414
// If the ID is a temp ID and we have authenticated user, consider it own profile
448415
if (profileId.startsWith('user-') || profileId == 'unknown-user-id') {
449-
debugPrint('Router: Temp ID detected, marking as own profile');
450416
return true;
451417
}
452418
}
@@ -512,14 +478,11 @@ class _ProfileLoadingScreenState extends State<ProfileLoadingScreen> {
512478
_navigationTimer = Timer(const Duration(milliseconds: 300), () {
513479
if (!mounted) return;
514480

515-
debugPrint("ProfileLoadingScreen: Direct navigation attempt");
516-
517481
// Generate a profile ID - either use existing athlete ID or create a new unique one
518482
final String profileId = authState.athlete?.id.isNotEmpty == true
519483
? authState.athlete!.id
520484
: 'user-${DateTime.now().millisecondsSinceEpoch}';
521485

522-
debugPrint("ProfileLoadingScreen: Using profile ID: $profileId");
523486
context.go('/profile/$profileId');
524487
});
525488
}
@@ -556,7 +519,6 @@ class _ProfileLoadingScreenState extends State<ProfileLoadingScreen> {
556519

557520
// Generate a unique ID for the user
558521
final uniqueId = 'user-${DateTime.now().millisecondsSinceEpoch}';
559-
debugPrint("Retry button: Using generated profile ID: $uniqueId");
560522

561523
// Navigate directly to profile with the unique ID
562524
context.go('/profile/$uniqueId');

0 commit comments

Comments
 (0)