current outlet

This commit is contained in:
efrilm 2025-10-24 13:55:00 +07:00
parent 97c03bcf96
commit 4dbdcadeaf
27 changed files with 2201 additions and 11 deletions

View File

@ -4,6 +4,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:injectable/injectable.dart';
import '../../domain/auth/auth.dart';
import '../../domain/outlet/outlet.dart';
part 'auth_event.dart';
part 'auth_state.dart';
@ -12,7 +13,9 @@ part 'auth_bloc.freezed.dart';
@injectable
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final IAuthRepository _repository;
AuthBloc(this._repository) : super(AuthState.initial()) {
final IOutletRepository _outletRepository;
AuthBloc(this._repository, this._outletRepository)
: super(AuthState.initial()) {
on<AuthEvent>(_onAuthEvent);
}
@ -43,6 +46,20 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
),
),
);
add(AuthEvent.fetchCurrentOutlet(state.user.outletId));
},
fetchCurrentOutlet: (e) async {
emit(state.copyWith(failureOutletOption: none()));
final failureOrOutlet = await _outletRepository.getOutletById(
e.outletId,
);
failureOrOutlet.fold(
(f) => emit(state.copyWith(failureOutletOption: optionOf(f))),
(outlet) => emit(state.copyWith(outlet: outlet)),
);
},
);
}

View File

