feat: standard error handling, web bug fixes, and mock data setup
This commit is contained in:
100
lib/core/utils/snackbar_utils.dart
Normal file
100
lib/core/utils/snackbar_utils.dart
Normal file
@@ -0,0 +1,100 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:doormile/core/theme/app_colors.dart';
|
||||
import 'package:doormile/core/theme/app_theme.dart';
|
||||
|
||||
class SnackbarUtils {
|
||||
static void showError(BuildContext context, String rawError) {
|
||||
String message = _getProfessionalErrorMessage(rawError);
|
||||
|
||||
final snackBar = SnackBar(
|
||||
content: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error_outline_rounded, color: Colors.white, size: 24),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
message,
|
||||
style: AppTheme.bodyMd.copyWith(color: Colors.white, fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
backgroundColor: AppColors.error,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
elevation: 4,
|
||||
duration: const Duration(seconds: 4),
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context)
|
||||
..hideCurrentSnackBar()
|
||||
..showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
static void showSuccess(BuildContext context, String message) {
|
||||
final snackBar = SnackBar(
|
||||
content: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.check_circle_outline_rounded, color: Colors.white, size: 24),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
message,
|
||||
style: AppTheme.bodyMd.copyWith(color: Colors.white, fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
backgroundColor: const Color(0xFF4CAF50), // Green success color
|
||||
behavior: SnackBarBehavior.floating,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
elevation: 4,
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context)
|
||||
..hideCurrentSnackBar()
|
||||
..showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
static String _getProfessionalErrorMessage(String raw) {
|
||||
final lowerRaw = raw.toLowerCase();
|
||||
|
||||
// Check for network errors
|
||||
if (lowerRaw.contains('socketexception') ||
|
||||
lowerRaw.contains('connection refused') ||
|
||||
lowerRaw.contains('failed host lookup') ||
|
||||
lowerRaw.contains('network') ||
|
||||
lowerRaw.contains('timeout')) {
|
||||
return 'Please check your internet connection and try again.';
|
||||
}
|
||||
|
||||
// Common auth and business errors
|
||||
if (lowerRaw.contains('invalid otp') || lowerRaw.contains('incorrect otp')) {
|
||||
return 'The OTP you entered is incorrect. Please try again.';
|
||||
}
|
||||
if (lowerRaw.contains('user not found') || lowerRaw.contains('not registered')) {
|
||||
return 'Account not found. Please check your details.';
|
||||
}
|
||||
if (lowerRaw.contains('already registered') || lowerRaw.contains('exists')) {
|
||||
return 'This phone number is already registered.';
|
||||
}
|
||||
if (lowerRaw.contains('pin')) {
|
||||
return 'Incorrect PIN. Please try again.';
|
||||
}
|
||||
if (lowerRaw.contains('unauthorized') || lowerRaw.contains('expired')) {
|
||||
return 'Your session has expired. Please log in again.';
|
||||
}
|
||||
|
||||
// Default generic server / unknown error
|
||||
return 'Something went wrong. Please try again later.';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user