feat: Update session navigation and enhance error handling in data services

This commit is contained in:
Achintha Isuru
2026-02-17 15:46:52 -05:00
parent 5b78f339a1
commit 631af65a2f
5 changed files with 48 additions and 22 deletions

View File

@@ -52,7 +52,7 @@ class _SessionListenerState extends State<SessionListener> {
// Only show dialog if user was previously authenticated (session expired)
if (_isInitialState) {
_isInitialState = false;
Modular.to.toGetStartedPage();
Modular.to.toClientGetStartedPage();
} else if (!_sessionExpiredDialogShown) {
_sessionExpiredDialogShown = true;
_showSessionExpiredDialog();
@@ -77,7 +77,7 @@ class _SessionListenerState extends State<SessionListener> {
_showSessionErrorDialog(state.errorMessage ?? 'Session error occurred');
} else {
_isInitialState = false;
Modular.to.toInitialPage();
Modular.to.toClientGetStartedPage();
}
break;
@@ -149,7 +149,7 @@ class _SessionListenerState extends State<SessionListener> {
DataConnectService.instance.handleSignOut();
// Navigate to authentication
Modular.to.toInitialPage();
Modular.to.toClientGetStartedPage();
}
@override

View File

@@ -77,7 +77,7 @@ class _SessionListenerState extends State<SessionListener> {
_showSessionErrorDialog(state.errorMessage ?? 'Session error occurred');
} else {
_isInitialState = false;
Modular.to.toInitialPage();
Modular.to.toGetStartedPage();
}
break;
@@ -149,7 +149,7 @@ class _SessionListenerState extends State<SessionListener> {
DataConnectService.instance.handleSignOut();
// Navigate to authentication
Modular.to.toInitialPage();
Modular.to.toGetStartedPage();
}
@override

View File

@@ -83,7 +83,7 @@ class DataConnectService with DataErrorHandler, SessionHandlerMixin {
// 2. Check Cache
if (_cachedBusinessId != null) return _cachedBusinessId!;
// 3. Check Auth Status
// 3. Fetch from Data Connect using Firebase UID
final firebase_auth.User? user = _auth.currentUser;
if (user == null) {
throw const NotAuthenticatedException(
@@ -91,8 +91,24 @@ class DataConnectService with DataErrorHandler, SessionHandlerMixin {
);
}
// 4. Fallback (should ideally not happen if DB is seeded and session is initialized)
// Ideally we'd have a getBusinessByUserId query here.
try {
final fdc.QueryResult<
dc.GetBusinessesByUserIdData,
dc.GetBusinessesByUserIdVariables
>
response = await executeProtected(
() => connector.getBusinessesByUserId(userId: user.uid).execute(),
);
if (response.data.businesses.isNotEmpty) {
_cachedBusinessId = response.data.businesses.first.id;
return _cachedBusinessId!;
}
} catch (e) {
throw Exception('Failed to fetch business ID from Data Connect: $e');
}
// 4. Fallback (should ideally not happen if DB is seeded)
return user.uid;
}

View File

@@ -20,8 +20,12 @@ mixin DataErrorHandler {
try {
return await action().timeout(timeout);
} on TimeoutException {
debugPrint(
'DataErrorHandler: Request timed out after ${timeout.inSeconds}s',
);
throw ServiceUnavailableException(
technicalMessage: 'Request timed out after ${timeout.inSeconds}s');
technicalMessage: 'Request timed out after ${timeout.inSeconds}s',
);
} on SocketException catch (e) {
throw NetworkException(technicalMessage: 'SocketException: ${e.message}');
} on FirebaseException catch (e) {
@@ -32,16 +36,26 @@ mixin DataErrorHandler {
msg.contains('offline') ||
msg.contains('network') ||
msg.contains('connection failed')) {
debugPrint(
'DataErrorHandler: Firebase network error: ${e.code} - ${e.message}',
);
throw NetworkException(
technicalMessage: 'Firebase ${e.code}: ${e.message}');
technicalMessage: 'Firebase ${e.code}: ${e.message}',
);
}
if (code == 'deadline-exceeded') {
debugPrint(
'DataErrorHandler: Firebase timeout error: ${e.code} - ${e.message}',
);
throw ServiceUnavailableException(
technicalMessage: 'Firebase ${e.code}: ${e.message}');
technicalMessage: 'Firebase ${e.code}: ${e.message}',
);
}
debugPrint('DataErrorHandler: Firebase error: ${e.code} - ${e.message}');
// Fallback for other Firebase errors
throw ServerException(
technicalMessage: 'Firebase ${e.code}: ${e.message}');
technicalMessage: 'Firebase ${e.code}: ${e.message}',
);
} catch (e) {
final String errorStr = e.toString().toLowerCase();
if (errorStr.contains('socketexception') ||
@@ -56,15 +70,16 @@ mixin DataErrorHandler {
errorStr.contains('grpc error') ||
errorStr.contains('terminated') ||
errorStr.contains('connectexception')) {
debugPrint('DataErrorHandler: Network-related error: $e');
throw NetworkException(technicalMessage: e.toString());
}
// If it's already an AppException, rethrow it
if (e is AppException) rethrow;
// Debugging: Log unexpected errors
debugPrint('DataErrorHandler: Unhandled exception caught: $e');
throw UnknownException(technicalMessage: e.toString());
}
}

View File

@@ -1,18 +1,15 @@
import 'package:krow_domain/krow_domain.dart' as domain;
class StaffSession {
const StaffSession({required this.user, this.staff, this.ownerId});
final domain.User user;
final domain.Staff? staff;
final String? ownerId;
const StaffSession({
required this.user,
this.staff,
this.ownerId,
});
}
class StaffSessionStore {
StaffSessionStore._();
StaffSession? _session;
StaffSession? get session => _session;
@@ -26,6 +23,4 @@ class StaffSessionStore {
}
static final StaffSessionStore instance = StaffSessionStore._();
StaffSessionStore._();
}