Merge branch 'dev' into 312-feature-integrate-google-maps-places-autocomplete-for-hub-address-validation
This commit is contained in:
@@ -94,3 +94,6 @@ export 'src/entities/profile/experience_skill.dart';
|
||||
export 'src/adapters/profile/bank_account_adapter.dart';
|
||||
export 'src/adapters/profile/tax_form_adapter.dart';
|
||||
export 'src/adapters/financial/payment_adapter.dart';
|
||||
|
||||
// Exceptions
|
||||
export 'src/exceptions/app_exception.dart';
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
/// Base sealed class for all application exceptions.
|
||||
///
|
||||
/// Provides type-safe error handling with user-friendly message keys.
|
||||
/// Technical details are captured for logging but never shown to users.
|
||||
sealed class AppException implements Exception {
|
||||
const AppException({
|
||||
required this.code,
|
||||
this.technicalMessage,
|
||||
});
|
||||
|
||||
/// Unique error code for logging/tracking (e.g., "AUTH_001")
|
||||
final String code;
|
||||
|
||||
/// Technical details for developers (never shown to users)
|
||||
final String? technicalMessage;
|
||||
|
||||
/// Returns the localization key for user-friendly message
|
||||
String get messageKey;
|
||||
|
||||
@override
|
||||
String toString() => 'AppException($code): $technicalMessage';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// AUTH EXCEPTIONS
|
||||
// ============================================================
|
||||
|
||||
/// Base class for authentication-related exceptions.
|
||||
sealed class AuthException extends AppException {
|
||||
const AuthException({required super.code, super.technicalMessage});
|
||||
}
|
||||
|
||||
/// Thrown when email/password combination is incorrect.
|
||||
class InvalidCredentialsException extends AuthException {
|
||||
const InvalidCredentialsException({String? technicalMessage})
|
||||
: super(code: 'AUTH_001', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.invalid_credentials';
|
||||
}
|
||||
|
||||
/// Thrown when attempting to register with an email that already exists.
|
||||
class AccountExistsException extends AuthException {
|
||||
const AccountExistsException({String? technicalMessage})
|
||||
: super(code: 'AUTH_002', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.account_exists';
|
||||
}
|
||||
|
||||
/// Thrown when the user session has expired.
|
||||
class SessionExpiredException extends AuthException {
|
||||
const SessionExpiredException({String? technicalMessage})
|
||||
: super(code: 'AUTH_003', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.session_expired';
|
||||
}
|
||||
|
||||
/// Thrown when user profile is not found in database after Firebase auth.
|
||||
class UserNotFoundException extends AuthException {
|
||||
const UserNotFoundException({String? technicalMessage})
|
||||
: super(code: 'AUTH_004', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.user_not_found';
|
||||
}
|
||||
|
||||
/// Thrown when user is not authorized for the current app (wrong role).
|
||||
class UnauthorizedAppException extends AuthException {
|
||||
const UnauthorizedAppException({String? technicalMessage})
|
||||
: super(code: 'AUTH_005', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.unauthorized_app';
|
||||
}
|
||||
|
||||
/// Thrown when password doesn't meet security requirements.
|
||||
class WeakPasswordException extends AuthException {
|
||||
const WeakPasswordException({String? technicalMessage})
|
||||
: super(code: 'AUTH_006', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.weak_password';
|
||||
}
|
||||
|
||||
/// Thrown when sign-up process fails.
|
||||
class SignUpFailedException extends AuthException {
|
||||
const SignUpFailedException({String? technicalMessage})
|
||||
: super(code: 'AUTH_007', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.sign_up_failed';
|
||||
}
|
||||
|
||||
/// Thrown when sign-in process fails.
|
||||
class SignInFailedException extends AuthException {
|
||||
const SignInFailedException({String? technicalMessage})
|
||||
: super(code: 'AUTH_008', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.sign_in_failed';
|
||||
}
|
||||
|
||||
/// Thrown when email exists but password doesn't match.
|
||||
class PasswordMismatchException extends AuthException {
|
||||
const PasswordMismatchException({String? technicalMessage})
|
||||
: super(code: 'AUTH_009', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.password_mismatch';
|
||||
}
|
||||
|
||||
/// Thrown when account exists only with Google provider (no password).
|
||||
class GoogleOnlyAccountException extends AuthException {
|
||||
const GoogleOnlyAccountException({String? technicalMessage})
|
||||
: super(code: 'AUTH_010', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.google_only_account';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// HUB EXCEPTIONS
|
||||
// ============================================================
|
||||
|
||||
/// Base class for hub-related exceptions.
|
||||
sealed class HubException extends AppException {
|
||||
const HubException({required super.code, super.technicalMessage});
|
||||
}
|
||||
|
||||
/// Thrown when attempting to delete a hub that has active orders.
|
||||
class HubHasOrdersException extends HubException {
|
||||
const HubHasOrdersException({String? technicalMessage})
|
||||
: super(code: 'HUB_001', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.hub.has_orders';
|
||||
}
|
||||
|
||||
/// Thrown when hub is not found.
|
||||
class HubNotFoundException extends HubException {
|
||||
const HubNotFoundException({String? technicalMessage})
|
||||
: super(code: 'HUB_002', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.hub.not_found';
|
||||
}
|
||||
|
||||
/// Thrown when hub creation fails.
|
||||
class HubCreationFailedException extends HubException {
|
||||
const HubCreationFailedException({String? technicalMessage})
|
||||
: super(code: 'HUB_003', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.hub.creation_failed';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// ORDER EXCEPTIONS
|
||||
// ============================================================
|
||||
|
||||
/// Base class for order-related exceptions.
|
||||
sealed class OrderException extends AppException {
|
||||
const OrderException({required super.code, super.technicalMessage});
|
||||
}
|
||||
|
||||
/// Thrown when order creation is attempted without a hub.
|
||||
class OrderMissingHubException extends OrderException {
|
||||
const OrderMissingHubException({String? technicalMessage})
|
||||
: super(code: 'ORDER_001', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.order.missing_hub';
|
||||
}
|
||||
|
||||
/// Thrown when order creation is attempted without a vendor.
|
||||
class OrderMissingVendorException extends OrderException {
|
||||
const OrderMissingVendorException({String? technicalMessage})
|
||||
: super(code: 'ORDER_002', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.order.missing_vendor';
|
||||
}
|
||||
|
||||
/// Thrown when order creation fails.
|
||||
class OrderCreationFailedException extends OrderException {
|
||||
const OrderCreationFailedException({String? technicalMessage})
|
||||
: super(code: 'ORDER_003', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.order.creation_failed';
|
||||
}
|
||||
|
||||
/// Thrown when shift creation fails.
|
||||
class ShiftCreationFailedException extends OrderException {
|
||||
const ShiftCreationFailedException({String? technicalMessage})
|
||||
: super(code: 'ORDER_004', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.order.shift_creation_failed';
|
||||
}
|
||||
|
||||
/// Thrown when order is missing required business context.
|
||||
class OrderMissingBusinessException extends OrderException {
|
||||
const OrderMissingBusinessException({String? technicalMessage})
|
||||
: super(code: 'ORDER_005', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.order.missing_business';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// PROFILE EXCEPTIONS
|
||||
// ============================================================
|
||||
|
||||
/// Base class for profile-related exceptions.
|
||||
sealed class ProfileException extends AppException {
|
||||
const ProfileException({required super.code, super.technicalMessage});
|
||||
}
|
||||
|
||||
/// Thrown when staff profile is not found.
|
||||
class StaffProfileNotFoundException extends ProfileException {
|
||||
const StaffProfileNotFoundException({String? technicalMessage})
|
||||
: super(code: 'PROFILE_001', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.profile.staff_not_found';
|
||||
}
|
||||
|
||||
/// Thrown when business profile is not found.
|
||||
class BusinessNotFoundException extends ProfileException {
|
||||
const BusinessNotFoundException({String? technicalMessage})
|
||||
: super(code: 'PROFILE_002', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.profile.business_not_found';
|
||||
}
|
||||
|
||||
/// Thrown when profile update fails.
|
||||
class ProfileUpdateFailedException extends ProfileException {
|
||||
const ProfileUpdateFailedException({String? technicalMessage})
|
||||
: super(code: 'PROFILE_003', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.profile.update_failed';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// SHIFT EXCEPTIONS
|
||||
// ============================================================
|
||||
|
||||
/// Base class for shift-related exceptions.
|
||||
sealed class ShiftException extends AppException {
|
||||
const ShiftException({required super.code, super.technicalMessage});
|
||||
}
|
||||
|
||||
/// Thrown when no open roles are available for a shift.
|
||||
class NoOpenRolesException extends ShiftException {
|
||||
const NoOpenRolesException({String? technicalMessage})
|
||||
: super(code: 'SHIFT_001', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.shift.no_open_roles';
|
||||
}
|
||||
|
||||
/// Thrown when application for shift is not found.
|
||||
class ApplicationNotFoundException extends ShiftException {
|
||||
const ApplicationNotFoundException({String? technicalMessage})
|
||||
: super(code: 'SHIFT_002', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.shift.application_not_found';
|
||||
}
|
||||
|
||||
/// Thrown when no active shift is found for clock out.
|
||||
class NoActiveShiftException extends ShiftException {
|
||||
const NoActiveShiftException({String? technicalMessage})
|
||||
: super(code: 'SHIFT_003', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.shift.no_active_shift';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// NETWORK/GENERIC EXCEPTIONS
|
||||
// ============================================================
|
||||
|
||||
/// Thrown when there is no network connection.
|
||||
class NetworkException extends AppException {
|
||||
const NetworkException({String? technicalMessage})
|
||||
: super(code: 'NET_001', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.generic.no_connection';
|
||||
}
|
||||
|
||||
/// Thrown when an unexpected error occurs.
|
||||
class UnknownException extends AppException {
|
||||
const UnknownException({String? technicalMessage})
|
||||
: super(code: 'UNKNOWN', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.generic.unknown';
|
||||
}
|
||||
|
||||
/// Thrown when user is not authenticated.
|
||||
class NotAuthenticatedException extends AppException {
|
||||
const NotAuthenticatedException({String? technicalMessage})
|
||||
: super(code: 'AUTH_NOT_LOGGED', technicalMessage: technicalMessage);
|
||||
|
||||
@override
|
||||
String get messageKey => 'errors.auth.not_authenticated';
|
||||
}
|
||||
Reference in New Issue
Block a user