Implemnent Voluntary works and civic API

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-05-02 08:26:42 +08:00
parent 7f39bd5cd9
commit 1c6b291889
19 changed files with 2139 additions and 679 deletions

View File

@ -1,6 +1,8 @@
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/profile/voluntary_works.dart';
import '../../../../model/location/city.dart';
import '../../../../model/location/country.dart';

View File

@ -23,3 +23,12 @@ class ShowEditAddressForm extends AddressEvent{
class CallErrorState extends AddressEvent{
}
class AddAddress extends EligibilityEvent{
final MainAdress address;
final String token;
final int profileId;
const AddAddress({required this.address, required this.profileId, required this.token});
@override
List<Object> get props => [address,token,profileId];
}

View File

@ -37,6 +37,15 @@ class AddAddressState extends AddressState {
List<Object> get props => [countries, regions,];
}
////AddedState
class AddressAddedState extends AddressState{
final Map<dynamic,dynamic> response;
const AddressAddedState({required this.response});
@override
List<Object> get props => [response];
}
class EditAddressState extends AddressState{
final MainAdress address;
final List<Country> countries;

View File

@ -1,14 +1,19 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:unit2/sevices/profile/volunatary_services.dart';
import 'package:unit2/utils/profile_utilities.dart';
import '../../../model/location/city.dart';
import '../../../model/location/country.dart';
import '../../../model/location/provinces.dart';
import '../../../model/location/region.dart';
import '../../../model/profile/voluntary_works.dart';
import '../../../model/utils/agency.dart';
import '../../../model/utils/category.dart';
import '../../../model/utils/position.dart';
import '../../../utils/location_utilities.dart';
part 'voluntary_work_event.dart';
part 'voluntary_work_state.dart';
@ -21,21 +26,36 @@ class VoluntaryWorkBloc extends Bloc<VoluntaryWorkEvent, VoluntaryWorkState> {
List<Region> globalRegions = [];
List<Position> agencyPositions = [];
List<Agency> agencies = [];
List<Province> provinces = [];
List<CityMunicipality> cities = [];
///// current
Position currentPosition;
Agency currentAgency;
Region? currentRegion;
Country currentCountry;
Province? currentProvince;
CityMunicipality? currentCity;
////Get Voluntary Works
on<GetVoluntarWorks>((event, emit) async {
emit(VoluntaryWorkLoadingState());
try {
List<VoluntaryWork> works = await VoluntaryService.instance.getVoluntaryWorks(event.profileId, event.token);
List<VoluntaryWork> works = await VoluntaryService.instance
.getVoluntaryWorks(event.profileId, event.token);
voluntaryWorks = works;
emit(VoluntaryWorkLoadedState(voluntaryWorks: voluntaryWorks));
} catch (e) {
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});
//// Load
on<LoadVoluntaryWorks>((event, emit) {
emit(VoluntaryWorkLoadedState(voluntaryWorks: voluntaryWorks));
});
//// Show Add form Event
on<ShowAddVoluntaryWorks>((event, emit) async {
try {
emit(VoluntaryWorkLoadingState());
//// POSITIONS
if (agencyPositions.isEmpty) {
List<Position> positions =
await ProfileUtilities.instance.getAgencyPosition();
@ -55,12 +75,177 @@ class VoluntaryWorkBloc extends Bloc<VoluntaryWorkEvent, VoluntaryWorkState> {
await ProfileUtilities.instance.agencyCategory();
agencyCategory = categoryAgencies;
}
emit(AddVoluntaryWorkState(agencies: agencies,positions: agencyPositions,agencyCategory: agencyCategory,regions: globalRegions,countries: globalCountries));
////regions
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
//// country
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
emit(AddVoluntaryWorkState(
agencies: agencies,
positions: agencyPositions,
agencyCategory: agencyCategory,
regions: globalRegions,
countries: globalCountries));
} catch (e) {
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});on<ShowErrorState>((event,emit){
});
on<ShowErrorState>((event, emit) {
emit(VoluntaryWorkErrorState(message: event.message));
});
//// Add Voluntary Work
on<AddVoluntaryWork>((event, emit) async {
try {
Map<dynamic, dynamic> status = await VoluntaryService.instance.add(
voluntaryWork: event.work,
profileId: event.profileId,
token: event.token);
if (status['success']) {
VoluntaryWork work = VoluntaryWork.fromJson(status['data']);
voluntaryWorks.add(work);
emit(VoluntaryWorkAddedState(response: status));
} else {
emit(VoluntaryWorkAddedState(response: status));
}
} catch (e) {
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});
////Update
on<UpdateVolunataryWork>((event, emit) async {
final DateFormat formatter = DateFormat('yyyy-MM-dd');
try{
Map<dynamic, dynamic> status = await VoluntaryService.instance.update(
voluntaryWork: event.work,
profileId: event.profileId,
token: event.token,
oldPosId: event.oldPosId,
oldAgencyId: event.oldAgencyId,
oldFromDate: formatter.format(DateTime.parse(event.oldFromDate)));
if (status['success']) {
VoluntaryWork work = VoluntaryWork.fromJson(status['data']);
voluntaryWorks.removeWhere((VoluntaryWork element) =>
element.position!.id == event.oldPosId &&
element.agency!.id == event.oldAgencyId &&
element.fromDate.toString() == event.oldFromDate.toString());
voluntaryWorks.add(work);
emit(VoluntaryWorkEditedState(response: status));
} else {
emit(VoluntaryWorkEditedState(response: status));
}
}catch(e){
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});
/////SHOW EDIT FORM
on<ShowEditVoluntaryWorks>((event, emit) async {
try {
//// POSITIONS
if (agencyPositions.isEmpty) {
List<Position> positions =
await ProfileUtilities.instance.getAgencyPosition();
agencyPositions = positions;
}
currentPosition = event.work.position!;
/////AGENCIES------------------------------------------
if (agencies.isEmpty) {
List<Agency> newAgencies =
await ProfileUtilities.instance.getAgecies();
agencies = newAgencies;
}
currentAgency = event.work.agency!;
/////Category Agency------------------------------------------
if (agencyCategory.isEmpty) {
List<Category> categoryAgencies =
await ProfileUtilities.instance.agencyCategory();
agencyCategory = categoryAgencies;
}
////regions
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
//// country
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
currentCountry = globalCountries.firstWhere((Country country) =>
event.work.address!.country!.code == country.code);
////If overseas
if (!event.isOverseas) {
//// if not overseas
currentRegion = globalRegions.firstWhere((Region region) =>
event.work.address!.cityMunicipality!.province!.region!.code ==
region.code);
provinces = await LocationUtils.instance
.getProvinces(regionCode: currentRegion!.code.toString());
currentProvince = provinces.firstWhere((Province province) =>
event.work.address!.cityMunicipality!.province!.code ==
province.code);
cities = await LocationUtils.instance
.getCities(code: currentProvince!.code.toString());
currentCity = cities.firstWhere((CityMunicipality cityMunicipality) =>
event.work.address!.cityMunicipality!.code ==
cityMunicipality.code);
}
emit(EditVoluntaryWorks(
overseas: event.isOverseas,
agencies: agencies,
agencyCategory: agencyCategory,
cities: cities,
countries: globalCountries,
positions: agencyPositions,
provinces: provinces,
regions: globalRegions,
work: event.work,
currentAgency: currentAgency,
currentCity: currentCity,
currentCountry: currentCountry,
currentPosition: currentPosition,
currentProvince: currentProvince,
currentRegion: currentRegion));
} catch (e) {
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});
//// Delete
on<DeleteVoluntaryWork>((event, emit) async {
try {
final DateFormat formatter = DateFormat('yyyy-MM-dd');
final bool success = await VoluntaryService.instance.delete(
agencyId: event.work.agency!.id!,
positionId: event.work.position!.id!,
fromDate: formatter.format(event.work.fromDate!),
token: event.token,
profileId: event.profileId);
if (success) {
voluntaryWorks.removeWhere((VoluntaryWork element) =>
element.position!.id == event.work.position!.id &&
element.agency!.id == event.work.agency!.id &&
element.fromDate == event.work.fromDate);
emit(VoluntaryWorkDeletedState(success: success));
} else {
emit(VoluntaryWorkDeletedState(success: success));
}
} catch (e) {
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});
}
}

View File

@ -14,11 +14,61 @@ class GetVoluntarWorks extends VoluntaryWorkEvent{
@override
List<Object> get props => [profileId, token];
}
class ShowAddVoluntaryWorks extends VoluntaryWorkEvent{
class ShowAddVoluntaryWorks extends VoluntaryWorkEvent {}
class ShowEditVoluntaryWorks extends VoluntaryWorkEvent {
final VoluntaryWork work;
final int profileId;
final String token;
final bool isOverseas;
// final int oldPosId;
// final int oldAgencyId;
// final String oldFromDate;
const ShowEditVoluntaryWorks(
{required this.profileId,
required this.token,
required this.work,
// required this.oldAgencyId,
// required this.oldFromDate,
// required this.oldPosId,
required this.isOverseas});
@override
List<Object> get props => [profileId, token, work];
}
class LoadVoluntaryWorks extends VoluntaryWorkEvent {}
class ShowErrorState extends VoluntaryWorkEvent {
final String message;
const ShowErrorState({required this.message});
}
class UpdateVolunataryWork extends VoluntaryWorkEvent{
final int oldPosId;
final int oldAgencyId;
final String oldFromDate;
final VoluntaryWork work;
final int profileId;
final String token;
const UpdateVolunataryWork({required this.oldAgencyId, required this.oldFromDate, required this.oldPosId, required this.profileId, required this.token, required this.work});
}
class AddVoluntaryWork extends VoluntaryWorkEvent {
final int profileId;
final String token;
final VoluntaryWork work;
const AddVoluntaryWork(
{required this.profileId, required this.token, required this.work});
@override
List<Object> get props => [profileId, token, work];
}
class DeleteVoluntaryWork extends VoluntaryWorkEvent {
final String token;
final int profileId;
final VoluntaryWork work;
const DeleteVoluntaryWork(
{required this.profileId, required this.token, required this.work});
@override
List<Object> get props => [profileId, token, work];
}

View File

@ -26,8 +26,41 @@ class VoluntaryWorkErrorState extends VoluntaryWorkState{
class VoluntaryWorkLoadingState extends VoluntaryWorkState{
}
////Added State
class VoluntaryWorkAddedState extends VoluntaryWorkState{
final Map<dynamic,dynamic> response;
const VoluntaryWorkAddedState({required this.response});
@override
List<Object> get props => [response];
}
////Added State
class VoluntaryWorkEditedState extends VoluntaryWorkState{
final Map<dynamic,dynamic> response;
const VoluntaryWorkEditedState({required this.response});
@override
List<Object> get props => [response];
}
class EditVoluntaryWorks extends VoluntaryWorkState{
final VoluntaryWork work;
final List<Position> positions;
final List<Agency> agencies;
final List<Category> agencyCategory;
final List<Country> countries;
final List<Region> regions;
final List<Province> provinces;
final List<CityMunicipality> cities;
final Position currentPosition;
final Agency currentAgency;
final Region? currentRegion;
final Country currentCountry;
final Province? currentProvince;
final CityMunicipality? currentCity;
final bool overseas;
const EditVoluntaryWorks({required this.agencies, required this.agencyCategory, required this.cities, required this.countries,required this.positions, required this.provinces, required this.regions, required this.work, required this.currentAgency, required this.currentCity,required this.currentCountry, required this.currentPosition, required this.currentProvince, required this.currentRegion,required this.overseas});
}
////Adding State
class AddVoluntaryWorkState extends VoluntaryWorkState{
final List<Position> positions;
final List<Agency> agencies;
@ -38,3 +71,10 @@ class AddVoluntaryWorkState extends VoluntaryWorkState{
@override
List<Object> get props => [positions,agencies,countries,regions];
}
//// Deleted State
class VoluntaryWorkDeletedState extends VoluntaryWorkState{
final bool success;
const VoluntaryWorkDeletedState({required this.success});
@override
List<Object> get props => [success];
}

View File

@ -29,12 +29,12 @@ class VoluntaryWork {
final DateTime? toDate;
final Position? position;
final DateTime? fromDate;
final int? totalHours;
final double? totalHours;
factory VoluntaryWork.fromJson(Map<String, dynamic> json) => VoluntaryWork(
agency: json["agency"] == null ? null : Agency.fromJson(json["agency"]),
address: json["address"] == null ? null : Address.fromJson(json["address"]),
toDate: json["to_date"] == null? null : DateTime.parse(json['to_data']),
toDate: json["to_date"] == null? null : DateTime.parse(json['to_date']),
position: json["position"] == null ? null : Position.fromJson(json["position"]),
fromDate: json["from_date"] == null ? null : DateTime.parse(json["from_date"]),
totalHours: json["total_hours"],

View File

@ -6,6 +6,7 @@ import 'package:flutter_form_builder/flutter_form_builder.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/utils/category.dart';
import 'package:unit2/utils/global.dart';
@ -38,6 +39,8 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
bool cityCall = false;
bool barangayCall = false;
////selected
AddressCategory? selectedAddressCategory;
String? selectedAreaClass;
Region? selectedRegion;
Province? selectedProvince;
CityMunicipality? selectedMunicipality;
@ -54,7 +57,7 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
const Area(value: "Metropolis", 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<CityMunicipality>? citymuns;
List<Barangay>? barangays;
@ -75,17 +78,17 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
child: Column(
children: [
//// category
FormBuilderDropdown<String>(
FormBuilderDropdown(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration:
normalTextFieldStyle("Category*", "Category"),
name: "category",
onChanged: (String? category) {},
items: category.map<DropdownMenuItem<String>>(
(String category) {
onChanged: (AddressCategory? category) {},
items: category.map<DropdownMenuItem<AddressCategory>>(
(AddressCategory category) {
return DropdownMenuItem(
value: category, child: Text(category));
value: category, child: Text(category.name!));
}).toList()),
const SizedBox(
height: 12,
@ -97,7 +100,9 @@ class _AddAddressScreenState extends State<AddAddressScreen> {
decoration: normalTextFieldStyle(
"Area class *", "Area class"),
name: "area_class",
onChanged: (Area? area) {},
onChanged: (Area? area) {
selectedAreaClass = area!.value;
},
items: areaClass
.map<DropdownMenuItem<Area>>((Area area) {
return area.group == 0

View File

@ -448,6 +448,9 @@ class _AddEducationScreenState extends State<AddEducationScreen> {
if (!graduated) {
unitsEarned = int.parse(formKey
.currentState!.value['units_earned']);
yearGraduated.text = '';
}else{
}
////education
Education newEducation = Education(

View File

@ -92,7 +92,6 @@ class _EditEducationScreenState extends State<EditEducationScreen> {
}
fromController.text = state.educationalBackground.periodFrom!;
untilController.text = state.educationalBackground.periodTo!;
////honors
////get all honors
valueItemHonorList = state.honors.map((Honor honor) {
@ -147,6 +146,10 @@ class _EditEducationScreenState extends State<EditEducationScreen> {
////school
StatefulBuilder(builder: (context, setState) {
return SearchField(
suggestionAction: SuggestionAction.next,
onSubmit: (p0) {
schoolFocusNode.unfocus();
},
controller: currentSchoolController,
itemHeight: 50,
suggestionsDecoration: box1(),
@ -171,7 +174,9 @@ class _EditEducationScreenState extends State<EditEducationScreen> {
searchInputDecoration:
normalTextFieldStyle("School *", "").copyWith(
suffixIcon:
const Icon(Icons.arrow_drop_down)),
GestureDetector(child: const Icon(Icons.arrow_drop_down),onTap: (){
schoolFocusNode.unfocus();
},)),
onSuggestionTap: (school) {
setState(() {
selectedSchool = school.item;
@ -498,9 +503,11 @@ class _EditEducationScreenState extends State<EditEducationScreen> {
selectedLevel!.value == "Senior High") {
selectedProgram = null;
} else {
selectedProgram ??= state.educationalBackground.education!.course;
selectedProgram ??= state
.educationalBackground.education!.course;
}
selectedSchool ??= state.educationalBackground.education!.school;
selectedSchool ??=
state.educationalBackground.education!.school;
////education
Education newEducation = Education(
id: null,

View File

@ -18,6 +18,7 @@ import 'package:unit2/widgets/error_state.dart';
import '../../../bloc/profile/education/education_bloc.dart';
import '../../../utils/alerts.dart';
import '../../../widgets/Leadings/close_leading.dart';
import 'education/edit_modal.dart';
class EducationScreen extends StatelessWidget {
@ -32,11 +33,15 @@ class EducationScreen extends StatelessWidget {
title: const Text(educationScreenTitle),
centerTitle: true,
backgroundColor: primary,
actions: [
actions: context.watch<EducationBloc>().state is EducationalBackgroundLoadedState?[
AddLeading(onPressed: () {
context.read<EducationBloc>().add(ShowAddEducationForm());
})
],
]:(context.watch<EducationBloc>().state is AddEducationState || context.watch<EducationBloc>().state is EditEducationState)?[
CloseLeading(onPressed: () {
context.read<EducationBloc>().add( LoadEducations());
})
]:[],
),
//userbloc
body: ProgressHUD(

View File

@ -398,11 +398,11 @@ class _AddEligibilityScreenState extends State<AddEligibilityScreen> {
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
//rating
////rating
double? rate = rating == null
? null
: double.parse(rating!);
//lisence
////lisence
String? licenseNumber = license;
CityMunicipality? cityMunicipality =
selectedMunicipality;

View File

@ -0,0 +1,685 @@
import 'package:date_time_picker/date_time_picker.dart';
import 'package:flutter/material.dart';
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:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/profile/voluntary_works/voluntary_work_bloc.dart';
import 'package:unit2/utils/global.dart';
import '../../../../model/location/barangay.dart';
import '../../../../model/location/city.dart';
import '../../../../model/location/country.dart';
import '../../../../model/location/provinces.dart';
import '../../../../model/location/region.dart';
import '../../../../model/profile/voluntary_works.dart';
import '../../../../model/utils/agency.dart';
import '../../../../model/utils/category.dart';
import '../../../../model/utils/position.dart';
import '../../../../theme-data.dart/box_shadow.dart';
import '../../../../theme-data.dart/btn-style.dart';
import '../../../../theme-data.dart/colors.dart';
import '../../../../theme-data.dart/form-style.dart';
import '../../../../utils/location_utilities.dart';
import '../../../../utils/text_container.dart';
import '../../shared/add_for_empty_search.dart';
class AddVoluntaryWorkScreen extends StatefulWidget {
final int profileId;
final String token;
const AddVoluntaryWorkScreen(
{super.key, required this.profileId, required this.token});
@override
State<AddVoluntaryWorkScreen> createState() => _AddVoluntaryWorkScreenState();
}
class _AddVoluntaryWorkScreenState extends State<AddVoluntaryWorkScreen> {
final formKey = GlobalKey<FormBuilderState>();
////controllers
final addPositionController = TextEditingController();
final addAgencyController = TextEditingController();
final toDateController = TextEditingController();
final fromDateController = TextEditingController();
////focus nodes
final positionFocusNode = FocusNode();
final agencyFocusNode = FocusNode();
final agencyCategoryFocusNode = FocusNode();
////booleans
bool showAgency = false;
bool showIsPrivateRadio = false;
bool currentlyInvolved = false;
bool overseas = false;
bool provinceCall = false;
bool cityCall = false;
bool isPrivate = false;
////Lists
List<Province>? provinces;
List<CityMunicipality>? citymuns;
////Selected
Position? selectedPosition;
Agency? selectedAgency;
Category? selectedCategoty;
Region? selectedRegion;
Province? selectedProvince;
CityMunicipality? selectedMunicipality;
Country? selectedCountry;
@override
Widget build(BuildContext context) {
return BlocBuilder<VoluntaryWorkBloc, VoluntaryWorkState>(
builder: (context, state) {
if (state is AddVoluntaryWorkState) {
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 18),
child: FormBuilder(
key: formKey,
child: ListView(
children: [
////POSITIONS
StatefulBuilder(builder: (context, setState) {
return SearchField(
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.positions
.map((Position position) => SearchFieldListItem(
position.title!,
item: position,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: ListTile(
title: Text(position.title!),
))))
.toList(),
focusNode: positionFocusNode,
searchInputDecoration:
normalTextFieldStyle("Position *", "").copyWith(
suffixIcon: GestureDetector(
child: const Icon(Icons.arrow_drop_down),
onTap: () => positionFocusNode.unfocus(),
)),
onSuggestionTap: (position) {
setState(() {
selectedPosition = position.item;
positionFocusNode.unfocus();
});
},
////EMPTY WIDGET
emptyWidget: EmptyWidget(
title: "Add Position",
controller: addPositionController,
onpressed: () {
setState(() {
Position newAgencyPosition = Position(
id: null,
title: addPositionController.text
.toUpperCase());
state.positions.insert(0, newAgencyPosition);
addPositionController.text = "";
Navigator.pop(context);
});
}),
validator: (position) {
if (position!.isEmpty) {
return "This field is required";
}
return null;
},
);
}),
const SizedBox(
height: 12,
),
////AGENCY
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
SearchField(
itemHeight: 70,
focusNode: agencyFocusNode,
suggestions: state.agencies
.map((Agency agency) =>
SearchFieldListItem(agency.name!,
item: agency,
child: ListTile(
title: Text(
agency.name!,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
agency.privateEntity == true
? "Private"
: agency.privateEntity ==
false
? "Government"
: ""),
)))
.toList(),
searchInputDecoration:
normalTextFieldStyle("Agency *", "")
.copyWith(
suffixIcon: GestureDetector(
child: const Icon(
Icons.arrow_drop_down,
),
onTap: () => agencyFocusNode.unfocus(),
)),
////SELETECTED
onSuggestionTap: (agency) {
setState(() {
selectedAgency = agency.item;
if (selectedAgency!.privateEntity == null) {
showAgency = true;
showIsPrivateRadio = true;
} else {
showAgency = false;
showIsPrivateRadio = false;
}
agencyFocusNode.unfocus();
});
},
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
emptyWidget: EmptyWidget(
controller: addAgencyController,
onpressed: () {
setState(() {
Agency newAgency = Agency(
id: null,
name: addAgencyController.text
.toUpperCase(),
category: null,
privateEntity: null);
state.agencies.insert(0, newAgency);
addAgencyController.text = "";
Navigator.pop(context);
});
},
title: "Add Agency")),
SizedBox(
height: showAgency ? 12 : 0,
),
////SHOW CATEGORY AGENCY
SizedBox(
child: showAgency
? SearchField(
focusNode: agencyCategoryFocusNode,
itemHeight: 70,
suggestions: state.agencyCategory
.map((Category category) =>
SearchFieldListItem(
category.name!,
item: category,
child: ListTile(
title: Text(category.name!),
subtitle: Text(category
.industryClass!.name!),
)))
.toList(),
emptyWidget: Container(
height: 100,
decoration: box1(),
child: const Center(
child: Text("No result found ...")),
),
onSuggestionTap: (agencyCategory) {
setState(() {
selectedCategoty =
agencyCategory.item;
agencyCategoryFocusNode.unfocus();
});
},
searchInputDecoration:
normalTextFieldStyle("Category *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
validator: (value) {
if (value!.isEmpty) {
return "This field is required";
}
return null;
},
)
: const SizedBox(),
),
SizedBox(
height: showIsPrivateRadio ? 12 : 0,
),
////PRVIATE SECTOR
SizedBox(
child: showIsPrivateRadio
? FormBuilderSwitch(
initialValue: false,
title: Text(isPrivate ? "YES" : "NO"),
decoration: normalTextFieldStyle(
"Private Entity?",
'Private Entity?'),
////onvhange private sector
onChanged: (value) {
setState(() {
isPrivate = value!;
agencyCategoryFocusNode.unfocus();
});
},
name: 'isPrivate',
validator:
FormBuilderValidators.required(),
)
: const SizedBox()),
const SizedBox(
height: 12,
),
//// total hours
FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This Field is required"),
name: "total_hours",
keyboardType: TextInputType.number,
decoration:
normalTextFieldStyle("Total Hours*", "0"),
),
const SizedBox(
height: 12,
),
////Currently Involved
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderSwitch(
initialValue: currentlyInvolved,
activeColor: second,
onChanged: (value) {
setState(() {
currentlyInvolved = value!;
});
},
decoration: normalTextFieldStyle(
"Currently Involved?", 'Graduated?'),
name: 'currently_involved',
title:
Text(currentlyInvolved ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: screenWidth,
child: Row(
children: [
//// FROM DATE
Flexible(
flex: 1,
child: DateTimePicker(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
use24HourFormat: false,
icon:
const Icon(Icons.date_range),
controller: fromDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
timeHintText:
"Date of Examination/Conferment",
decoration: normalTextFieldStyle(
"From *", "From *")
.copyWith(
prefixIcon: const Icon(
Icons.date_range,
color: Colors.black87,
)),
initialValue: null,
)),
const SizedBox(
width: 12,
),
//// TO DATE
Flexible(
flex: 1,
child: currentlyInvolved
? TextFormField(
enabled: false,
initialValue: "PRESENT",
style: const TextStyle(
color: Colors.black45),
decoration:
normalTextFieldStyle(
"", "")
.copyWith(),
)
: DateTimePicker(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
controller: toDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
decoration: normalTextFieldStyle(
"To *", "To *")
.copyWith(
prefixIcon:
const Icon(
Icons.date_range,
color:
Colors.black87,
),
prefixText:
currentlyInvolved
? "PRESENT"
: ""),
initialValue: null,
),
),
],
),
),
],
);
}),
],
);
}),
const SizedBox(
height: 12,
),
//// OVERSEAS
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderSwitch(
initialValue: overseas,
activeColor: second,
onChanged: (value) {
setState(() {
overseas = value!;
});
},
decoration:
normalTextFieldStyle("Overseas Address?", ''),
name: 'overseas',
title: Text(overseas ? "YES" : "NO"),
),
SizedBox(
height: overseas == true ? 8 : 0,
),
SizedBox(
child: overseas == false
? Column(
children: [
const SizedBox(
height: 12,
),
////REGION DROPDOWN
FormBuilderDropdown<Region?>(
autovalidateMode: AutovalidateMode
.onUserInteraction,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
onChanged: (Region? region) async {
if (selectedRegion != region) {
setState(() {
provinceCall = true;
});
selectedRegion = region;
getProvinces();
}
},
initialValue: null,
decoration: normalTextFieldStyle(
"Region*", "Region"),
name: 'region',
items: state.regions
.map<DropdownMenuItem<Region>>(
(Region region) {
return DropdownMenuItem<Region>(
value: region,
child:
Text(region.description!));
}).toList(),
),
const SizedBox(
height: 8,
),
//// PROVINCE DROPDOWN
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.transparent,
inAsyncCall: provinceCall,
child: DropdownButtonFormField<
Province?>(
autovalidateMode:
AutovalidateMode
.onUserInteraction,
validator: (value) =>
value == null
? 'required'
: null,
isExpanded: true,
value: selectedProvince,
onChanged:
(Province? province) {
if (selectedProvince !=
province) {
setState(() {
cityCall = true;
});
selectedProvince = province;
getCities();
}
},
items: provinces == null
? []
: provinces!.map<
DropdownMenuItem<
Province>>(
(Province province) {
return DropdownMenuItem(
value: province,
child: FittedBox(
child: Text(province
.description!),
));
}).toList(),
decoration:
normalTextFieldStyle(
"Province*",
"Province")),
),
),
////CITY MUNICIPALITY
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: cityCall,
child: DropdownButtonFormField<
CityMunicipality>(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
isExpanded: true,
onChanged:
(CityMunicipality? city) {
if (selectedMunicipality !=
city) {
selectedMunicipality = city;
}
},
decoration: normalTextFieldStyle(
"Municipality*",
"Municipality"),
value: selectedMunicipality,
items: citymuns == null
? []
: citymuns!.map<
DropdownMenuItem<
CityMunicipality>>(
(CityMunicipality c) {
return DropdownMenuItem(
value: c,
child: Text(
c.description!));
}).toList(),
),
),
),
],
)
//// COUNTRY DROPDOWN
: SizedBox(
height: 60,
child: FormBuilderDropdown<Country>(
initialValue: null,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
items: state.countries
.map<DropdownMenuItem<Country>>(
(Country country) {
return DropdownMenuItem<Country>(
value: country,
child: FittedBox(
child: Text(country.name!)));
}).toList(),
name: 'country',
decoration: normalTextFieldStyle(
"Country*", "Country"),
onChanged: (Country? value) {
selectedCountry = value;
},
),
),
),
],
);
}),
Expanded(
child: SizedBox(
height: blockSizeVertical * 8,
)),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
if (formKey.currentState!.saveAndValidate()) {
Country country = selectedCountry ??=
Country(
id: 175,
name: 'Philippines',
code: 'PH');
Address address = Address(
barangay: null,
id: null,
addressCategory: null,
addressClass: null,
cityMunicipality: selectedMunicipality,
country: country);
if (selectedCategoty != null) {
selectedAgency = Agency(
id: selectedAgency?.id,
name: selectedAgency!.name,
category: selectedCategoty,
privateEntity: isPrivate);
}
VoluntaryWork work = VoluntaryWork(
////address
address: address,
//// agency
agency: selectedAgency,
////
position: selectedPosition,
////total hours
totalHours: double.parse(formKey
.currentState!.value["total_hours"]),
////to date
toDate: toDateController.text.isEmpty ||
toDateController.text.toUpperCase() ==
"PRESENT"
? null
: DateTime.parse(toDateController.text),
////from date
fromDate:
DateTime.parse(fromDateController.text),
);
final progress = ProgressHUD.of(context);
progress!.showWithText("Loading...");
context.read<VoluntaryWorkBloc>().add(
AddVoluntaryWork(
profileId: widget.profileId,
token: widget.token,
work: work));
}
},
child: const Text(submit)),
)
],
)),
),
);
}
return const Placeholder();
},
);
}
Future<void> getProvinces() async {
try {
List<Province> newProvinces = await LocationUtils.instance
.getProvinces(regionCode: selectedRegion!.code.toString());
setState(() {
provinces = newProvinces;
selectedProvince = provinces![0];
provinceCall = false;
cityCall = true;
getCities();
});
} catch (e) {
context
.read<VoluntaryWorkBloc>()
.add(ShowErrorState(message: e.toString()));
}
}
Future<void> getCities() async {
try {
List<CityMunicipality> newCities = await LocationUtils.instance
.getCities(code: selectedProvince!.code.toString());
citymuns = newCities;
setState(() {
selectedMunicipality = newCities[0];
cityCall = false;
});
} catch (e) {
context
.read<VoluntaryWorkBloc>()
.add(ShowErrorState(message: e.toString()));
}
}
}

View File

@ -0,0 +1,754 @@
import 'package:date_time_picker/date_time_picker.dart';
import 'package:flutter/material.dart';
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:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/profile/voluntary_works/voluntary_work_bloc.dart';
import 'package:unit2/utils/global.dart';
import 'package:unit2/utils/global_context.dart';
import '../../../../model/location/barangay.dart';
import '../../../../model/location/city.dart';
import '../../../../model/location/country.dart';
import '../../../../model/location/provinces.dart';
import '../../../../model/location/region.dart';
import '../../../../model/profile/voluntary_works.dart';
import '../../../../model/utils/agency.dart';
import '../../../../model/utils/category.dart';
import '../../../../model/utils/position.dart';
import '../../../../theme-data.dart/box_shadow.dart';
import '../../../../theme-data.dart/btn-style.dart';
import '../../../../theme-data.dart/colors.dart';
import '../../../../theme-data.dart/form-style.dart';
import '../../../../utils/location_utilities.dart';
import '../../../../utils/text_container.dart';
import '../../shared/add_for_empty_search.dart';
class EditVoluntaryWorkScreen extends StatefulWidget {
final int profileId;
final String token;
const EditVoluntaryWorkScreen(
{super.key, required this.profileId, required this.token});
@override
State<EditVoluntaryWorkScreen> createState() =>
_EditVoluntaryWorkScreenState();
}
class _EditVoluntaryWorkScreenState extends State<EditVoluntaryWorkScreen> {
final formKey = GlobalKey<FormBuilderState>();
////controllers
final addPositionController = TextEditingController();
final addAgencyController = TextEditingController();
final toDateController = TextEditingController();
final fromDateController = TextEditingController();
final positionController = TextEditingController();
final agencyController = TextEditingController();
////focus nodes
final positionFocusNode = FocusNode();
final agencyFocusNode = FocusNode();
final agencyCategoryFocusNode = FocusNode();
////booleans
bool showAgency = false;
bool showIsPrivateRadio = false;
bool currentlyInvolved = false;
bool overseas = false;
bool provinceCall = false;
bool cityCall = false;
bool isPrivate = false;
////Lists
List<Province>? provinces;
List<CityMunicipality>? citymuns;
////Selected
Position? selectedPosition;
Agency? selectedAgency;
Category? selectedCategoty;
Region? selectedRegion;
Province? selectedProvince;
CityMunicipality? selectedMunicipality;
Country? selectedCountry;
@override
Widget build(BuildContext context) {
return BlocBuilder<VoluntaryWorkBloc, VoluntaryWorkState>(
buildWhen: (previous, current) {
return false;
},
builder: (context, state) {
if (state is EditVoluntaryWorks) {
////config
String? todate = state.work.toDate?.toString();
provinces = state.provinces;
citymuns = state.cities;
positionController.text = state.currentPosition.title!;
agencyController.text = state.currentAgency.name!;
fromDateController.text = state.work.fromDate.toString();
toDateController.text = todate ??= "";
currentlyInvolved = todate.isEmpty || todate == "null" ? true : false;
overseas = state.overseas;
selectedCountry = state.currentCountry;
selectedPosition = state.currentPosition;
selectedAgency = state.currentAgency;
selectedRegion = state.currentRegion;
selectedProvince = state.currentProvince;
selectedMunicipality = state.currentCity;
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 18),
child: FormBuilder(
key: formKey,
child: ListView(
children: [
////POSITIONS
StatefulBuilder(builder: (context, setState) {
return SearchField(
controller: positionController,
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.positions
.map((Position position) => SearchFieldListItem(
position.title!,
item: position,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: ListTile(
title: Text(position.title!),
))))
.toList(),
focusNode: positionFocusNode,
searchInputDecoration:
normalTextFieldStyle("Position *", "").copyWith(
suffixIcon: GestureDetector(
child: const Icon(Icons.arrow_drop_down),
onTap: () => positionFocusNode.unfocus(),
)),
onSuggestionTap: (position) {
setState(() {
selectedPosition = position.item;
positionFocusNode.unfocus();
});
},
////EMPTY WIDGET
emptyWidget: EmptyWidget(
title: "Add Position",
controller: addPositionController,
onpressed: () {
setState(() {
Position newAgencyPosition = Position(
id: null,
title: addPositionController.text
.toUpperCase());
state.positions.insert(0, newAgencyPosition);
addPositionController.text = "";
Navigator.pop(context);
});
}),
validator: (position) {
if (position!.isEmpty) {
return "This field is required";
}
return null;
},
);
}),
const SizedBox(
height: 12,
),
////AGENCY
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
SearchField(
controller: agencyController,
itemHeight: 70,
focusNode: agencyFocusNode,
suggestions: state.agencies
.map((Agency agency) =>
SearchFieldListItem(agency.name!,
item: agency,
child: ListTile(
title: Text(
agency.name!,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
agency.privateEntity == true
? "Private"
: agency.privateEntity ==
false
? "Government"
: ""),
)))
.toList(),
searchInputDecoration:
normalTextFieldStyle("Agency *", "")
.copyWith(
suffixIcon: GestureDetector(
child: const Icon(
Icons.arrow_drop_down,
),
onTap: () => agencyFocusNode.unfocus(),
)),
////SELETECTED
onSuggestionTap: (agency) {
setState(() {
selectedAgency = agency.item;
if (selectedAgency!.privateEntity == null) {
showAgency = true;
showIsPrivateRadio = true;
} else {
showAgency = false;
showIsPrivateRadio = false;
}
agencyFocusNode.unfocus();
});
},
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
emptyWidget: EmptyWidget(
controller: addAgencyController,
onpressed: () {
setState(() {
Agency newAgency = Agency(
id: null,
name: addAgencyController.text
.toUpperCase(),
category: null,
privateEntity: null);
state.agencies.insert(0, newAgency);
addAgencyController.text = "";
Navigator.pop(context);
});
},
title: "Add Agency")),
SizedBox(
height: showAgency ? 12 : 0,
),
////SHOW CATEGORY AGENCY
SizedBox(
child: showAgency
? SearchField(
focusNode: agencyCategoryFocusNode,
itemHeight: 70,
suggestions: state.agencyCategory
.map((Category category) =>
SearchFieldListItem(
category.name!,
item: category,
child: ListTile(
title: Text(category.name!),
subtitle: Text(category
.industryClass!.name!),
)))
.toList(),
emptyWidget: Container(
height: 100,
decoration: box1(),
child: const Center(
child: Text("No result found ...")),
),
onSuggestionTap: (agencyCategory) {
setState(() {
selectedCategoty =
agencyCategory.item;
agencyCategoryFocusNode.unfocus();
});
},
searchInputDecoration:
normalTextFieldStyle("Category *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
validator: (value) {
if (value!.isEmpty) {
return "This field is required";
}
return null;
},
)
: const SizedBox(),
),
SizedBox(
height: showIsPrivateRadio ? 12 : 0,
),
////PRVIATE SECTOR
SizedBox(
child: showIsPrivateRadio
? FormBuilderSwitch(
initialValue: false,
title: Text(isPrivate ? "YES" : "NO"),
decoration: normalTextFieldStyle(
"Private Entity?",
'Private Entity?'),
////onvhange private sector
onChanged: (value) {
setState(() {
isPrivate = value!;
agencyCategoryFocusNode.unfocus();
});
},
name: 'isPrivate',
validator:
FormBuilderValidators.required(),
)
: const SizedBox()),
const SizedBox(
height: 12,
),
//// total hours
FormBuilderTextField(
initialValue: state.work.totalHours.toString(),
validator: FormBuilderValidators.required(
errorText: "This Field is required"),
name: "total_hours",
keyboardType: TextInputType.number,
decoration:
normalTextFieldStyle("Total Hours*", "0"),
),
const SizedBox(
height: 12,
),
////Currently Involved
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderSwitch(
initialValue: currentlyInvolved,
activeColor: second,
onChanged: (value) {
setState(() {
currentlyInvolved = value!;
});
},
decoration: normalTextFieldStyle(
"Currently Involved?", 'Graduated?'),
name: 'currently_involved',
title:
Text(currentlyInvolved ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: screenWidth,
child: Row(
children: [
//// FROM DATE
Flexible(
flex: 1,
child: DateTimePicker(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
use24HourFormat: false,
icon:
const Icon(Icons.date_range),
controller: fromDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
timeHintText:
"Date of Examination/Conferment",
decoration: normalTextFieldStyle(
"From *", "From *")
.copyWith(
prefixIcon: const Icon(
Icons.date_range,
color: Colors.black87,
)),
initialValue: null,
)),
const SizedBox(
width: 12,
),
//// TO DATE
Flexible(
flex: 1,
child: currentlyInvolved
? TextFormField(
enabled: false,
initialValue: "PRESENT",
style: const TextStyle(
color: Colors.black45),
decoration:
normalTextFieldStyle(
"", "")
.copyWith(),
)
: DateTimePicker(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
controller: toDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
decoration: normalTextFieldStyle(
"To *", "To *")
.copyWith(
prefixIcon:
const Icon(
Icons.date_range,
color:
Colors.black87,
),
prefixText:
currentlyInvolved
? "PRESENT"
: ""),
initialValue: null,
),
),
],
),
),
],
);
}),
],
);
}),
const SizedBox(
height: 12,
),
//// OVERSEAS
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderSwitch(
initialValue: overseas,
activeColor: second,
onChanged: (value) {
setState(() {
overseas = value!;
});
},
decoration:
normalTextFieldStyle("Overseas Address?", ''),
name: 'overseas',
title: Text(overseas ? "YES" : "NO"),
),
SizedBox(
height: overseas == true ? 8 : 0,
),
SizedBox(
child: overseas == false
? Column(
children: [
const SizedBox(
height: 12,
),
////REGION DROPDOWN
DropdownButtonFormField<Region?>(
isExpanded: true,
autovalidateMode: AutovalidateMode
.onUserInteraction,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
onChanged: (Region? region) async {
if (selectedRegion != region) {
setState(() {
provinceCall = true;
});
selectedRegion = region;
try {
provinces = await LocationUtils
.instance
.getProvinces(
regionCode:
selectedRegion!.code
.toString());
selectedProvince =
provinces![0];
setState(() {
provinceCall = false;
cityCall = true;
});
try {
citymuns = await LocationUtils
.instance
.getCities(
code:
selectedProvince!
.code
.toString());
selectedMunicipality =
citymuns![0];
setState(() {
cityCall = false;
});
} catch (e) {
NavigationService.navigatorKey
.currentContext
?.read<
VoluntaryWorkBloc>()
.add(ShowErrorState(
message:
e.toString()));
}
} catch (e) {
context
.read<VoluntaryWorkBloc>()
.add(ShowErrorState(
message: e.toString()));
}
}
},
value: selectedRegion,
decoration: normalTextFieldStyle(
"Region*", "Region"),
items: state.regions
.map<DropdownMenuItem<Region>>(
(Region region) {
return DropdownMenuItem<Region>(
value: region,
child:
Text(region.description!));
}).toList(),
),
const SizedBox(
height: 8,
),
//// PROVINCE DROPDOWN
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.transparent,
inAsyncCall: provinceCall,
child: DropdownButtonFormField<
Province?>(
autovalidateMode:
AutovalidateMode
.onUserInteraction,
validator: (value) =>
value == null
? 'required'
: null,
isExpanded: true,
value: selectedProvince,
onChanged:
(Province? province) async {
if (selectedProvince !=
province) {
setState(() {
cityCall = true;
});
selectedProvince = province;
try {
citymuns = await LocationUtils
.instance
.getCities(
code: selectedProvince!
.code
.toString());
selectedMunicipality =
citymuns![0];
setState(() {
cityCall = false;
});
} catch (e) {
context
.read<
VoluntaryWorkBloc>()
.add(ShowErrorState(
message: e
.toString()));
}
}
},
items: provinces == null
? []
: provinces!.map<
DropdownMenuItem<
Province>>(
(Province province) {
return DropdownMenuItem(
value: province,
child: FittedBox(
child: Text(province
.description!),
));
}).toList(),
decoration:
normalTextFieldStyle(
"Province*",
"Province")),
),
),
////CITY MUNICIPALITY
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: cityCall,
child: DropdownButtonFormField<
CityMunicipality>(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
isExpanded: true,
onChanged:
(CityMunicipality? city) {
if (selectedMunicipality !=
city) {
selectedMunicipality = city;
}
},
decoration: normalTextFieldStyle(
"Municipality*",
"Municipality"),
value: selectedMunicipality,
items: citymuns == null
? []
: citymuns!.map<
DropdownMenuItem<
CityMunicipality>>(
(CityMunicipality c) {
return DropdownMenuItem(
value: c,
child: Text(
c.description!));
}).toList(),
),
),
),
],
)
//// COUNTRY DROPDOWN
: SizedBox(
height: 60,
child: DropdownButtonFormField<Country>(
isExpanded: true,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
items: state.countries
.map<DropdownMenuItem<Country>>(
(Country country) {
return DropdownMenuItem<Country>(
value: country,
child: FittedBox(
child: Text(country.name!)));
}).toList(),
value: selectedCountry,
decoration: normalTextFieldStyle(
"Country*", "Country"),
onChanged: (Country? value) {
selectedCountry = value;
},
),
),
),
],
);
}),
Expanded(
child: SizedBox(
height: blockSizeVertical * 8,
)),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
if (formKey.currentState!.saveAndValidate()) {
Address address;
//// if not overseas
if (!overseas) {
address = Address(
barangay: null,
id: state.work.address?.id,
addressCategory:
state.work.address?.addressCategory,
addressClass:
state.work.address?.addressClass ,
cityMunicipality: selectedMunicipality,
country: selectedCountry);
} else {
////if overseas
address = Address(
barangay: null,
id: state.work.address?.id,
addressCategory:
state.work.address?.addressCategory,
addressClass:
state.work.address?.addressClass,
cityMunicipality: null,
country: selectedCountry);
}
if (selectedCategoty != null) {
selectedAgency = Agency(
id: selectedAgency?.id,
name: selectedAgency!.name,
category: selectedCategoty,
privateEntity: isPrivate);
}
VoluntaryWork work = VoluntaryWork(
////address
address: address,
//// agency
agency: selectedAgency,
////
position: selectedPosition,
////total hours
totalHours: double.parse(formKey
.currentState!.value["total_hours"]),
////to date
toDate: toDateController.text.isEmpty ||
toDateController.text.toUpperCase() ==
"PRESENT"
? null
: DateTime.parse(toDateController.text),
////from date
fromDate:
DateTime.parse(fromDateController.text),
);
final progress = ProgressHUD.of(context);
progress!.showWithText("Loading...");
context.read<VoluntaryWorkBloc>().add(
UpdateVolunataryWork(
oldAgencyId: state.work.agency!.id!,
oldFromDate:
state.work.fromDate.toString(),
oldPosId: state.work.position!.id!,
profileId: widget.profileId,
token: widget.token,
work: work));
}
},
child: const Text(submit)),
)
],
)),
),
);
}
return const Placeholder();
},
);
}
}

