From 66adcf924fc1d30949ac668f8e7e2d1520fd9df4 Mon Sep 17 00:00:00 2001 From: PGAN-MIS Date: Mon, 27 Feb 2023 14:26:27 +0800 Subject: [PATCH] add eligibility implemented --- ios/Podfile.lock | 6 + lib/bloc/profile/profile_bloc.dart | 99 +++--- lib/bloc/profile/profile_event.dart | 47 +-- lib/bloc/profile/profile_state.dart | 9 + lib/main.dart | 3 + lib/model/location/city.dart | 6 +- lib/model/location/country.dart | 6 + lib/model/location/provinces.dart | 5 + lib/model/location/region.dart | 5 + lib/model/profile/eligibility.dart | 124 ++++--- lib/model/utils/eligibility.dart | 5 + .../components/eligibility/add_modal.dart | 252 ++++++++++----- .../components/eligibility_screen.dart | 304 ++++++++++-------- lib/sevices/profile/eligibility_services.dart | 74 ++++- lib/theme-data.dart/form-style.dart | 2 + lib/utils/alerts.dart | 7 +- lib/utils/urls.dart | 8 +- 17 files changed, 599 insertions(+), 363 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8fa5b72..e6a0ac0 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -12,6 +12,8 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) + - modal_progress_hud_nsn (0.0.1): + - Flutter - MTBBarcodeScanner (5.0.11) - package_info_plus (0.4.5): - Flutter @@ -34,6 +36,7 @@ DEPENDENCIES: - easy_app_installer (from `.symlinks/plugins/easy_app_installer/ios`) - Flutter (from `Flutter`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + - modal_progress_hud_nsn (from `.symlinks/plugins/modal_progress_hud_nsn/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) @@ -56,6 +59,8 @@ EXTERNAL SOURCES: :path: Flutter fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" + modal_progress_hud_nsn: + :path: ".symlinks/plugins/modal_progress_hud_nsn/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -73,6 +78,7 @@ SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 diff --git a/lib/bloc/profile/profile_bloc.dart b/lib/bloc/profile/profile_bloc.dart index b7aace6..5db9328 100644 --- a/lib/bloc/profile/profile_bloc.dart +++ b/lib/bloc/profile/profile_bloc.dart @@ -1,39 +1,34 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:unit2/model/profile/basic_info.dart'; -import 'package:unit2/model/profile/basic_information/primary-information.dart'; import 'package:unit2/model/profile/eligibility.dart'; import 'package:unit2/model/profile/profileInfomation.dart'; import 'package:unit2/model/utils/eligibility.dart'; import 'package:unit2/sevices/profile/eligibility_services.dart'; import 'package:unit2/sevices/profile/profile_service.dart'; -import 'package:unit2/test_data.dart'; import 'package:unit2/utils/location_utilities.dart'; import 'package:unit2/utils/profile_utilities.dart'; import '../../model/location/country.dart'; import '../../model/location/region.dart'; import '../../model/location/provinces.dart'; import '../../model/location/city.dart'; -import '../../model/location/barangay.dart'; part 'profile_event.dart'; part 'profile_state.dart'; class ProfileBloc extends Bloc { ProfileBloc() : super(ProfileInitial()) { - ProfileInformation? _profileInformation; - List? _countries; - List? _regions; - List? _eligibilities; - List? _provinces; - List? _cities; + ProfileInformation? globalProfileInformation; + List? globalCountries; + List? globalRegions; + List? globalEligibilities; + List? eligibilities; ////========================================================================= on((event, emit) async { // try { emit(ProfileLoading()); ProfileInformation? profileInformation = await ProfileService.instance.getProfile(event.token, event.userID); - _profileInformation = profileInformation; - emit(ProfileLoaded(profileInformation: _profileInformation!)); + globalProfileInformation = profileInformation; + emit(ProfileLoaded(profileInformation: globalProfileInformation!)); // } catch (e) { // emit(ProfileErrorState(mesage: e.toString())); // } @@ -41,46 +36,34 @@ class ProfileBloc extends Bloc { ////===================================================================== on((event, emit) { emit(ProfileLoading()); + eligibilities = event.eligibilities; emit(EligibilityLoaded(eligibilities: event.eligibilities)); }); ////==================================================================== on((event, emit) async { - Region? currentRegion; - Province? currentProvince; - CityMunicipality? currentCity; // try{ emit(ProfileLoading()); - if (_countries == null) { + if (globalCountries == null) { List countries = await LocationUtils.instance.getCountries(); - _countries = countries; + globalCountries = countries; } - if (_regions == null) { + if (globalRegions == null) { List regions = await LocationUtils.instance.getRegions(); - _regions = regions; + globalRegions = regions; } - if (_eligibilities == null) { + if (globalEligibilities == null) { List eligibilities = await ProfileUtilities.instance.getEligibilities(); - _eligibilities = eligibilities; + globalEligibilities = eligibilities; } - -// get current country - Country? currentCountry = _countries!.firstWhere((Country country) => - country.code == event.eligibityCert.examAddress?.country!.code); -// get current eligibility - Eligibility currentEligibility = _eligibilities!.firstWhere( - (Eligibility eligibility) => - event.eligibityCert.eligibility!.id == eligibility.id); - bool? isOverseas = event.eligibityCert.overseas; - emit(EditEligibilityState( isOverseas: isOverseas!, eligibityCert: event.eligibityCert, - countries: _countries!, - regions: _regions!, - eligibilities: _eligibilities!)); + countries: globalCountries!, + regions: globalRegions!, + eligibilities: globalEligibilities!)); // }catch(e){ // emit(ProfileErrorState(mesage: e.toString())); @@ -88,29 +71,26 @@ class ProfileBloc extends Bloc { ////==================================================================== }); - on((event, emit) async { - List? cities; - List? provinces; - Eligibility? currentEligibility; + on((event, emit) async { emit(ProfileLoading()); - if (_regions == null) { + if (globalRegions == null) { List regions = await LocationUtils.instance.getRegions(); - _regions = regions; + globalRegions = regions; } - if (_eligibilities == null) { + if (globalEligibilities == null) { List eligibilities = await ProfileUtilities.instance.getEligibilities(); - _eligibilities = eligibilities; + globalEligibilities = eligibilities; } - if (_countries == null) { + if (globalCountries == null) { List countries = await LocationUtils.instance.getCountries(); - _countries = countries; + globalCountries = countries; } - + emit(AddEligibilityState( - eligibilities: _eligibilities!, - regions: _regions!, - countries: _countries!)); + eligibilities: globalEligibilities!, + regions: globalRegions!, + countries: globalCountries!)); }); ////==================================================================== on((event, emit) async { @@ -133,5 +113,28 @@ class ProfileBloc extends Bloc { emit(ProfileErrorState(mesage: e.toString())); } }); + on( + (event, emit) async { + try { + emit(ProfileLoading()); + Map status = await EligibilityService.instance.add( + eligibityCert: event.eligibityCert, + token: event.token, + profileId: int.parse(event.profileId)); + if (status['success']) { + EligibityCert? eligibityCert = + EligibityCert.fromJson(status['data']); + eligibilities!.add(eligibityCert); + emit(EligibilityAddedState( + eligibilities: eligibilities!, response: status)); + } else { + emit(EligibilityAddedState( + eligibilities: eligibilities!, response: status)); + } + } catch (e) { + emit(ProfileErrorState(mesage: e.toString())); + } + }, + ); } } diff --git a/lib/bloc/profile/profile_event.dart b/lib/bloc/profile/profile_event.dart index 11bd0d3..7d1b96e 100644 --- a/lib/bloc/profile/profile_event.dart +++ b/lib/bloc/profile/profile_event.dart @@ -7,46 +7,55 @@ abstract class ProfileEvent extends Equatable { List get props => []; } -class LoadProfile extends ProfileEvent{ -final String token; -final int userID; -const LoadProfile({required this.token, required this.userID}); - @override - List get props => [token,userID]; - +class LoadProfile extends ProfileEvent { + final String token; + final int userID; + const LoadProfile({required this.token, required this.userID}); + @override + List get props => [token, userID]; } -class LoadProfileInformation extends ProfileEvent{ +class LoadProfileInformation extends ProfileEvent { @override List get props => []; } -class LoadEligibility extends ProfileEvent{ +class LoadEligibility extends ProfileEvent { final List eligibilities; const LoadEligibility({required this.eligibilities}); - @override + @override List get props => []; } -class EditEligibility extends ProfileEvent{ +class EditEligibility extends ProfileEvent { final EligibityCert eligibityCert; const EditEligibility({required this.eligibityCert}); - @override + @override List get props => []; } -class DeleteEligibility extends ProfileEvent{ +class DeleteEligibility extends ProfileEvent { final List eligibilities; final String profileId; final int eligibilityId; final String token; -const DeleteEligibility({ required this.eligibilities, required this.eligibilityId, required this.profileId, required this.token}); - @override - List get props => [eligibilities,profileId,eligibilityId,token]; + const DeleteEligibility( + {required this.eligibilities, + required this.eligibilityId, + required this.profileId, + required this.token}); + @override + List get props => [eligibilities, profileId, eligibilityId, token]; } +class ShowAddEligibilityForm extends ProfileEvent { + +} class AddEligibility extends ProfileEvent{ - + final EligibityCert eligibityCert; + final String profileId; + final String token; + const AddEligibility({required this.eligibityCert, required this.profileId, required this.token}); + @override + List get props => [eligibityCert, profileId, token]; } - - diff --git a/lib/bloc/profile/profile_state.dart b/lib/bloc/profile/profile_state.dart index 52a2eb5..d84f750 100644 --- a/lib/bloc/profile/profile_state.dart +++ b/lib/bloc/profile/profile_state.dart @@ -69,3 +69,12 @@ class AddEligibilityState extends ProfileState { @override List get props => [eligibilities,countries,regions]; } + +class EligibilityAddedState extends ProfileState{ + final List eligibilities; + final Map response; + + const EligibilityAddedState({required this.eligibilities, required this.response}); + @override + List get props =>[eligibilities,response]; +} diff --git a/lib/main.dart b/lib/main.dart index d41d56d..d4dcacd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:device_preview/device_preview.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/app_router.dart'; import 'package:unit2/utils/global_context.dart'; import 'package:unit2/utils/global_context.dart'; @@ -55,8 +56,10 @@ class MyApp extends StatelessWidget { // routeInformationParser: goRouter.routeInformationParser, // routerDelegate: goRouter.routerDelegate, // routeInformationProvider: goRouter.routeInformationProvider, + title: 'uniT2 - Universal Tracker and Tracer', theme: ThemeData( + primarySwatch: Colors.red, appBarTheme: const AppBarTheme( systemOverlayStyle: SystemUiOverlayStyle( statusBarBrightness: Brightness.dark, diff --git a/lib/model/location/city.dart b/lib/model/location/city.dart index c9c449a..1fc77cd 100644 --- a/lib/model/location/city.dart +++ b/lib/model/location/city.dart @@ -38,10 +38,14 @@ class CityMunicipality { Map toJson() => { "code": code, "description": description, - "province": province!.toJson(), + "province": province?.toJson(), "psgc_code": psgcCode, "zipcode": zipcode, }; + @override + String toString(){ + return 'CityMunicipality{code:$code, description:$description, provice:${province.toString()} }'; + } } diff --git a/lib/model/location/country.dart b/lib/model/location/country.dart index e1136b1..fe54ce8 100644 --- a/lib/model/location/country.dart +++ b/lib/model/location/country.dart @@ -31,4 +31,10 @@ class Country { "name": name, "code": code, }; + + @override + String toString() { + return '$id $name $code '; + + } } diff --git a/lib/model/location/provinces.dart b/lib/model/location/provinces.dart index d14881d..597587d 100644 --- a/lib/model/location/provinces.dart +++ b/lib/model/location/provinces.dart @@ -41,4 +41,9 @@ class Province { "psgc_code": psgcCode, "shortname": shortname, }; + + @override + String toString(){ + return 'Province(name:$description ${region.toString()})'; + } } diff --git a/lib/model/location/region.dart b/lib/model/location/region.dart index 99a7c8d..17bd41d 100644 --- a/lib/model/location/region.dart +++ b/lib/model/location/region.dart @@ -31,4 +31,9 @@ class Region { "description": description, "psgc_code": psgcCode, }; + + @override + String toString(){ + return 'Region(name:$description)'; + } } diff --git a/lib/model/profile/eligibility.dart b/lib/model/profile/eligibility.dart index 5f7e7fd..84566da 100644 --- a/lib/model/profile/eligibility.dart +++ b/lib/model/profile/eligibility.dart @@ -12,90 +12,110 @@ import '../location/city.dart'; import '../location/country.dart'; import '../utils/eligibility.dart'; -EligibityCert eligibityFromJson(String str) => EligibityCert.fromJson(json.decode(str)); +EligibityCert eligibityFromJson(String str) => + EligibityCert.fromJson(json.decode(str)); String eligibityToJson(EligibityCert data) => json.encode(data.toJson()); class EligibityCert { - EligibityCert({ - required this.id, - required this.rating, - required this.examDate, - required this.attachments, - required this.eligibility, - required this.examAddress, - required this.validityDate, - required this.licenseNumber, - required this.overseas, - }); - bool? overseas; - final int? id; - final double? rating; - final DateTime? examDate; - final dynamic attachments; - final Eligibility? eligibility; - final ExamAddress? examAddress; - final DateTime? validityDate; - final String? licenseNumber; + EligibityCert({ + required this.id, + required this.rating, + required this.examDate, + required this.attachments, + required this.eligibility, + required this.examAddress, + required this.validityDate, + required this.licenseNumber, + required this.overseas, + }); + bool? overseas; + final int? id; + final double? rating; + final DateTime? examDate; + final dynamic attachments; + final Eligibility? eligibility; + final ExamAddress? examAddress; + final DateTime? validityDate; + final String? licenseNumber; - factory EligibityCert.fromJson(Map json) => EligibityCert( + factory EligibityCert.fromJson(Map json) => EligibityCert( id: json["id"], rating: json["rating"]?.toDouble(), - examDate: json['exam_date'] == null? null: DateTime.parse(json["exam_date"]), + examDate: json['exam_date'] == null + ? null + : DateTime.parse(json["exam_date"]), attachments: null, - eligibility: json['eligibility'] == null?null: Eligibility.fromJson(json["eligibility"]), - examAddress: json['exam_address'] == null? null: ExamAddress.fromJson(json["exam_address"]), + eligibility: json['eligibility'] == null + ? null + : Eligibility.fromJson(json["eligibility"]), + examAddress: json['exam_address'] == null + ? null + : ExamAddress.fromJson(json["exam_address"]), validityDate: json["validity_date"], licenseNumber: json["license_number"], overseas: null, - ); + ); - Map toJson() => { + Map toJson() => { "id": id, "rating": rating, - "exam_date": "${examDate!.year.toString().padLeft(4, '0')}-${examDate!.month.toString().padLeft(2, '0')}-${examDate!.day.toString().padLeft(2, '0')}", + "exam_date": + "${examDate!.year.toString().padLeft(4, '0')}-${examDate!.month.toString().padLeft(2, '0')}-${examDate!.day.toString().padLeft(2, '0')}", "attachments": attachments, "eligibility": eligibility!.toJson(), "exam_address": examAddress!.toJson(), "validity_date": validityDate, "license_number": licenseNumber, - }; + }; + @override + String toString() { + return 'eligibility:${eligibility.toString()}, rating:$rating, examDate:${examDate.toString()},validydate:${validityDate.toString()}, lisence:$licenseNumber, examAddress:${examAddress.toString()}'; + } } - class ExamAddress { - ExamAddress({ - required this.id, - required this.examAddressClass, - required this.country, - required this.barangay, - required this.addressCategory, - required this.cityMunicipality, - }); + ExamAddress({ + required this.id, + required this.examAddressClass, + required this.country, + required this.barangay, + required this.addressCategory, + required this.cityMunicipality, + }); - final int? id; - final dynamic examAddressClass; - final Country? country; - final dynamic barangay; - final AddressCategory? addressCategory; - final CityMunicipality? cityMunicipality; + final int? id; + final dynamic examAddressClass; + final Country? country; + final dynamic barangay; + final AddressCategory? addressCategory; + final CityMunicipality? cityMunicipality; - factory ExamAddress.fromJson(Map json) => ExamAddress( + factory ExamAddress.fromJson(Map json) => ExamAddress( id: json["id"], examAddressClass: json["class"], - country:json["country"] == null? null: Country.fromJson(json["country"]), + country: + json["country"] == null ? null : Country.fromJson(json["country"]), barangay: json["barangay"], - addressCategory: json["address_category"] == null?null: AddressCategory.fromJson(json["address_category"]), - cityMunicipality: json["city_municipality"]==null? null: CityMunicipality.fromJson(json["city_municipality"]), - ); + addressCategory: json["address_category"] == null + ? null + : AddressCategory.fromJson(json["address_category"]), + cityMunicipality: json["city_municipality"] == null + ? null + : CityMunicipality.fromJson(json["city_municipality"]), + ); - Map toJson() => { + Map toJson() => { "id": id, "class": examAddressClass, "country": country!.toJson(), "barangay": barangay, "address_category": addressCategory!.toJson(), "city_municipality": cityMunicipality!.toJson(), - }; -} + }; + @override + String toString() { + return 'country:${country.toString()} , address:${cityMunicipality.toString()}'; + } +} diff --git a/lib/model/utils/eligibility.dart b/lib/model/utils/eligibility.dart index c9b3a04..b2ec606 100644 --- a/lib/model/utils/eligibility.dart +++ b/lib/model/utils/eligibility.dart @@ -31,4 +31,9 @@ class Eligibility { "title": title, "type": type, }; + @override + String toString() { +return title; + + } } diff --git a/lib/screens/profile/components/eligibility/add_modal.dart b/lib/screens/profile/components/eligibility/add_modal.dart index 7a79eea..f0b247c 100644 --- a/lib/screens/profile/components/eligibility/add_modal.dart +++ b/lib/screens/profile/components/eligibility/add_modal.dart @@ -3,10 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:intl/intl.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; +import 'package:unit2/model/profile/eligibility.dart'; import '../../../../model/location/city.dart'; import '../../../../model/location/country.dart'; @@ -28,7 +30,7 @@ class AddEligibilityScreen extends StatefulWidget { } class _AddEligibilityScreenState extends State { - final formKey = GlobalKey(); + final formKey = GlobalKey(); final provinceKey = GlobalKey(); bool? overseas; DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); @@ -41,6 +43,12 @@ class _AddEligibilityScreenState extends State { List? citymuns; bool provinceCall = false; bool cityCall = false; + final examDateController = TextEditingController(); + final validityDateController = TextEditingController(); + String? token; + String? profileId; + String? rating; + String? license; @override Widget build(BuildContext context) { //USERBLOC @@ -49,6 +57,8 @@ class _AddEligibilityScreenState extends State { //LOGGED IN USER STATE if (state is UserLoggedIn) { //PROFIILE BLOC + token = state.userData!.user!.login!.token; + profileId = state.userData!.user!.login!.user!.profileId.toString(); return BlocBuilder( buildWhen: (previous, current) { if (state is EditEligibilityState) {} @@ -70,27 +80,23 @@ class _AddEligibilityScreenState extends State { children: [ //ELIGIBILITIES DROPDOWN FormBuilderDropdown( - onChanged: (Eligibility? eligibility) { - selectedEligibility = eligibility; - }, - initialValue: state.eligibilities[0], - items: state.eligibilities - .map>( - (Eligibility eligibility) { - return DropdownMenuItem( - value: eligibility, - child: Text(eligibility.title)); - }).toList(), - name: "eligibility", - decoration: - normalTextFieldStyle("Eligibility", "") - .copyWith( - hintStyle: const TextStyle( - color: Colors.black, - ), - labelStyle: const TextStyle( - color: Colors.black)), - ), + onChanged: (Eligibility? eligibility) { + selectedEligibility = eligibility; + }, + autovalidateMode: + AutovalidateMode.onUserInteraction, + validator: (value) => + value == null ? 'required' : null, + items: state.eligibilities + .map>( + (Eligibility eligibility) { + return DropdownMenuItem( + value: eligibility, + child: Text(eligibility.title)); + }).toList(), + name: "eligibility", + decoration: normalTextFieldStyle( + "Eligibility", "Eligibility")), const SizedBox( height: 20, ), @@ -103,9 +109,10 @@ class _AddEligibilityScreenState extends State { Flexible( flex: 1, child: FormBuilderTextField( + onChanged: (value) { + license = value; + }, name: 'license_number', - initialValue:null, - decoration: normalTextFieldStyle( "license number", "license number"), ), @@ -117,14 +124,12 @@ class _AddEligibilityScreenState extends State { Flexible( flex: 1, child: FormBuilderTextField( + onChanged: (value) { + rating = value; + }, name: 'rating', - - // ignore: prefer_null_aware_operators - initialValue:null, - - decoration: normalTextFieldStyle( - 'rating', 'rating'), + 'rating %', 'rating'), ), ), ], @@ -141,12 +146,21 @@ class _AddEligibilityScreenState extends State { Flexible( flex: 1, child: DateTimePicker( - // controller: examDateController, - firstDate: DateTime(2000), - lastDate: DateTime(2100), + use24HourFormat: false, + icon: const Icon(Icons.date_range), + controller: examDateController, + firstDate: DateTime(1970), + lastDate: DateTime(2100), + timeHintText: + "Date of Examination/Conferment", decoration: normalTextFieldStyle( - "Exam date", "Exam date"), - initialValue:null, + "Exam date", "") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + initialValue: null, )), const SizedBox( width: 12, @@ -155,12 +169,18 @@ class _AddEligibilityScreenState extends State { Flexible( flex: 1, child: DateTimePicker( - // controller: validityDateController, - firstDate: DateTime(2000), + controller: validityDateController, + firstDate: DateTime(1970), lastDate: DateTime(2100), decoration: normalTextFieldStyle( - "Validity date", "Validity date"), - initialValue:null, + "Validity date", + "Validity date") + .copyWith( + prefixIcon: const Icon( + Icons.date_range, + color: Colors.black87, + )), + initialValue: null, ), ), ], @@ -170,7 +190,7 @@ class _AddEligibilityScreenState extends State { height: 20, ), Text( - "Placement of Examination/Confinement", + "Placement of Examination/Conferment", style: Theme.of(context) .textTheme .displaySmall! @@ -202,6 +222,8 @@ class _AddEligibilityScreenState extends State { child: overseas == true ? FormBuilderDropdown( initialValue: null, + validator: (value) => + value == null ? 'required' : null, items: state.countries.map< DropdownMenuItem< Country>>( @@ -224,6 +246,11 @@ class _AddEligibilityScreenState extends State { children: [ //REGION DROPDOWN FormBuilderDropdown( + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null ? 'required' : null, onChanged: (Region? region) async { setState(() { @@ -253,19 +280,26 @@ class _AddEligibilityScreenState extends State { ), //PROVINCE DROPDOWN SizedBox( - height: 50, + height: 70, child: ModalProgressHUD( + color: Colors.transparent, inAsyncCall: cityCall, child: DropdownButtonFormField< Province?>( - isExpanded: true, + autovalidateMode: + AutovalidateMode + .onUserInteraction, + validator: (value) => + value == null ? 'required' : null, + isExpanded: true, value: selectedProvince, onChanged: (Province? province) { setState(() { - cityCall = true; + cityCall = true; }); - selectedProvince = province; + selectedProvince = + province; getCities(); }, items: provinces == null @@ -278,7 +312,8 @@ class _AddEligibilityScreenState extends State { return DropdownMenuItem( value: province, - child: FittedBox( + child: + FittedBox( child: Text( province .description!), @@ -294,33 +329,37 @@ class _AddEligibilityScreenState extends State { height: 20, ), SizedBox( - height: 50, - child: DropdownButtonFormField< + height: 70, + child: + DropdownButtonFormField< CityMunicipality>( - onChanged: - (CityMunicipality? - 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(), - ), + validator: (value) => + value == null ? 'required' : null, + isExpanded: true, + onChanged: + (CityMunicipality? + 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(), + ), ), const SizedBox( height: 20, @@ -340,7 +379,56 @@ class _AddEligibilityScreenState extends State { child: ElevatedButton( style: mainBtnStyle( primary, Colors.transparent, second), - onPressed: () {}, + onPressed: () { + double? rate = rating == null + ? null + : double.parse(rating!); + String? licenseNumber = license; + CityMunicipality? cityMunicipality = + selectedMunicipality; + DateTime? examDate = + examDateController.text.isEmpty + ? null + : DateTime.parse( + examDateController.text); + DateTime? validityDate = + validityDateController.text.isEmpty + ? null + : DateTime.parse( + validityDateController.text); + + ExamAddress examAddress = ExamAddress( + barangay: null, + id: null, + addressCategory: null, + examAddressClass: null, + country: selectedCountry ?? + Country( + id: 175, + name: 'Philippines', + code: 'PH'), + cityMunicipality: cityMunicipality); + EligibityCert eligibityCert = + EligibityCert( + id: null, + rating: rate, + examDate: examDate, + attachments: null, + eligibility: selectedEligibility, + examAddress: examAddress, + validityDate: validityDate, + licenseNumber: licenseNumber, + overseas: overseas); + if (formKey.currentState! + .saveAndValidate()) { + context.read().add( + AddEligibility( + eligibityCert: eligibityCert, + profileId: profileId!, + token: token!)); + } + // context.read().add(AddEligibility(eligibityCert: eligibityCert, profileId: profileId, token: token)) + }, child: const Text(submit)), ), const SizedBox( @@ -362,21 +450,23 @@ class _AddEligibilityScreenState extends State { } Future getProvinces() async { - List _provinces = await LocationUtils.instance + List newProvinces = await LocationUtils.instance .getProvinces(regionCode: selectedRegion!.code.toString()); setState(() { - provinces = _provinces; + provinces = newProvinces; selectedProvince = provinces![0]; getCities(); provinceCall = false; }); } - Future getCities()async{ - List _cities = await LocationUtils.instance.getCities(code: selectedProvince!.code.toString()); - citymuns = _cities; - setState(() { - selectedMunicipality = _cities[0]; - cityCall = false; - }); + + Future getCities() async { + List newCities = await LocationUtils.instance + .getCities(code: selectedProvince!.code.toString()); + citymuns = newCities; + setState(() { + selectedMunicipality = newCities[0]; + cityCall = false; + }); } } diff --git a/lib/screens/profile/components/eligibility_screen.dart b/lib/screens/profile/components/eligibility_screen.dart index 44d548d..ba937eb 100644 --- a/lib/screens/profile/components/eligibility_screen.dart +++ b/lib/screens/profile/components/eligibility_screen.dart @@ -13,6 +13,7 @@ import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/global.dart'; import 'package:unit2/utils/text_container.dart'; import 'package:unit2/widgets/add_leading.dart'; +import 'package:unit2/widgets/empty_data.dart'; import '../../../utils/alerts.dart'; @@ -28,9 +29,11 @@ class EligibiltyScreen extends StatelessWidget { title: const Text(elibilityScreenTitle), centerTitle: true, backgroundColor: primary, - actions: [AddLeading(onPressed: () { - context.read().add( AddEligibility()); - })], + actions: [ + AddLeading(onPressed: () { + context.read().add(ShowAddEligibilityForm()); + }) + ], ), body: BlocBuilder( builder: (context, state) { @@ -49,12 +52,11 @@ class EligibiltyScreen extends StatelessWidget { final progress = ProgressHUD.of(context); progress!.showWithText("Loading"); } - if (state is EligibilityLoaded) { + if (state is EligibilityLoaded || + state is AddEligibilityState || + state is ProfileErrorState) { final progress = ProgressHUD.of(context); progress!.dismiss(); - }if(state is AddEligibilityState){ - final progress = ProgressHUD.of(context); - progress!.dismiss(); } if (state is DeletedState) { if (state.success) { @@ -66,158 +68,180 @@ class EligibiltyScreen extends StatelessWidget { } else { errorAlert(context, "Deletion Failed", "Error deleting eligibility", () { + Navigator.of(context).pop(); + context.read().add(LoadEligibility( + eligibilities: state.eligibilities)); + }); + } + } + if (state is EligibilityAddedState) { + if (state.response['success']) { + Navigator.of(context).pop(); + successAlert(context, "Adding Successfull!", + state.response['message'], () { + context.read().add(LoadEligibility( + eligibilities: state.eligibilities)); + }); + } else { + errorAlert(context, "Adding Failed", + "Something went wrong. Please try again.", () { + Navigator.of(context).pop(); context.read().add(LoadEligibility( eligibilities: state.eligibilities)); }); } } - // TODO: implement listener }, builder: (context, state) { return BlocBuilder( builder: (context, state) { if (state is EligibilityLoaded) { - return ListView.builder( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 10), - itemCount: state.eligibilities.length, - itemBuilder: (BuildContext context, int index) { - String title = state - .eligibilities[index].eligibility!.title; - return Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: screenWidth, - padding: const EdgeInsets.symmetric( - horizontal: 12, vertical: 8), - decoration: box1(), - child: Row( - children: [ - Expanded( - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - title, - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith( - fontWeight: - FontWeight - .w500), - ), - const Divider(), - const SizedBox( - height: 5, - ), - Text( - "$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}", + if (state.eligibilities.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 10), + itemCount: state.eligibilities.length, + itemBuilder: (BuildContext context, int index) { + String title = state + .eligibilities[index].eligibility!.title; + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + width: screenWidth, + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + decoration: box1(), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + title, style: Theme.of(context) .textTheme - .titleSmall), - const SizedBox( - height: 3, - ), - Text( - "Rating : ${state.eligibilities[index].rating ?? 'N/A'}.", - style: Theme.of(context) - .textTheme - .titleSmall) - ]), - ), - AppPopupMenu( - offset: const Offset(-10, -10), - elevation: 3, - onSelected: (value) { - if (value == 2) { - confirmAlert(context, () { - BlocProvider.of< - ProfileBloc>(context) - .add(DeleteEligibility( - eligibilities: state - .eligibilities, - eligibilityId: state - .eligibilities[ - index] - .id!, - profileId: profileId!, - token: token!)); - }, "Delete?", - "Confirm Delete?"); - } - if (value == 1) { - EligibityCert eligibityCert = - state.eligibilities[index]; - bool overseas = eligibityCert - .examAddress! - .country! - .id - .toString() == - '175' - ? false - : true; - eligibityCert.overseas = - overseas; - final progress = - ProgressHUD.of(context); - eligibityCert.overseas = - overseas; - progress! - .showWithText("Loading..."); - context.read().add( - EditEligibility( - - eligibityCert: - eligibityCert)); - } - }, - 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, - color: Colors.grey, + .titleMedium! + .copyWith( + fontWeight: + FontWeight + .w500), + ), + const Divider(), + const SizedBox( + height: 5, + ), + Text( + "$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}", + style: Theme.of(context) + .textTheme + .titleSmall), + const SizedBox( + height: 3, + ), + Text( + "Rating : ${state.eligibilities[index].rating ?? 'N/A'}.", + style: Theme.of(context) + .textTheme + .titleSmall) + ]), ), - tooltip: "Options", - ) - ], + AppPopupMenu( + offset: const Offset(-10, -10), + elevation: 3, + onSelected: (value) { + if (value == 2) { + confirmAlert(context, () { + BlocProvider.of< + ProfileBloc>( + context) + .add(DeleteEligibility( + eligibilities: state + .eligibilities, + eligibilityId: state + .eligibilities[ + index] + .id!, + profileId: + profileId!, + token: token!)); + }, "Delete?", + "Confirm Delete?"); + } + if (value == 1) { + EligibityCert eligibityCert = + state + .eligibilities[index]; + bool overseas = eligibityCert + .examAddress! + .country! + .id + .toString() == + '175' + ? false + : true; + eligibityCert.overseas = + overseas; + final progress = + ProgressHUD.of(context); + eligibityCert.overseas = + overseas; + progress!.showWithText( + "Loading..."); + context + .read() + .add(EditEligibility( + eligibityCert: + eligibityCert)); + } + }, + 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, + color: Colors.grey, + ), + tooltip: "Options", + ) + ], + ), ), - ), - const SizedBox( - height: 5, - ) - ], - ); - }); + const SizedBox( + height: 5, + ) + ], + ); + }); + } else { + return const EmptyData( + message: + "You don't have any eligibilities added. Please click + to add"); + } } if (state is EditEligibilityState) { return EditEligibilityScreen( eligibityCert: state.eligibityCert); - }if(state is AddEligibilityState){ - return const AddEligibilityScreen(); } - if (state is DeletedState) { - return Center( - child: Container( - child: Text(state.success.toString())), - ); + if (state is AddEligibilityState) { + return const AddEligibilityScreen(); } if (state is ProfileErrorState) { return Center( diff --git a/lib/sevices/profile/eligibility_services.dart b/lib/sevices/profile/eligibility_services.dart index 0f3cbda..fa24736 100644 --- a/lib/sevices/profile/eligibility_services.dart +++ b/lib/sevices/profile/eligibility_services.dart @@ -1,35 +1,77 @@ import 'dart:convert'; +import 'package:unit2/model/profile/eligibility.dart'; import 'package:unit2/utils/request.dart'; import 'package:unit2/utils/urls.dart'; import 'package:http/http.dart' as http; -class EligibilityService{ + +class EligibilityService { static final EligibilityService _instance = EligibilityService(); static EligibilityService get instance => _instance; - Future delete({required int eligibilityId, required int profileId,required String token})async{ - bool? success; - String Authtoken = "Token $token"; - String path = "${Url.instance.deleteEligibility()}$profileId/"; - Map body = { "eligibility_id": eligibilityId}; - Map params ={"force_mode":"true"}; - Map headers = { + Future delete( + {required int eligibilityId, + required int profileId, + required String token}) async { + bool? success; + String authtoken = "Token $token"; + String path = "${Url.instance.deleteEligibility()}$profileId/"; + Map body = {"eligibility_id": eligibilityId}; + Map params = {"force_mode": "true"}; + Map headers = { 'Content-Type': 'application/json; charset=UTF-8', - 'Authorization': "Token $token" + '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); + 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{ + } else { success = false; - } - + } + // }catch(e){ // throw(e.toString()); // } return success!; } -} \ No newline at end of file + Future> add( + {required EligibityCert eligibityCert, + required String token, + required int profileId}) async { + Map? _response={}; + String authtoken = "Token $token+1"; + String path = '${Url.instance.addEligibility()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + + Map body = { + 'eligibility_id': eligibityCert.eligibility!.id, + 'license_number': eligibityCert.licenseNumber, + 'exam_date': eligibityCert.examDate?.toString(), + 'validity_date': eligibityCert.validityDate?.toString(), + 'rating': eligibityCert.rating, + '_citymunCode': eligibityCert.examAddress?.cityMunicipality?.code, + '_countryId': eligibityCert.examAddress?.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; + } else { + _response.addAll({'success':false}); + } + + return _response; + } catch (e) { + throw e.toString(); + } + } +} diff --git a/lib/theme-data.dart/form-style.dart b/lib/theme-data.dart/form-style.dart index 7089e98..22d1e79 100644 --- a/lib/theme-data.dart/form-style.dart +++ b/lib/theme-data.dart/form-style.dart @@ -49,6 +49,8 @@ InputDecoration normalTextFieldStyle(String labelText, String hintText) { filled: false); } + + InputDecoration loginTextFieldStyle() { return InputDecoration( floatingLabelBehavior: FloatingLabelBehavior.never, diff --git a/lib/utils/alerts.dart b/lib/utils/alerts.dart index 5257be1..0994f39 100644 --- a/lib/utils/alerts.dart +++ b/lib/utils/alerts.dart @@ -1,5 +1,6 @@ import 'package:awesome_dialog/awesome_dialog.dart'; import 'package:flutter/material.dart'; +import 'package:unit2/theme-data.dart/btn-style.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/global.dart'; @@ -45,8 +46,7 @@ errorAlert(context, title, description,Function() func) { headerAnimationLoop: false, title: title, desc: description, - btnOkOnPress: func, - btnOkColor: Colors.red, + btnOk: SizedBox(height: 50,child: ElevatedButton(onPressed:func, style: mainBtnStyle(primary, Colors.transparent, second), child: const Text("OK")), ) ).show(); } successAlert(context, title, description,Function() func) { @@ -58,7 +58,6 @@ successAlert(context, title, description,Function() func) { headerAnimationLoop: false, title: title, desc: description, - btnOkOnPress: func, - btnOkColor: Colors.red, + btnOk: SizedBox(height: 50,child: ElevatedButton(style: mainBtnStyle(primary, Colors.transparent, second), onPressed: func, child: const Text("OK")), ) ).show(); } diff --git a/lib/utils/urls.dart b/lib/utils/urls.dart index d53cead..953752f 100644 --- a/lib/utils/urls.dart +++ b/lib/utils/urls.dart @@ -5,8 +5,8 @@ class Url { String host() { // return '192.168.10.221:3003'; // return 'agusandelnorte.gov.ph'; - return "192.168.10.219:3000"; - // return 'devweb.agusandelnorte.gov.ph'; + // return "192.168.10.219:3000"; + return 'devweb.agusandelnorte.gov.ph'; } String authentication() { @@ -24,6 +24,10 @@ class Url { String eligibilities(){ return "/api/jobnet_app/eligibilities/"; } + +String addEligibility(){ + return "/api/jobnet_app/profile/pds/eligibility/"; +} String deleteEligibility(){ return "/api/jobnet_app/profile/pds/eligibility/"; }