@ -20,27 +20,33 @@ mixin _$AuthEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() fetchCurrentUser,
required TResult Function(String outletId) fetchCurrentOutlet,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? fetchCurrentUser,
TResult? Function(String outletId)? fetchCurrentOutlet,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? fetchCurrentUser,
TResult Function(String outletId)? fetchCurrentOutlet,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_FetchCurrentUser value) fetchCurrentUser,
required TResult Function(_FetchCurrentOutlet value) fetchCurrentOutlet,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_FetchCurrentUser value)? fetchCurrentUser,
TResult? Function(_FetchCurrentOutlet value)? fetchCurrentOutlet,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_FetchCurrentUser value)? fetchCurrentUser,
TResult Function(_FetchCurrentOutlet value)? fetchCurrentOutlet,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
}
@ -109,6 +115,7 @@ class _$FetchCurrentUserImpl implements _FetchCurrentUser {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() fetchCurrentUser,
required TResult Function(String outletId) fetchCurrentOutlet,
}) {
return fetchCurrentUser();
}
@ -117,6 +124,7 @@ class _$FetchCurrentUserImpl implements _FetchCurrentUser {
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? fetchCurrentUser,
TResult? Function(String outletId)? fetchCurrentOutlet,
}) {
return fetchCurrentUser?.call();
}
@ -125,6 +133,7 @@ class _$FetchCurrentUserImpl implements _FetchCurrentUser {
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? fetchCurrentUser,
TResult Function(String outletId)? fetchCurrentOutlet,
required TResult orElse(),
}) {
if (fetchCurrentUser != null) {
@ -137,6 +146,7 @@ class _$FetchCurrentUserImpl implements _FetchCurrentUser {
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_FetchCurrentUser value) fetchCurrentUser,
required TResult Function(_FetchCurrentOutlet value) fetchCurrentOutlet,
}) {
return fetchCurrentUser(this);
}
@ -145,6 +155,7 @@ class _$FetchCurrentUserImpl implements _FetchCurrentUser {
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_FetchCurrentUser value)? fetchCurrentUser,
TResult? Function(_FetchCurrentOutlet value)? fetchCurrentOutlet,
}) {
return fetchCurrentUser?.call(this);
}
@ -153,6 +164,7 @@ class _$FetchCurrentUserImpl implements _FetchCurrentUser {
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_FetchCurrentUser value)? fetchCurrentUser,
TResult Function(_FetchCurrentOutlet value)? fetchCurrentOutlet,
required TResult orElse(),
}) {
if (fetchCurrentUser != null) {
@ -166,12 +178,163 @@ abstract class _FetchCurrentUser implements AuthEvent {
const factory _FetchCurrentUser() = _$FetchCurrentUserImpl;
}
/// @nodoc
abstract class _$$FetchCurrentOutletImplCopyWith<$Res> {
factory _$$FetchCurrentOutletImplCopyWith(
_$FetchCurrentOutletImpl value,
$Res Function(_$FetchCurrentOutletImpl) then,
) = __$$FetchCurrentOutletImplCopyWithImpl<$Res>;
@useResult
$Res call({String outletId});
}
/// @nodoc
class __$$FetchCurrentOutletImplCopyWithImpl<$Res>
extends _$AuthEventCopyWithImpl<$Res, _$FetchCurrentOutletImpl>
implements _$$FetchCurrentOutletImplCopyWith<$Res> {
__$$FetchCurrentOutletImplCopyWithImpl(
_$FetchCurrentOutletImpl _value,
$Res Function(_$FetchCurrentOutletImpl) _then,
) : super(_value, _then);
/// Create a copy of AuthEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({Object? outletId = null}) {
return _then(
_$FetchCurrentOutletImpl(
null == outletId
? _value.outletId
: outletId // ignore: cast_nullable_to_non_nullable
as String,
),
);
}
}
/// @nodoc
class _$FetchCurrentOutletImpl implements _FetchCurrentOutlet {
const _$FetchCurrentOutletImpl(this.outletId);
@override
final String outletId;
@override
String toString() {
return 'AuthEvent.fetchCurrentOutlet(outletId: $outletId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$FetchCurrentOutletImpl &&
(identical(other.outletId, outletId) ||
other.outletId == outletId));
}
@override
int get hashCode => Object.hash(runtimeType, outletId);
/// Create a copy of AuthEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$FetchCurrentOutletImplCopyWith<_$FetchCurrentOutletImpl> get copyWith =>
__$$FetchCurrentOutletImplCopyWithImpl<_$FetchCurrentOutletImpl>(
this,
_$identity,
);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() fetchCurrentUser,
required TResult Function(String outletId) fetchCurrentOutlet,
}) {
return fetchCurrentOutlet(outletId);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? fetchCurrentUser,
TResult? Function(String outletId)? fetchCurrentOutlet,
}) {
return fetchCurrentOutlet?.call(outletId);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? fetchCurrentUser,
TResult Function(String outletId)? fetchCurrentOutlet,
required TResult orElse(),
}) {
if (fetchCurrentOutlet != null) {
return fetchCurrentOutlet(outletId);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_FetchCurrentUser value) fetchCurrentUser,
required TResult Function(_FetchCurrentOutlet value) fetchCurrentOutlet,
}) {
return fetchCurrentOutlet(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_FetchCurrentUser value)? fetchCurrentUser,
TResult? Function(_FetchCurrentOutlet value)? fetchCurrentOutlet,
}) {
return fetchCurrentOutlet?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_FetchCurrentUser value)? fetchCurrentUser,
TResult Function(_FetchCurrentOutlet value)? fetchCurrentOutlet,
required TResult orElse(),
}) {
if (fetchCurrentOutlet != null) {
return fetchCurrentOutlet(this);
}
return orElse();
}
}
abstract class _FetchCurrentOutlet implements AuthEvent {
const factory _FetchCurrentOutlet(final String outletId) =
_$FetchCurrentOutletImpl;
String get outletId;
/// Create a copy of AuthEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$FetchCurrentOutletImplCopyWith<_$FetchCurrentOutletImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$AuthState {
User get user => throw _privateConstructorUsedError;
Outlet get outlet => throw _privateConstructorUsedError;
AuthStatus get status => throw _privateConstructorUsedError;
Option<AuthFailure> get failureOption => throw _privateConstructorUsedError;
Option<OutletFailure> get failureOutletOption =>
throw _privateConstructorUsedError;
bool get isFetching => throw _privateConstructorUsedError;
bool get isFetchingOutlet => throw _privateConstructorUsedError;
/// Create a copy of AuthState
/// with the given fields replaced by the non-null parameter values.
@ -187,12 +350,16 @@ abstract class $AuthStateCopyWith<$Res> {
@useResult
$Res call({
User user,
Outlet outlet,
AuthStatus status,
Option<AuthFailure> failureOption,
Option<OutletFailure> failureOutletOption,
bool isFetching,
bool isFetchingOutlet,
});
$UserCopyWith<$Res> get user;
$OutletCopyWith<$Res> get outlet;
$AuthStatusCopyWith<$Res> get status;
}
@ -212,9 +379,12 @@ class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState>
@override
$Res call({
Object? user = null,
Object? outlet = null,
Object? status = null,
Object? failureOption = null,
Object? failureOutletOption = null,
Object? isFetching = null,
Object? isFetchingOutlet = null,
}) {
return _then(
_value.copyWith(
@ -222,6 +392,10 @@ class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState>
? _value.user
: user // ignore: cast_nullable_to_non_nullable
as User,
outlet: null == outlet
? _value.outlet
: outlet // ignore: cast_nullable_to_non_nullable
as Outlet,
status: null == status
? _value.status
: status // ignore: cast_nullable_to_non_nullable
@ -230,10 +404,18 @@ class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState>
? _value.failureOption
: failureOption // ignore: cast_nullable_to_non_nullable
as Option<AuthFailure>,
failureOutletOption: null == failureOutletOption
? _value.failureOutletOption
: failureOutletOption // ignore: cast_nullable_to_non_nullable
as Option<OutletFailure>,
isFetching: null == isFetching
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
isFetchingOutlet: null == isFetchingOutlet
? _value.isFetchingOutlet
: isFetchingOutlet // ignore: cast_nullable_to_non_nullable
as bool,
)
as $Val,
);
@ -249,6 +431,16 @@ class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState>
});
}
/// Create a copy of AuthState
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$OutletCopyWith<$Res> get outlet {
return $OutletCopyWith<$Res>(_value.outlet, (value) {
return _then(_value.copyWith(outlet: value) as $Val);
});
}
/// Create a copy of AuthState
/// with the given fields replaced by the non-null parameter values.
@override
@ -271,14 +463,19 @@ abstract class _$$AuthStateImplCopyWith<$Res>
@useResult
$Res call({
User user,
Outlet outlet,
AuthStatus status,
Option<AuthFailure> failureOption,
Option<OutletFailure> failureOutletOption,
bool isFetching,
bool isFetchingOutlet,
});
@override
$UserCopyWith<$Res> get user;
@override
$OutletCopyWith<$Res> get outlet;
@override
$AuthStatusCopyWith<$Res> get status;
}
@ -297,9 +494,12 @@ class __$$AuthStateImplCopyWithImpl<$Res>
@override
$Res call({
Object? user = null,
Object? outlet = null,
Object? status = null,
Object? failureOption = null,
Object? failureOutletOption = null,
Object? isFetching = null,
Object? isFetchingOutlet = null,
}) {
return _then(
_$AuthStateImpl(
@ -307,6 +507,10 @@ class __$$AuthStateImplCopyWithImpl<$Res>
? _value.user
: user // ignore: cast_nullable_to_non_nullable
as User,
outlet: null == outlet
? _value.outlet
: outlet // ignore: cast_nullable_to_non_nullable
as Outlet,
status: null == status
? _value.status
: status // ignore: cast_nullable_to_non_nullable
@ -315,10 +519,18 @@ class __$$AuthStateImplCopyWithImpl<$Res>
? _value.failureOption
: failureOption // ignore: cast_nullable_to_non_nullable
as Option<AuthFailure>,
failureOutletOption: null == failureOutletOption
? _value.failureOutletOption
: failureOutletOption // ignore: cast_nullable_to_non_nullable
as Option<OutletFailure>,
isFetching: null == isFetching
? _value.isFetching
: isFetching // ignore: cast_nullable_to_non_nullable
as bool,
isFetchingOutlet: null == isFetchingOutlet
? _value.isFetchingOutlet
: isFetchingOutlet // ignore: cast_nullable_to_non_nullable
as bool,
),
);
}
@ -329,25 +541,35 @@ class __$$AuthStateImplCopyWithImpl<$Res>
class _$AuthStateImpl extends _AuthState {
const _$AuthStateImpl({
required this.user,
required this.outlet,
this.status = const AuthStatus.initial(),
required this.failureOption,
required this.failureOutletOption,
this.isFetching = false,
this.isFetchingOutlet = false,
}) : super._();
@override
final User user;
@override
final Outlet outlet;
@override
@JsonKey()
final AuthStatus status;
@override
final Option<AuthFailure> failureOption;
@override
final Option<OutletFailure> failureOutletOption;
@override
@JsonKey()
final bool isFetching;
@override
@JsonKey()
final bool isFetchingOutlet;
@override
String toString() {
return 'AuthState(user: $user, status: $status, failureOption: $failureOption, isFetching: $isFetching)';
return 'AuthState(user: $user, outlet: $outlet, status: $status, failureOption: $failureOption, failureOutletOption: $failureOutletOption, isFetching: $isFetching, isFetchingOutlet: $isFetchingOutlet)';
}
@override
@ -356,16 +578,29 @@ class _$AuthStateImpl extends _AuthState {
(other.runtimeType == runtimeType &&
other is _$AuthStateImpl &&
(identical(other.user, user) || other.user == user) &&
(identical(other.outlet, outlet) || other.outlet == outlet) &&
(identical(other.status, status) || other.status == status) &&
(identical(other.failureOption, failureOption) ||
other.failureOption == failureOption) &&
(identical(other.failureOutletOption, failureOutletOption) ||
other.failureOutletOption == failureOutletOption) &&
(identical(other.isFetching, isFetching) ||
other.isFetching == isFetching));
other.isFetching == isFetching) &&
(identical(other.isFetchingOutlet, isFetchingOutlet) ||
other.isFetchingOutlet == isFetchingOutlet));
}
@override
int get hashCode =>
Object.hash(runtimeType, user, status, failureOption, isFetching);
int get hashCode => Object.hash(
runtimeType,
user,
outlet,
status,
failureOption,
failureOutletOption,
isFetching,
isFetchingOutlet,
);
/// Create a copy of AuthState
/// with the given fields replaced by the non-null parameter values.
@ -379,20 +614,29 @@ class _$AuthStateImpl extends _AuthState {
abstract class _AuthState extends AuthState {
const factory _AuthState({
required final User user,
required final Outlet outlet,
final AuthStatus status,
required final Option<AuthFailure> failureOption,
required final Option<OutletFailure> failureOutletOption,
final bool isFetching,
final bool isFetchingOutlet,
}) = _$AuthStateImpl;
const _AuthState._() : super._();
@override
User get user;
@override
Outlet get outlet;
@override
AuthStatus get status;
@override
Option<AuthFailure> get failureOption;
@override
Option<OutletFailure> get failureOutletOption;
@override
bool get isFetching;
@override
bool get isFetchingOutlet;
/// Create a copy of AuthState
/// with the given fields replaced by the non-null parameter values.

View File

@ -3,4 +3,6 @@ part of 'auth_bloc.dart';
@freezed
class AuthEvent with _$AuthEvent {
const factory AuthEvent.fetchCurrentUser() = _FetchCurrentUser;
const factory AuthEvent.fetchCurrentOutlet(String outletId) =
_FetchCurrentOutlet;
}

View File

@ -6,13 +6,20 @@ class AuthState with _$AuthState {
const factory AuthState({
required User user,
required Outlet outlet,
@Default(AuthStatus.initial()) AuthStatus status,
required Option<AuthFailure> failureOption,
required Option<OutletFailure> failureOutletOption,
@Default(false) bool isFetching,
@Default(false) bool isFetchingOutlet,
}) = _AuthState;
factory AuthState.initial() =>
AuthState(user: User.empty(), failureOption: none());
factory AuthState.initial() => AuthState(
user: User.empty(),
failureOption: none(),
outlet: Outlet.empty(),
failureOutletOption: none(),
);
bool get isAuthenticated => status == const AuthStatus.authenticated();
bool get isInitial => status == const AuthStatus.initial();

View File

@ -1,4 +1,5 @@
class LocalStorageKey {
static const String token = 'token';
static const String user = 'user';
static const String outlet = 'outlet';
}

View File

@ -0,0 +1,7 @@
part of 'extension.dart';
extension BuildContextExt on BuildContext {
double get deviceHeight => MediaQuery.of(this).size.height;
double get deviceWidth => MediaQuery.of(this).size.width;
}

View File

@ -1 +1,3 @@
// TODO: define your code
import 'package:flutter/material.dart';
part 'build_context_extension.dart';

View File

@ -1,4 +1,8 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../injection.dart';
import '../constant/local_storage_key.dart';
void dismissKeyboard(BuildContext context) {
final currentFocus = FocusScope.of(context);
@ -6,3 +10,10 @@ void dismissKeyboard(BuildContext context) {
FocusManager.instance.primaryFocus?.unfocus();
}
}
Map<String, dynamic> getAuthorizationHeader() {
return {
'Authorization':
'Bearer ${getIt<SharedPreferences>().getString(LocalStorageKey.token)}',
};
}

View File

@ -1,3 +1,4 @@
class ApiPath {
static const String login = '/api/v1/auth/login';
static const String outlets = '/api/v1/outlets';
}

View File

@ -0,0 +1,32 @@
part of '../outlet.dart';
@freezed
class Outlet with _$Outlet {
const factory Outlet({
required String id,
required String organizationId,
required String name,
required String address,
required String phoneNumber,
required String businessType,
required String currency,
required double taxRate,
required bool isActive,
required String createdAt,
required String updatedAt,
}) = _Outlet;
factory Outlet.empty() => const Outlet(
id: '',
organizationId: '',
name: '',
address: '',
phoneNumber: '',
businessType: '',
currency: '',
taxRate: 0.0,
isActive: false,
createdAt: '',
updatedAt: '',
);
}

View File

@ -0,0 +1,10 @@
part of '../outlet.dart';
@freezed
sealed class OutletFailure with _$OutletFailure {
const factory OutletFailure.serverError(ApiFailure failure) = _ServerError;
const factory OutletFailure.unexpectedError() = _UnexpectedError;
const factory OutletFailure.empty() = _Empty;
const factory OutletFailure.dynamicErrorMessage(String erroMessage) =
_DynamicErrorMessage;
}

View File

@ -0,0 +1,10 @@
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../common/api/api_failure.dart';
part 'outlet.freezed.dart';
part 'failures/outlet_failure.dart';
part 'entities/outlet_entity.dart';
part 'repositories/i_outlet_repository.dart';

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
part of '../outlet.dart';
abstract class IOutletRepository {
Future<Either<OutletFailure, List<Outlet>>> getOutlets({
int page = 1,
int limit = 10,
});
Future<Either<OutletFailure, Outlet>> getOutletById(String id);
}

View File

@ -0,0 +1,37 @@
import 'dart:convert';
import 'package:injectable/injectable.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../common/constant/local_storage_key.dart';
import '../../../domain/outlet/outlet.dart';
import '../outlet_dtos.dart';
@injectable
class OutletLocalDatasource {
final SharedPreferences _sharedPreferences;
// final String _logName = 'OutletLocalDataProvider';
OutletLocalDatasource(this._sharedPreferences);
Future<void> saveCurrentOutlet(OutletDto outlet) async {
final outletJsonString = jsonEncode(outlet.toJson());
await _sharedPreferences.setString(
LocalStorageKey.outlet,
outletJsonString,
);
}
Future<Outlet> currentOutlet() async {
final outletString = _sharedPreferences.getString(LocalStorageKey.outlet);
if (outletString == null) return Outlet.empty();
final Map<String, dynamic> outletMap = jsonDecode(outletString);
final outletDto = OutletDto.fromJson(outletMap);
return outletDto.toDomain();
}
Future<void> deleteCurrentOutlet() async {
await _sharedPreferences.remove(LocalStorageKey.outlet);
}
}

View File

@ -0,0 +1,67 @@
import 'dart:developer';
import 'package:data_channel/data_channel.dart';
import 'package:injectable/injectable.dart';
import '../../../common/api/api_client.dart';
import '../../../common/api/api_failure.dart';
import '../../../common/function/app_function.dart';
import '../../../common/url/api_path.dart';
import '../../../domain/outlet/outlet.dart';
import '../outlet_dtos.dart';
@injectable
class OutletRemoteDataProvider {
final ApiClient _apiClient;
final _logName = 'OutletRemoteDataProvider';
OutletRemoteDataProvider(this._apiClient);
Future<DC<OutletFailure, List<OutletDto>>> fetchOutlets({
int page = 1,
int limit = 10,
}) async {
try {
final response = await _apiClient.get(
'${ApiPath.outlets}/list',
params: {'page': page, 'limit': limit},
headers: getAuthorizationHeader(),
);
if (response.data['data'] == null) {
return DC.error(OutletFailure.empty());
}
final outlets = (response.data['data'] as List)
.map((e) => OutletDto.fromJson(e as Map<String, dynamic>))
.toList();
return DC.data(outlets);
} on ApiFailure catch (e, s) {
log('fetchOutletError', name: _logName, error: e, stackTrace: s);
return DC.error(OutletFailure.serverError(e));
}
}
Future<DC<OutletFailure, OutletDto>> fetchOutletById(String id) async {
try {
final response = await _apiClient.get(
'${ApiPath.outlets}/detail/$id',
headers: getAuthorizationHeader(),
);
if (response.data['data'] == null) {
return DC.error(OutletFailure.empty());
}
final outlet = OutletDto.fromJson(
response.data['data'] as Map<String, dynamic>,
);
return DC.data(outlet);
} on ApiFailure catch (e, s) {
log('fetchOutletByIdError', name: _logName, error: e, stackTrace: s);
return DC.error(OutletFailure.serverError(e));
}
}
}

View File

@ -0,0 +1,38 @@
part of '../outlet_dtos.dart';
@freezed
class OutletDto with _$OutletDto {
const OutletDto._();
const factory OutletDto({
@JsonKey(name: "id") String? id,
@JsonKey(name: "organization_id") String? organizationId,
@JsonKey(name: "name") String? name,
@JsonKey(name: "address") String? address,
@JsonKey(name: "phone_number") String? phoneNumber,
@JsonKey(name: "business_type") String? businessType,
@JsonKey(name: "currency") String? currency,
@JsonKey(name: "tax_rate") double? taxRate,
@JsonKey(name: "is_active") bool? isActive,
@JsonKey(name: "created_at") String? createdAt,
@JsonKey(name: "updated_at") String? updatedAt,
}) = _OutletDto;
factory OutletDto.fromJson(Map<String, dynamic> json) =>
_$OutletDtoFromJson(json);
/// Mapping ke domain
Outlet toDomain() => Outlet(
id: id ?? '',
organizationId: organizationId ?? '',
name: name ?? '',
address: address ?? '',
phoneNumber: phoneNumber ?? '',
businessType: businessType ?? '',
currency: currency ?? '',
taxRate: taxRate ?? 0.0,
isActive: isActive ?? false,
createdAt: createdAt ?? '',
updatedAt: updatedAt ?? '',
);
}

View File

@ -0,0 +1,8 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../domain/outlet/outlet.dart';
part 'outlet_dtos.freezed.dart';
part 'outlet_dtos.g.dart';
part 'dtos/outlet_dto.dart';

View File

@ -0,0 +1,431 @@
// 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 'outlet_dtos.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',
);
OutletDto _$OutletDtoFromJson(Map<String, dynamic> json) {
return _OutletDto.fromJson(json);
}
/// @nodoc
mixin _$OutletDto {
@JsonKey(name: "id")
String? get id => throw _privateConstructorUsedError;
@JsonKey(name: "organization_id")
String? get organizationId => throw _privateConstructorUsedError;
@JsonKey(name: "name")
String? get name => throw _privateConstructorUsedError;
@JsonKey(name: "address")
String? get address => throw _privateConstructorUsedError;
@JsonKey(name: "phone_number")
String? get phoneNumber => throw _privateConstructorUsedError;
@JsonKey(name: "business_type")
String? get businessType => throw _privateConstructorUsedError;
@JsonKey(name: "currency")
String? get currency => throw _privateConstructorUsedError;
@JsonKey(name: "tax_rate")
double? get taxRate => throw _privateConstructorUsedError;
@JsonKey(name: "is_active")
bool? get isActive => throw _privateConstructorUsedError;
@JsonKey(name: "created_at")
String? get createdAt => throw _privateConstructorUsedError;
@JsonKey(name: "updated_at")
String? get updatedAt => throw _privateConstructorUsedError;
/// Serializes this OutletDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of OutletDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$OutletDtoCopyWith<OutletDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $OutletDtoCopyWith<$Res> {
factory $OutletDtoCopyWith(OutletDto value, $Res Function(OutletDto) then) =
_$OutletDtoCopyWithImpl<$Res, OutletDto>;
@useResult
$Res call({
@JsonKey(name: "id") String? id,
@JsonKey(name: "organization_id") String? organizationId,
@JsonKey(name: "name") String? name,
@JsonKey(name: "address") String? address,
@JsonKey(name: "phone_number") String? phoneNumber,
@JsonKey(name: "business_type") String? businessType,
@JsonKey(name: "currency") String? currency,
@JsonKey(name: "tax_rate") double? taxRate,
@JsonKey(name: "is_active") bool? isActive,
@JsonKey(name: "created_at") String? createdAt,
@JsonKey(name: "updated_at") String? updatedAt,
});
}
/// @nodoc
class _$OutletDtoCopyWithImpl<$Res, $Val extends OutletDto>
implements $OutletDtoCopyWith<$Res> {
_$OutletDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of OutletDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = freezed,
Object? organizationId = freezed,
Object? name = freezed,
Object? address = freezed,
Object? phoneNumber = freezed,
Object? businessType = freezed,
Object? currency = freezed,
Object? taxRate = freezed,
Object? isActive = freezed,
Object? createdAt = freezed,
Object? updatedAt = freezed,
}) {
return _then(
_value.copyWith(
id: freezed == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String?,
organizationId: freezed == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String?,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
address: freezed == address
? _value.address
: address // ignore: cast_nullable_to_non_nullable
as String?,
phoneNumber: freezed == phoneNumber
? _value.phoneNumber
: phoneNumber // ignore: cast_nullable_to_non_nullable
as String?,
businessType: freezed == businessType
? _value.businessType
: businessType // ignore: cast_nullable_to_non_nullable
as String?,
currency: freezed == currency
? _value.currency
: currency // ignore: cast_nullable_to_non_nullable
as String?,
taxRate: freezed == taxRate
? _value.taxRate
: taxRate // ignore: cast_nullable_to_non_nullable
as double?,
isActive: freezed == isActive
? _value.isActive
: isActive // ignore: cast_nullable_to_non_nullable
as bool?,
createdAt: freezed == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as String?,
updatedAt: freezed == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as String?,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$OutletDtoImplCopyWith<$Res>
implements $OutletDtoCopyWith<$Res> {
factory _$$OutletDtoImplCopyWith(
_$OutletDtoImpl value,
$Res Function(_$OutletDtoImpl) then,
) = __$$OutletDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
@JsonKey(name: "id") String? id,
@JsonKey(name: "organization_id") String? organizationId,
@JsonKey(name: "name") String? name,
@JsonKey(name: "address") String? address,
@JsonKey(name: "phone_number") String? phoneNumber,
@JsonKey(name: "business_type") String? businessType,
@JsonKey(name: "currency") String? currency,
@JsonKey(name: "tax_rate") double? taxRate,
@JsonKey(name: "is_active") bool? isActive,
@JsonKey(name: "created_at") String? createdAt,
@JsonKey(name: "updated_at") String? updatedAt,
});
}
/// @nodoc
class __$$OutletDtoImplCopyWithImpl<$Res>
extends _$OutletDtoCopyWithImpl<$Res, _$OutletDtoImpl>
implements _$$OutletDtoImplCopyWith<$Res> {
__$$OutletDtoImplCopyWithImpl(
_$OutletDtoImpl _value,
$Res Function(_$OutletDtoImpl) _then,
) : super(_value, _then);
/// Create a copy of OutletDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = freezed,
Object? organizationId = freezed,
Object? name = freezed,
Object? address = freezed,
Object? phoneNumber = freezed,
Object? businessType = freezed,
Object? currency = freezed,
Object? taxRate = freezed,
Object? isActive = freezed,
Object? createdAt = freezed,
Object? updatedAt = freezed,
}) {
return _then(
_$OutletDtoImpl(
id: freezed == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String?,
organizationId: freezed == organizationId
? _value.organizationId
: organizationId // ignore: cast_nullable_to_non_nullable
as String?,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
address: freezed == address
? _value.address
: address // ignore: cast_nullable_to_non_nullable
as String?,
phoneNumber: freezed == phoneNumber
? _value.phoneNumber
: phoneNumber // ignore: cast_nullable_to_non_nullable
as String?,
businessType: freezed == businessType
? _value.businessType
: businessType // ignore: cast_nullable_to_non_nullable
as String?,
currency: freezed == currency
? _value.currency
: currency // ignore: cast_nullable_to_non_nullable
as String?,
taxRate: freezed == taxRate
? _value.taxRate
: taxRate // ignore: cast_nullable_to_non_nullable
as double?,
isActive: freezed == isActive
? _value.isActive
: isActive // ignore: cast_nullable_to_non_nullable
as bool?,
createdAt: freezed == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as String?,
updatedAt: freezed == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as String?,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$OutletDtoImpl extends _OutletDto {
const _$OutletDtoImpl({
@JsonKey(name: "id") this.id,
@JsonKey(name: "organization_id") this.organizationId,
@JsonKey(name: "name") this.name,
@JsonKey(name: "address") this.address,
@JsonKey(name: "phone_number") this.phoneNumber,
@JsonKey(name: "business_type") this.businessType,
@JsonKey(name: "currency") this.currency,
@JsonKey(name: "tax_rate") this.taxRate,
@JsonKey(name: "is_active") this.isActive,
@JsonKey(name: "created_at") this.createdAt,
@JsonKey(name: "updated_at") this.updatedAt,
}) : super._();
factory _$OutletDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$OutletDtoImplFromJson(json);
@override
@JsonKey(name: "id")
final String? id;
@override
@JsonKey(name: "organization_id")
final String? organizationId;
@override
@JsonKey(name: "name")
final String? name;
@override
@JsonKey(name: "address")
final String? address;
@override
@JsonKey(name: "phone_number")
final String? phoneNumber;
@override
@JsonKey(name: "business_type")
final String? businessType;
@override
@JsonKey(name: "currency")
final String? currency;
@override
@JsonKey(name: "tax_rate")
final double? taxRate;
@override
@JsonKey(name: "is_active")
final bool? isActive;
@override
@JsonKey(name: "created_at")
final String? createdAt;
@override
@JsonKey(name: "updated_at")
final String? updatedAt;
@override
String toString() {
return 'OutletDto(id: $id, organizationId: $organizationId, name: $name, address: $address, phoneNumber: $phoneNumber, businessType: $businessType, currency: $currency, taxRate: $taxRate, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$OutletDtoImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.organizationId, organizationId) ||
other.organizationId == organizationId) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.address, address) || other.address == address) &&
(identical(other.phoneNumber, phoneNumber) ||
other.phoneNumber == phoneNumber) &&
(identical(other.businessType, businessType) ||
other.businessType == businessType) &&
(identical(other.currency, currency) ||
other.currency == currency) &&
(identical(other.taxRate, taxRate) || other.taxRate == taxRate) &&
(identical(other.isActive, isActive) ||
other.isActive == isActive) &&
(identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
id,
organizationId,
name,
address,
phoneNumber,
businessType,
currency,
taxRate,
isActive,
createdAt,
updatedAt,
);
/// Create a copy of OutletDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$OutletDtoImplCopyWith<_$OutletDtoImpl> get copyWith =>
__$$OutletDtoImplCopyWithImpl<_$OutletDtoImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$OutletDtoImplToJson(this);
}
}
abstract class _OutletDto extends OutletDto {
const factory _OutletDto({
@JsonKey(name: "id") final String? id,
@JsonKey(name: "organization_id") final String? organizationId,
@JsonKey(name: "name") final String? name,
@JsonKey(name: "address") final String? address,
@JsonKey(name: "phone_number") final String? phoneNumber,
@JsonKey(name: "business_type") final String? businessType,
@JsonKey(name: "currency") final String? currency,
@JsonKey(name: "tax_rate") final double? taxRate,
@JsonKey(name: "is_active") final bool? isActive,
@JsonKey(name: "created_at") final String? createdAt,
@JsonKey(name: "updated_at") final String? updatedAt,
}) = _$OutletDtoImpl;
const _OutletDto._() : super._();
factory _OutletDto.fromJson(Map<String, dynamic> json) =
_$OutletDtoImpl.fromJson;
@override
@JsonKey(name: "id")
String? get id;
@override
@JsonKey(name: "organization_id")
String? get organizationId;
@override
@JsonKey(name: "name")
String? get name;
@override
@JsonKey(name: "address")
String? get address;
@override
@JsonKey(name: "phone_number")
String? get phoneNumber;
@override
@JsonKey(name: "business_type")
String? get businessType;
@override
@JsonKey(name: "currency")
String? get currency;
@override
@JsonKey(name: "tax_rate")
double? get taxRate;
@override
@JsonKey(name: "is_active")
bool? get isActive;
@override
@JsonKey(name: "created_at")
String? get createdAt;
@override
@JsonKey(name: "updated_at")
String? get updatedAt;
/// Create a copy of OutletDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$OutletDtoImplCopyWith<_$OutletDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -0,0 +1,37 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'outlet_dtos.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$OutletDtoImpl _$$OutletDtoImplFromJson(Map<String, dynamic> json) =>
_$OutletDtoImpl(
id: json['id'] as String?,
organizationId: json['organization_id'] as String?,
name: json['name'] as String?,
address: json['address'] as String?,
phoneNumber: json['phone_number'] as String?,
businessType: json['business_type'] as String?,
currency: json['currency'] as String?,
taxRate: (json['tax_rate'] as num?)?.toDouble(),
isActive: json['is_active'] as bool?,
createdAt: json['created_at'] as String?,
updatedAt: json['updated_at'] as String?,
);
Map<String, dynamic> _$$OutletDtoImplToJson(_$OutletDtoImpl instance) =>
<String, dynamic>{
'id': instance.id,
'organization_id': instance.organizationId,
'name': instance.name,
'address': instance.address,
'phone_number': instance.phoneNumber,
'business_type': instance.businessType,
'currency': instance.currency,
'tax_rate': instance.taxRate,
'is_active': instance.isActive,
'created_at': instance.createdAt,
'updated_at': instance.updatedAt,
};

View File

@ -0,0 +1,62 @@
import 'dart:developer';
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../domain/outlet/outlet.dart';
import '../datasources/local_data_provider.dart';
import '../datasources/remote_data_provider.dart';
@Injectable(as: IOutletRepository)
class OutletRepository implements IOutletRepository {
final OutletRemoteDataProvider _remoteDataProvider;
final OutletLocalDatasource _localDataProvider;
final _logName = 'OutletRepository';
OutletRepository(this._remoteDataProvider, this._localDataProvider);
@override
Future<Either<OutletFailure, List<Outlet>>> getOutlets({
int page = 1,
int limit = 10,
}) async {
try {
final result = await _remoteDataProvider.fetchOutlets(
page: page,
limit: limit,
);
if (result.hasError) {
return left(result.error!);
}
final outlets = result.data!.map((dto) => dto.toDomain()).toList();
return right(outlets);
} catch (e, s) {
log('getOutlets', name: _logName, error: e, stackTrace: s);
return left(const OutletFailure.unexpectedError());
}
}
@override
Future<Either<OutletFailure, Outlet>> getOutletById(String id) async {
try {
final localOutlet = await _localDataProvider.currentOutlet();
if (localOutlet.id == id) {
return right(localOutlet);
}
final result = await _remoteDataProvider.fetchOutletById(id);
if (result.hasError) {
return left(result.error!);
}
final outlet = result.data!.toDomain();
return right(outlet);
} catch (e, s) {
log('getOutletById', name: _logName, error: e, stackTrace: s);
return left(const OutletFailure.unexpectedError());
}
}
}

View File

@ -21,6 +21,7 @@ import 'package:apskel_pos_flutter_v2/common/di/di_shared_preferences.dart'
import 'package:apskel_pos_flutter_v2/common/network/network_client.dart'
as _i171;
import 'package:apskel_pos_flutter_v2/domain/auth/auth.dart' as _i776;
import 'package:apskel_pos_flutter_v2/domain/outlet/outlet.dart' as _i552;
import 'package:apskel_pos_flutter_v2/env.dart' as _i923;
import 'package:apskel_pos_flutter_v2/infrastructure/auth/datasources/local_data_provider.dart'
as _i204;
@ -28,6 +29,12 @@ import 'package:apskel_pos_flutter_v2/infrastructure/auth/datasources/remote_dat
as _i370;
import 'package:apskel_pos_flutter_v2/infrastructure/auth/repositories/auth_repository.dart'
as _i941;
import 'package:apskel_pos_flutter_v2/infrastructure/outlet/datasources/local_data_provider.dart'
as _i693;
import 'package:apskel_pos_flutter_v2/infrastructure/outlet/datasources/remote_data_provider.dart'
as _i132;
import 'package:apskel_pos_flutter_v2/infrastructure/outlet/repositories/outlet_repository.dart'
as _i845;
import 'package:apskel_pos_flutter_v2/presentation/router/app_router.dart'
as _i800;
import 'package:connectivity_plus/connectivity_plus.dart' as _i895;
@ -64,6 +71,9 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i204.AuthLocalDataProvider>(
() => _i204.AuthLocalDataProvider(gh<_i460.SharedPreferences>()),
);
gh.factory<_i693.OutletLocalDatasource>(
() => _i693.OutletLocalDatasource(gh<_i460.SharedPreferences>()),
);
gh.lazySingleton<_i457.ApiClient>(
() => _i457.ApiClient(gh<_i361.Dio>(), gh<_i923.Env>()),
);
@ -71,18 +81,30 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i370.AuthRemoteDataProvider>(
() => _i370.AuthRemoteDataProvider(gh<_i457.ApiClient>()),
);
gh.factory<_i132.OutletRemoteDataProvider>(
() => _i132.OutletRemoteDataProvider(gh<_i457.ApiClient>()),
);
gh.factory<_i776.IAuthRepository>(
() => _i941.AuthRepository(
gh<_i370.AuthRemoteDataProvider>(),
gh<_i204.AuthLocalDataProvider>(),
),
);
gh.factory<_i343.AuthBloc>(
() => _i343.AuthBloc(gh<_i776.IAuthRepository>()),
gh.factory<_i552.IOutletRepository>(
() => _i845.OutletRepository(
gh<_i132.OutletRemoteDataProvider>(),
gh<_i693.OutletLocalDatasource>(),
),
);
gh.factory<_i46.LoginFormBloc>(
() => _i46.LoginFormBloc(gh<_i776.IAuthRepository>()),
);
gh.factory<_i343.AuthBloc>(
() => _i343.AuthBloc(
gh<_i776.IAuthRepository>(),
gh<_i552.IOutletRepository>(),
),
);
return this;
}
}

View File

@ -0,0 +1,27 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import '../../../common/theme/theme.dart';
import '../spaces/space.dart';
class LoaderWithText extends StatelessWidget {
const LoaderWithText({super.key});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SpinKitFadingCircle(color: AppColor.primary),
SpaceWidth(10),
Text(
'Loading...',
style: AppStyle.md.copyWith(
color: AppColor.primary,
fontWeight: FontWeight.w500,
),
),
],
);
}
}

