Implemented Address API

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-05-02 16:42:15 +08:00
parent 1c6b291889
commit bfe1ee538b
9 changed files with 925 additions and 163 deletions

View File

@ -2,7 +2,9 @@ import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart'; import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart';
import 'package:unit2/model/location/barangay.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/model/profile/voluntary_works.dart';
import 'package:unit2/sevices/profile/address_service.dart';
import '../../../../model/location/city.dart'; import '../../../../model/location/city.dart';
import '../../../../model/location/country.dart'; import '../../../../model/location/country.dart';
@ -16,55 +18,188 @@ part 'address_state.dart';
class AddressBloc extends Bloc<AddressEvent, AddressState> { class AddressBloc extends Bloc<AddressEvent, AddressState> {
AddressBloc() : super(AddressInitial()) { AddressBloc() : super(AddressInitial()) {
List<Country> globalCountries=[]; List<Country> globalCountries = [];
List<Region> globalRegions=[]; List<Region> globalRegions = [];
List<MainAdress> addresses = []; List<MainAdress> addresses = [];
List<Province> provinces = [];
List<CityMunicipality> cities = [];
List<Barangay> barangays = [];
Region? currentRegion;
Country currentCountry;
Province? currentProvince;
CityMunicipality? currentCity;
Barangay? currentBarangay;
on<GetAddress>((event, emit) { on<GetAddress>((event, emit) {
emit(AddressLoadingState()); emit(AddressLoadingState());
try{ try {
addresses = event.addresses; addresses = event.addresses;
emit(AddressLoadedState(addresses: addresses));
} catch (e) {
emit(AddressErrorState(message: e.toString()));
}
});
////Load
on<LoadAddress>((event, emit) {
emit(AddressLoadedState(addresses: addresses)); emit(AddressLoadedState(addresses: addresses));
}catch(e){ });
emit(AddressErrorState(message: e.toString()));
} //// show add form
//// show add form on<ShowAddAddressForm>((event, emit) async {
});on<ShowAddAddressForm>((event,emit)async{
emit(AddressLoadingState()); emit(AddressLoadingState());
try{ try {
if (globalRegions.isEmpty) { if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions(); List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions; globalRegions = regions;
} }
if (globalCountries.isEmpty) { if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries(); List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries; globalCountries = countries;
} }
emit(AddAddressState(countries: globalCountries, regions: globalRegions));
}catch(e){ emit(AddAddressState(
countries: globalCountries, regions: globalRegions));
} catch (e) {
emit(AddressErrorState(message: e.toString())); emit(AddressErrorState(message: e.toString()));
} }
}); });
//// Show Edit Form //// Show Edit Form
on<ShowEditAddressForm>((event,emit)async{ on<ShowEditAddressForm>((event, emit) async {
try {
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
currentCountry = globalCountries.firstWhere((Country country) =>
event.address.address!.country!.code == country.code);
try{ if (!event.overseas) {
if (globalRegions.isEmpty) { //// if not overseas
List<Region> regions = await LocationUtils.instance.getRegions(); currentRegion = globalRegions.firstWhere((Region region) =>
globalRegions = regions; event.address.address!.cityMunicipality!.province!.region!.code ==
} region.code);
if (globalCountries.isEmpty) { provinces = await LocationUtils.instance
List<Country> countries = await LocationUtils.instance.getCountries(); .getProvinces(regionCode: currentRegion!.code.toString());
globalCountries = countries; currentProvince = provinces.firstWhere((Province province) =>
} event.address.address!.cityMunicipality!.province!.code ==
emit(EditAddressState(countries: globalCountries, regions: globalRegions,address: event.address)); province.code);
}catch(e){
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())); emit(AddressErrorState(message: e.toString()));
} }
}); });
////Add
on<AddAddress>(
(event, emit) async {
try {
Map<String, dynamic> 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<UpdateAddress>(
(event, emit) async {
// try {
Map<String, dynamic> 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<DeleteAddress>((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 ////call error state
on<CallErrorState>((event, emit) { on<CallErrorState>((event, emit) {
emit(const AddressErrorState( emit(const AddressErrorState(
message: "Something went wrong. Please try again")); message: "Something went wrong. Please try again"));
}); });

View File

@ -7,28 +7,78 @@ abstract class AddressEvent extends Equatable {
List<Object> get props => []; List<Object> get props => [];
} }
class GetAddress extends AddressEvent{ class GetAddress extends AddressEvent {
final List<MainAdress> addresses; final List<MainAdress> addresses;
const GetAddress({required this.addresses}); const GetAddress({required this.addresses});
@override @override
List<Object> get props => [addresses]; List<Object> get props => [addresses];
} }
class ShowAddAddressForm extends AddressEvent{
} class ShowAddAddressForm extends AddressEvent {}
class ShowEditAddressForm extends AddressEvent{
class ShowEditAddressForm extends AddressEvent {
final bool overseas;
final MainAdress address; final MainAdress address;
const ShowEditAddressForm({required this.address}); const ShowEditAddressForm({required this.address, required this.overseas});
}
class CallErrorState extends AddressEvent{
} }
class AddAddress extends EligibilityEvent{ class CallErrorState extends AddressEvent {}
final MainAdress address;
class AddAddress extends AddressEvent {
final AddressClass address;
final int categoryId;
final String? details;
final int? blockNumber;
final int? lotNumber;
final String token; final String token;
final int profileId; final int profileId;
const AddAddress({required this.address, required this.profileId, required this.token}); const AddAddress(
@override {required this.address,
List<Object> get props => [address,token,profileId]; required this.profileId,
required this.token,
required this.blockNumber,
required this.categoryId,
required this.details,
required this.lotNumber});
@override
List<Object> 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<Object> 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<Object> get props => [ profileId, id, token];
}

View File

@ -8,6 +8,7 @@ abstract class AddressState extends Equatable {
} }
class AddressInitial extends AddressState {} class AddressInitial extends AddressState {}
//// LOADED STATE //// LOADED STATE
class AddressLoadedState extends AddressState { class AddressLoadedState extends AddressState {
final List<MainAdress> addresses; final List<MainAdress> addresses;
@ -15,6 +16,7 @@ class AddressLoadedState extends AddressState {
@override @override
List<Object> get props => [addresses]; List<Object> get props => [addresses];
} }
////ERROR STATE ////ERROR STATE
class AddressErrorState extends AddressState { class AddressErrorState extends AddressState {
final String message; final String message;
@ -22,6 +24,7 @@ class AddressErrorState extends AddressState {
@override @override
List<Object> get props => [message]; List<Object> get props => [message];
} }
//// LOADING STATE //// LOADING STATE
class AddressLoadingState extends AddressState {} class AddressLoadingState extends AddressState {}
@ -29,28 +32,66 @@ class AddressLoadingState extends AddressState {}
class AddAddressState extends AddressState { class AddAddressState extends AddressState {
final List<Country> countries; final List<Country> countries;
final List<Region> regions; final List<Region> regions;
const AddAddressState( const AddAddressState({required this.countries, required this.regions});
{
required this.countries,
required this.regions});
@override @override
List<Object> get props => [countries, regions,]; List<Object> get props => [
countries,
regions,
];
}
//// DeletedState
class AddressDeletedState extends AddressState {
final bool success;
const AddressDeletedState({required this.success});
@override
List<Object> get props => [success];
} }
////AddedState ////AddedState
class AddressAddedState extends AddressState{ class AddressAddedState extends AddressState {
final Map<dynamic,dynamic> response; final Map<dynamic, dynamic> response;
const AddressAddedState({required this.response}); const AddressAddedState({required this.response});
@override @override
List<Object> get props => [response]; List<Object> get props => [response];
} }
class EditAddressState extends AddressState{ ////Edited State
class AddressUpdatedState extends AddressState {
final Map<dynamic, dynamic> response;
const AddressUpdatedState({required this.response});
@override
List<Object> get props => [response];
}
class EditAddressState extends AddressState {
final MainAdress address; final MainAdress address;
final List<Country> countries; final List<Country> countries;
final List<Region> regions; final List<Region> regions;
const EditAddressState({required this.address, required this.countries, required this.regions}); final List<Province> provinces;
@override final List<CityMunicipality> cities;
List<Object> get props => [countries, regions,address]; final List<Barangay> 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<Object> get props => [countries, regions, address];
} }

View File

@ -3,10 +3,13 @@ import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart'; import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.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:form_builder_validators/form_builder_validators.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.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/bloc/profile/primary_information/address/address_bloc.dart';
import 'package:unit2/model/location/address_category.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/model/utils/category.dart';
import 'package:unit2/utils/global.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 '../../../../../theme-data.dart/form-style.dart';
import '../../../../../utils/location_utilities.dart'; import '../../../../../utils/location_utilities.dart';
import '../../../../../utils/text_container.dart'; import '../../../../../utils/text_container.dart';
import '../../../../../utils/validators.dart';
class AddAddressScreen extends StatefulWidget { class AddAddressScreen extends StatefulWidget {
final int profileId; final int profileId;
@ -57,7 +61,11 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
const Area(value: "Metropolis", group: 1), const Area(value: "Metropolis", group: 1),
const Area(value: "Megacity", group: 1), const Area(value: "Megacity", group: 1),
]; ];
final List<AddressCategory> category = [AddressCategory(id: 1, name: "Permanent", type: "home"), AddressCategory(id: 2, name: "Residential", type: "home"), AddressCategory(id: 3, name: "Birthplace", type: "home")]; final List<AddressCategory> category = [
AddressCategory(id: 1, name: "Permanent", type: "home"),
AddressCategory(id: 2, name: "Residential", type: "home"),
AddressCategory(id: 3, name: "Birthplace", type: "home")
];
List<Province>? provinces; List<Province>? provinces;
List<CityMunicipality>? citymuns; List<CityMunicipality>? citymuns;
List<Barangay>? barangays; List<Barangay>? barangays;
@ -84,9 +92,12 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
decoration: decoration:
normalTextFieldStyle("Category*", "Category"), normalTextFieldStyle("Category*", "Category"),
name: "category", name: "category",
onChanged: (AddressCategory? category) {}, onChanged: (AddressCategory? category) {
items: category.map<DropdownMenuItem<AddressCategory>>( selectedAddressCategory = category;
(AddressCategory category) { },
items: category
.map<DropdownMenuItem<AddressCategory>>(
(AddressCategory category) {
return DropdownMenuItem( return DropdownMenuItem(
value: category, child: Text(category.name!)); value: category, child: Text(category.name!));
}).toList()), }).toList()),
@ -151,6 +162,8 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
Flexible( Flexible(
flex: 1, flex: 1,
child: FormBuilderTextField( child: FormBuilderTextField(
validator: FormBuilderValidators.compose([numericRequired]),
keyboardType: TextInputType.number,
name: "block_number", name: "block_number",
decoration: decoration:
normalTextFieldStyle( normalTextFieldStyle(
@ -163,7 +176,9 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
Flexible( Flexible(
flex: 1, flex: 1,
child: FormBuilderTextField( child: FormBuilderTextField(
validator: FormBuilderValidators.compose([numericRequired]),
name: "lot_number", name: "lot_number",
keyboardType: TextInputType.number,
decoration: decoration:
normalTextFieldStyle( normalTextFieldStyle(
"Lot #*", "Lot #"), "Lot #*", "Lot #"),
@ -180,6 +195,7 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
), ),
//// Address Line //// Address Line
FormBuilderTextField( FormBuilderTextField(
name: "address_line", name: "address_line",
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Address Line *", "Address Line"), "Address Line *", "Address Line"),
@ -391,31 +407,64 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
name: 'country', name: 'country',
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Country*", "Country"), "Country*", "Country"),
onChanged: (Country? value) {}, onChanged: (Country? value) {
selectedCountry = value;
},
), ),
), ),
), ),
], ],
); );
}), }),
////sumit button ////sumit button
const Expanded(child: SizedBox()), const Expanded(child: SizedBox()),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 60, height: 60,
child: ElevatedButton( child: ElevatedButton(
style: mainBtnStyle( style: mainBtnStyle(
primary, Colors.transparent, second), primary, Colors.transparent, second),
onPressed: () {}, onPressed: () {
child: const Text(submit)), if (formKey.currentState!.saveAndValidate()) {
), String? lotNumber;
const SizedBox( String? blockNumber;
height: 20, 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<AddressBloc>().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,
),
], ],
), ),
)), )),
), ),
); );