View File

@ -1,18 +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:intl/intl.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/screens/profile/components/work_history/voluntary_works/add_modal.dart';
import 'package:unit2/screens/profile/components/voluntary_works/add_modal.dart';
import 'package:unit2/screens/profile/components/voluntary_works/edit_modal.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/text_container.dart';
import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/empty_data.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../bloc/profile/voluntary_works/voluntary_work_bloc.dart';
import '../../../utils/alerts.dart';
class VolunataryWorkScreen extends StatelessWidget {
const VolunataryWorkScreen({super.key});
@ -26,9 +31,11 @@ class VolunataryWorkScreen extends StatelessWidget {
appBar: AppBar(
title: const Text(voluntaryScreenTitle),
backgroundColor: primary,
actions: [AddLeading(onPressed: () {
actions: [
AddLeading(onPressed: () {
context.read<VoluntaryWorkBloc>().add(ShowAddVoluntaryWorks());
})],
})
],
),
body: ProgressHUD(
padding: const EdgeInsets.all(24),
@ -38,8 +45,7 @@ class VolunataryWorkScreen extends StatelessWidget {
builder: (context, state) {
if (state is UserLoggedIn) {
token = state.userData!.user!.login!.token;
profileId =
state.userData!.user!.login!.user!.profileId;
profileId = state.userData!.user!.login!.user!.profileId;
return BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
if (state is ProfileLoaded) {
@ -51,10 +57,78 @@ class VolunataryWorkScreen extends StatelessWidget {
progress!.showWithText("Please wait...");
}
if (state is VoluntaryWorkLoadedState ||
state is VoluntaryWorkErrorState|| state is AddVoluntaryWorkState) {
state is VoluntaryWorkErrorState ||
state is AddVoluntaryWorkState ||
state is VoluntaryWorkAddedState ||
state is VoluntaryWorkDeletedState ||
state is EditVoluntaryWorks) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
//// Added State
if (state is VoluntaryWorkAddedState) {
if (state.response['success']) {
successAlert(context, "Adding Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<VoluntaryWorkBloc>()
.add(LoadVoluntaryWorks());
});
} else {
errorAlert(context, "Adding Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<VoluntaryWorkBloc>()
.add(LoadVoluntaryWorks());
});
}
}
//// Updated State
if (state is VoluntaryWorkEditedState) {
if (state.response['success']) {
successAlert(context, "Updated Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<VoluntaryWorkBloc>()
.add(LoadVoluntaryWorks());
});
} else {
errorAlert(context, "Update Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<VoluntaryWorkBloc>()
.add(LoadVoluntaryWorks());
});
}
}
////Deleted State
if (state is VoluntaryWorkDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull!",
"Deleted Successfully", () {
Navigator.of(context).pop();
context
.read<VoluntaryWorkBloc>()
.add(LoadVoluntaryWorks());
});
} else {
errorAlert(context, "Deletion Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<VoluntaryWorkBloc>()
.add(LoadVoluntaryWorks());
});
}
}
},
builder: (context, state) {
if (state is VoluntaryWorkLoadedState) {
@ -128,10 +202,84 @@ class VolunataryWorkScreen extends StatelessWidget {
"$numberOfHours : $hours hours"),
]),
),
IconButton(
onPressed: () {},
AppPopupMenu<int>(
offset: const Offset(-10, -10),
elevation: 3,
onSelected: (value) {
////delete eligibilty-= = = = = = = = =>>
if (value == 2) {
confirmAlert(context, () {
final progress =
ProgressHUD.of(
context);
progress!.showWithText(
"Loading...");
BlocProvider.of<
VoluntaryWorkBloc>(
context)
.add(DeleteVoluntaryWork(
work: state
.voluntaryWorks[
index],
profileId:
profileId!,
token: token!));
}, "Delete?",
"Confirm Delete?");
}
if (value == 1) {
bool isOverseas;
////edit voluntary work-= = = = = = = = =>>
final progress =
ProgressHUD.of(context);
progress!.showWithText(
"Loading...");
if (state
.voluntaryWorks[
index]
.address?.cityMunicipality == null
) {
isOverseas = true;
}else{
isOverseas = false;
}
context
.read<
VoluntaryWorkBloc>()
.add(ShowEditVoluntaryWorks(
profileId:
profileId!,
token: token!,
work: state
.voluntaryWorks[
index],
isOverseas:
isOverseas));
}
},
menuItems: [
popMenuItem(
text: "Edit",
value: 1,
icon: Icons.edit),
popMenuItem(
text: "Delete",
value: 2,
icon: Icons.delete),
popMenuItem(
text: "Attachment",
value: 3,
icon: FontAwesome.attach)
],
icon: const Icon(
Icons.more_vert))
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
)
],
),
),
@ -146,8 +294,22 @@ class VolunataryWorkScreen extends StatelessWidget {
message:
"You don't have any Voluntary Works added. Please click + to add.");
}
}if(state is AddVoluntaryWorkState){
return AddVoluntaryWorkScreen(profileId: profileId!,token: token!,);
}
if (state is AddVoluntaryWorkState) {
return AddVoluntaryWorkScreen(
profileId: profileId!,
token: token!,
);
}
if (state is VoluntaryWorkErrorState) {
return SomethingWentWrong(
message: state.toString(), onpressed: () {});
}
if (state is EditVoluntaryWorks) {
return EditVoluntaryWorkScreen(
profileId: profileId!,
token: token!,
);
}
return Container();
},
@ -162,4 +324,23 @@ class VolunataryWorkScreen extends StatelessWidget {
)),
);
}
PopupMenuItem<int> popMenuItem({String? text, int? value, IconData? icon}) {
return PopupMenuItem(
value: value,
child: Row(
children: [
Icon(
icon,
),
const SizedBox(
width: 10,
),
Text(
text!,
),
],
),
);
}
}