View File

@ -1,12 +1,33 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import '../../../../../common/theme/theme.dart';
import 'widgets/home_left_panel.dart';
import 'widgets/home_right_panel.dart';
@RoutePage()
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return const Center(child: Text('Home Page'));
return Hero(
tag: 'confirmation_screen',
child: Scaffold(
backgroundColor: AppColor.white,
body: Column(
children: [
Expanded(
child: Row(
children: [
Expanded(flex: 3, child: HomeLeftPanel()),
Expanded(flex: 2, child: HomeRightPanel()),
],
),
),
],
),
),
);
}
}

View File

@ -0,0 +1,16 @@
import 'package:flutter/widgets.dart';
import 'home_title.dart';
class HomeLeftPanel extends StatelessWidget {
const HomeLeftPanel({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
HomeTitle(controller: TextEditingController(), onChanged: (value) {}),
],
);
}
}

View File

@ -0,0 +1,10 @@
import 'package:flutter/widgets.dart';
class HomeRightPanel extends StatelessWidget {
const HomeRightPanel({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

View File

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../../application/auth/auth_bloc.dart';
import '../../../../../../common/extension/extension.dart';
import '../../../../../../common/theme/theme.dart';
import '../../../../../components/spaces/space.dart';
class HomeTitle extends StatelessWidget {
final TextEditingController controller;
final Function(String value)? onChanged;
const HomeTitle({super.key, required this.controller, this.onChanged});
@override
Widget build(BuildContext context) {
return Container(
height: context.deviceHeight * 0.1,
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
decoration: BoxDecoration(color: AppColor.white),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BlocBuilder<AuthBloc, AuthState>(
builder: (context, state) {
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
state.outlet.name,
style: AppStyle.xl.copyWith(
color: AppColor.primary,
fontWeight: FontWeight.w600,
),
),
SpaceWidth(2),
Icon(
Icons.keyboard_arrow_down,
color: AppColor.primary,
size: 18,
),
],
);
},
),
],
),
);
}
}