logout
This commit is contained in:
parent
0a8f8d93bb
commit
b2b2e2b111
38
lib/application/auth/logout/logout_bloc.dart
Normal file
38
lib/application/auth/logout/logout_bloc.dart
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../../domain/auth/auth.dart';
|
||||||
|
|
||||||
|
part 'logout_event.dart';
|
||||||
|
part 'logout_state.dart';
|
||||||
|
part 'logout_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class LogoutBloc extends Bloc<LogoutEvent, LogoutState> {
|
||||||
|
final IAuthRepository _authRepository;
|
||||||
|
LogoutBloc(this._authRepository) : super(LogoutState.initial()) {
|
||||||
|
on<LogoutEvent>(_onLogoutEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onLogoutEvent(LogoutEvent event, Emitter<LogoutState> emit) {
|
||||||
|
return event.map(
|
||||||
|
logout: (e) async {
|
||||||
|
Either<AuthFailure, Unit>? failureOrSuccess;
|
||||||
|
emit(
|
||||||
|
state.copyWith(isLoggingOut: true, logoutFailureOrSuccess: none()),
|
||||||
|
);
|
||||||
|
|
||||||
|
failureOrSuccess = await _authRepository.logout();
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isLoggingOut: false,
|
||||||
|
logoutFailureOrSuccess: optionOf(failureOrSuccess),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
332
lib/application/auth/logout/logout_bloc.freezed.dart
Normal file
332
lib/application/auth/logout/logout_bloc.freezed.dart
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'logout_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LogoutEvent {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({required TResult Function() logout}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({TResult? Function()? logout}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function()? logout,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_Logout value) logout,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_Logout value)? logout,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_Logout value)? logout,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LogoutEventCopyWith<$Res> {
|
||||||
|
factory $LogoutEventCopyWith(
|
||||||
|
LogoutEvent value,
|
||||||
|
$Res Function(LogoutEvent) then,
|
||||||
|
) = _$LogoutEventCopyWithImpl<$Res, LogoutEvent>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LogoutEventCopyWithImpl<$Res, $Val extends LogoutEvent>
|
||||||
|
implements $LogoutEventCopyWith<$Res> {
|
||||||
|
_$LogoutEventCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LogoutImplCopyWith<$Res> {
|
||||||
|
factory _$$LogoutImplCopyWith(
|
||||||
|
_$LogoutImpl value,
|
||||||
|
$Res Function(_$LogoutImpl) then,
|
||||||
|
) = __$$LogoutImplCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LogoutImplCopyWithImpl<$Res>
|
||||||
|
extends _$LogoutEventCopyWithImpl<$Res, _$LogoutImpl>
|
||||||
|
implements _$$LogoutImplCopyWith<$Res> {
|
||||||
|
__$$LogoutImplCopyWithImpl(
|
||||||
|
_$LogoutImpl _value,
|
||||||
|
$Res Function(_$LogoutImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LogoutEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$LogoutImpl implements _Logout {
|
||||||
|
const _$LogoutImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LogoutEvent.logout()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType && other is _$LogoutImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({required TResult Function() logout}) {
|
||||||
|
return logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({TResult? Function()? logout}) {
|
||||||
|
return logout?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function()? logout,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (logout != null) {
|
||||||
|
return logout();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_Logout value) logout,
|
||||||
|
}) {
|
||||||
|
return logout(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_Logout value)? logout,
|
||||||
|
}) {
|
||||||
|
return logout?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_Logout value)? logout,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (logout != null) {
|
||||||
|
return logout(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _Logout implements LogoutEvent {
|
||||||
|
const factory _Logout() = _$LogoutImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LogoutState {
|
||||||
|
Option<Either<AuthFailure, Unit>> get logoutFailureOrSuccess =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
bool get isLoggingOut => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$LogoutStateCopyWith<LogoutState> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LogoutStateCopyWith<$Res> {
|
||||||
|
factory $LogoutStateCopyWith(
|
||||||
|
LogoutState value,
|
||||||
|
$Res Function(LogoutState) then,
|
||||||
|
) = _$LogoutStateCopyWithImpl<$Res, LogoutState>;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
Option<Either<AuthFailure, Unit>> logoutFailureOrSuccess,
|
||||||
|
bool isLoggingOut,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LogoutStateCopyWithImpl<$Res, $Val extends LogoutState>
|
||||||
|
implements $LogoutStateCopyWith<$Res> {
|
||||||
|
_$LogoutStateCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? logoutFailureOrSuccess = null,
|
||||||
|
Object? isLoggingOut = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
logoutFailureOrSuccess: null == logoutFailureOrSuccess
|
||||||
|
? _value.logoutFailureOrSuccess
|
||||||
|
: logoutFailureOrSuccess // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Unit>>,
|
||||||
|
isLoggingOut: null == isLoggingOut
|
||||||
|
? _value.isLoggingOut
|
||||||
|
: isLoggingOut // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LogoutStateImplCopyWith<$Res>
|
||||||
|
implements $LogoutStateCopyWith<$Res> {
|
||||||
|
factory _$$LogoutStateImplCopyWith(
|
||||||
|
_$LogoutStateImpl value,
|
||||||
|
$Res Function(_$LogoutStateImpl) then,
|
||||||
|
) = __$$LogoutStateImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
Option<Either<AuthFailure, Unit>> logoutFailureOrSuccess,
|
||||||
|
bool isLoggingOut,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LogoutStateImplCopyWithImpl<$Res>
|
||||||
|
extends _$LogoutStateCopyWithImpl<$Res, _$LogoutStateImpl>
|
||||||
|
implements _$$LogoutStateImplCopyWith<$Res> {
|
||||||
|
__$$LogoutStateImplCopyWithImpl(
|
||||||
|
_$LogoutStateImpl _value,
|
||||||
|
$Res Function(_$LogoutStateImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LogoutState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? logoutFailureOrSuccess = null,
|
||||||
|
Object? isLoggingOut = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$LogoutStateImpl(
|
||||||
|
logoutFailureOrSuccess: null == logoutFailureOrSuccess
|
||||||
|
? _value.logoutFailureOrSuccess
|
||||||
|
: logoutFailureOrSuccess // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Unit>>,
|
||||||
|
isLoggingOut: null == isLoggingOut
|
||||||
|
? _value.isLoggingOut
|
||||||
|
: isLoggingOut // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$LogoutStateImpl implements _LogoutState {
|
||||||
|
_$LogoutStateImpl({
|
||||||
|
required this.logoutFailureOrSuccess,
|
||||||
|
this.isLoggingOut = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Option<Either<AuthFailure, Unit>> logoutFailureOrSuccess;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final bool isLoggingOut;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LogoutState(logoutFailureOrSuccess: $logoutFailureOrSuccess, isLoggingOut: $isLoggingOut)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LogoutStateImpl &&
|
||||||
|
(identical(other.logoutFailureOrSuccess, logoutFailureOrSuccess) ||
|
||||||
|
other.logoutFailureOrSuccess == logoutFailureOrSuccess) &&
|
||||||
|
(identical(other.isLoggingOut, isLoggingOut) ||
|
||||||
|
other.isLoggingOut == isLoggingOut));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
Object.hash(runtimeType, logoutFailureOrSuccess, isLoggingOut);
|
||||||
|
|
||||||
|
/// Create a copy of LogoutState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LogoutStateImplCopyWith<_$LogoutStateImpl> get copyWith =>
|
||||||
|
__$$LogoutStateImplCopyWithImpl<_$LogoutStateImpl>(this, _$identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _LogoutState implements LogoutState {
|
||||||
|
factory _LogoutState({
|
||||||
|
required final Option<Either<AuthFailure, Unit>> logoutFailureOrSuccess,
|
||||||
|
final bool isLoggingOut,
|
||||||
|
}) = _$LogoutStateImpl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Option<Either<AuthFailure, Unit>> get logoutFailureOrSuccess;
|
||||||
|
@override
|
||||||
|
bool get isLoggingOut;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$LogoutStateImplCopyWith<_$LogoutStateImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
6
lib/application/auth/logout/logout_event.dart
Normal file
6
lib/application/auth/logout/logout_event.dart
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
part of 'logout_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LogoutEvent with _$LogoutEvent {
|
||||||
|
const factory LogoutEvent.logout() = _Logout;
|
||||||
|
}
|
||||||
11
lib/application/auth/logout/logout_state.dart
Normal file
11
lib/application/auth/logout/logout_state.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
part of 'logout_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LogoutState with _$LogoutState {
|
||||||
|
factory LogoutState({
|
||||||
|
required Option<Either<AuthFailure, Unit>> logoutFailureOrSuccess,
|
||||||
|
@Default(false) bool isLoggingOut,
|
||||||
|
}) = _LogoutState;
|
||||||
|
|
||||||
|
factory LogoutState.initial() => LogoutState(logoutFailureOrSuccess: none());
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
class ApiPath {
|
class ApiPath {
|
||||||
static const String login = '/api/v1/auth/login';
|
static const String login = '/api/v1/auth/login';
|
||||||
|
static const String logout = '/api/v1/auth/logout';
|
||||||
static const String outlets = '/api/v1/outlets';
|
static const String outlets = '/api/v1/outlets';
|
||||||
static const String categories = '/api/v1/categories';
|
static const String categories = '/api/v1/categories';
|
||||||
static const String products = '/api/v1/products';
|
static const String products = '/api/v1/products';
|
||||||
|
|||||||
@ -5,6 +5,7 @@ abstract class IAuthRepository {
|
|||||||
required String email,
|
required String email,
|
||||||
required String password,
|
required String password,
|
||||||
});
|
});
|
||||||
|
Future<Either<AuthFailure, Unit>> logout();
|
||||||
Future<bool> hasToken();
|
Future<bool> hasToken();
|
||||||
Future<Either<AuthFailure, User>> currentUser();
|
Future<Either<AuthFailure, User>> currentUser();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:data_channel/data_channel.dart';
|
import 'package:data_channel/data_channel.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
import '../../../common/api/api_client.dart';
|
import '../../../common/api/api_client.dart';
|
||||||
import '../../../common/api/api_failure.dart';
|
import '../../../common/api/api_failure.dart';
|
||||||
|
import '../../../common/function/app_function.dart';
|
||||||
import '../../../common/url/api_path.dart';
|
import '../../../common/url/api_path.dart';
|
||||||
import '../../../domain/auth/auth.dart';
|
import '../../../domain/auth/auth.dart';
|
||||||
import '../auth_dtos.dart';
|
import '../auth_dtos.dart';
|
||||||
@ -41,4 +43,22 @@ class AuthRemoteDataProvider {
|
|||||||
return DC.error(AuthFailure.serverError(e));
|
return DC.error(AuthFailure.serverError(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<DC<AuthFailure, Unit>> logout() async {
|
||||||
|
try {
|
||||||
|
final response = await _apiClient.post(
|
||||||
|
ApiPath.logout,
|
||||||
|
headers: getAuthorizationHeader(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.data['success'] == false) {
|
||||||
|
return DC.error(AuthFailure.unexpectedError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return DC.data(unit);
|
||||||
|
} on ApiFailure catch (e, s) {
|
||||||
|
log('logout', name: _logName, error: e, stackTrace: s);
|
||||||
|
return DC.error(AuthFailure.serverError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,4 +57,21 @@ class AuthRepository implements IAuthRepository {
|
|||||||
Future<bool> hasToken() async {
|
Future<bool> hasToken() async {
|
||||||
return await _localDataProvider.hasToken();
|
return await _localDataProvider.hasToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Either<AuthFailure, Unit>> logout() async {
|
||||||
|
try {
|
||||||
|
final result = await _dataProvider.logout();
|
||||||
|
|
||||||
|
if (result.hasError) {
|
||||||
|
return left(result.error!);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _localDataProvider.deleteAllAuth();
|
||||||
|
return right(unit);
|
||||||
|
} catch (e, s) {
|
||||||
|
log('logoutError', name: _logName, error: e, stackTrace: s);
|
||||||
|
return left(const AuthFailure.unexpectedError());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,8 @@ import 'package:apskel_pos_flutter_v2/application/analytic/sales_analytic_loader
|
|||||||
import 'package:apskel_pos_flutter_v2/application/auth/auth_bloc.dart' as _i343;
|
import 'package:apskel_pos_flutter_v2/application/auth/auth_bloc.dart' as _i343;
|
||||||
import 'package:apskel_pos_flutter_v2/application/auth/login_form/login_form_bloc.dart'
|
import 'package:apskel_pos_flutter_v2/application/auth/login_form/login_form_bloc.dart'
|
||||||
as _i46;
|
as _i46;
|
||||||
|
import 'package:apskel_pos_flutter_v2/application/auth/logout/logout_bloc.dart'
|
||||||
|
as _i641;
|
||||||
import 'package:apskel_pos_flutter_v2/application/category/category_loader/category_loader_bloc.dart'
|
import 'package:apskel_pos_flutter_v2/application/category/category_loader/category_loader_bloc.dart'
|
||||||
as _i1018;
|
as _i1018;
|
||||||
import 'package:apskel_pos_flutter_v2/application/checkout/checkout_form/checkout_form_bloc.dart'
|
import 'package:apskel_pos_flutter_v2/application/checkout/checkout_form/checkout_form_bloc.dart'
|
||||||
@ -293,6 +295,9 @@ extension GetItInjectableX on _i174.GetIt {
|
|||||||
gh.factory<_i46.LoginFormBloc>(
|
gh.factory<_i46.LoginFormBloc>(
|
||||||
() => _i46.LoginFormBloc(gh<_i776.IAuthRepository>()),
|
() => _i46.LoginFormBloc(gh<_i776.IAuthRepository>()),
|
||||||
);
|
);
|
||||||
|
gh.factory<_i641.LogoutBloc>(
|
||||||
|
() => _i641.LogoutBloc(gh<_i776.IAuthRepository>()),
|
||||||
|
);
|
||||||
gh.factory<_i1018.CategoryLoaderBloc>(
|
gh.factory<_i1018.CategoryLoaderBloc>(
|
||||||
() => _i1018.CategoryLoaderBloc(gh<_i502.ICategoryRepository>()),
|
() => _i1018.CategoryLoaderBloc(gh<_i502.ICategoryRepository>()),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../application/auth/auth_bloc.dart';
|
import '../application/auth/auth_bloc.dart';
|
||||||
|
import '../application/auth/logout/logout_bloc.dart';
|
||||||
import '../application/category/category_loader/category_loader_bloc.dart';
|
import '../application/category/category_loader/category_loader_bloc.dart';
|
||||||
import '../application/checkout/checkout_form/checkout_form_bloc.dart';
|
import '../application/checkout/checkout_form/checkout_form_bloc.dart';
|
||||||
import '../application/customer/customer_loader/customer_loader_bloc.dart';
|
import '../application/customer/customer_loader/customer_loader_bloc.dart';
|
||||||
@ -57,6 +58,7 @@ class _AppWidgetState extends State<AppWidget> {
|
|||||||
BlocProvider(create: (context) => getIt<PrinterLoaderBloc>()),
|
BlocProvider(create: (context) => getIt<PrinterLoaderBloc>()),
|
||||||
BlocProvider(create: (context) => getIt<PrintStruckBloc>()),
|
BlocProvider(create: (context) => getIt<PrintStruckBloc>()),
|
||||||
BlocProvider(create: (context) => getIt<SyncSettingBloc>()),
|
BlocProvider(create: (context) => getIt<SyncSettingBloc>()),
|
||||||
|
BlocProvider(create: (context) => getIt<LogoutBloc>()),
|
||||||
],
|
],
|
||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
|
|||||||
57
lib/presentation/components/dialog/logout_modal_dialog.dart
Normal file
57
lib/presentation/components/dialog/logout_modal_dialog.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../../../application/auth/logout/logout_bloc.dart';
|
||||||
|
import '../../../common/theme/theme.dart';
|
||||||
|
import '../button/button.dart';
|
||||||
|
import '../spaces/space.dart';
|
||||||
|
import 'dialog.dart';
|
||||||
|
|
||||||
|
class LogoutModalDialog extends StatelessWidget {
|
||||||
|
const LogoutModalDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<LogoutBloc, LogoutState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return CustomModalDialog(
|
||||||
|
title: 'Konfirmasi',
|
||||||
|
contentPadding: EdgeInsets.all(16),
|
||||||
|
bottom: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: AppElevatedButton.outlined(
|
||||||
|
onPressed: () => context.maybePop(),
|
||||||
|
label: 'Batal',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SpaceWidth(12),
|
||||||
|
Expanded(
|
||||||
|
child: AppElevatedButton.filled(
|
||||||
|
onPressed: state.isLoggingOut
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
context.read<LogoutBloc>().add(
|
||||||
|
const LogoutEvent.logout(),
|
||||||
|
);
|
||||||
|
context.maybePop();
|
||||||
|
},
|
||||||
|
label: 'Ya',
|
||||||
|
isLoading: state.isLoggingOut,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Apakah anda yakin ingin keluar?',
|
||||||
|
style: AppStyle.lg.copyWith(fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,12 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../../../application/auth/logout/logout_bloc.dart';
|
||||||
import '../../../common/theme/theme.dart';
|
import '../../../common/theme/theme.dart';
|
||||||
import '../../components/assets/assets.gen.dart';
|
import '../../components/assets/assets.gen.dart';
|
||||||
|
import '../../components/dialog/logout_modal_dialog.dart';
|
||||||
|
import '../../components/toast/flushbar.dart';
|
||||||
import '../../router/app_router.gr.dart';
|
import '../../router/app_router.gr.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
@ -11,107 +15,140 @@ class MainPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AutoTabsRouter(
|
return BlocListener<LogoutBloc, LogoutState>(
|
||||||
routes: [
|
listenWhen: (p, c) =>
|
||||||
HomeRoute(),
|
p.logoutFailureOrSuccess != c.logoutFailureOrSuccess,
|
||||||
TableRoute(),
|
listener: (context, state) {
|
||||||
ReportRoute(),
|
state.logoutFailureOrSuccess.fold(
|
||||||
CustomerRoute(),
|
() => null,
|
||||||
SettingRoute(),
|
(either) => either.fold(
|
||||||
],
|
(f) {
|
||||||
builder: (context, child) {
|
AppFlushbar.showAuthFailureToast(context, f);
|
||||||
final tabsRouter = AutoTabsRouter.of(context);
|
if (context.mounted) {
|
||||||
|
context.router.replaceAll([const LoginRoute()]);
|
||||||
return Scaffold(
|
}
|
||||||
body: Row(
|
},
|
||||||
children: [
|
(_) {
|
||||||
NavigationRail(
|
if (context.mounted) {
|
||||||
selectedIndex: tabsRouter.activeIndex,
|
context.router.replaceAll([const LoginRoute()]);
|
||||||
onDestinationSelected: tabsRouter.setActiveIndex,
|
}
|
||||||
labelType: NavigationRailLabelType.none,
|
},
|
||||||
backgroundColor: AppColor.primary,
|
|
||||||
selectedIconTheme: const IconThemeData(color: Colors.white),
|
|
||||||
indicatorColor: AppColor.disabled.withOpacity(0.25),
|
|
||||||
indicatorShape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
|
||||||
),
|
|
||||||
minExtendedWidth: 56,
|
|
||||||
leading: Padding(
|
|
||||||
padding: EdgeInsets.all(8.0),
|
|
||||||
child: Assets.images.logoWhite.image(
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: Expanded(
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 16.0),
|
|
||||||
child: IconButton(
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.logout,
|
|
||||||
color: AppColor.disabled,
|
|
||||||
),
|
|
||||||
onPressed: () {},
|
|
||||||
tooltip: 'Logout',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
destinations: const [
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(Icons.home_outlined, color: AppColor.disabled),
|
|
||||||
selectedIcon: Icon(Icons.home, color: AppColor.white),
|
|
||||||
label: Text('POS'),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
|
||||||
),
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.table_bar_outlined,
|
|
||||||
color: AppColor.disabled,
|
|
||||||
),
|
|
||||||
selectedIcon: Icon(Icons.table_bar, color: AppColor.white),
|
|
||||||
label: Text('Meja'),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
|
||||||
),
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.pie_chart_outline_outlined,
|
|
||||||
color: AppColor.disabled,
|
|
||||||
),
|
|
||||||
selectedIcon: Icon(Icons.pie_chart, color: AppColor.white),
|
|
||||||
label: Text('Laporan'),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
|
||||||
),
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.person_2_outlined,
|
|
||||||
color: AppColor.disabled,
|
|
||||||
),
|
|
||||||
selectedIcon: Icon(Icons.person_2, color: AppColor.white),
|
|
||||||
label: Text('Pelanggan'),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
|
||||||
),
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.settings_outlined,
|
|
||||||
color: AppColor.disabled,
|
|
||||||
),
|
|
||||||
selectedIcon: Icon(Icons.settings, color: AppColor.white),
|
|
||||||
label: Text('Pengaturan'),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const VerticalDivider(thickness: 1, width: 1),
|
|
||||||
// Main content area
|
|
||||||
Expanded(child: child),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
child: AutoTabsRouter(
|
||||||
|
routes: [
|
||||||
|
HomeRoute(),
|
||||||
|
TableRoute(),
|
||||||
|
ReportRoute(),
|
||||||
|
CustomerRoute(),
|
||||||
|
SettingRoute(),
|
||||||
|
],
|
||||||
|
builder: (context, child) {
|
||||||
|
final tabsRouter = AutoTabsRouter.of(context);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
body: Row(
|
||||||
|
children: [
|
||||||
|
NavigationRail(
|
||||||
|
selectedIndex: tabsRouter.activeIndex,
|
||||||
|
onDestinationSelected: tabsRouter.setActiveIndex,
|
||||||
|
labelType: NavigationRailLabelType.none,
|
||||||
|
backgroundColor: AppColor.primary,
|
||||||
|
selectedIconTheme: const IconThemeData(color: Colors.white),
|
||||||
|
indicatorColor: AppColor.disabled.withOpacity(0.25),
|
||||||
|
indicatorShape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
minExtendedWidth: 56,
|
||||||
|
leading: Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: Assets.images.logoWhite.image(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: Expanded(
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.logout,
|
||||||
|
color: AppColor.disabled,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => LogoutModalDialog(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
tooltip: 'Logout',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
destinations: const [
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(Icons.home_outlined, color: AppColor.disabled),
|
||||||
|
selectedIcon: Icon(Icons.home, color: AppColor.white),
|
||||||
|
label: Text('POS'),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
),
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.table_bar_outlined,
|
||||||
|
color: AppColor.disabled,
|
||||||
|
),
|
||||||
|
selectedIcon: Icon(
|
||||||
|
Icons.table_bar,
|
||||||
|
color: AppColor.white,
|
||||||
|
),
|
||||||
|
label: Text('Meja'),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
),
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.pie_chart_outline_outlined,
|
||||||
|
color: AppColor.disabled,
|
||||||
|
),
|
||||||
|
selectedIcon: Icon(
|
||||||
|
Icons.pie_chart,
|
||||||
|
color: AppColor.white,
|
||||||
|
),
|
||||||
|
label: Text('Laporan'),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
),
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.person_2_outlined,
|
||||||
|
color: AppColor.disabled,
|
||||||
|
),
|
||||||
|
selectedIcon: Icon(Icons.person_2, color: AppColor.white),
|
||||||
|
label: Text('Pelanggan'),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
),
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.settings_outlined,
|
||||||
|
color: AppColor.disabled,
|
||||||
|
),
|
||||||
|
selectedIcon: Icon(Icons.settings, color: AppColor.white),
|
||||||
|
label: Text('Pengaturan'),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const VerticalDivider(thickness: 1, width: 1),
|
||||||
|
// Main content area
|
||||||
|
Expanded(child: child),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user