View File

@ -3,10 +3,15 @@ import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart'; import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.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:form_builder_validators/form_builder_validators.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.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/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/model/utils/category.dart';
import 'package:unit2/screens/profile/components/other_information/org_membership/add_modal.dart';
import 'package:unit2/utils/global.dart'; import 'package:unit2/utils/global.dart';
import '../../../../../model/location/barangay.dart'; import '../../../../../model/location/barangay.dart';
@ -19,6 +24,7 @@ import '../../../../../theme-data.dart/colors.dart';
import '../../../../../theme-data.dart/form-style.dart'; import '../../../../../theme-data.dart/form-style.dart';
import '../../../../../utils/location_utilities.dart'; import '../../../../../utils/location_utilities.dart';
import '../../../../../utils/text_container.dart'; import '../../../../../utils/text_container.dart';
import '../../../../../utils/validators.dart';
class EditAddressScreen extends StatefulWidget { class EditAddressScreen extends StatefulWidget {
final int profileId; final int profileId;
@ -38,6 +44,8 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
bool cityCall = false; bool cityCall = false;
bool barangayCall = false; bool barangayCall = false;
////selected ////selected
AddressCategory? selectedAddressCategory;
Area? selectedAreaClass;
Region? selectedRegion; Region? selectedRegion;
Province? selectedProvince; Province? selectedProvince;
CityMunicipality? selectedMunicipality; CityMunicipality? selectedMunicipality;
@ -54,7 +62,11 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
const Area(value: "Metropolis", group: 1), const Area(value: "Metropolis", group: 1),
const Area(value: "Megacity", group: 1), const Area(value: "Megacity", group: 1),
]; ];
final List<String> category = ["Permanent", "Residential", "Birthplace"]; final List<AddressCategory> category = [
AddressCategory(id: 1, name: "Permanent", type: "home"),
AddressCategory(id: 2, name: "Residential", type: "home"),
AddressCategory(id: 3, name: "Birthplace", type: "home")
];
List<Province>? provinces; List<Province>? provinces;
List<CityMunicipality>? citymuns; List<CityMunicipality>? citymuns;
List<Barangay>? barangays; List<Barangay>? barangays;
@ -64,6 +76,33 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
return BlocBuilder<AddressBloc, AddressState>( return BlocBuilder<AddressBloc, AddressState>(
builder: (context, state) { builder: (context, state) {
if (state is EditAddressState) { 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( return SingleChildScrollView(
child: SizedBox( child: SizedBox(
height: screenHeight * .90, height: screenHeight * .90,
@ -72,32 +111,39 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 25, horizontal: 18), vertical: 25, horizontal: 18),
child: Column( child: ListView(
children: [ children: [
//// category //// category
FormBuilderDropdown<String>( FormBuilderDropdown(
initialValue: selectedAddressCategory,
validator: FormBuilderValidators.required( validator: FormBuilderValidators.required(
errorText: "This field is required"), errorText: "This field is required"),
decoration: decoration:
normalTextFieldStyle("Category*", "Category"), normalTextFieldStyle("Category*", "Category"),
name: "category", name: "category",
onChanged: (String? category) {}, onChanged: (AddressCategory? category) {
items: category.map<DropdownMenuItem<String>>( selectedAddressCategory = category;
(String category) { },
items: category
.map<DropdownMenuItem<AddressCategory>>(
(AddressCategory category) {
return DropdownMenuItem( return DropdownMenuItem(
value: category, child: Text(category)); value: category, child: Text(category.name!));
}).toList()), }).toList()),
const SizedBox( const SizedBox(
height: 12, height: 12,
), ),
////Area Class ////Area Class
FormBuilderDropdown( FormBuilderDropdown(
initialValue: selectedAreaClass,
validator: FormBuilderValidators.required( validator: FormBuilderValidators.required(
errorText: "This field is required"), errorText: "This field is required"),
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Area class *", "Area class"), "Area class *", "Area class"),
name: "area_class", name: "area_class",
onChanged: (Area? area) {}, onChanged: (Area? area) {
selectedAreaClass = area;
},
items: areaClass items: areaClass
.map<DropdownMenuItem<Area>>((Area area) { .map<DropdownMenuItem<Area>>((Area area) {
return area.group == 0 return area.group == 0
@ -146,6 +192,11 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
Flexible( Flexible(
flex: 1, flex: 1,
child: FormBuilderTextField( child: FormBuilderTextField(
initialValue: state.address.subdivision?.blockNo?.toString(),
validator: FormBuilderValidators
.compose([numericRequired]),
keyboardType:
TextInputType.number,
name: "block_number", name: "block_number",
decoration: decoration:
normalTextFieldStyle( normalTextFieldStyle(
@ -158,7 +209,12 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
Flexible( Flexible(
flex: 1, flex: 1,
child: FormBuilderTextField( child: FormBuilderTextField(
initialValue: state.address.subdivision?.lotNo?.toString(),
validator: FormBuilderValidators
.compose([numericRequired]),
name: "lot_number", name: "lot_number",
keyboardType:
TextInputType.number,
decoration: decoration:
normalTextFieldStyle( normalTextFieldStyle(
"Lot #*", "Lot #"), "Lot #*", "Lot #"),
@ -175,6 +231,7 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
), ),
//// Address Line //// Address Line
FormBuilderTextField( FormBuilderTextField(
initialValue: state.address.details,
name: "address_line", name: "address_line",
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Address Line *", "Address Line"), "Address Line *", "Address Line"),
@ -209,7 +266,9 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
height: 12, height: 12,
), ),
////REGION DROPDOWN ////REGION DROPDOWN
FormBuilderDropdown<Region?>( DropdownButtonFormField<Region?>(
isExpanded: true,
value: selectedRegion,
autovalidateMode: AutovalidateMode autovalidateMode: AutovalidateMode
.onUserInteraction, .onUserInteraction,
validator: validator:
@ -222,13 +281,71 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
provinceCall = true; provinceCall = true;
}); });
selectedRegion = region; 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( decoration: normalTextFieldStyle(
"Region*", "Region"), "Region*", "Region"),
name: 'region',
items: state.regions items: state.regions
.map<DropdownMenuItem<Region>>( .map<DropdownMenuItem<Region>>(
(Region region) { (Region region) {
@ -258,16 +375,41 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
: null, : null,
isExpanded: true, isExpanded: true,
value: selectedProvince, value: selectedProvince,
onChanged: onChanged: (Province?
(Province? province) { province) async {
if (selectedProvince != if (selectedProvince !=
province) { province) {
selectedProvince =
province;
setState(() { setState(() {
cityCall = true; cityCall = true;
}); });
selectedProvince =
province; //// GET CITIES
getCities(); 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 items: provinces == null
@ -302,15 +444,27 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
errorText: errorText:
"This field is required"), "This field is required"),
isExpanded: true, isExpanded: true,
onChanged: onChanged: (CityMunicipality?
(CityMunicipality? city) { city) async {
if (selectedMunicipality != if (selectedMunicipality !=
city) { city) {
setState(() { setState(() {
barangayCall = true; barangayCall = true;
}); });
selectedMunicipality = city; selectedMunicipality = city;
getBarangays(); selectedMunicipality = city;
//// GET BARANGAYS
barangays = await LocationUtils
.instance
.getBarangay(
code:
selectedMunicipality!
.code!);
selectedBarangay =
barangays![0];
setState(() {
barangayCall = false;
});
} }
}, },
decoration: decoration:
@ -369,7 +523,7 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
: SizedBox( : SizedBox(
height: 60, height: 60,
child: FormBuilderDropdown<Country>( child: FormBuilderDropdown<Country>(
initialValue: null, initialValue: selectedCountry,
validator: validator:
FormBuilderValidators.required( FormBuilderValidators.required(
errorText: errorText:
@ -386,31 +540,73 @@ class _EditAddressScreenState extends State<EditAddressScreen> {
name: 'country', name: 'country',
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Country*", "Country"), "Country*", "Country"),
onChanged: (Country? value) {}, onChanged: (Country? value) {
selectedCountry = value;
},
), ),
), ),
), ),
], ],
); );
}), }),
////sumit button ////sumit button
const Expanded(child: SizedBox()), const Expanded(child: SizedBox()),
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 60, height: 60,
child: ElevatedButton( child: ElevatedButton(
style: mainBtnStyle( style: mainBtnStyle(
primary, Colors.transparent, second), primary, Colors.transparent, second),
onPressed: () {}, onPressed: () {
child: const Text(submit)), if (formKey.currentState!.saveAndValidate()) {
), String? lotNumber;
const SizedBox( String? blockNumber;
height: 20, 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<AddressBloc>().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,
),
], ],
), ),
)), )),
), ),
); );

View File

@ -39,11 +39,11 @@ class AddressScreen extends StatelessWidget {
], ],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
indicatorWidget: const SpinKitFadingCircle( indicatorWidget: const SpinKitFadingCircle(
color: Colors.white, color: Colors.white,
), ),
backgroundColor: Colors.black87, backgroundColor: Colors.black87,
child: BlocBuilder<UserBloc, UserState>( child: BlocBuilder<UserBloc, UserState>(
builder: (context, state) { builder: (context, state) {
if (state is UserLoggedIn) { if (state is UserLoggedIn) {
@ -61,13 +61,67 @@ class AddressScreen extends StatelessWidget {
if (state is AddressLoadedState || if (state is AddressLoadedState ||
state is AddressErrorState || state is AddressErrorState ||
state is AddAddressState || state is AddAddressState ||
state is EditAddressState) { state is EditAddressState ||
state is AddressAddedState || state is EditAddressState || state is AddressUpdatedState) {
final progress = ProgressHUD.of(context); final progress = ProgressHUD.of(context);
progress!.dismiss(); 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<AddressBloc>().add(LoadAddress());
});
} else {
errorAlert(context, "Adding Failed",
state.response['message'], () {
Navigator.of(context).pop();
context.read<AddressBloc>().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<AddressBloc>().add(LoadAddress());
});
} else {
errorAlert(context, "Update Failed",
state.response['message'], () {
Navigator.of(context).pop();
context.read<AddressBloc>().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<AddressBloc>().add(LoadAddress());
});
} else {
errorAlert(context, "Deletion Failed",
"Error deleting Address", () {
Navigator.of(context).pop();
context.read<AddressBloc>().add(LoadAddress());
});
}
}
}, },
builder: (context, state) { builder: (context, state) {
if (state is AddressLoadedState) { if (state is AddressLoadedState) {
bool overseas;
String? cityMunicipality;
String? province;
String? region;
String? barangay;
if (state.addresses.isNotEmpty) { if (state.addresses.isNotEmpty) {
return ListView.builder( return ListView.builder(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@ -79,29 +133,37 @@ class AddressScreen extends StatelessWidget {
state.addresses[index].details ?? ''; state.addresses[index].details ?? '';
String category = state.addresses[index] String category = state.addresses[index]
.address!.category!.name!; .address!.category!.name!;
String? barangay = state.addresses[index] if (state.addresses[index].address!.country!
.address!.barangay != .id ==
null 175) {
? '${state.addresses[index].address!.barangay!.description!.toUpperCase()},' barangay = state.addresses[index].address!
: ''; .barangay !=
String cityMunicipality = state null
.addresses[index] ? '${state.addresses[index].address!.barangay!.description!.toUpperCase()},'
.address! : '';
.cityMunicipality! cityMunicipality = state
.description!; .addresses[index]
String province = state .address!
.addresses[index] .cityMunicipality!
.address! .description!;
.cityMunicipality! province = state
.province! .addresses[index]
.description!; .address!
String region = state .cityMunicipality!
.addresses[index] .province!
.address! .description!;
.cityMunicipality! region = state
.province! .addresses[index]
.region! .address!
.description!; .cityMunicipality!
.province!
.region!
.description!;
overseas = false;
} else {
overseas = true;
}
return Column( return Column(
children: [ children: [
Column( Column(
@ -115,6 +177,10 @@ class AddressScreen extends StatelessWidget {
child: Row(children: [ child: Row(children: [
Expanded( Expanded(
child: Column( child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
@ -141,12 +207,25 @@ class AddressScreen extends StatelessWidget {
const SizedBox( const SizedBox(
height: 5, height: 5,
), ),
Text( Container(
"$barangay $cityMunicipality, $province, $region", child: overseas
style: Theme.of(context) ? Text(
.textTheme "COUNTRY: ${state.addresses[index].address!.country!.name!.toUpperCase()}",
.labelLarge, textAlign:
), TextAlign
.start,
style: Theme.of(
context)
.textTheme
.labelLarge,
)
: Text(
"$barangay $cityMunicipality, $province, $region",
style: Theme.of(
context)
.textTheme
.labelLarge,
)),
], ],
)), )),
AppPopupMenu<int>( AppPopupMenu<int>(
@ -164,8 +243,19 @@ class AddressScreen extends StatelessWidget {
"Loading..."); "Loading...");
}, "Delete?", }, "Delete?",
"Confirm Delete?"); "Confirm Delete?");
context
.read<AddressBloc>()
.add(DeleteAddress(
id: state
.addresses[
index]
.id!,
profileId: profileId
.toString(),
token: token!));
} }
if (value == 1) { if (value == 1) {
bool overseas;
////edit eligibilty-= = = = = = = = =>> ////edit eligibilty-= = = = = = = = =>>
final progress = final progress =
ProgressHUD.of( ProgressHUD.of(
@ -173,9 +263,20 @@ class AddressScreen extends StatelessWidget {
progress!.showWithText( progress!.showWithText(
"Loading..."); "Loading...");
if (state
.addresses[index]
.address
?.cityMunicipality ==
null) {
overseas = true;
} else {
overseas = false;
}
context context
.read<AddressBloc>() .read<AddressBloc>()
.add(ShowEditAddressForm( .add(ShowEditAddressForm(
overseas:
overseas,
address: state address: state
.addresses[ .addresses[
index])); index]));
@ -225,8 +326,10 @@ class AddressScreen extends StatelessWidget {
if (state is AddAddressState) { if (state is AddAddressState) {
return AddAddressScreen( return AddAddressScreen(
profileId: profileId!, token: token!); 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(); return Container();
}, },

View File

@ -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<Map<String, dynamic>> add(
{required AddressClass address,
required int categoryId,
required String? details,
required int? blockNumber,
required int? lotNumber,
required String token,
required int profileId}) async {
Map<String, dynamic>? _response = {};
String authtoken = "Token $token";
String path = '${Url.instance.addressPath()}$profileId/';
Map<String, String> 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<bool> 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<String, dynamic> params = {"force_mode": "true"};
Map<String, String> 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<Map<String, dynamic>> update(
{required AddressClass address,
required int categoryId,
required String? details,
required int? blockNumber,
required int? lotNumber,
required String token,
required int profileId}) async {
Map<String, dynamic>? _response = {};
String authtoken = "Token $token";
String path = '${Url.instance.addressPath()}$profileId/';
Map<String, String> 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(<String, dynamic>{
"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();
}
}
}

View File

@ -137,6 +137,47 @@ class Request {
} }
return response; return response;
} }
Future<Response> patch(
{required String path,
required Map<String, String>? headers,
required Map? body,
required Map<String, dynamic>? 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<Response> deleteRequest( Future<Response> deleteRequest(
{required String path, {required String path,

View File

@ -125,6 +125,11 @@ String getServiceTypes(){
return "/api/jobnet_app/comm_service_type/"; return "/api/jobnet_app/comm_service_type/";
} }
//// address path
String addressPath(){
return "/api/jobnet_app/profile/pds/basic/address/";
}
String contactPath(){ String contactPath(){
return "/api/jobnet_app/profile/pds/basic/contact/"; return "/api/jobnet_app/profile/pds/basic/contact/";
} }