View File

@ -1,597 +0,0 @@
import 'package:date_time_picker/date_time_picker.dart';
import 'package:flutter/material.dart';
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:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/profile/voluntary_works/voluntary_work_bloc.dart';
import 'package:unit2/utils/global.dart';
import '../../../../../model/location/barangay.dart';
import '../../../../../model/location/city.dart';
import '../../../../../model/location/country.dart';
import '../../../../../model/location/provinces.dart';
import '../../../../../model/location/region.dart';
import '../../../../../model/utils/agency.dart';
import '../../../../../model/utils/category.dart';
import '../../../../../model/utils/position.dart';
import '../../../../../theme-data.dart/box_shadow.dart';
import '../../../../../theme-data.dart/colors.dart';
import '../../../../../theme-data.dart/form-style.dart';
import '../../../../../utils/location_utilities.dart';
import '../../../shared/add_for_empty_search.dart';
class AddVoluntaryWorkScreen extends StatefulWidget {
final int profileId;
final String token;
const AddVoluntaryWorkScreen(
{super.key, required this.profileId, required this.token});
@override
State<AddVoluntaryWorkScreen> createState() => _AddVoluntaryWorkScreenState();
}
class _AddVoluntaryWorkScreenState extends State<AddVoluntaryWorkScreen> {
final formKey = GlobalKey<FormBuilderState>();
////controllers
final addPositionController = TextEditingController();
final addAgencyController = TextEditingController();
final toDateController = TextEditingController();
final fromDateController = TextEditingController();
////focus nodes
final positionFocusNode = FocusNode();
final agencyFocusNode = FocusNode();
final agencyCategoryFocusNode = FocusNode();
////booleans
bool showAgency = false;
bool showIsPrivateRadio = false;
bool currentlyInvolved = false;
bool overseas = false;
bool provinceCall = false;
bool cityCall = false;
////Lists
List<Province>? provinces;
List<CityMunicipality>? citymuns;
////Selected
Region? selectedRegion;
Province? selectedProvince;
CityMunicipality? selectedMunicipality;
@override
Widget build(BuildContext context) {
return BlocBuilder<VoluntaryWorkBloc, VoluntaryWorkState>(
builder: (context, state) {
if (state is AddVoluntaryWorkState) {
return SingleChildScrollView(
child: SizedBox(
height: screenHeight * .90,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 25, horizontal: 18),
child: FormBuilder(
child: Column(
children: [
////POSITIONS
StatefulBuilder(builder: (context, setState) {
return SearchField(
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.positions
.map((Position position) => SearchFieldListItem(
position.title!,
item: position,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: ListTile(
title: Text(position.title!),
))))
.toList(),
focusNode: positionFocusNode,
searchInputDecoration:
normalTextFieldStyle("Position *", "").copyWith(
suffixIcon:
const Icon(Icons.arrow_drop_down)),
onSuggestionTap: (position) {
setState(() {
positionFocusNode.unfocus();
});
},
////EMPTY WIDGET
emptyWidget: EmptyWidget(
title: "Add Position",
controller: addPositionController,
onpressed: () {
setState(() {
Navigator.pop(context);
});
}),
validator: (position) {
if (position!.isEmpty) {
return "This field is required";
}
return null;
},
);
}),
const SizedBox(
height: 12,
),
////AGENCY
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
SearchField(
itemHeight: 70,
focusNode: agencyFocusNode,
suggestions: state.agencies
.map((Agency agency) =>
SearchFieldListItem(agency.name!,
item: agency,
child: ListTile(
title: Text(
agency.name!,
overflow:
TextOverflow.ellipsis,
),
subtitle: Text(agency
.privateEntity ==
true
? "Private"
: agency.privateEntity ==
false
? "Government"
: ""),
)))
.toList(),
searchInputDecoration:
normalTextFieldStyle("Agency *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
onSuggestionTap: (agency) {
setState(() {
agencyFocusNode.unfocus();
});
},
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
emptyWidget: EmptyWidget(
controller: addAgencyController,
onpressed: () {
setState(() {
Navigator.pop(context);
});
},
title: "Add Agency")),
SizedBox(
height: showAgency ? 12 : 0,
),
////SHOW CATEGORY AGENCY
SizedBox(
child: showAgency
? SearchField(
focusNode: agencyCategoryFocusNode,
itemHeight: 70,
suggestions: state.agencyCategory
.map((Category category) =>
SearchFieldListItem(
category.name!,
item: category,
child: ListTile(
title:
Text(category.name!),
subtitle: Text(category
.industryClass!
.name!),
)))
.toList(),
emptyWidget: Container(
height: 100,
decoration: box1(),
child: const Center(
child:
Text("No result found ...")),
),
onSuggestionTap: (agencyCategory) {
setState(() {});
},
searchInputDecoration:
normalTextFieldStyle(
"Category *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
validator: (value) {
if (value!.isEmpty) {
return "This field is required";
}
return null;
},
)
: const SizedBox(),
),
////PRVIATE SECTOR
SizedBox(
child: showIsPrivateRadio
? FormBuilderRadioGroup(
decoration: InputDecoration(
border: InputBorder.none,
label: Row(
children: [
Text(
"Is this private sector? ",
style: Theme.of(context)
.textTheme
.headlineSmall!
.copyWith(fontSize: 24),
),
const Icon(
FontAwesome.help_circled)
],
),
),
////onvhange private sector
onChanged: (value) {
setState(() {
agencyCategoryFocusNode.unfocus();
});
},
name: 'isPrivate',
validator:
FormBuilderValidators.required(),
options: ["YES", "NO"]
.map((lang) =>
FormBuilderFieldOption(
value: lang))
.toList(growable: false),
)
: const SizedBox()),
const SizedBox(
height: 12,
),
FormBuilderTextField(
name: "total_hours",
keyboardType: TextInputType.number,
decoration:
normalTextFieldStyle("Total Hours*", "0"),
),
const SizedBox(
height: 12,
),
////Currently Involved
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderSwitch(
initialValue: currentlyInvolved,
activeColor: second,
onChanged: (value) {
setState(() {
currentlyInvolved = value!;
});
},
decoration: normalTextFieldStyle(
"Currently Involved?", 'Graduated?'),
name: 'currently_involved',
title: Text(
currentlyInvolved ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: screenWidth,
child: Row(
children: [
//// FROM DATE
Flexible(
flex: 1,
child: DateTimePicker(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
use24HourFormat: false,
icon: const Icon(
Icons.date_range),
controller: fromDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
timeHintText:
"Date of Examination/Conferment",
decoration:
normalTextFieldStyle(
"From *", "From *")
.copyWith(
prefixIcon:
const Icon(
Icons.date_range,
color: Colors.black87,
)),
initialValue: null,
)),
const SizedBox(
width: 12,
),
//// TO DATE
Flexible(
flex: 1,
child: currentlyInvolved
? TextFormField(
enabled: false,
initialValue: "PRESENT",
style: const TextStyle(
color: Colors.black45),
decoration:
normalTextFieldStyle(
"", "")
.copyWith(),
)
: DateTimePicker(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
controller:
toDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
decoration: normalTextFieldStyle(
"To *", "To *")
.copyWith(
prefixIcon:
const Icon(
Icons.date_range,
color: Colors
.black87,
),
prefixText:
currentlyInvolved
? "PRESENT"
: ""),
initialValue: null,
),
),
],
),
),
],
);
}),
],
);
}),
const SizedBox(height: 12,),
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderSwitch(
initialValue: overseas,
activeColor: second,
onChanged: (value) {
setState(() {
overseas = value!;
});
},
decoration: normalTextFieldStyle(
"Overseas Address?", ''),
name: 'overseas',
title: Text(overseas ? "YES" : "NO"),
),
SizedBox(
height: overseas == true ? 8 : 0,
),
SizedBox(
child: overseas == false
? Column(
children: [
const SizedBox(
height: 12,
),
////REGION DROPDOWN
FormBuilderDropdown<Region?>(
autovalidateMode: AutovalidateMode
.onUserInteraction,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
onChanged: (Region? region) async {
if (selectedRegion != region) {
setState(() {
provinceCall = true;
});
selectedRegion = region;
getProvinces();
}
},
initialValue: null,
decoration: normalTextFieldStyle(
"Region*", "Region"),
name: 'region',
items: state.regions
.map<DropdownMenuItem<Region>>(
(Region region) {
return DropdownMenuItem<Region>(
value: region,
child: Text(
region.description!));
}).toList(),
),
const SizedBox(
height: 8,
),
//// PROVINCE DROPDOWN
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.transparent,
inAsyncCall: provinceCall,
child: DropdownButtonFormField<
Province?>(
autovalidateMode:
AutovalidateMode
.onUserInteraction,
validator: (value) =>
value == null
? 'required'
: null,
isExpanded: true,
value: selectedProvince,
onChanged:
(Province? province) {
if (selectedProvince !=
province) {
setState(() {
cityCall = true;
});
selectedProvince =
province;
getCities();
}
},
items: provinces == null
? []
: provinces!.map<
DropdownMenuItem<
Province>>(
(Province province) {
return DropdownMenuItem(
value: province,
child: FittedBox(
child: Text(province
.description!),
));
}).toList(),
decoration:
normalTextFieldStyle(
"Province*",
"Province")),
),
),
////CITY MUNICIPALITY
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: cityCall,
child: DropdownButtonFormField<
CityMunicipality>(
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
isExpanded: true,
onChanged:
(CityMunicipality? city) {
if (selectedMunicipality !=
city) {
selectedMunicipality = city;
}
},
decoration:
normalTextFieldStyle(
"Municipality*",
"Municipality"),
value: selectedMunicipality,
items: citymuns == null
? []
: citymuns!.map<
DropdownMenuItem<
CityMunicipality>>(
(CityMunicipality c) {
return DropdownMenuItem(
value: c,
child: Text(c
.description!));
}).toList(),
),
),
),
],
)
//// COUNTRY DROPDOWN
: SizedBox(
height: 60,
child: FormBuilderDropdown<Country>(
initialValue: null,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
items: state.countries
.map<DropdownMenuItem<Country>>(
(Country country) {
return DropdownMenuItem<Country>(
value: country,
child: FittedBox(
child:
Text(country.name!)));
}).toList(),
name: 'country',
decoration: normalTextFieldStyle(
"Country*", "Country"),
onChanged: (Country? value) {},
),
),
),
],
);
}),
],
)),
),
)),
);
}
return const Placeholder();
},
);
}
Future<void> getProvinces() async {
try {
List<Province> newProvinces = await LocationUtils.instance
.getProvinces(regionCode: selectedRegion!.code.toString());
setState(() {
provinces = newProvinces;
selectedProvince = provinces![0];
provinceCall = false;
cityCall = true;
getCities();
});
} catch (e) {
context.read<VoluntaryWorkBloc>().add(ShowErrorState(message: e.toString()));
}
}
Future<void> getCities() async {
try {
List<CityMunicipality> newCities = await LocationUtils.instance
.getCities(code: selectedProvince!.code.toString());
citymuns = newCities;
setState(() {
selectedMunicipality = newCities[0];
cityCall = false;
});
} catch (e) {
context.read<VoluntaryWorkBloc>().add(ShowErrorState(message: e.toString()));
}
}
}

