diff --git a/lib/bloc/profile/primary_information/address/address_bloc.dart b/lib/bloc/profile/primary_information/address/address_bloc.dart index 75cafa4..c6022e1 100644 --- a/lib/bloc/profile/primary_information/address/address_bloc.dart +++ b/lib/bloc/profile/primary_information/address/address_bloc.dart @@ -2,7 +2,9 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart'; import 'package:unit2/model/location/barangay.dart'; +import 'package:unit2/model/location/subdivision.dart'; import 'package:unit2/model/profile/voluntary_works.dart'; +import 'package:unit2/sevices/profile/address_service.dart'; import '../../../../model/location/city.dart'; import '../../../../model/location/country.dart'; @@ -16,55 +18,188 @@ part 'address_state.dart'; class AddressBloc extends Bloc { AddressBloc() : super(AddressInitial()) { - List globalCountries=[]; - List globalRegions=[]; - List addresses = []; + List globalCountries = []; + List globalRegions = []; + List addresses = []; + List provinces = []; + List cities = []; + List barangays = []; + Region? currentRegion; + Country currentCountry; + Province? currentProvince; + CityMunicipality? currentCity; + Barangay? currentBarangay; on((event, emit) { emit(AddressLoadingState()); - try{ - addresses = event.addresses; + try { + addresses = event.addresses; + emit(AddressLoadedState(addresses: addresses)); + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }); + ////Load + on((event, emit) { emit(AddressLoadedState(addresses: addresses)); - }catch(e){ - emit(AddressErrorState(message: e.toString())); - } - //// show add form - });on((event,emit)async{ + }); + + //// show add form + on((event, emit) async { emit(AddressLoadingState()); - try{ - if (globalRegions.isEmpty) { - List regions = await LocationUtils.instance.getRegions(); - globalRegions = regions; - } - if (globalCountries.isEmpty) { - List countries = await LocationUtils.instance.getCountries(); - globalCountries = countries; - } - emit(AddAddressState(countries: globalCountries, regions: globalRegions)); - }catch(e){ + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + + emit(AddAddressState( + countries: globalCountries, regions: globalRegions)); + } catch (e) { emit(AddressErrorState(message: e.toString())); } }); //// Show Edit Form - on((event,emit)async{ + on((event, emit) async { + try { + if (globalRegions.isEmpty) { + List regions = await LocationUtils.instance.getRegions(); + globalRegions = regions; + } + if (globalCountries.isEmpty) { + List countries = await LocationUtils.instance.getCountries(); + globalCountries = countries; + } + currentCountry = globalCountries.firstWhere((Country country) => + event.address.address!.country!.code == country.code); - try{ - if (globalRegions.isEmpty) { - List regions = await LocationUtils.instance.getRegions(); - globalRegions = regions; - } - if (globalCountries.isEmpty) { - List countries = await LocationUtils.instance.getCountries(); - globalCountries = countries; - } - emit(EditAddressState(countries: globalCountries, regions: globalRegions,address: event.address)); - }catch(e){ + if (!event.overseas) { + //// if not overseas + currentRegion = globalRegions.firstWhere((Region region) => + event.address.address!.cityMunicipality!.province!.region!.code == + region.code); + provinces = await LocationUtils.instance + .getProvinces(regionCode: currentRegion!.code.toString()); + currentProvince = provinces.firstWhere((Province province) => + event.address.address!.cityMunicipality!.province!.code == + province.code); + + cities = await LocationUtils.instance + .getCities(code: currentProvince!.code.toString()); + + currentCity = cities.firstWhere((CityMunicipality cityMunicipality) => + event.address.address!.cityMunicipality!.code == + cityMunicipality.code); + barangays = await LocationUtils.instance + .getBarangay(code: currentCity!.code.toString()); + if (event.address.address?.barangay != null) { + currentBarangay = barangays.firstWhere((Barangay barangay) => + event.address.address?.barangay?.code == barangay.code); + } else { + currentBarangay = null; + } + } + + emit(EditAddressState( + countries: globalCountries, + regions: globalRegions, + address: event.address, + baragays: barangays, + cities: cities, + currentCity: currentCity, + currentCountry: currentCountry, + currentProvince: currentProvince, + currentRegion: currentRegion, + overseas: event.overseas, + provinces: provinces, + currentBarangay: currentBarangay)); + } catch (e) { emit(AddressErrorState(message: e.toString())); } }); + ////Add + on( + (event, emit) async { + try { + Map status = await AddressService.instance.add( + address: event.address, + categoryId: event.categoryId, + token: event.token, + details: event.details, + blockNumber: event.blockNumber, + lotNumber: event.lotNumber, + profileId: event.profileId); + if (status['success']) { + AddressClass addressClass = AddressClass.fromJson(status['address']); + Subdivision? subdivision = status['subdivision'] !=null? Subdivision.fromJson(status['subdivision']):null; + + MainAdress address = MainAdress(address: addressClass,subdivision: subdivision,id: status['id'],details: status['details']); + addresses.add(address); + emit(AddressAddedState(response: status)); + } else { + emit(AddressAddedState(response: status)); + } + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }, + ); + ////update + on( + (event, emit) async { + // try { + Map status = await AddressService.instance.update( + address: event.address, + categoryId: event.categoryId, + token: event.token, + details: event.details, + blockNumber: event.blockNumber, + lotNumber: event.lotNumber, + profileId: event.profileId); + if (status['success']) { + AddressClass addressClass = AddressClass.fromJson(status['address']); + Subdivision? subdivision = status['subdivision'] !=null? Subdivision.fromJson(status['subdivision']):null; + MainAdress address = MainAdress(address: addressClass,subdivision: subdivision,id: status['id'],details: status['details']); + addresses.removeWhere((address)=>address.id == event.address.id); + addresses.add(address); + + emit(AddressUpdatedState(response: status)); + } else { + emit(AddressUpdatedState(response: status)); + } + // } catch (e) { + // emit(AddressErrorState(message: e.toString())); + // } + }, + ); + ////Update +////Delete + on((event, emit) async { + try { + final bool success = await AddressService.instance.delete( + addressId: event.id, + profileId: int.parse(event.profileId), + token: event.token); + if (success) { + addresses + .removeWhere(((MainAdress element) => element.id == event.id)); + emit(AddressDeletedState( + success: success, + )); + } else { + emit(AddressDeletedState(success: success)); + } + } catch (e) { + emit(AddressErrorState(message: e.toString())); + } + }); ////call error state - on((event, emit) { + on((event, emit) { emit(const AddressErrorState( message: "Something went wrong. Please try again")); }); diff --git a/lib/bloc/profile/primary_information/address/address_event.dart b/lib/bloc/profile/primary_information/address/address_event.dart index 9446ba2..193fc74 100644 --- a/lib/bloc/profile/primary_information/address/address_event.dart +++ b/lib/bloc/profile/primary_information/address/address_event.dart @@ -7,28 +7,78 @@ abstract class AddressEvent extends Equatable { List get props => []; } -class GetAddress extends AddressEvent{ - final List addresses; - const GetAddress({required this.addresses}); - @override +class GetAddress extends AddressEvent { + final List addresses; + const GetAddress({required this.addresses}); + @override List get props => [addresses]; } -class ShowAddAddressForm extends AddressEvent{ - -} -class ShowEditAddressForm extends AddressEvent{ + +class ShowAddAddressForm extends AddressEvent {} + +class ShowEditAddressForm extends AddressEvent { + final bool overseas; final MainAdress address; - const ShowEditAddressForm({required this.address}); -} -class CallErrorState extends AddressEvent{ - + const ShowEditAddressForm({required this.address, required this.overseas}); } -class AddAddress extends EligibilityEvent{ - final MainAdress address; +class CallErrorState extends AddressEvent {} + +class AddAddress extends AddressEvent { + final AddressClass address; + final int categoryId; + final String? details; + final int? blockNumber; + final int? lotNumber; final String token; final int profileId; - const AddAddress({required this.address, required this.profileId, required this.token}); - @override - List get props => [address,token,profileId]; + const AddAddress( + {required this.address, + required this.profileId, + required this.token, + required this.blockNumber, + required this.categoryId, + required this.details, + required this.lotNumber}); + @override + List get props => [address, token, profileId,categoryId]; } + +class UpdateAddress extends AddressEvent { + final AddressClass address; + final int categoryId; + final String? details; + final int? blockNumber; + final int? lotNumber; + final String token; + final int profileId; + const UpdateAddress( + {required this.address, + required this.profileId, + required this.token, + required this.blockNumber, + required this.categoryId, + required this.details, + required this.lotNumber}); + @override + List get props => [address, token, profileId,categoryId]; +} + + +class LoadAddress extends AddressEvent{ + +} + +class DeleteAddress extends AddressEvent { + final String profileId; + final int id; + final String token; + const DeleteAddress( + { + required this.id, + required this.profileId, + required this.token}); + @override + List get props => [ profileId, id, token]; +} + diff --git a/lib/bloc/profile/primary_information/address/address_state.dart b/lib/bloc/profile/primary_information/address/address_state.dart index 6c9e70d..efef785 100644 --- a/lib/bloc/profile/primary_information/address/address_state.dart +++ b/lib/bloc/profile/primary_information/address/address_state.dart @@ -8,6 +8,7 @@ abstract class AddressState extends Equatable { } class AddressInitial extends AddressState {} + //// LOADED STATE class AddressLoadedState extends AddressState { final List addresses; @@ -15,6 +16,7 @@ class AddressLoadedState extends AddressState { @override List get props => [addresses]; } + ////ERROR STATE class AddressErrorState extends AddressState { final String message; @@ -22,6 +24,7 @@ class AddressErrorState extends AddressState { @override List get props => [message]; } + //// LOADING STATE class AddressLoadingState extends AddressState {} @@ -29,28 +32,66 @@ class AddressLoadingState extends AddressState {} class AddAddressState extends AddressState { final List countries; final List regions; - const AddAddressState( - { - required this.countries, - required this.regions}); + const AddAddressState({required this.countries, required this.regions}); @override - List get props => [countries, regions,]; + List get props => [ + countries, + regions, + ]; +} + +//// DeletedState +class AddressDeletedState extends AddressState { + final bool success; + const AddressDeletedState({required this.success}); + @override + List get props => [success]; } ////AddedState -class AddressAddedState extends AddressState{ - final Map response; - const AddressAddedState({required this.response}); - @override +class AddressAddedState extends AddressState { + final Map response; + const AddressAddedState({required this.response}); + @override List get props => [response]; - } -class EditAddressState extends AddressState{ +////Edited State +class AddressUpdatedState extends AddressState { + final Map response; + const AddressUpdatedState({required this.response}); + @override + List get props => [response]; +} + +class EditAddressState extends AddressState { final MainAdress address; - final List countries; + final List countries; final List regions; - const EditAddressState({required this.address, required this.countries, required this.regions}); - @override - List get props => [countries, regions,address]; -} \ No newline at end of file + final List provinces; + final List cities; + final List baragays; + final Region? currentRegion; + final Country currentCountry; + final Province? currentProvince; + final CityMunicipality? currentCity; + final Barangay? currentBarangay; + final bool overseas; + + const EditAddressState( + {required this.address, + required this.countries, + required this.regions, + required this.baragays, + required this.cities, + required this.currentCity, + required this.currentCountry, + required this.currentProvince, + required this.currentRegion, + required this.overseas, + required this.provinces, + required this.currentBarangay + }); + @override + List get props => [countries, regions, address]; +} diff --git a/lib/screens/profile/components/basic_information/address/add_modal.dart b/lib/screens/profile/components/basic_information/address/add_modal.dart index af4e8af..21acda2 100644 --- a/lib/screens/profile/components/basic_information/address/add_modal.dart +++ b/lib/screens/profile/components/basic_information/address/add_modal.dart @@ -3,10 +3,13 @@ import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter/src/widgets/placeholder.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:form_builder_validators/form_builder_validators.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/profile/basic_information/adress.dart'; +import 'package:unit2/model/profile/voluntary_works.dart'; import 'package:unit2/model/utils/category.dart'; import 'package:unit2/utils/global.dart'; @@ -20,6 +23,7 @@ import '../../../../../theme-data.dart/colors.dart'; import '../../../../../theme-data.dart/form-style.dart'; import '../../../../../utils/location_utilities.dart'; import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; class AddAddressScreen extends StatefulWidget { final int profileId; @@ -57,7 +61,11 @@ class _AddAddressScreenState extends State { const Area(value: "Metropolis", group: 1), const Area(value: "Megacity", group: 1), ]; - final List category = [AddressCategory(id: 1, name: "Permanent", type: "home"), AddressCategory(id: 2, name: "Residential", type: "home"), AddressCategory(id: 3, name: "Birthplace", type: "home")]; + final List category = [ + AddressCategory(id: 1, name: "Permanent", type: "home"), + AddressCategory(id: 2, name: "Residential", type: "home"), + AddressCategory(id: 3, name: "Birthplace", type: "home") + ]; List? provinces; List? citymuns; List? barangays; @@ -84,9 +92,12 @@ class _AddAddressScreenState extends State { decoration: normalTextFieldStyle("Category*", "Category"), name: "category", - onChanged: (AddressCategory? category) {}, - items: category.map>( - (AddressCategory category) { + onChanged: (AddressCategory? category) { + selectedAddressCategory = category; + }, + items: category + .map>( + (AddressCategory category) { return DropdownMenuItem( value: category, child: Text(category.name!)); }).toList()), @@ -151,6 +162,8 @@ class _AddAddressScreenState extends State { Flexible( flex: 1, child: FormBuilderTextField( + validator: FormBuilderValidators.compose([numericRequired]), + keyboardType: TextInputType.number, name: "block_number", decoration: normalTextFieldStyle( @@ -163,7 +176,9 @@ class _AddAddressScreenState extends State { Flexible( flex: 1, child: FormBuilderTextField( + validator: FormBuilderValidators.compose([numericRequired]), name: "lot_number", + keyboardType: TextInputType.number, decoration: normalTextFieldStyle( "Lot #*", "Lot #"), @@ -180,6 +195,7 @@ class _AddAddressScreenState extends State { ), //// Address Line FormBuilderTextField( + name: "address_line", decoration: normalTextFieldStyle( "Address Line *", "Address Line"), @@ -391,31 +407,64 @@ class _AddAddressScreenState extends State { name: 'country', decoration: normalTextFieldStyle( "Country*", "Country"), - onChanged: (Country? value) {}, + onChanged: (Country? value) { + selectedCountry = value; + }, ), ), ), - ], ); }), - ////sumit button - const Expanded(child: SizedBox()), - SizedBox( - width: double.infinity, - height: 60, - child: ElevatedButton( - style: mainBtnStyle( - primary, Colors.transparent, second), - onPressed: () {}, - child: const Text(submit)), - ), - const SizedBox( - height: 20, - ), + ////sumit button + const Expanded(child: SizedBox()), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + String? lotNumber; + String? blockNumber; + String? addressLine; + Country country = selectedCountry ??= Country( + id: 175, name: 'Philippines', code: 'PH'); + AddressClass address = AddressClass( + barangay: selectedBarangay, + id: null, + category: null, + areaClass: selectedAreaClass, + cityMunicipality: selectedMunicipality, + country: country); + if (hasLotandBlock) { + lotNumber = formKey + .currentState!.value['lot_number']; + blockNumber = formKey + .currentState!.value['block_number']; + } + addressLine = formKey + .currentState?.value['address_line']; + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(AddAddress( + address: address, + profileId: widget.profileId, + token: widget.token, + blockNumber: blockNumber != null?int.parse(blockNumber):null, + categoryId: selectedAddressCategory!.id!, + details: addressLine, + lotNumber: lotNumber != null?int.parse(lotNumber):null)); + } + }, + child: const Text(submit)), + ), + const SizedBox( + height: 20, + ), ], ), - )), ), ); diff --git a/lib/screens/profile/components/basic_information/address/edit_modal.dart b/lib/screens/profile/components/basic_information/address/edit_modal.dart index 5760b17..9eb828f 100644 --- a/lib/screens/profile/components/basic_information/address/edit_modal.dart +++ b/lib/screens/profile/components/basic_information/address/edit_modal.dart @@ -3,10 +3,15 @@ import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter/src/widgets/placeholder.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:form_builder_validators/form_builder_validators.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; +import 'package:unit2/model/location/address_category.dart'; +import 'package:unit2/model/profile/basic_information/adress.dart'; +import 'package:unit2/model/profile/voluntary_works.dart'; import 'package:unit2/model/utils/category.dart'; +import 'package:unit2/screens/profile/components/other_information/org_membership/add_modal.dart'; import 'package:unit2/utils/global.dart'; import '../../../../../model/location/barangay.dart'; @@ -19,6 +24,7 @@ import '../../../../../theme-data.dart/colors.dart'; import '../../../../../theme-data.dart/form-style.dart'; import '../../../../../utils/location_utilities.dart'; import '../../../../../utils/text_container.dart'; +import '../../../../../utils/validators.dart'; class EditAddressScreen extends StatefulWidget { final int profileId; @@ -38,6 +44,8 @@ class _EditAddressScreenState extends State { bool cityCall = false; bool barangayCall = false; ////selected + AddressCategory? selectedAddressCategory; + Area? selectedAreaClass; Region? selectedRegion; Province? selectedProvince; CityMunicipality? selectedMunicipality; @@ -54,7 +62,11 @@ class _EditAddressScreenState extends State { const Area(value: "Metropolis", group: 1), const Area(value: "Megacity", group: 1), ]; - final List category = ["Permanent", "Residential", "Birthplace"]; + final List category = [ + AddressCategory(id: 1, name: "Permanent", type: "home"), + AddressCategory(id: 2, name: "Residential", type: "home"), + AddressCategory(id: 3, name: "Birthplace", type: "home") + ]; List? provinces; List? citymuns; List? barangays; @@ -64,6 +76,33 @@ class _EditAddressScreenState extends State { return BlocBuilder( builder: (context, state) { if (state is EditAddressState) { + overseas = state.overseas; + if (!overseas) { + selectedRegion = state.currentRegion; + provinces = state.provinces; + selectedProvince = state.currentProvince; + citymuns = state.cities; + selectedMunicipality = state.currentCity; + barangays = state.baragays; + selectedBarangay = state.currentBarangay; + } else { + selectedCountry = state.currentCountry; + } + selectedAddressCategory = category.firstWhere( + (AddressCategory category) => + category.id == state.address.address!.category!.id); + if (state.address.address?.areaClass != null) { + selectedAreaClass = areaClass.firstWhere((Area area) => + area.value.toLowerCase() == + state.address.address!.areaClass!.toLowerCase()); + } else { + selectedAreaClass = null; + } + if (state.address.subdivision != null) { + hasLotandBlock = true; + } else { + hasLotandBlock = false; + } return SingleChildScrollView( child: SizedBox( height: screenHeight * .90, @@ -72,32 +111,39 @@ class _EditAddressScreenState extends State { child: Padding( padding: const EdgeInsets.symmetric( vertical: 25, horizontal: 18), - child: Column( + child: ListView( children: [ //// category - FormBuilderDropdown( + FormBuilderDropdown( + initialValue: selectedAddressCategory, validator: FormBuilderValidators.required( errorText: "This field is required"), decoration: normalTextFieldStyle("Category*", "Category"), name: "category", - onChanged: (String? category) {}, - items: category.map>( - (String category) { + onChanged: (AddressCategory? category) { + selectedAddressCategory = category; + }, + items: category + .map>( + (AddressCategory category) { return DropdownMenuItem( - value: category, child: Text(category)); + value: category, child: Text(category.name!)); }).toList()), const SizedBox( height: 12, ), ////Area Class FormBuilderDropdown( + initialValue: selectedAreaClass, validator: FormBuilderValidators.required( errorText: "This field is required"), decoration: normalTextFieldStyle( "Area class *", "Area class"), name: "area_class", - onChanged: (Area? area) {}, + onChanged: (Area? area) { + selectedAreaClass = area; + }, items: areaClass .map>((Area area) { return area.group == 0 @@ -146,6 +192,11 @@ class _EditAddressScreenState extends State { Flexible( flex: 1, child: FormBuilderTextField( + initialValue: state.address.subdivision?.blockNo?.toString(), + validator: FormBuilderValidators + .compose([numericRequired]), + keyboardType: + TextInputType.number, name: "block_number", decoration: normalTextFieldStyle( @@ -158,7 +209,12 @@ class _EditAddressScreenState extends State { Flexible( flex: 1, child: FormBuilderTextField( + initialValue: state.address.subdivision?.lotNo?.toString(), + validator: FormBuilderValidators + .compose([numericRequired]), name: "lot_number", + keyboardType: + TextInputType.number, decoration: normalTextFieldStyle( "Lot #*", "Lot #"), @@ -175,6 +231,7 @@ class _EditAddressScreenState extends State { ), //// Address Line FormBuilderTextField( + initialValue: state.address.details, name: "address_line", decoration: normalTextFieldStyle( "Address Line *", "Address Line"), @@ -209,7 +266,9 @@ class _EditAddressScreenState extends State { height: 12, ), ////REGION DROPDOWN - FormBuilderDropdown( + DropdownButtonFormField( + isExpanded: true, + value: selectedRegion, autovalidateMode: AutovalidateMode .onUserInteraction, validator: @@ -222,13 +281,71 @@ class _EditAddressScreenState extends State { provinceCall = true; }); selectedRegion = region; - getProvinces(); + //// GET PROVINCES + provinces = await LocationUtils + .instance + .getProvinces( + regionCode: + selectedRegion!.code + .toString()); + selectedProvince = + provinces![0]; + setState(() { + provinceCall = false; + cityCall = true; + }); + //// GET CITIES + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAY + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); + ////GET CITY MUNICIPALITY + citymuns = await LocationUtils + .instance + .getCities( + code: selectedProvince! + .code!); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAYS + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); } }, - initialValue: null, decoration: normalTextFieldStyle( "Region*", "Region"), - name: 'region', items: state.regions .map>( (Region region) { @@ -258,16 +375,41 @@ class _EditAddressScreenState extends State { : null, isExpanded: true, value: selectedProvince, - onChanged: - (Province? province) { + onChanged: (Province? + province) async { if (selectedProvince != province) { + selectedProvince = + province; setState(() { cityCall = true; }); - selectedProvince = - province; - getCities(); + + //// GET CITIES + citymuns = await LocationUtils + .instance + .getCities( + code: + selectedProvince! + .code!); + selectedMunicipality = + citymuns![0]; + setState(() { + cityCall = false; + barangayCall = true; + }); + //// GET BARANGAY + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); } }, items: provinces == null @@ -302,15 +444,27 @@ class _EditAddressScreenState extends State { errorText: "This field is required"), isExpanded: true, - onChanged: - (CityMunicipality? city) { + onChanged: (CityMunicipality? + city) async { if (selectedMunicipality != city) { setState(() { barangayCall = true; }); selectedMunicipality = city; - getBarangays(); + selectedMunicipality = city; + //// GET BARANGAYS + barangays = await LocationUtils + .instance + .getBarangay( + code: + selectedMunicipality! + .code!); + selectedBarangay = + barangays![0]; + setState(() { + barangayCall = false; + }); } }, decoration: @@ -369,7 +523,7 @@ class _EditAddressScreenState extends State { : SizedBox( height: 60, child: FormBuilderDropdown( - initialValue: null, + initialValue: selectedCountry, validator: FormBuilderValidators.required( errorText: @@ -386,31 +540,73 @@ class _EditAddressScreenState extends State { name: 'country', decoration: normalTextFieldStyle( "Country*", "Country"), - onChanged: (Country? value) {}, + onChanged: (Country? value) { + selectedCountry = value; + }, ), ), ), - ], ); }), - ////sumit button - const Expanded(child: SizedBox()), - SizedBox( - width: double.infinity, - height: 60, - child: ElevatedButton( - style: mainBtnStyle( - primary, Colors.transparent, second), - onPressed: () {}, - child: const Text(submit)), - ), - const SizedBox( - height: 20, - ), + ////sumit button + const Expanded(child: SizedBox()), + SizedBox( + width: double.infinity, + height: 60, + child: ElevatedButton( + style: mainBtnStyle( + primary, Colors.transparent, second), + onPressed: () { + if (formKey.currentState!.saveAndValidate()) { + String? lotNumber; + String? blockNumber; + String? addressLine; + if(overseas){ + selectedCountry = selectedCountry; + }else{ + selectedCountry = Country( + id: 175, name: 'Philippines', code: 'PH'); + } + + AddressClass address = AddressClass( + barangay: overseas?null:selectedBarangay, + id: state.address.id, + category: null, + areaClass: selectedAreaClass!.value, + cityMunicipality: overseas?null:selectedMunicipality, + country: selectedCountry); + if (hasLotandBlock) { + lotNumber = formKey + .currentState!.value['lot_number']; + blockNumber = formKey + .currentState!.value['block_number']; + } + addressLine = formKey + .currentState?.value['address_line']; + final progress = ProgressHUD.of(context); + progress!.showWithText("Loading..."); + context.read().add(UpdateAddress( + address: address, + profileId: widget.profileId, + token: widget.token, + blockNumber: blockNumber != null + ? int.parse(blockNumber) + : null, + categoryId: selectedAddressCategory!.id!, + details: addressLine, + lotNumber: lotNumber != null + ? int.parse(lotNumber) + : null)); + } + }, + child: const Text(submit)), + ), + const SizedBox( + height: 20, + ), ], ), - )), ), ); diff --git a/lib/screens/profile/components/basic_information/address_screen.dart b/lib/screens/profile/components/basic_information/address_screen.dart index 9801069..f025239 100644 --- a/lib/screens/profile/components/basic_information/address_screen.dart +++ b/lib/screens/profile/components/basic_information/address_screen.dart @@ -39,11 +39,11 @@ class AddressScreen extends StatelessWidget { ], ), body: ProgressHUD( - padding: const EdgeInsets.all(24), - indicatorWidget: const SpinKitFadingCircle( - color: Colors.white, - ), - backgroundColor: Colors.black87, + padding: const EdgeInsets.all(24), + indicatorWidget: const SpinKitFadingCircle( + color: Colors.white, + ), + backgroundColor: Colors.black87, child: BlocBuilder( builder: (context, state) { if (state is UserLoggedIn) { @@ -61,13 +61,67 @@ class AddressScreen extends StatelessWidget { if (state is AddressLoadedState || state is AddressErrorState || state is AddAddressState || - state is EditAddressState) { + state is EditAddressState || + state is AddressAddedState || state is EditAddressState || state is AddressUpdatedState) { final progress = ProgressHUD.of(context); progress!.dismiss(); } + ////Added State + if (state is AddressAddedState) { + if (state.response['success']) { + successAlert(context, "Adding Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } else { + errorAlert(context, "Adding Failed", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } + } + ////updated State + if (state is AddressUpdatedState) { + if (state.response['success']) { + successAlert(context, "Update Successfull!", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } else { + errorAlert(context, "Update Failed", + state.response['message'], () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } + } + //// Deleted + if (state is AddressDeletedState) { + if (state.success) { + successAlert(context, "Deletion Successfull", + "Address has been deleted successfully", () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } else { + errorAlert(context, "Deletion Failed", + "Error deleting Address", () { + Navigator.of(context).pop(); + context.read().add(LoadAddress()); + }); + } + } }, builder: (context, state) { if (state is AddressLoadedState) { + bool overseas; + String? cityMunicipality; + String? province; + String? region; + String? barangay; if (state.addresses.isNotEmpty) { return ListView.builder( padding: const EdgeInsets.symmetric( @@ -79,29 +133,37 @@ class AddressScreen extends StatelessWidget { state.addresses[index].details ?? ''; String category = state.addresses[index] .address!.category!.name!; - String? barangay = state.addresses[index] - .address!.barangay != - null - ? '${state.addresses[index].address!.barangay!.description!.toUpperCase()},' - : ''; - String cityMunicipality = state - .addresses[index] - .address! - .cityMunicipality! - .description!; - String province = state - .addresses[index] - .address! - .cityMunicipality! - .province! - .description!; - String region = state - .addresses[index] - .address! - .cityMunicipality! - .province! - .region! - .description!; + if (state.addresses[index].address!.country! + .id == + 175) { + barangay = state.addresses[index].address! + .barangay != + null + ? '${state.addresses[index].address!.barangay!.description!.toUpperCase()},' + : ''; + cityMunicipality = state + .addresses[index] + .address! + .cityMunicipality! + .description!; + province = state + .addresses[index] + .address! + .cityMunicipality! + .province! + .description!; + region = state + .addresses[index] + .address! + .cityMunicipality! + .province! + .region! + .description!; + overseas = false; + } else { + overseas = true; + } + return Column( children: [ Column( @@ -115,6 +177,10 @@ class AddressScreen extends StatelessWidget { child: Row(children: [ Expanded( child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Row( children: [ @@ -141,12 +207,25 @@ class AddressScreen extends StatelessWidget { const SizedBox( height: 5, ), - Text( - "$barangay $cityMunicipality, $province, $region", - style: Theme.of(context) - .textTheme - .labelLarge, - ), + Container( + child: overseas + ? Text( + "COUNTRY: ${state.addresses[index].address!.country!.name!.toUpperCase()}", + textAlign: + TextAlign + .start, + style: Theme.of( + context) + .textTheme + .labelLarge, + ) + : Text( + "$barangay $cityMunicipality, $province, $region", + style: Theme.of( + context) + .textTheme + .labelLarge, + )), ], )), AppPopupMenu( @@ -164,8 +243,19 @@ class AddressScreen extends StatelessWidget { "Loading..."); }, "Delete?", "Confirm Delete?"); + context + .read() + .add(DeleteAddress( + id: state + .addresses[ + index] + .id!, + profileId: profileId + .toString(), + token: token!)); } if (value == 1) { + bool overseas; ////edit eligibilty-= = = = = = = = =>> final progress = ProgressHUD.of( @@ -173,9 +263,20 @@ class AddressScreen extends StatelessWidget { progress!.showWithText( "Loading..."); + if (state + .addresses[index] + .address + ?.cityMunicipality == + null) { + overseas = true; + } else { + overseas = false; + } context .read() .add(ShowEditAddressForm( + overseas: + overseas, address: state .addresses[ index])); @@ -225,8 +326,10 @@ class AddressScreen extends StatelessWidget { if (state is AddAddressState) { return AddAddressScreen( profileId: profileId!, token: token!); - }if(state is EditAddressState){ - return EditAddressScreen(profileId: profileId!, token: token!); + } + if (state is EditAddressState) { + return EditAddressScreen( + profileId: profileId!, token: token!); } return Container(); }, diff --git a/lib/sevices/profile/address_service.dart b/lib/sevices/profile/address_service.dart new file mode 100644 index 0000000..5458c98 --- /dev/null +++ b/lib/sevices/profile/address_service.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:unit2/theme-data.dart/colors.dart'; + +import '../../model/profile/basic_information/adress.dart'; +import '../../utils/request.dart'; +import '../../utils/urls.dart'; +import 'package:http/http.dart' as http; + +class AddressService { + static final AddressService _instance = AddressService(); + static AddressService get instance => _instance; +////add + Future> add( + {required AddressClass address, + required int categoryId, + required String? details, + required int? blockNumber, + required int? lotNumber, + required String token, + required int profileId}) async { + Map? _response = {}; + String authtoken = "Token $token"; + String path = '${Url.instance.addressPath()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { + "id": address.id, + "details": details, + "_addressCatId": categoryId, + "_areaClass": address.areaClass, + "_blockNo": blockNumber, + "_lotNo": lotNumber, + "_citymunCode": address.cityMunicipality?.code, + "_brgyCode": address.barangay?.code, + "_countryId": address.country!.id + }; + try { + http.Response response = await Request.instance + .postRequest(path: path, body: body, headers: headers, param: {}); + if (response.statusCode == 201) { + Map data = jsonDecode(response.body); + _response = data['response']['data']; + _response!.addAll({'success': true}); + } else { + _response.addAll({'success': false}); + } + + return _response; + } catch (e) { + throw e.toString(); + } + } + + ////delete + Future delete( + {required int addressId, + required int profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.addressPath()}$profileId/"; + Map body = {"id": addressId}; + Map params = {"force_mode": "true"}; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + try { + http.Response response = await Request.instance.deleteRequest( + path: path, headers: headers, body: body, param: params); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + success = data['success']; + } else { + success = false; + } + } catch (e) { + throw (e.toString()); + } + return success!; + } + + ////update + Future> update( + {required AddressClass address, + required int categoryId, + required String? details, + required int? blockNumber, + required int? lotNumber, + required String token, + required int profileId}) async { + Map? _response = {}; + String authtoken = "Token $token"; + String path = '${Url.instance.addressPath()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = { + "id": address.id, + "details": details, + "_addressCatId": categoryId, + "_areaClass": address.areaClass, + "_blockNo": blockNumber, + "_lotNo": lotNumber, + "_citymunCode": address.cityMunicipality?.code, + "_brgyCode": address.barangay?.code, + "_countryId": address.country!.id + }; + try { + http.Response response = await http.patch( + Uri.parse( + 'http://${Url.instance.host()}${Url.instance.addressPath()}$profileId/'), + headers: headers, + body: jsonEncode({ + "id": address.id, + "details": details, + "_addressCatId": categoryId, + "_areaClass": address.areaClass, + "_blockNo": blockNumber, + "_lotNo": lotNumber, + "_citymunCode": address.cityMunicipality?.code, + "_brgyCode": address.barangay?.code, + "_countryId": address.country!.id + })); + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + _response = data['response']['data']; + _response!.addAll({'success': true}); + } else { + _response.addAll({'success': false}); + } + + return _response; + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/utils/request.dart b/lib/utils/request.dart index c224af0..329b3c4 100644 --- a/lib/utils/request.dart +++ b/lib/utils/request.dart @@ -137,6 +137,47 @@ class Request { } return response; } + Future patch( + {required String path, + required Map? headers, + required Map? body, + required Map? param}) async { + Response response; + try { + response =await patch(path: host+path, headers: headers,body: body,param: param); + } on TimeoutException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on SocketException catch (_) { + Fluttertoast.showToast( + msg: timeoutError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (timeoutError); + } on FormatException catch (_) { + throw const FormatException(formatError); + } on HttpException catch (_) { + throw const HttpException(httpError); + } on Error catch (e) { + debugPrint("post request error: $e"); + Fluttertoast.showToast( + msg: onError, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + backgroundColor: Colors.black, + ); + throw (e.toString()); + } + return response; + } + Future deleteRequest( {required String path, diff --git a/lib/utils/urls.dart b/lib/utils/urls.dart index 7f3839d..3d755e1 100644 --- a/lib/utils/urls.dart +++ b/lib/utils/urls.dart @@ -125,6 +125,11 @@ String getServiceTypes(){ return "/api/jobnet_app/comm_service_type/"; } +//// address path +String addressPath(){ + return "/api/jobnet_app/profile/pds/basic/address/"; +} + String contactPath(){ return "/api/jobnet_app/profile/pds/basic/contact/"; }