From 3789d998a8114bca97949bf4a8edbcd6e461ffb1 Mon Sep 17 00:00:00 2001 From: PGAN-MIS Date: Wed, 5 Apr 2023 08:54:24 +0800 Subject: [PATCH] Add save credentials feature --- .../contact/contact_bloc.dart | 75 +++++ .../contact/contact_event.dart | 59 +++- .../contact/contact_state.dart | 58 +++- .../profile/references/references_bloc.dart | 1 - lib/bloc/user/user_bloc.dart | 31 +- lib/bloc/user/user_state.dart | 4 +- lib/main.dart | 19 +- .../contact_information/add_modal.dart | 246 ++++++++++++++ .../contact_information/edit_modal.dart | 278 ++++++++++++++++ .../contact_information_screen.dart | 161 +++++++++- .../components/eligibility/add_modal.dart | 3 + .../components/eligibility/edit_modal.dart | 20 +- .../components/reference/add_modal.dart | 3 +- .../profile/components/references_screen.dart | 2 + .../unit2/homepage.dart/components/menu.dart | 8 +- lib/screens/unit2/login/login.dart | 44 ++- .../components/custom_switch.dart | 3 +- .../qr_code_scanner.dart/settings_screen.dart | 2 +- lib/sevices/profile/contact_services.dart | 128 ++++++++ lib/utils/alerts.dart | 34 ++ lib/utils/global.dart | 9 +- lib/utils/profile_utilities.dart | 33 +- lib/utils/urls.dart | 14 + lib/widgets/error_state.dart | 2 +- lib/widgets/splash_screen.dart | 16 +- pubspec.lock | 300 +++++++++++++++++- pubspec.yaml | 8 +- 27 files changed, 1497 insertions(+), 64 deletions(-) create mode 100644 lib/screens/profile/components/basic_information/contact_information/add_modal.dart create mode 100644 lib/screens/profile/components/basic_information/contact_information/edit_modal.dart create mode 100644 lib/sevices/profile/contact_services.dart diff --git a/lib/bloc/profile/primary_information/contact/contact_bloc.dart b/lib/bloc/profile/primary_information/contact/contact_bloc.dart index b01bb81..9f8070d 100644 --- a/lib/bloc/profile/primary_information/contact/contact_bloc.dart +++ b/lib/bloc/profile/primary_information/contact/contact_bloc.dart @@ -1,5 +1,10 @@ +import 'dart:math'; + import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:unit2/sevices/profile/contact_services.dart'; +import 'package:unit2/utils/profile_utilities.dart'; import '../../../../model/profile/basic_information/contact_information.dart'; @@ -9,6 +14,8 @@ part 'contact_state.dart'; class ContactBloc extends Bloc { ContactBloc() : super(ContactInitial()) { List contactInformations = []; + List serviceTypes =[]; + //// get all contacts on((event, emit) { emit(ContactLoadingState()); try { @@ -18,5 +25,73 @@ class ContactBloc extends Bloc { emit(ContactErrorState(message: e.toString())); } }); + //// Load Contacts + on((event,emit){ + emit(ContactLoadedState(contactInformation: event.contactInformation)); + }); + //// show add form + on((event,emit)async{ + try{ + emit(ContactLoadingState()); + if(serviceTypes.isEmpty){ + serviceTypes = await ProfileUtilities.instance.getServiceType(); + } + emit(ContactAddingState(serviceTypes: serviceTypes)); + }catch(e){ + emit(ContactErrorState(message: e.toString())); + } + }); + ///// Show edit form + on((event,emit)async{ + ServiceType serviceType; + List serviceProvivers; + ServiceProvider serviceProvider; + try{ + if(serviceTypes.isEmpty){ + serviceTypes = await ProfileUtilities.instance.getServiceType(); + } + serviceType = serviceTypes.firstWhere((var element){ + return event.contactInfo.commService!.serviceType!.id == element.id; + }); + serviceProvivers = await ContactService.instance.getServiceProvider(serviceTypeId: serviceType.id!); + serviceProvider = serviceProvivers.firstWhere((element) => element.id == event.contactInfo.commService!.serviceProvider!.id); + emit(ContactEditingState(serviceTypes: serviceTypes,selectedServiceType: serviceType,serviceProviders: serviceProvivers,selectedProvider: serviceProvider, contactInfo: event.contactInfo)); + }catch(e){ + emit(ContactErrorState(message: e.toString())); + } + }); + ////edit contact + on((event,emit)async{ + Map responseStatus = await ContactService.instance.update(profileId: event.profileId, token: event.token, contactInfo: event.contactInfo); + if(responseStatus['success']){ + ContactInfo contactInfo = ContactInfo.fromJson(responseStatus['data']['contact_info']); + contactInformations.removeWhere((ContactInfo element) => element.id == event.contactInfo.id); + contactInformations.add(contactInfo); + emit(ContactEditedState(contactInformation: contactInformations, response: responseStatus)); + }else{ + emit(ContactEditedState(contactInformation: contactInformations, response: responseStatus)); + } + }); + + //// add contact + try{ + + }catch(e){ + emit(ContactErrorState(message: e.toString())); + } + //// delete contact + on((event, emit)async{ + try{ + final bool success = await ContactService.instance.deleteContact(profileId: event.profileId, token: event.token, contactInfo: event.contactInfo); + if(success){ + contactInformations.removeWhere((element) => element.id == event.contactInfo.id); + emit(ContactDeletedState(contactInformation: contactInformations, succcess: success)); + }else{ + emit(ContactDeletedState(contactInformation: contactInformations, succcess: success)); + } + }catch(e){ + emit(ContactErrorState(message: e.toString())); + } + }); } } diff --git a/lib/bloc/profile/primary_information/contact/contact_event.dart b/lib/bloc/profile/primary_information/contact/contact_event.dart index e2bdc88..e5259eb 100644 --- a/lib/bloc/profile/primary_information/contact/contact_event.dart +++ b/lib/bloc/profile/primary_information/contact/contact_event.dart @@ -7,10 +7,65 @@ abstract class ContactEvent extends Equatable { List get props => []; } - +////get contacts class GetContacts extends ContactEvent{ final List contactInformations; const GetContacts({required this.contactInformations}); @override List get props => []; -} \ No newline at end of file +} + +//// load contacts +class LoadContacts extends ContactEvent{ + final List contactInformation; + const LoadContacts({required this.contactInformation}); + @override + List get props => [contactInformation]; +} + +//// show add form +class ShowAddForm extends ContactEvent{ + +} + +//// show edit form +class ShowEditForm extends ContactEvent{ + final ContactInfo contactInfo; + const ShowEditForm({required this.contactInfo}); + @override + List get props => [contactInfo]; + +} + +////add event +class AddContactInformation extends ContactEvent{ + final int profileId; + final String token; + final ContactInfo contactInfo; + const AddContactInformation({required this.contactInfo, required this.profileId, required this.token}); + @override + List get props => [profileId,token,contactInfo]; +} + +////edit event +class EditContactInformation extends ContactEvent{ + final int profileId; + final String token; + final ContactInfo contactInfo; + const EditContactInformation({required this.contactInfo, required this.profileId, required this.token}); + @override + List get props => [profileId,token,contactInfo]; +} + +//// delete event + +class DeleteContactInformation extends ContactEvent{ + final int profileId; + final String token; + final ContactInfo contactInfo; + const DeleteContactInformation({required this.contactInfo, required this.profileId, required this.token}); + @override + List get props => [profileId,token,contactInfo]; +} + + diff --git a/lib/bloc/profile/primary_information/contact/contact_state.dart b/lib/bloc/profile/primary_information/contact/contact_state.dart index f5a403b..863f11c 100644 --- a/lib/bloc/profile/primary_information/contact/contact_state.dart +++ b/lib/bloc/profile/primary_information/contact/contact_state.dart @@ -9,19 +9,73 @@ abstract class ContactState extends Equatable { class ContactInitial extends ContactState {} +////loaded state class ContactLoadedState extends ContactState{ final List contactInformation; const ContactLoadedState({required this.contactInformation}); @override List get props => []; } - +////loading state class ContactLoadingState extends ContactState{ } +//// adding state +class ContactAddingState extends ContactState{ + final List serviceTypes; + const ContactAddingState({ required this.serviceTypes}); + @override + List get props => [serviceTypes]; +} +//// Editing state +class ContactEditingState extends ContactState{ + final List serviceTypes; + final List serviceProviders; + final ServiceProvider selectedProvider; + final ServiceType selectedServiceType; + final ContactInfo contactInfo; + const ContactEditingState({ required this.serviceTypes, required this.selectedServiceType, required this.selectedProvider, required this.serviceProviders, required this.contactInfo}); + @override + List get props => [serviceTypes]; +} + + +//// added state +class ContactAddedState extends ContactState{ + final List contactInformation; + final Map response; + const ContactAddedState({required this.contactInformation, required this.response}); + @override + List get props => [contactInformation,response]; +} + + + + +//// edited state +class ContactEditedState extends ContactState{ + final List contactInformation; + final Map response; + const ContactEditedState({required this.contactInformation, required this.response}); + @override + List get props => [contactInformation,response]; +} +////deleted state +class ContactDeletedState extends ContactState{ + final List contactInformation; + final bool succcess; + const ContactDeletedState({required this.contactInformation, required this.succcess}); + @override + List get props => [contactInformation,succcess]; +} + +////error state class ContactErrorState extends ContactState{ final String message; const ContactErrorState({required this.message}); @override List get props => [message]; -} \ No newline at end of file +} + + + diff --git a/lib/bloc/profile/references/references_bloc.dart b/lib/bloc/profile/references/references_bloc.dart index 5c2b2f8..3564706 100644 --- a/lib/bloc/profile/references/references_bloc.dart +++ b/lib/bloc/profile/references/references_bloc.dart @@ -162,7 +162,6 @@ class ReferencesBloc extends Bloc { //// add reference event on((event, emit) async { try { - emit(ReferencesLoadingState()); Map status = await ReferencesServices.instace .addReference( ref: event.reference, diff --git a/lib/bloc/user/user_bloc.dart b/lib/bloc/user/user_bloc.dart index 1042352..26e3e2f 100644 --- a/lib/bloc/user/user_bloc.dart +++ b/lib/bloc/user/user_bloc.dart @@ -1,13 +1,14 @@ import 'dart:async'; import 'dart:io'; - import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:unit2/model/login_data/user_info/user_data.dart'; import 'package:unit2/model/login_data/version_info.dart'; import 'package:unit2/screens/unit2/login/functions/get_app_version.dart'; import 'package:unit2/sevices/login_service/auth_service.dart'; +import 'package:unit2/utils/global.dart'; import '../../utils/scanner.dart'; import '../../utils/text_container.dart'; @@ -19,6 +20,7 @@ class UserBloc extends Bloc { UserData? _userData; VersionInfo? _versionInfo; String? _apkVersion; + bool save = false; UserBloc() : super(UserInitial()) { // this event is called when opening the app to check if // there is new app version @@ -29,7 +31,16 @@ class UserBloc extends Bloc { _versionInfo = versionInfo; String apkVersion = await getAppVersion(); _apkVersion = apkVersion; - emit(VersionLoaded(versionInfo: _versionInfo, apkVersion: _apkVersion)); + final String? saved = CREDENTIALS?.get('saved'); + final String? username = CREDENTIALS?.get('username'); + final String? password = CREDENTIALS?.get('password'); + if (saved != null) { + save = true; + add(UserLogin(username: username, password: password)); + } else { + emit(VersionLoaded( + versionInfo: _versionInfo, apkVersion: _apkVersion)); + } } catch (e) { emit(UserError( message: e.toString(), @@ -48,14 +59,10 @@ class UserBloc extends Bloc { if (response['status'] == true) { UserData userData = UserData.fromJson(response['data']); emit(UserLoggedIn( - userData: userData, - success: true, - message: response['message'])); - }else{ - emit(UserLoggedIn( - userData: null, - success: false, - message: response['message'])); + userData: userData, success: true, message: response['message'],savedCredentials: save)); + } else { + emit(UserLoggedIn( + userData: null, success: false, message: response['message'],savedCredentials: save)); } } on TimeoutException catch (_) { emit(InternetTimeout(message: timeoutError)); @@ -68,7 +75,7 @@ class UserBloc extends Bloc { UserData? userData = await AuthService.instance .qrLogin(uuid: event.uuid, password: event.password); _userData = userData; - emit(UserLoggedIn(userData: _userData)); + emit(UserLoggedIn(userData: _userData,savedCredentials: save)); } on TimeoutException catch (_) { emit(InternetTimeout(message: timeoutError)); } on SocketException catch (_) { @@ -78,7 +85,7 @@ class UserBloc extends Bloc { } }); on((event, emit) { - emit(UserLoggedIn(userData: _userData)); + emit(UserLoggedIn(userData: _userData,savedCredentials: save)); }); on((event, emit) async { ScanResult result = await QRCodeBarCodeScanner.instance.scanner(); diff --git a/lib/bloc/user/user_state.dart b/lib/bloc/user/user_state.dart index 26d815f..de6688f 100644 --- a/lib/bloc/user/user_state.dart +++ b/lib/bloc/user/user_state.dart @@ -20,6 +20,7 @@ class UserLoading extends UserState { } class SplashScreen extends UserState { + @override List get props => []; } @@ -34,7 +35,8 @@ class UserLoggedIn extends UserState{ final UserData? userData; final String? message; final bool? success; - UserLoggedIn({this.userData,this.message,this.success}); + final bool? savedCredentials; + UserLoggedIn({this.userData,this.message,this.success,this.savedCredentials}); } class VersionLoaded extends UserState { diff --git a/lib/main.dart b/lib/main.dart index ce06e14..da7df5a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,17 +3,28 @@ import 'package:flutter/material.dart'; import 'package:device_preview/device_preview.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hive/hive.dart'; +import 'package:hive_flutter/hive_flutter.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/app_router.dart'; import 'package:unit2/utils/global_context.dart'; import 'package:unit2/utils/global_context.dart'; +import 'package:path_provider/path_provider.dart' as path_provider; import './utils/router.dart'; import './utils/global.dart'; -void main() { - runApp(MyApp()); +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + var appDirectory = await path_provider.getApplicationDocumentsDirectory(); + await Hive.initFlutter(appDirectory.path); + CREDENTIALS = await Hive.openBox('credentials'); + SOSCONTACTS = await Hive.openBox('soscontacts'); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) + .then((_) { + runApp(MyApp()); + }); } // void main() => runApp( @@ -48,7 +59,7 @@ class MyApp extends StatelessWidget { BlocProvider( create: (_) => UserBloc(), ), - BlocProvider( + BlocProvider( create: (_) => ProfileBloc(), ), ], @@ -60,7 +71,7 @@ class MyApp extends StatelessWidget { // routeInformationParser: goRouter.routeInformationParser, // routerDelegate: goRouter.routerDelegate, // routeInformationProvider: goRouter.routeInformationProvider, - + title: 'uniT2 - Universal Tracker and Tracer', theme: ThemeData( primarySwatch: Colors.red, diff --git a/lib/screens/profile/components/basic_information/contact_information/add_modal.dart b/lib/screens/profile/components/basic_information/contact_information/add_modal.dart new file mode 100644 index 0000000..362d88f --- /dev/null +++ b/lib/screens/profile/components/basic_information/contact_information/add_modal.dart @@ -0,0 +1,246 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart'; +import 'package:unit2/sevices/profile/contact_services.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; + +import '../../../../../theme-data.dart/colors.dart'; + +class AddContactInformationScreen extends StatefulWidget { + final int profileId; + final String token; + const AddContactInformationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _AddContactInformationScreenState(); +} + +class _AddContactInformationScreenState + extends State { + final formKey = GlobalKey(); + ServiceType? selectedServiceType; + ServiceProvider? selectedProvider; + List serviceProviders = []; + bool callServiceType = false; + bool primaryaContact = false; + bool active = false; + String? numberMail; + var mobileFormatter = MaskTextInputFormatter( + mask: "+63 (##) ###-###", + filter: {"#": RegExp(r"^[1-9][0-9]*$")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + var landLineFormatter = MaskTextInputFormatter( + mask: "(###) ###-###", + filter: {"#": RegExp(r"^[0-9]")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is ContactAddingState) { + return FormBuilder( + key: formKey, + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 24, horizontal: 12), + child: Column( + children: [ + const SizedBox( + height: 24, + ), + ////Service Type + FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "service_type", + items: state.serviceTypes + .map>( + (ServiceType e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + decoration: normalTextFieldStyle("Service Type*", ""), + onChanged: (var service) async { + if (selectedServiceType != service) { + selectedServiceType = service; + setState(() { + callServiceType = true; + }); + serviceProviders = await ContactService.instance + .getServiceProvider( + serviceTypeId: selectedServiceType!.id!); + setState(() { + setState(() { + callServiceType = false; + }); + }); + } + }), + const SizedBox( + height: 12, + ), + ////Service Provider + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: callServiceType, + child: FormBuilderDropdown( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "Service Provider", + items: serviceProviders.isEmpty + ? [] + : serviceProviders + .map>( + (ServiceProvider e) { + return DropdownMenuItem( + value: e, child: Text(e.agency!.name!)); + }).toList(), + decoration: normalTextFieldStyle( + "Communication Service *", ""), + onChanged: (var serviceProvider) { + selectedProvider = serviceProvider; + }), + ), + ), + selectedServiceType != null + ? selectedServiceType?.id == 2 + //// Landline + ? FormBuilderTextField( + inputFormatters: [landLineFormatter], + name: 'number-mail', + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Landline number *", + "(area code) xxx - xxxx"), + ) + : selectedServiceType!.id == 1 || + selectedServiceType!.id == 19 + //// Mobile number + ? FormBuilderTextField( + name: 'number-mail', + inputFormatters: [mobileFormatter], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Mobile number *", + "+63 (9xx) xxx - xxxx"), + ) + : selectedServiceType!.id == 4 + ////Social Media + ? FormBuilderTextField( + name: 'number-mail', + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "Account ID / Username *", ""), + ) + : selectedServiceType!.id == 3 + ////Email Address + ? FormBuilderTextField( + name: 'number-mail', + validator: + FormBuilderValidators.compose([ + FormBuilderValidators.email( + errorText: + "Input vaild email"), + FormBuilderValidators.required( + errorText: + "This field is required") + ]), + decoration: normalTextFieldStyle( + "Email Address*", ""), + ) + : Container() + : const SizedBox(), + SizedBox( + height: selectedServiceType != null ? 12 : 0, + ), + //// Primary + FormBuilderSwitch( + initialValue: primaryaContact, + activeColor: second, + onChanged: (value) { + setState(() { + primaryaContact = value!; + }); + }, + decoration: normalTextFieldStyle("Primary?", 'Primary?'), + name: 'overseas', + title: Text(primaryaContact ? "YES" : "NO"), + ), + //// Active + const SizedBox( + height: 12, + ), + FormBuilderSwitch( + initialValue: primaryaContact, + activeColor: second, + onChanged: (value) { + setState(() { + active = value!; + }); + }, + decoration: normalTextFieldStyle("Active?", ''), + name: 'overseas', + title: Text(active ? "YES" : "NO"), + ), + const Expanded(child: SizedBox()), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + + numberMail = + formKey.currentState!.value['number-mail']; + CommService commService = CommService( + id: null, + serviceType: selectedServiceType, + serviceProvider: selectedProvider); + ContactInfo contactInfo = ContactInfo( + id: null, + active: active, + primary: primaryaContact, + numbermail: numberMail, + commService: commService); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(AddContactInformation(contactInfo: contactInfo, profileId: widget.profileId, token: widget.token)); + } + }, + style: + mainBtnStyle(primary, Colors.transparent, second), + child: const Text(submit), + ), + ) + ], + ), + )); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/basic_information/contact_information/edit_modal.dart b/lib/screens/profile/components/basic_information/contact_information/edit_modal.dart new file mode 100644 index 0000000..9b6b1e4 --- /dev/null +++ b/lib/screens/profile/components/basic_information/contact_information/edit_modal.dart @@ -0,0 +1,278 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:fluttericon/entypo_icons.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; +import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; +import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart'; +import 'package:unit2/sevices/profile/contact_services.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/utils/text_container.dart'; + +import '../../../../../theme-data.dart/colors.dart'; + +class EditContactInformationScreen extends StatefulWidget { + final int profileId; + final String token; + const EditContactInformationScreen( + {super.key, required this.profileId, required this.token}); + + @override + State createState() => + _EditContactInformationScreenState(); +} + +class _EditContactInformationScreenState + extends State { + final formKey = GlobalKey(); + ServiceType? selectedServiceType; + ServiceProvider? selectedProvider; + List serviceProviders = []; + String? numberMail; + bool callServiceType = false; + bool? primaryaContact; + bool? active; + + var mobileFormatter = MaskTextInputFormatter( + mask: "+63 (##) ###-###", + filter: {"#": RegExp(r"^[1-9][0-9]*$")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + var landLineFormatter = MaskTextInputFormatter( + mask: "(###) ###-###", + filter: {"#": RegExp(r"^[0-9]")}, + type: MaskAutoCompletionType.lazy, + initialText: "0"); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is ContactEditingState) { + selectedServiceType = state.selectedServiceType; + selectedProvider = state.selectedProvider; + serviceProviders = state.serviceProviders; + primaryaContact = state.contactInfo.primary!; + active = state.contactInfo.active!; + return FormBuilder( + key: formKey, + child: Padding( + padding: + const EdgeInsets.symmetric(vertical: 24, horizontal: 12), + child: Column( + children: [ + const SizedBox( + height: 24, + ), + StatefulBuilder(builder: (context, setState) { + return Column(children: [ + ////Service Type + DropdownButtonFormField( + validator: FormBuilderValidators.required( + errorText: "This field is required"), + value: selectedServiceType, + items: state.serviceTypes + .map>( + (ServiceType e) { + return DropdownMenuItem( + value: e, child: Text(e.name!)); + }).toList(), + decoration: + normalTextFieldStyle("Service Type*", ""), + onChanged: (var service) async { + if (selectedServiceType!.id != service!.id) { + selectedServiceType = service; + setState(() { + callServiceType = true; + }); + serviceProviders = await ContactService.instance + .getServiceProvider( + serviceTypeId: + selectedServiceType!.id!); + selectedProvider = null; + setState(() { + setState(() { + callServiceType = false; + }); + }); + } + }), + const SizedBox( + height: 12, + ), + ////Service Provider + SizedBox( + height: 60, + child: ModalProgressHUD( + color: Colors.transparent, + inAsyncCall: callServiceType, + child: DropdownButtonFormField( + value: selectedProvider, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + items: serviceProviders.isEmpty + ? [] + : serviceProviders + .map>( + (ServiceProvider e) { + return DropdownMenuItem< + ServiceProvider>( + value: e, + child: Text(e.agency!.name!)); + }).toList(), + decoration: normalTextFieldStyle( + "Communication Service *", ""), + onChanged: (var serviceProvider) { + selectedProvider = serviceProvider; + }), + ), + ), + selectedServiceType != null + ? selectedServiceType?.id == 2 + //// Landline + ? FormBuilderTextField( + name: 'number-mail', + initialValue: state.contactInfo.numbermail, + inputFormatters: [landLineFormatter], + validator: FormBuilderValidators.required( + errorText: "This field is required"), + decoration: normalTextFieldStyle( + "Landline number *", + "(area code) xxx - xxxx"), + ) + : selectedServiceType!.id == 1 || + selectedServiceType!.id == 19 + //// Mobile number + ? FormBuilderTextField( + name: 'number-mail', + inputFormatters: [mobileFormatter], + initialValue: + state.contactInfo.numbermail, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "Mobile number *", + "+63 (9xx) xxx - xxxx"), + ) + : selectedServiceType!.id == 4 + ////Social Media + ? FormBuilderTextField( + name: 'number-mail', + initialValue: + state.contactInfo.numbermail, + validator: + FormBuilderValidators.required( + errorText: + "This field is required"), + decoration: normalTextFieldStyle( + "Account ID / Username *", ""), + ) + : selectedServiceType!.id == 3 + ////Email Address + ? FormBuilderTextField( + name: 'number-mail', + initialValue: state + .contactInfo.numbermail, + validator: FormBuilderValidators + .compose([ + FormBuilderValidators.email( + errorText: + "Input vaild email"), + FormBuilderValidators.required( + errorText: + "This field is required") + ]), + decoration: + normalTextFieldStyle( + "Email Address*", ""), + ) + : Container() + : const SizedBox(), + ]); + }), + SizedBox( + height: selectedServiceType != null ? 12 : 0, + ), + //// Primary + StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: primaryaContact, + activeColor: second, + onChanged: (value) { + setState(() { + primaryaContact = value; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Primary ?"), + ); + }), + //// Active + const SizedBox( + height: 12, + ), + StatefulBuilder(builder: (context, setState) { + return FormBuilderSwitch( + initialValue: active, + activeColor: second, + onChanged: (value) { + setState(() { + active = value; + }); + }, + decoration: normalTextFieldStyle("", ''), + name: 'overseas', + title: const Text("Active ?"), + ); + }), + const Expanded(child: SizedBox()), + SizedBox( + height: 60, + width: double.infinity, + child: ElevatedButton( + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + numberMail = + formKey.currentState!.value['number-mail']; + CommService commService = CommService( + id: state.contactInfo.commService!.id, + serviceType: selectedServiceType, + serviceProvider: selectedProvider); + ContactInfo contactInfo = ContactInfo( + id: state.contactInfo.id, + active: active, + primary: primaryaContact, + numbermail: numberMail, + commService: commService); + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add( + EditContactInformation( + contactInfo: contactInfo, + profileId: widget.profileId, + token: widget.token)); + } + }, + style: + mainBtnStyle(primary, Colors.transparent, second), + child: const Text(submit), + ), + ) + ], + ), + )); + } + return Container(); + }, + ); + } +} diff --git a/lib/screens/profile/components/basic_information/contact_information_screen.dart b/lib/screens/profile/components/basic_information/contact_information_screen.dart index e7601a1..721ab4c 100644 --- a/lib/screens/profile/components/basic_information/contact_information_screen.dart +++ b/lib/screens/profile/components/basic_information/contact_information_screen.dart @@ -1,16 +1,23 @@ +import 'package:app_popup_menu/app_popup_menu.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttericon/font_awesome_icons.dart'; import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/screens/profile/components/basic_information/contact_information/add_modal.dart'; +import 'package:unit2/screens/profile/components/basic_information/contact_information/edit_modal.dart'; import 'package:unit2/theme-data.dart/box_shadow.dart'; import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/utils/alerts.dart'; import 'package:unit2/utils/text_container.dart'; import 'package:unit2/widgets/Leadings/add_leading.dart'; import 'package:unit2/widgets/empty_data.dart'; +import '../../../../bloc/profile/eligibility/eligibility_bloc.dart'; + class ContactInformationScreen extends StatelessWidget { const ContactInformationScreen({ super.key, @@ -18,13 +25,19 @@ class ContactInformationScreen extends StatelessWidget { @override Widget build(BuildContext context) { + int profileId; + String token; return SafeArea( child: Scaffold( appBar: AppBar( title: const Text(contactScreenTitle), centerTitle: true, backgroundColor: primary, - actions: [AddLeading(onPressed: () {})], + actions: [ + AddLeading(onPressed: () { + context.read().add(ShowAddForm()); + }) + ], ), body: ProgressHUD( padding: const EdgeInsets.all(24), @@ -33,6 +46,8 @@ class ContactInformationScreen extends StatelessWidget { child: BlocBuilder( builder: (context, state) { if (state is UserLoggedIn) { + token = state.userData!.user!.login!.token!; + profileId = state.userData!.user!.login!.user!.profileId!; return BlocBuilder( builder: (context, state) { if (state is ProfileLoaded) { @@ -43,10 +58,58 @@ class ContactInformationScreen extends StatelessWidget { progress!.showWithText("Please wait..."); } if (state is ContactLoadedState || - state is ContactErrorState) { + state is ContactErrorState || + state is ContactAddingState || + state is ContactEditingState || + state is ContactDeletedState || + state is ContactAddedState || + state is ContactEditedState) { final progress = ProgressHUD.of(context); progress!.dismiss(); } + ////EDIT CONTACT STATE + if (state is ContactEditedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadContacts( + contactInformation: + state.contactInformation)); + }); + } else { + errorAlert(context, "Update Failed", + "Something went wrong. Please try again.", + () { + Navigator.of(context).pop(); + context.read().add(LoadContacts( + contactInformation: + state.contactInformation)); + }); + } + } + + ////DELETED STATE + if (state is ContactDeletedState) { + if (state.succcess) { + successAlert(context, "Deletion Successfull", + "Contact Info has been deleted successfully", + () { + Navigator.of(context).pop(); + context.read().add(LoadContacts( + contactInformation: + state.contactInformation)); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Contact Info", () { + Navigator.of(context).pop(); + context.read().add(LoadContacts( + contactInformation: + state.contactInformation)); + }); + } + } }, builder: (context, state) { if (state is ContactLoadedState) { @@ -151,12 +214,65 @@ class ContactInformationScreen extends StatelessWidget { .toString()), ]), ), - IconButton( - onPressed: () {}, - icon: const Icon( - Icons.more_vert, - color: Colors.grey, - )) + AppPopupMenu( + offset: + const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + ////delete contact-= = = = = = = = =>> + if (value == 2) { + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + confirmAlert( + context, + () => context + .read< + ContactBloc>() + .add(DeleteContactInformation( + contactInfo: + state.contactInformation[ + index], + profileId: + profileId, + token: + token)), + "Delete?", + "Are you sure you want to delete this contact info?"); + } + if (value == 1) { + ////edit contact-= = = = = = = = =>> + context + .read() + .add(ShowEditForm( + contactInfo: state + .contactInformation[ + index])); + final progress = + ProgressHUD.of( + context); + progress!.showWithText( + "Loading..."); + } + }, + menuItems: [ + popMenuItem( + text: "Edit", + value: 1, + icon: Icons.edit), + popMenuItem( + text: "Delete", + value: 2, + icon: Icons.delete), + ], + icon: const Icon( + Icons.more_vert, + color: Colors.grey, + ), + tooltip: "Options", + ) ], ), ), @@ -172,6 +288,16 @@ class ContactInformationScreen extends StatelessWidget { "You don't have contact information added. Please click + to add"); } } + if (state is ContactAddingState) { + return AddContactInformationScreen( + profileId: profileId, + token: token, + ); + } + if (state is ContactEditingState) { + return EditContactInformationScreen( + profileId: profileId, token: token); + } return Container(); }, ); @@ -186,4 +312,23 @@ class ContactInformationScreen extends StatelessWidget { )), ); } + + PopupMenuItem popMenuItem({String? text, int? value, IconData? icon}) { + return PopupMenuItem( + value: value, + child: Row( + children: [ + Icon( + icon, + ), + const SizedBox( + width: 10, + ), + Text( + text!, + ), + ], + ), + ); + } } diff --git a/lib/screens/profile/components/eligibility/add_modal.dart b/lib/screens/profile/components/eligibility/add_modal.dart index 561c76b..7b896fa 100644 --- a/lib/screens/profile/components/eligibility/add_modal.dart +++ b/lib/screens/profile/components/eligibility/add_modal.dart @@ -152,6 +152,7 @@ class _AddEligibilityScreenState extends State { Flexible( flex: 1, child: DateTimePicker( + validator: FormBuilderValidators.required(errorText: "This field is required"), use24HourFormat: false, icon: const Icon( Icons.date_range), @@ -178,6 +179,7 @@ class _AddEligibilityScreenState extends State { Flexible( flex: 1, child: DateTimePicker( + validator: FormBuilderValidators.required(errorText: "This field is required"), controller: validityDateController, firstDate: DateTime(1970), @@ -214,6 +216,7 @@ class _AddEligibilityScreenState extends State { Column( children: [ FormBuilderSwitch( + validator: FormBuilderValidators.required(errorText: 'This field is required'), initialValue: overseas, activeColor: second, onChanged: (value) { diff --git a/lib/screens/profile/components/eligibility/edit_modal.dart b/lib/screens/profile/components/eligibility/edit_modal.dart index 69b7f64..24df914 100644 --- a/lib/screens/profile/components/eligibility/edit_modal.dart +++ b/lib/screens/profile/components/eligibility/edit_modal.dart @@ -2,6 +2,7 @@ import 'package:date_time_picker/date_time_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:intl/intl.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart'; @@ -173,6 +174,7 @@ class _EditEligibilityScreenState extends State { Flexible( flex: 1, child: DateTimePicker( + validator: FormBuilderValidators.required(errorText: "This field is required"), use24HourFormat: false, controller: examDateController, firstDate: DateTime(1970), @@ -188,7 +190,7 @@ class _EditEligibilityScreenState extends State { const SizedBox( width: 12, ), - //VALIDITY DATE + ////VALIDITY DATE Flexible( flex: 1, child: DateTimePicker( @@ -335,7 +337,7 @@ class _EditEligibilityScreenState extends State { const SizedBox( height: 20, ), - //PROVINCE DROPDOWN + ////PROVINCE DROPDOWN SizedBox( height: 70, child: ModalProgressHUD( @@ -395,7 +397,7 @@ class _EditEligibilityScreenState extends State { ), ), - // City municipality + //// City municipality SizedBox( height: 70, child: ModalProgressHUD( @@ -458,29 +460,29 @@ class _EditEligibilityScreenState extends State { style: mainBtnStyle( primary, Colors.transparent, second), onPressed: () { - //rating + ////rating double? rate = rating == null ? null : double.parse(rating!); - //license + ////license String? newLicense = license; - //city municipality + ////city municipality CityMunicipality? cityMunicipality = selectedMunicipality; - //exam date + ////exam date DateTime? examDate = examDateController.text.isEmpty ? null : DateTime.parse( examDateController.text); - // validity date + // // validity date DateTime? validityDate = validityDateController.text.isEmpty ? null : DateTime.parse( validityDateController .text); - // exam address + //// exam address ExamAddress examAddress = ExamAddress( barangay: state.eligibityCert .examAddress?.barangay, diff --git a/lib/screens/profile/components/reference/add_modal.dart b/lib/screens/profile/components/reference/add_modal.dart index 0060bbc..d3f73b9 100644 --- a/lib/screens/profile/components/reference/add_modal.dart +++ b/lib/screens/profile/components/reference/add_modal.dart @@ -468,7 +468,8 @@ class _AddReferenceScreenState extends State { firstName: firstname, middleName: middlename); } - +final progress = ProgressHUD.of(context); +progress!.showWithText("Please wait..."); context.read().add( AddReference( profileId: diff --git a/lib/screens/profile/components/references_screen.dart b/lib/screens/profile/components/references_screen.dart index 495bf3a..9282301 100644 --- a/lib/screens/profile/components/references_screen.dart +++ b/lib/screens/profile/components/references_screen.dart @@ -215,6 +215,8 @@ class ReferencesScreen extends StatelessWidget { ////delete eligibilty-= = = = = = = = =>> if (value == 2) { + final progress = ProgressHUD.of(context); +progress!.showWithText("Please wait..."); confirmAlert(context, () { context .read< diff --git a/lib/screens/unit2/homepage.dart/components/menu.dart b/lib/screens/unit2/homepage.dart/components/menu.dart index 17922a4..d635fd0 100644 --- a/lib/screens/unit2/homepage.dart/components/menu.dart +++ b/lib/screens/unit2/homepage.dart/components/menu.dart @@ -3,6 +3,7 @@ import 'package:unit2/model/login_data/employee_info/employee_info.dart'; import 'package:unit2/model/login_data/user_info/user_data.dart'; import 'package:unit2/utils/alerts.dart'; import '../../../../theme-data.dart/colors.dart'; +import '../../../../utils/global.dart'; Widget getTile( IconData icondata, String title, String route, BuildContext context,UserData userData) { @@ -18,7 +19,8 @@ Widget getTile( ), onTap: () async { if (title.toLowerCase() == "logout") { - confirmAlert(context, () { + confirmAlert(context, () async{ + await CREDENTIALS!.clear(); Navigator.pushReplacementNamed (context,"/"); },"Logout","Are You sure you want to logout?"); @@ -26,9 +28,7 @@ Widget getTile( ProfileArguments profileArguments = ProfileArguments(token: userData.user!.login!.token!, userID:userData.user!.login!.user!.profileId!); Navigator.pushNamed(context, route,arguments: profileArguments); } - else { - Navigator.pushNamed(context, route); - } + }, ); } diff --git a/lib/screens/unit2/login/login.dart b/lib/screens/unit2/login/login.dart index b5dc6b5..11e7dce 100644 --- a/lib/screens/unit2/login/login.dart +++ b/lib/screens/unit2/login/login.dart @@ -14,6 +14,7 @@ import 'package:unit2/utils/internet_time_out.dart'; import 'package:unit2/utils/text_container.dart'; import 'package:unit2/widgets/error_state.dart'; import '../../../bloc/user/user_bloc.dart'; +import '../../../utils/global_context.dart'; import '../../../widgets/splash_screen.dart'; import '../../../widgets/wave.dart'; import '../../../utils/global.dart'; @@ -34,6 +35,7 @@ class _UniT2LoginState extends State { final _formKey = GlobalKey(); bool showSuffixIcon = false; bool _showPassword = true; + String? password; @override Widget build(BuildContext context) { return WillPopScope( @@ -46,12 +48,31 @@ class _UniT2LoginState extends State { if (state is UserLoggedIn || state is UuidLoaded) { final progress = ProgressHUD.of(context); progress!.dismiss(); - } if (state is UserLoggedIn) { if (state.success == true) { - Fluttertoast.showToast(msg: state.message!,toastLength: Toast.LENGTH_LONG,gravity: ToastGravity.CENTER); - Navigator.pushReplacementNamed(context, '/module-screen'); + if (!state.savedCredentials!) { + confirmAlertWithCancel(context, () async { + await CREDENTIALS?.put('saved', "saved"); + await CREDENTIALS?.put('username', + state.userData!.user!.login!.user!.username!); + await CREDENTIALS?.put('password', password); + Fluttertoast.showToast( + msg: "Credentials Successfully saved", + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + Navigator.pushReplacementNamed(context, '/module-screen'); + }, + () => Navigator.pushReplacementNamed( + context, '/module-screen'), + "Save credentials?", + "Do you want to save credentials so you don't have to login again next time?."); + }else{ + Navigator.pushReplacementNamed( + context, '/module-screen'); + } } else { final progress = ProgressHUD.of(context); progress!.dismiss(); @@ -215,6 +236,7 @@ class _UniT2LoginState extends State { TextStyle(color: Colors.white), ), onPressed: () { + password = "nav071394"; final progress = ProgressHUD.of(context); @@ -228,8 +250,7 @@ class _UniT2LoginState extends State { BlocProvider.of(context) .add(UserLogin( - username: - "rjvincentlopeplopez", + username: "rjvincentlopeplopez", password: "shesthequ33n", // username: _formKey // .currentState! @@ -293,7 +314,9 @@ class _UniT2LoginState extends State { third, Colors.transparent, Colors.white38), - onPressed: () {}, + onPressed: () { + + }, label: const Text( requestSOS, style: @@ -321,7 +344,14 @@ class _UniT2LoginState extends State { if (state is UserError) { return SomethingWentWrong( message: onError, - onpressed: () {}, + onpressed: () { + BlocProvider.of( + NavigationService.navigatorKey.currentContext!) + .add(GetApkVersion()); + return MaterialPageRoute(builder: (_) { + return const UniT2Login(); + }); + }, ); } if (state is InternetTimeout) { diff --git a/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart b/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart index 907993f..0255d85 100644 --- a/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart +++ b/lib/screens/unit2/roles/qr_code_scanner.dart/components/custom_switch.dart @@ -24,6 +24,7 @@ final int initialLabelIndex; padding: const EdgeInsets.all(15), height: 80, child: ToggleSwitch( + animate: true, minWidth: 150.0, cornerRadius: 25.0, activeBgColors: [ @@ -37,7 +38,7 @@ final int initialLabelIndex; totalSwitches: 2, labels: labels, icons: icons, - radiusStyle: false, + radiusStyle: true, onToggle: onToggle), ); } diff --git a/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart b/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart index 72b3f18..57081ed 100644 --- a/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart +++ b/lib/screens/unit2/roles/qr_code_scanner.dart/settings_screen.dart @@ -94,7 +94,7 @@ class _QRCodeScannerSettingsState extends State { ), FittedBox( child: CostumToggleSwitch( - activeBGColors: [Colors.green[800]!, Colors.red[800]!], + activeBGColors: [ Colors.red[800]!,Colors.green[800]!], initialLabelIndex: scanMode == 'INCOMING' ? 0 : 1, icons: const [ Entypo.down_bold, diff --git a/lib/sevices/profile/contact_services.dart b/lib/sevices/profile/contact_services.dart new file mode 100644 index 0000000..6e23edf --- /dev/null +++ b/lib/sevices/profile/contact_services.dart @@ -0,0 +1,128 @@ +import 'dart:convert'; + +import 'package:unit2/model/profile/basic_information/contact_information.dart'; +import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/urls.dart'; +import 'package:http/http.dart' as http; + +class ContactService { + static final ContactService _instance = ContactService(); + static ContactService get instance => _instance; + + Future> getServiceProvider( + {required int serviceTypeId}) async { + String path = Url.instance.getServiceType(); + Map params = {"service_type__id": serviceTypeId.toString()}; + List serviceProviders = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + try { + http.Response response = await Request.instance + .getRequest(param: params, path: path, headers: headers); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + if (data['data'] != null) { + for (var element in data['data']) { + CommService commService = CommService.fromJson(element); + serviceProviders.add(commService.serviceProvider!); + } + } + } + } catch (e) { + throw e.toString(); + } + return serviceProviders; + } + +//// update + Future> update( + {required int profileId, + required String token, + required ContactInfo contactInfo}) async { + String path = "${Url.instance.contactPath()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authToken + }; + Map body = { + "personid": profileId, + "contactinfoid": contactInfo.id, + "_numbermail": contactInfo.numbermail, + "_active": contactInfo.active, + "_primary": contactInfo.primary, + "_commServiceId": contactInfo.commService!.serviceProvider!.id! + }; + Map responseStatus = {}; + try { + http.Response response = await Request.instance + .putRequest(path: path, headers: headers, body: body, param: {}); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + responseStatus = data; + } else { + responseStatus.addAll({'success': false}); + } + return responseStatus; + } catch (e) { + throw e.toString(); + } + } + + //// add +// Future> update( +// {required int profileId, +// required String token, +// required ContactInfo contactInfo}) async { +// String path = "${Url.instance.contactPath()}$profileId/"; +// String authToken = "Token $token"; +// Map headers = { +// 'Content-Type': 'application/json; charset=UTF-8', +// 'Authorization': authToken +// }; +// Map body ={ +// "personid": profileId, +// "_numbermail": contactInfo.numbermail, +// "_active": contactInfo.active, +// "_primary": contactInfo.primary, +// "_commServiceId": contactInfo +// } + // } + +////delete + Future deleteContact( + {required int profileId, + required String token, + required ContactInfo contactInfo}) async { + String path = "${Url.instance.deleteContact()}$profileId/"; + String authToken = "Token $token"; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'mode': 'same-origin', + 'include': 'credentials', + 'Authorization': authToken + }; + bool success = false; + Map params = {"force_mode": "true"}; + Map body = { + "personid": profileId, + "contactinfoid": contactInfo.id, + "_numbermail": contactInfo.numbermail, + "_active": contactInfo.active, + "_primary": contactInfo.primary, + "_commServiceId": contactInfo.commService!.id + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 20) { + Map data = jsonDecode(response.body); + success = data['success']; + } + } catch (e) { + throw e.toString(); + } + return success; + } +} diff --git a/lib/utils/alerts.dart b/lib/utils/alerts.dart index a3e6f4e..1cd6a82 100644 --- a/lib/utils/alerts.dart +++ b/lib/utils/alerts.dart @@ -37,6 +37,40 @@ confirmAlert(context, Function() yes,String title, String subtitle) { ).show(); } +confirmAlertWithCancel(context, Function() yes,Function() no,String title, String subtitle) { + AwesomeDialog( + context: context, + dialogType: DialogType.question, + borderSide: const BorderSide( + color: Colors.green, + width: 0, + ), + width: blockSizeHorizontal * 90, + buttonsBorderRadius: const BorderRadius.all( + Radius.circular(2), + ), + dismissOnTouchOutside: false, + dismissOnBackKeyPress: false, + // onDismissCallback: (type) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text('Dismissed by $type'), + // ), + // ); + // }, + headerAnimationLoop: false, + animType: AnimType.bottomSlide, + title: title, + desc: subtitle, + btnOkText: "Yes", + btnCancelText: "No", + showCloseIcon: false, + btnCancelOnPress: no, + btnOkOnPress: yes, + ).show(); +} + + errorAlert(context, title, description,Function() func) { AwesomeDialog( width: blockSizeHorizontal * 90, diff --git a/lib/utils/global.dart b/lib/utils/global.dart index ccbabf2..de816db 100644 --- a/lib/utils/global.dart +++ b/lib/utils/global.dart @@ -1,3 +1,5 @@ +import 'package:hive/hive.dart'; + double screenWidth = 0; double screenHeight = 0; double blockSizeHorizontal = 0; @@ -5,4 +7,9 @@ double blockSizeVertical = 0; double safeAreaHorizontal = 0; double safeAreaVertical = 0; double safeBlockHorizontal = 0; -double safeBlockVertical = 0; \ No newline at end of file +double safeBlockVertical = 0; + + +//// hive boxes +Box? CREDENTIALS; +Box? SOSCONTACTS; \ No newline at end of file diff --git a/lib/utils/profile_utilities.dart b/lib/utils/profile_utilities.dart index 50ec5d3..310dc61 100644 --- a/lib/utils/profile_utilities.dart +++ b/lib/utils/profile_utilities.dart @@ -8,6 +8,7 @@ import 'package:unit2/model/utils/eligibility.dart'; import 'package:unit2/utils/request.dart'; import 'package:unit2/utils/urls.dart'; +import '../model/profile/basic_information/contact_information.dart'; import '../model/utils/agency.dart'; import '../model/utils/category.dart'; class ProfileUtilities { @@ -21,7 +22,7 @@ class ProfileUtilities { Map headers = { 'Content-Type': 'application/json; charset=UTF-8', }; - // try{ + try{ http.Response response = await Request.instance.getRequest(path: path, param: {},headers: headers); if(response.statusCode == 200){ Map data = jsonDecode(response.body); @@ -32,9 +33,9 @@ class ProfileUtilities { }); } } - // }catch(e){ - // throw(e.toString()); - // } + }catch(e){ + throw(e.toString()); + } return eligibilities; } @@ -89,5 +90,29 @@ class ProfileUtilities { return agencyCategory; } +//// get service type + Future> getServiceType()async{ + List serviceTypes = []; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + }; + String path = Url.instance.getServiceTypes(); + + try{ + http.Response response = await Request.instance.getRequest(param: {},path:path,headers: headers ); + if(response.statusCode == 200){ + Map data = jsonDecode(response.body); + if(data['data'] != null){ + for(var element in data['data']){ + ServiceType newServiceType = ServiceType.fromJson(element); + serviceTypes.add(newServiceType); + } + } + } + }catch(e){ + throw e.toString(); + } + return serviceTypes; + } } \ No newline at end of file diff --git a/lib/utils/urls.dart b/lib/utils/urls.dart index 38c24aa..e872d95 100644 --- a/lib/utils/urls.dart +++ b/lib/utils/urls.dart @@ -103,6 +103,20 @@ String getFamilies(){ return "/api/jobnet_app/profile/pds/family/"; } +//// contacts path +String getServiceTypes(){ + return "/api/jobnet_app/comm_service_type/"; + +} +String contactPath(){ + return "/api/jobnet_app/profile/pds/basic/contact/"; +} +String getServiceType(){ + return "/api/jobnet_app/comm_services/"; +} +String deleteContact (){ + return "/api/jobnet_app/profile/pds/basic/contact/"; +} // location utils path String getCounties(){ diff --git a/lib/widgets/error_state.dart b/lib/widgets/error_state.dart index e66a523..b23027f 100644 --- a/lib/widgets/error_state.dart +++ b/lib/widgets/error_state.dart @@ -20,7 +20,7 @@ class SomethingWentWrong extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ SvgPicture.asset( - 'assets/svgs/error.svg', + 'assets/svgs/timeout.svg', height: 200.0, width: 200.0, allowDrawingOutsideViewBox: true, diff --git a/lib/widgets/splash_screen.dart b/lib/widgets/splash_screen.dart index 41a2a8d..69eaaca 100644 --- a/lib/widgets/splash_screen.dart +++ b/lib/widgets/splash_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/src/widgets/container.dart'; import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/global.dart'; @@ -14,7 +15,7 @@ class UniTSplashScreen extends StatelessWidget { Widget build(BuildContext context) { return Container( height: MediaQuery.of(context).size.height, - color: Colors.white, + color: Colors.black12, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -44,6 +45,19 @@ class UniTSplashScreen extends StatelessWidget { height: 1, color: Colors.black)), ), + const SizedBox(height: 5,), + SpinKitThreeBounce(color: Colors.black,size: 32,) + // Row( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // Flexible( + // flex: 2, + // child: Text("Please Wait ",style: Theme.of(context).textTheme.labelLarge!.copyWith(fontSize: 18))), + // const SizedBox(width: 5,), + // const SpinKitDoubleBounce(color: primary,size: 32,) + // ],) + ], ), ), diff --git a/pubspec.lock b/pubspec.lock index f35808f..ee61216 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + url: "https://pub.dev" + source: hosted + version: "47.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + url: "https://pub.dev" + source: hosted + version: "4.7.0" animate_do: dependency: "direct main" description: @@ -25,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.6" + args: + dependency: transitive + description: + name: args + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + url: "https://pub.dev" + source: hosted + version: "2.4.0" async: dependency: transitive description: @@ -89,6 +113,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + url: "https://pub.dev" + source: hosted + version: "2.0.10" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" + source: hosted + version: "2.3.3" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" + source: hosted + version: "7.2.7" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "31b7c748fd4b9adf8d25d72a4c4a59ef119f12876cf414f94f8af5131d5fa2b0" + url: "https://pub.dev" + source: hosted + version: "8.4.4" cached_network_image: dependency: "direct main" description: @@ -121,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" + source: hosted + version: "2.0.2" clock: dependency: transitive description: @@ -129,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" + source: hosted + version: "4.4.0" collection: dependency: transitive description: @@ -169,6 +273,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" + source: hosted + version: "2.2.4" date_time_picker: dependency: "direct main" description: @@ -421,6 +533,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" globbing: dependency: transitive description: @@ -437,6 +565,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + hive: + dependency: "direct main" + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + hive_generator: + dependency: "direct dev" + description: + name: hive_generator + sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" + url: "https://pub.dev" + source: hosted + version: "1.1.3" http: dependency: transitive description: @@ -445,6 +597,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.5" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -469,6 +629,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.17.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" js: dependency: transitive description: @@ -493,6 +661,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" + source: hosted + version: "1.1.1" lottie: dependency: transitive description: @@ -501,6 +677,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.3" + mask_text_input_formatter: + dependency: "direct main" + description: + name: mask_text_input_formatter + sha256: "19bb7809c3c2559277e95521b3ee421e1409eb2cc85efd2feb191696c92490f4" + url: "https://pub.dev" + source: hosted + version: "2.4.0" matcher: dependency: transitive description: @@ -525,6 +709,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" modal_progress_hud_nsn: dependency: "direct main" description: @@ -549,6 +741,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" package_info_plus: dependency: "direct main" description: @@ -593,10 +793,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4 url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.0.14" path_provider_android: dependency: transitive description: @@ -717,6 +917,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.6.2" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" process: dependency: transitive description: @@ -741,6 +949,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: ec85d7d55339d85f44ec2b682a82fea340071e8978257e5a43e69f79e98ef50c + url: "https://pub.dev" + source: hosted + version: "1.2.2" qr: dependency: transitive description: @@ -845,6 +1069,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + shelf: + dependency: transitive + description: + name: shelf + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" + source: hosted + version: "1.4.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" + source: hosted + version: "1.0.3" signature: dependency: "direct main" description: @@ -866,6 +1106,22 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + url: "https://pub.dev" + source: hosted + version: "1.2.6" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + url: "https://pub.dev" + source: hosted + version: "1.3.3" source_span: dependency: transitive description: @@ -906,6 +1162,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -946,6 +1210,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.16" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" toggle_switch: dependency: "direct main" description: @@ -978,6 +1250,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" + source: hosted + version: "2.3.0" win32: dependency: transitive description: @@ -1002,6 +1290,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.2" + yaml: + dependency: transitive + description: + name: yaml + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" + source: hosted + version: "3.1.1" sdks: dart: ">=2.19.0 <3.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index bc3e3a5..5cd2be5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: equatable: ^2.0.5 package_info_plus: ^3.0.2 easy_app_installer: ^1.0.0 - path_provider: ^2.0.11 + path_provider: ^2.0.14 dio: ^4.0.6 cool_alert: ^1.1.0 permission_handler: ^10.2.0 @@ -73,7 +73,9 @@ dependencies: searchfield: ^0.7.5 filter_list: ^1.0.2 simple_chips_input: ^1.0.0 - + hive: ^2.0.5 + hive_flutter: ^1.1.0 + mask_text_input_formatter: ^2.4.0 dev_dependencies: flutter_test: @@ -85,6 +87,8 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^2.0.0 + build_runner: ^2.1.7 + hive_generator: ^1.1.2 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec