feat: Refactor code structure and optimize performance across multiple modules
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:krow/core/application/clients/api/api_client.dart';
|
||||
import 'package:krow/features/check_list/data/gql.dart';
|
||||
|
||||
@injectable
|
||||
class CheckListApiProvider {
|
||||
CheckListApiProvider(this._apiClient);
|
||||
|
||||
static const _verificationListKey = 'verification_check_list';
|
||||
|
||||
final ApiClient _apiClient;
|
||||
|
||||
Stream<Map<String, dynamic>> fetchCheckListWithCache() async* {
|
||||
await for (var result
|
||||
in _apiClient.queryWithCache(schema: getCheckListQuery)) {
|
||||
if (result == null || result.data == null) continue;
|
||||
|
||||
if (result.hasException) {
|
||||
throw Exception(result.exception.toString());
|
||||
}
|
||||
|
||||
if (result.data?[_verificationListKey] == null) continue;
|
||||
yield result.data?[_verificationListKey] ?? {};
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> fetchCheckList() async {
|
||||
final result = await _apiClient.query(schema: getCheckListQuery);
|
||||
|
||||
if (result.hasException) {
|
||||
throw Exception(result.exception.toString());
|
||||
}
|
||||
|
||||
return result.data?[_verificationListKey] ?? {};
|
||||
}
|
||||
|
||||
Future<void> submitVerification() async {
|
||||
var result = await _apiClient.mutate(schema: submitVerificationMutation);
|
||||
|
||||
if (result.hasException) {
|
||||
throw Exception(result.exception.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:krow/features/check_list/data/check_list_api_provider.dart';
|
||||
import 'package:krow/features/check_list/domain/check_list_repository.dart';
|
||||
|
||||
@Injectable(as: CheckListRepository)
|
||||
class CheckListRepositoryImpl implements CheckListRepository {
|
||||
final CheckListApiProvider remoteDataSource;
|
||||
|
||||
CheckListRepositoryImpl({required this.remoteDataSource});
|
||||
|
||||
@override
|
||||
Stream<Map<String, dynamic>> getCheckList() {
|
||||
return remoteDataSource.fetchCheckListWithCache();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> getCheckListUpdate() {
|
||||
return remoteDataSource.fetchCheckList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> submitVerification() async {
|
||||
return remoteDataSource.submitVerification();
|
||||
}
|
||||
}
|
||||
23
mobile-apps/staff-app/lib/features/check_list/data/gql.dart
Normal file
23
mobile-apps/staff-app/lib/features/check_list/data/gql.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
const String getCheckListQuery = '''
|
||||
query checkList{
|
||||
verification_check_list {
|
||||
personal_info
|
||||
emergency_contacts
|
||||
roles
|
||||
equipments
|
||||
uniforms
|
||||
working_areas
|
||||
bank_account
|
||||
certificates
|
||||
schedule
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const String submitVerificationMutation = '''
|
||||
mutation submitVerification{
|
||||
submit_staff_profile_for_verification {
|
||||
status
|
||||
}
|
||||
}
|
||||
''';
|
||||
@@ -0,0 +1,99 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow/core/application/di/injectable.dart';
|
||||
import 'package:krow/core/application/routing/routes.gr.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_event.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_state.dart';
|
||||
import 'package:krow/features/check_list/domain/check_list_repository.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
|
||||
class CheckListBloc extends Bloc<CheckListEvent, CheckListState> {
|
||||
CheckListBloc() : super(const CheckListState()) {
|
||||
on<CheckListEventFetch>(_onFetch);
|
||||
on<CheckForListUpdateEvent>(_onCheckForUpdate);
|
||||
on<CheckListEventSubmit>(_onSubmit);
|
||||
on<CheckListEventAgree>(_onAgree);
|
||||
}
|
||||
|
||||
void _onFetch(CheckListEventFetch event, Emitter<CheckListState> emit) async {
|
||||
if (state.checkListItems.isNotEmpty) return;
|
||||
|
||||
await for (var checkList in getIt<CheckListRepository>().getCheckList()) {
|
||||
emit(state.copyWith(checkListItems: _parseCheckListData(checkList)));
|
||||
}
|
||||
}
|
||||
|
||||
void _onCheckForUpdate(
|
||||
CheckForListUpdateEvent event,
|
||||
Emitter<CheckListState> emit,
|
||||
) async {
|
||||
if (event.editedItem.error == null) return;
|
||||
|
||||
final result = await getIt<CheckListRepository>().getCheckListUpdate();
|
||||
emit(
|
||||
state.copyWith(
|
||||
checkListItems: _parseCheckListData(result),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onSubmit(
|
||||
CheckListEventSubmit event,
|
||||
Emitter<CheckListState> emit,
|
||||
) async {
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
await getIt<CheckListRepository>().submitVerification();
|
||||
} finally {
|
||||
emit(state.copyWith(loading: false));
|
||||
}
|
||||
emit(state.copyWith(isSubmitted: true));
|
||||
}
|
||||
|
||||
void _onAgree(CheckListEventAgree event, Emitter<CheckListState> emit) {
|
||||
emit(state.copyWith(isAgree: !state.isAgree));
|
||||
}
|
||||
|
||||
List<CheckListItemState> _parseCheckListData(Map<String, dynamic> checkList) {
|
||||
return [
|
||||
CheckListItemState(
|
||||
title: 'Personal Information'.tr(),
|
||||
error: checkList['personal_info'],
|
||||
route: PersonalInfoRoute(isInEditMode: true)),
|
||||
CheckListItemState(
|
||||
title: 'Emergency contact'.tr(),
|
||||
error: checkList['emergency_contacts'],
|
||||
route: EmergencyContactsRoute()),
|
||||
CheckListItemState(
|
||||
title: 'Roles'.tr(), error: checkList['roles'], route: RoleRoute()),
|
||||
if (checkList.containsKey('equipments'))
|
||||
CheckListItemState(
|
||||
title: 'Equipment'.tr(),
|
||||
error: checkList['equipments'],
|
||||
route: RoleKitFlowRoute(roleKitType: RoleKitType.equipment)),
|
||||
if (checkList.containsKey('uniforms'))
|
||||
CheckListItemState(
|
||||
title: 'Uniform'.tr(),
|
||||
error: checkList['uniforms'],
|
||||
route: RoleKitFlowRoute(roleKitType: RoleKitType.uniform)),
|
||||
CheckListItemState(
|
||||
title: 'Working Area'.tr(),
|
||||
error: checkList['working_areas'],
|
||||
route: WorkingAreaRoute()),
|
||||
CheckListItemState(
|
||||
title: 'Availability'.tr(),
|
||||
error: checkList['schedule'],
|
||||
route: ScheduleRoute()),
|
||||
CheckListItemState(
|
||||
title: 'Bank Account'.tr(),
|
||||
error: checkList['bank_account'],
|
||||
route: const BankAccountFlowRoute()),
|
||||
CheckListItemState(title: 'Wages form'.tr(), error: checkList['']),
|
||||
CheckListItemState(
|
||||
title: 'Certificates'.tr(),
|
||||
error: checkList['certificates'],
|
||||
route: const CertificatesRoute()),
|
||||
CheckListItemState(title: 'Background check'.tr(), error: checkList['']),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_state.dart';
|
||||
|
||||
@immutable
|
||||
sealed class CheckListEvent {
|
||||
const CheckListEvent();
|
||||
}
|
||||
|
||||
class CheckListEventFetch extends CheckListEvent {
|
||||
const CheckListEventFetch();
|
||||
}
|
||||
|
||||
class CheckForListUpdateEvent extends CheckListEvent {
|
||||
final CheckListItemState editedItem;
|
||||
|
||||
const CheckForListUpdateEvent({required this.editedItem});
|
||||
}
|
||||
|
||||
class CheckListEventSubmit extends CheckListEvent {
|
||||
const CheckListEventSubmit();
|
||||
}
|
||||
|
||||
class CheckListEventAgree extends CheckListEvent {
|
||||
const CheckListEventAgree();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
@immutable
|
||||
class CheckListState {
|
||||
final List<CheckListItemState> checkListItems;
|
||||
final bool isSubmitted;
|
||||
final bool isAgree;
|
||||
final bool isSubmitEnabled;
|
||||
final bool loading;
|
||||
|
||||
const CheckListState({
|
||||
this.checkListItems = const [],
|
||||
this.isSubmitted = false,
|
||||
this.isAgree = false,
|
||||
this.loading = false,
|
||||
this.isSubmitEnabled = false,
|
||||
});
|
||||
|
||||
CheckListState copyWith({
|
||||
List<CheckListItemState>? checkListItems,
|
||||
bool? isSubmitted,
|
||||
bool? isAgree,
|
||||
bool? loading,
|
||||
bool? isSubmitEnabled,
|
||||
}) {
|
||||
return CheckListState(
|
||||
checkListItems: checkListItems ?? this.checkListItems,
|
||||
isSubmitted: isSubmitted ?? this.isSubmitted,
|
||||
isAgree: isAgree ?? this.isAgree,
|
||||
loading: loading ?? false,
|
||||
isSubmitEnabled: isSubmitEnabled ?? this.isSubmitEnabled,
|
||||
);
|
||||
}
|
||||
|
||||
bool get hasErrors => checkListItems.any((element) => element.error != null);
|
||||
}
|
||||
|
||||
@immutable
|
||||
class CheckListItemState {
|
||||
final String title;
|
||||
final String? error;
|
||||
final PageRouteInfo? route;
|
||||
|
||||
const CheckListItemState({required this.title, this.route, this.error});
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
abstract class CheckListRepository {
|
||||
Stream<Map<String,dynamic>> getCheckList();
|
||||
|
||||
Future<Map<String, dynamic>> getCheckListUpdate();
|
||||
|
||||
Future<void> submitVerification();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@RoutePage()
|
||||
class CheckListFlowScreen extends StatelessWidget {
|
||||
const CheckListFlowScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const AutoRouter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:krow/core/application/di/injectable.dart';
|
||||
import 'package:krow/core/application/routing/routes.gr.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/check_box.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_button.dart';
|
||||
import 'package:krow/core/sevices/auth_state_service/auth_service.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_bloc.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_event.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_state.dart';
|
||||
import 'package:krow/features/check_list/presentation/widgets/check_list_display_widget.dart';
|
||||
|
||||
@RoutePage()
|
||||
class CheckListScreen extends StatelessWidget implements AutoRouteWrapper {
|
||||
const CheckListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget wrappedRoute(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (_) => CheckListBloc()..add(const CheckListEventFetch()),
|
||||
child: this,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: KwAppBar(),
|
||||
body: BlocListener<CheckListBloc, CheckListState>(
|
||||
listenWhen: (previous, current) =>
|
||||
previous.isSubmitted != current.isSubmitted,
|
||||
listener: (context, state) {
|
||||
if (state.isSubmitted) {
|
||||
context.router.push(const WaitingValidationRoute());
|
||||
}
|
||||
},
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
child: ListView(
|
||||
primary: false,
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
Text(
|
||||
'finalize_your_profile'.tr(),
|
||||
style: AppTextStyles.headingH1,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'check_profile_verification'.tr(),
|
||||
style: AppTextStyles.bodyMediumReg
|
||||
.copyWith(color: AppColors.blackGray),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const CheckListDisplayWidget(),
|
||||
const Gap(36),
|
||||
const _AgreementWidget(),
|
||||
const Gap(36),
|
||||
const _SubmitButtonWidget(),
|
||||
const Gap(36),
|
||||
RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
text: '${'not_you'.tr()} ',
|
||||
style: AppTextStyles.bodyMediumReg
|
||||
.copyWith(color: AppColors.blackGray),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'log_out'.tr(),
|
||||
style: AppTextStyles.bodyMediumSmb.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
getIt<AuthService>().logout();
|
||||
context.router.replace(const AuthFlowRoute());
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AgreementWidget extends StatelessWidget {
|
||||
const _AgreementWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CheckListBloc>().add(const CheckListEventAgree());
|
||||
},
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BlocSelector<CheckListBloc, CheckListState, bool>(
|
||||
selector: (state) => state.isAgree,
|
||||
builder: (context, isAgree) {
|
||||
return KWCheckBox(value: isAgree);
|
||||
},
|
||||
),
|
||||
const Gap(8),
|
||||
Expanded(
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '${'i_agree_to_the'.tr()} ',
|
||||
style: AppTextStyles.bodyMediumMed,
|
||||
),
|
||||
TextSpan(
|
||||
text: 'terms_and_conditions'.tr(),
|
||||
style: AppTextStyles.bodyMediumSmb.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
//TODO(Sleep): Handle Terms and Conditions tap
|
||||
},
|
||||
),
|
||||
TextSpan(
|
||||
text: ' ${'and'.tr()} ',
|
||||
style: AppTextStyles.bodyMediumMed,
|
||||
),
|
||||
TextSpan(
|
||||
text: 'privacy_policy'.tr(),
|
||||
style: AppTextStyles.bodyMediumSmb.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
//TODO(Sleep): Handle Privacy Policy tap
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SubmitButtonWidget extends StatelessWidget {
|
||||
const _SubmitButtonWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<CheckListBloc, CheckListState>(
|
||||
buildWhen: (previous, current) {
|
||||
return previous.isAgree != current.isAgree ||
|
||||
previous.hasErrors != current.hasErrors;
|
||||
}, builder: (context, state) {
|
||||
return KwButton.primary(
|
||||
disabled: !state.isAgree || state.hasErrors,
|
||||
label: '${'submit_profile_verification'.tr()} ',
|
||||
onPressed: () {
|
||||
context.read<CheckListBloc>().add(const CheckListEventSubmit());
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:krow/core/data/static/contacts_data.dart';
|
||||
import 'package:krow/core/presentation/gen/assets.gen.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_box_decorations.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/core/presentation/widgets/contact_icon_button.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:whatsapp_unilink/whatsapp_unilink.dart';
|
||||
|
||||
@RoutePage()
|
||||
class WaitingValidationScreen extends StatefulWidget {
|
||||
const WaitingValidationScreen({super.key});
|
||||
|
||||
@override
|
||||
State<WaitingValidationScreen> createState() =>
|
||||
_WaitingValidationScreenState();
|
||||
}
|
||||
|
||||
class _WaitingValidationScreenState extends State<WaitingValidationScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
color: AppColors.bgColorDark,
|
||||
child: SvgPicture.asset(
|
||||
Assets.images.bg.path,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: buildAppBar(),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 120, left: 16, right: 16),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: KwBoxDecorations.primaryDark,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Assets.images.waitingValidation.coffeeBreak.svg(),
|
||||
const Gap(24),
|
||||
Text(
|
||||
'your_account_is_being_verified'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppTextStyles.headingH1.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
Text(
|
||||
'waiting_for_email_interview'.tr(),
|
||||
style: AppTextStyles.bodyMediumReg.copyWith(
|
||||
color: AppColors.textPrimaryInverted,
|
||||
),
|
||||
),
|
||||
const Gap(24),
|
||||
Text(
|
||||
'${'contact_support_via'.tr()}:',
|
||||
style: AppTextStyles.bodyMediumMed.copyWith(
|
||||
color: AppColors.primaryYellow,
|
||||
),
|
||||
),
|
||||
const Gap(12),
|
||||
buildContactsGroup()
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Row buildContactsGroup() {
|
||||
return Row(
|
||||
spacing: 24,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ContactIconButton(
|
||||
icon: Assets.images.waitingValidation.call,
|
||||
onTap: () {
|
||||
launchUrlString('tel:${ContactsData.supportPhone}');
|
||||
},
|
||||
),
|
||||
ContactIconButton(
|
||||
icon: Assets.images.waitingValidation.sms,
|
||||
onTap: () {
|
||||
launchUrlString('mailto:${ContactsData.supportEmail}');
|
||||
},
|
||||
),
|
||||
ContactIconButton(
|
||||
icon: Assets.images.waitingValidation.whatsapp,
|
||||
onTap: () {
|
||||
const link = WhatsAppUnilink(
|
||||
phoneNumber: ContactsData.supportPhone,
|
||||
text: 'Hey!',
|
||||
);
|
||||
launchUrlString(link.toString());
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
AppBar buildAppBar() {
|
||||
return KwAppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
iconColorStyle: AppBarIconColorStyle.inverted,
|
||||
showNotification: false,
|
||||
contentColor: AppColors.primaryYellow,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/check_box.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/check_box_card.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_bloc.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_event.dart';
|
||||
import 'package:krow/features/check_list/domain/bloc/check_list_state.dart';
|
||||
|
||||
class CheckListDisplayWidget extends StatelessWidget {
|
||||
const CheckListDisplayWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<CheckListBloc, CheckListState>(
|
||||
buildWhen: (previous, current) {
|
||||
return previous.checkListItems != current.checkListItems;
|
||||
},
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (final item in state.checkListItems)
|
||||
CheckBoxCard(
|
||||
title: item.title,
|
||||
isChecked: item.error == null,
|
||||
checkBoxStyle: item.error != null
|
||||
? CheckBoxStyle.black
|
||||
: CheckBoxStyle.green,
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
trailing: true,
|
||||
errorMessage: item.error,
|
||||
onTap: () {
|
||||
final route = item.route;
|
||||
if (route == null) return;
|
||||
|
||||
context.router.push<void>(route).then((_) {
|
||||
if (!context.mounted) return;
|
||||
|
||||
context
|
||||
.read<CheckListBloc>()
|
||||
.add(CheckForListUpdateEvent(editedItem: item));
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user