This is my app_router.dart
.
I am setting the redirection logic but there is this error of AsyncValue.
The redirection logic is - The methods in my repo - register user and register business- if true or false based on that it will go to the respective page also i want to add the shared preference for persistence.
import 'package:fundsaudit/src/features/Myshop/presentation/myproducts_screen.dart';
import 'package:fundsaudit/src/features/auth/data/firebaseauth_repository.dart';
import 'package:fundsaudit/src/features/auth/presentation/sign_in_screen.dart';
import 'package:fundsaudit/src/features/home/presentation/home_screen.dart';
import 'package:fundsaudit/src/features/registration/data/registration_repository.dart';
import 'package:fundsaudit/src/features/registration/presentation/account_setup_screen.dart';
import 'package:fundsaudit/src/features/registration/presentation/business_setup_screen.dart';
import 'package:fundsaudit/src/routing/go_refresh_stream.dart';
import 'package:go_router/go_router.dart';
import 'package:fundsaudit/bottomNav.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:fundsaudit/src/features/Myshop/presentation/myproducts_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
part "app_router.g.dart";
enum AppRoute {
signIn,
registration,
personalSetup,
businessSetup,
home,
phoneNo,
otp,
}
@riverpod
GoRouter goRouter(GoRouterRef ref) {
final authRepository = ref.watch(firebaseAuthRepositoryProvider);
final registrationRepo = ref.watch(registrationRepoProvider);
return GoRouter(
initialLocation: "/signIn",
debugLogDiagnostics: true,
refreshListenable: GoRouterRefreshStream(authRepository.authStateChanges()),
redirect: (context, state) async {
final currentUser = authRepository.currentUser;
if (currentUser == null) {
return '/signIn';
}
final isUserRegistered = await registrationRepo.registerUser(currentUser.uid);
final isBusinessRegistered = await registrationRepo.registerBusiness(currentUser.uid);
if (!isUserRegistered) {
return '/setup/personal';
} else if (!isBusinessRegistered) {
return '/setup/business';
} else {
return '/home';
}
},
routes: [
GoRoute(
path: '/home',
name: AppRoute.home.name,
pageBuilder: (context, state) => const NoTransitionPage(child: HomeScreen()),
),
GoRoute(
path: '/signIn',
name: AppRoute.signIn.name,
pageBuilder: (context, state) => const NoTransitionPage(child: PhoneNumber()),
routes: [
GoRoute(
path: 'otp/:phoneNo',
name: AppRoute.otp.name,
pageBuilder: (context, state) {
final phoneNo = state.pathParameters['phoneNo']!;
return NoTransitionPage(child: OTPPage(phoneNumber: phoneNo));
},
),
],
),
GoRoute(
path: '/setup/personal',
name: AppRoute.personalSetup.name,
pageBuilder: (context, state) => NoTransitionPage(child: AccountSetupScreen()),
),
GoRoute(
path: '/setup/business',
name: AppRoute.businessSetup.name,
pageBuilder: (context, state) => const NoTransitionPage(child: BusinessSetupScreen()),
),
],
);
}
class RegistrationRepo {
RegistrationRepo(
this._api,
);
final Api? _api;
Future<bool> registerUser(data) async {
if (_api == null) {
debugPrint("API instance not available");
return false; // API not available, registration cannot proceed
}
try {
await _api.post('/auth/registerUser', data);
debugPrint("User registration successful, $data");
return true; // Registration successful
} catch (e) {
debugPrint("Error registering user, $e");
return false; // Registration failed
}
}
Future<bool> registerBusiness(data) async {
if (_api == null) {
debugPrint("API instance not available");
return false;
}
try {
await _api.post('/auth/registerBusiness', data);
debugPrint("Business registration successful, $data");
return true;
} catch (e) {
debugPrint("Error registering business, $e");
return false;
}
}
@riverpod
Future<RegistrationRepo> registrationRepo(RegistrationRepoRef ref) async {
var api = await ref.watch(apiProvider.future);
return RegistrationRepo(api);
}
registrationRepo
returns a future, which makes reading the provider gives you an AsyncValue
.
Since registrationRepo
is only used inside a callback in goRouter
provider, and not directly in the provider body, you can instead use ref.read
directly inside the redirect
callback, and read the future
property of the provider:
@riverpod
GoRouter goRouter(GoRouterRef ref) {
// ...
return GoRouter(
// ...
redirect: (context, state) async {
// ...
// This will give you a `RegistrationRepo`
final registrationRepo = await ref.read(registrationRepoProvider.future);
final isUserRegistered = await registrationRepo.registerUser(currentUser.uid);