View File

@ -1,4 +1,3 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
@ -10,7 +9,8 @@ class VoluntaryService{
static final VoluntaryService _instance = VoluntaryService();
static VoluntaryService get instance => _instance;
Future< List<VoluntaryWork>> getVoluntaryWorks(int profileId, String token)async{
Future<List<VoluntaryWork>> getVoluntaryWorks(
int profileId, String token) async {
List<VoluntaryWork> voluntaryWorks = [];
String authToken = "Token $token";
String path = "${Url.instance.getVoluntaryWorks()}$profileId/";
@ -19,8 +19,9 @@ class VoluntaryService{
'Authorization': authToken
};
try{
http.Response response = await Request.instance.getRequest(path: path,param: {},headers: headers);
// try {
http.Response response = await Request.instance
.getRequest(path: path, param: {}, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
if (data['data'] != null) {
@ -30,10 +31,130 @@ class VoluntaryService{
});
}
}
}catch(e){
throw(e.toString());
}
// } catch (e) {
// throw (e.toString());
// }
return voluntaryWorks;
}
Future<Map<dynamic, dynamic>> add(
{required VoluntaryWork voluntaryWork,
required int profileId,
required String token}) async {
Map<dynamic, dynamic>? responseData = {};
String authToken = "Token $token";
String path = "${Url.instance.getVoluntaryWorks()}$profileId/";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authToken
};
Map body = {
"position_id": voluntaryWork.position?.id,
"agency_id": voluntaryWork.agency?.id,
"address_id": voluntaryWork.address?.id,
"from_date": voluntaryWork.fromDate.toString(),
"to_date": voluntaryWork.toDate == null?null:voluntaryWork.toDate.toString(),
"total_hours": voluntaryWork.totalHours,
"_positionName": voluntaryWork.position!.title,
"_agencyName": voluntaryWork.agency!.name,
"_agencyCatId": voluntaryWork.agency!.category!.id,
"_privateEntity": voluntaryWork.agency!.privateEntity,
"_citymunCode": voluntaryWork.address?.cityMunicipality?.code,
"_countryId": voluntaryWork.address?.country?.id
};
try {
http.Response response = await Request.instance
.postRequest(param: {}, path: path, body: body, headers: headers);
if (response.statusCode == 201) {
Map data = jsonDecode(response.body);
responseData = data;
} else {
responseData.addAll({'success': false});
}
} catch (e) {
throw e.toString();
}
return responseData;
}
////update
Future<Map<dynamic, dynamic>> update(
{required VoluntaryWork voluntaryWork,
required int profileId,
required String token,
required int oldPosId,
required int oldAgencyId,
required String oldFromDate}) async {
Map<dynamic, dynamic>? responseData = {};
String authToken = "Token $token";
String path = "${Url.instance.getVoluntaryWorks()}$profileId/";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authToken
};
Map body = {
"position_id": voluntaryWork.position?.id,
"agency_id": voluntaryWork.agency?.id,
"address_id": voluntaryWork.address!.id,
"from_date": voluntaryWork.fromDate.toString(),
"to_date": voluntaryWork.toDate == null?null:voluntaryWork.toDate.toString(),
"total_hours": voluntaryWork.totalHours,
"_positionName": voluntaryWork.position!.title,
"_agencyName": voluntaryWork.agency!.name,
"_agencyCatId": voluntaryWork.agency!.category!.id,
"_privateEntity": voluntaryWork.agency!.privateEntity,
"_citymunCode": voluntaryWork.address?.cityMunicipality?.code,
"_countryId": voluntaryWork.address!.country!.id,
"_oldPosId": oldPosId,
"_oldAgencyId": oldAgencyId,
"_oldFromDate": oldFromDate
};
try {
http.Response response = await Request.instance
.putRequest(param: {}, path: path, body: body, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
responseData = data;
} else {
responseData.addAll({'success': false});
}
} catch (e) {
throw e.toString();
}
return responseData;
}
////delete
Future<bool> delete(
{required int agencyId,
required int positionId,
required String fromDate,
required String token,
required int profileId}) async {
bool success = false;
String authToken = "Token $token";
String path = "${Url.instance.getVoluntaryWorks()}$profileId/";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authToken
};
Map<String, dynamic> params = {"force_mode": "true"};
Map body = {
"agency_id": agencyId,
"position_id": positionId,
"from_date": fromDate,
};
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'];
}
} catch (e) {
throw (e.toString());
}
return success;
}
}

View File

@ -6,8 +6,8 @@ class Url {
// return '192.168.10.183:3000';
// return 'agusandelnorte.gov.ph';
// return "192.168.10.219:3000";
// return "devweb.agusandelnorte.gov.ph";
return 'devapi.agusandelnorte.gov.ph:3004';
return "devweb.agusandelnorte.gov.ph";
// return 'devapi.agusandelnorte.gov.ph:3004';
}
String authentication() {

View File

@ -77,7 +77,8 @@ dependencies:
hive_flutter: ^1.1.0
mask_text_input_formatter: ^2.4.0
location: ^4.3.0
platform_device_id: ^1.0.1,
platform_device_id: ^1.0.1
multi_dropdown: ^1.0.9
dev_dependencies:
flutter_test: