implemented education profile API

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-04-25 15:50:36 +08:00
parent cf7902f923
commit 7f39bd5cd9
41 changed files with 5233 additions and 1429 deletions

View File

@ -0,0 +1,28 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:unit2/sevices/docsms/docsms_service.dart';
import '../../model/docsms/document.dart';
part 'docsms_event.dart';
part 'docsms_state.dart';
class DocsmsBloc extends Bloc<DocsmsEvent, DocsmsState> {
DocsmsBloc() : super(DocsmsInitial()) {
Document? document;
on<LoadDocument>((event, emit)async {
emit(DocSmsLoadingState());
try {
document = await AutoReceiveDocumentServices.instance.getDocument(event.documentId);
if(document != null){
emit(DocumentLoaded(document: document!));
}else{
emit(const DocSmsErrorState(message: "Invalid Qr code"));
}
} catch (e) {
emit(DocSmsErrorState(message: e.toString()));
}
});
}
}

View File

@ -0,0 +1,15 @@
part of 'docsms_bloc.dart';
abstract class DocsmsEvent extends Equatable {
const DocsmsEvent();
@override
List<Object> get props => [];
}
class LoadDocument extends DocsmsEvent{
final String documentId;
const LoadDocument({required this.documentId});
@override
List<Object> get props => [];
}

View File

@ -0,0 +1,28 @@
part of 'docsms_bloc.dart';
abstract class DocsmsState extends Equatable {
const DocsmsState();
@override
List<Object> get props => [];
}
class DocsmsInitial extends DocsmsState {}
class DocSmsLoadingState extends DocsmsState{
}
class DocumentLoaded extends DocsmsState{
final Document document;
const DocumentLoaded({required this.document});
@override
List<Object> get props => [document];
}
class DocSmsErrorState extends DocsmsState{
final String message;
const DocSmsErrorState({required this.message});
@override
List<Object> get props => [message];
}

View File

@ -8,10 +8,13 @@ part 'education_state.dart';
class EducationBloc extends Bloc<EducationEvent, EducationState> {
List<EducationalBackground> educationalBackgrounds = [];
List<School> schools = [];
List<Course> programs = [];
List<Honor> honors = [];
EducationBloc() : super(EducationInitial()) {
on<GetEducationalBackground>((event, emit) async {
emit(EducationalBackgroundLoadingState());
try {
try {
List<EducationalBackground> educations = await EducationService.instace
.getEducationalBackground(event.profileId, event.token);
educationalBackgrounds = educations;
@ -21,5 +24,108 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
emit(EducationalBackgroundErrorState(message: e.toString()));
}
});
//// SHOW ADD FORM
on<ShowAddEducationForm>((event, emit) async {
emit(EducationalBackgroundLoadingState());
try {
if (schools.isEmpty) {
List<School> newSchools = await EducationService.instace.getSchools();
schools = newSchools;
}
if (programs.isEmpty) {
List<Course> newPrograms =
await EducationService.instace.getPrograms();
programs = newPrograms;
}
if (honors.isEmpty) {
List<Honor> newHonors = await EducationService.instace.getHonors();
honors = newHonors;
}
emit(AddEducationState(
schools: schools, programs: programs, honors: honors));
} catch (e) {
emit(EducationalBackgroundErrorState(message: e.toString()));
}
});
////Add
on<AddEducation>((event, emit) async {
Map<dynamic, dynamic> status = await EducationService.instace.add(
honors: event.honors,
educationalBackground: event.educationalBackground,
token: event.token,
profileId: event.profileId);
if (status['success']) {
EducationalBackground educationalBackground =
EducationalBackground.fromJson(status['data']);
educationalBackgrounds.add(educationalBackground);
emit(EducationAddedState(response: status));
} else {
emit(EducationAddedState(response: status));
}
});
////Update
on<UpdateEducation>((event, emit) async {
Map<dynamic, dynamic> status = await EducationService.instace.edit(
honors: event.honors,
educationalBackground: event.educationalBackground,
token: event.token,
profileId: event.profileId);
if (status['success']) {
EducationalBackground educationalBackground =
EducationalBackground.fromJson(status['data']);
educationalBackgrounds.add(educationalBackground);
emit(EditedEducationState(response: status));
} else {
emit(EditedEducationState(response: status));
}
});
////LOAD
on<LoadEducations>((event, emit) {
emit(EducationalBackgroundLoadedState(
educationalBackground: educationalBackgrounds));
});
//// SHOW EDIT FORM
on<ShowEditEducationForm>((event, emit) async {
try {
if (schools.isEmpty) {
List<School> newSchools = await EducationService.instace.getSchools();
schools = newSchools;
}
if (programs.isEmpty) {
List<Course> newPrograms =
await EducationService.instace.getPrograms();
programs = newPrograms;
}
if (honors.isEmpty) {
List<Honor> newHonors = await EducationService.instace.getHonors();
honors = newHonors;
}
emit(EditEducationState(
schools: schools,
programs: programs,
honors: honors,
educationalBackground: event.educationalBackground));
} catch (e) {
emit(EducationalBackgroundErrorState(message: e.toString()));
}
});
////delete
on<DeleteEducation>((event, emit) async {
try {
final bool success = await EducationService.instace.delete(
profileId: event.profileId,
token: event.token,
educationalBackground: event.educationalBackground);
if (success) {
educationalBackgrounds.removeWhere(
(element) => element.id == event.educationalBackground.id);
emit(EducationDeletedState(success: success));
} else {
emit(EducationDeletedState(success: success));
}
} catch (e) {
emit(EducationalBackgroundErrorState(message: e.toString()));
}
});
}
}

View File

@ -6,10 +6,60 @@ abstract class EducationEvent extends Equatable {
@override
List<Object> get props => [];
}
class GetEducationalBackground extends EducationEvent{
class GetEducationalBackground extends EducationEvent {
final int profileId;
final String token;
const GetEducationalBackground({required this.profileId, required this.token});
@override
List<Object> get props => [profileId,token];
const GetEducationalBackground(
{required this.profileId, required this.token});
@override
List<Object> get props => [profileId, token];
}
////show add form
class ShowAddEducationForm extends EducationEvent {}
////show edit form
class ShowEditEducationForm extends EducationEvent {
final EducationalBackground educationalBackground;
final int profileId;
final String token;
const ShowEditEducationForm({required this.educationalBackground,required this.profileId, required this.token});
@override
List<Object> get props => [educationalBackground];
}
////load
class LoadEducations extends EducationEvent {}
////add
class AddEducation extends EducationEvent {
final List<Honor> honors;
final EducationalBackground educationalBackground;
final int profileId;
final String token;
const AddEducation(
{required this.educationalBackground,
required this.profileId,
required this.token, required this.honors});
@override
List<Object> get props => [educationalBackground, profileId, token];
}
////update education
class UpdateEducation extends EducationEvent{
final List<Honor> honors;
final EducationalBackground educationalBackground;
final int profileId;
final String token;
const UpdateEducation(
{required this.educationalBackground,
required this.profileId,
required this.token,required this.honors});
@override
List<Object> get props => [educationalBackground, profileId, token];
}
////delete
class DeleteEducation extends EducationEvent{
final int profileId;
final String token;
final EducationalBackground educationalBackground;
const DeleteEducation({required this.educationalBackground, required this.profileId, required this.token});
@override
List<Object> get props => [educationalBackground, profileId, token];
}

View File

@ -9,21 +9,66 @@ abstract class EducationState extends Equatable {
class EducationInitial extends EducationState {}
class EducationalBackgroundLoadedState extends EducationState{
class EducationalBackgroundLoadedState extends EducationState {
final List<EducationalBackground> educationalBackground;
const EducationalBackgroundLoadedState({required this.educationalBackground});
@override
@override
List<Object> get props => [educationalBackground];
}
class EducationalBackgroundErrorState extends EducationState{
class EducationalBackgroundErrorState extends EducationState {
final String message;
const EducationalBackgroundErrorState({required this.message});
@override
@override
List<Object> get props => [message];
}
class EducationalBackgroundLoadingState extends EducationState{
class EducationalBackgroundLoadingState extends EducationState {}
////Add
class AddEducationState extends EducationState {
final List<School> schools;
final List<Course> programs;
final List<Honor> honors;
const AddEducationState(
{required this.honors, required this.programs, required this.schools});
@override
List<Object> get props => [schools, programs, honors];
}
////Edit
class EditEducationState extends EducationState {
final EducationalBackground educationalBackground;
final List<School> schools;
final List<Course> programs;
final List<Honor> honors;
const EditEducationState({
required this.educationalBackground,
required this.honors,
required this.programs,
required this.schools,
});
}
//// Added State
class EducationAddedState extends EducationState {
final Map<dynamic, dynamic> response;
const EducationAddedState({required this.response});
@override
List<Object> get props => [response];
}
//// Edited State
class EditedEducationState extends EducationState {
final Map<dynamic, dynamic> response;
const EditedEducationState({required this.response});
@override
List<Object> get props => [response];
}
////deleted State
class EducationDeletedState extends EducationState {
final bool success;
const EducationDeletedState({required this.success});
@override
List<Object> get props => [success];
}

View File

@ -14,8 +14,8 @@ part 'eligibility_state.dart';
class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
EligibilityBloc() : super(EligibilityInitial()) {
List<Country>? globalCountries;
List<Region>? globalRegions;
List<Country> globalCountries = [];
List<Region> globalRegions = [];
List<Eligibility> globalEligibilities = [];
List<EligibityCert> eligibilities = [];
//// LOAD ELIGIBILTY
@ -67,11 +67,11 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
//// SHOW EDIT FORM
on<ShowEditEligibilityForm>((event, emit) async {
try {
if (globalCountries == null) {
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
if (globalRegions == null) {
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
@ -84,13 +84,13 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
(Eligibility eligibility) =>
event.eligibityCert.eligibility!.id == eligibility.id);
bool? isOverseas = event.eligibityCert.overseas;
Country currentCountry = globalCountries!.firstWhere(
Country currentCountry = globalCountries.firstWhere(
(Country country) =>
event.eligibityCert.examAddress!.country!.code == country.code);
if (event.eligibityCert.examAddress?.cityMunicipality?.province
?.region !=
null) {
Region currrentRegion = globalRegions!.firstWhere((Region region) =>
Region currrentRegion = globalRegions.firstWhere((Region region) =>
event.eligibityCert.examAddress!.cityMunicipality!.province!
.region!.code ==
region.code);
@ -117,8 +117,8 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
cities: cities,
isOverseas: isOverseas!,
eligibityCert: event.eligibityCert,
countries: globalCountries!,
regions: globalRegions!,
countries: globalCountries,
regions: globalRegions,
eligibilities: globalEligibilities));
} else {
emit(EditEligibilityState(
@ -131,8 +131,8 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
currentEligibility: currentEligibility,
isOverseas: isOverseas!,
eligibityCert: event.eligibityCert,
countries: globalCountries!,
regions: globalRegions!,
countries: globalCountries,
regions: globalRegions,
eligibilities: globalEligibilities));
}
} catch (e) {
@ -164,7 +164,7 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
//// SHOW ADD FORM
on<ShowAddEligibilityForm>((event, emit) async {
emit(EligibilityLoadingState());
if (globalRegions == null) {
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
@ -173,15 +173,15 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
await ProfileUtilities.instance.getEligibilities();
globalEligibilities = eligibilities;
}
if (globalCountries == null) {
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
emit(AddEligibilityState(
eligibilities: globalEligibilities,
regions: globalRegions!,
countries: globalCountries!));
regions: globalRegions,
countries: globalCountries));
});
//// ADD

View File

@ -1,13 +1,21 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:unit2/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/basic_information/adress.dart';
import '../../../../utils/location_utilities.dart';
part 'address_event.dart';
part 'address_state.dart';
class AddressBloc extends Bloc<AddressEvent, AddressState> {
AddressBloc() : super(AddressInitial()) {
List<Country> globalCountries=[];
List<Region> globalRegions=[];
List<MainAdress> addresses = [];
on<GetAddress>((event, emit) {
emit(AddressLoadingState());
@ -17,6 +25,46 @@ class AddressBloc extends Bloc<AddressEvent, AddressState> {
}catch(e){
emit(AddressErrorState(message: e.toString()));
}
//// show add form
});on<ShowAddAddressForm>((event,emit)async{
emit(AddressLoadingState());
try{
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
emit(AddAddressState(countries: globalCountries, regions: globalRegions));
}catch(e){
emit(AddressErrorState(message: e.toString()));
}
});
//// Show Edit Form
on<ShowEditAddressForm>((event,emit)async{
try{
if (globalRegions.isEmpty) {
List<Region> regions = await LocationUtils.instance.getRegions();
globalRegions = regions;
}
if (globalCountries.isEmpty) {
List<Country> countries = await LocationUtils.instance.getCountries();
globalCountries = countries;
}
emit(EditAddressState(countries: globalCountries, regions: globalRegions,address: event.address));
}catch(e){
emit(AddressErrorState(message: e.toString()));
}
});
////call error state
on<CallErrorState>((event, emit) {
emit(const AddressErrorState(
message: "Something went wrong. Please try again"));
});
}
}

View File

@ -13,3 +13,13 @@ class GetAddress extends AddressEvent{
@override
List<Object> get props => [addresses];
}
class ShowAddAddressForm extends AddressEvent{
}
class ShowEditAddressForm extends AddressEvent{
final MainAdress address;
const ShowEditAddressForm({required this.address});
}
class CallErrorState extends AddressEvent{
}

View File

@ -8,20 +8,40 @@ abstract class AddressState extends Equatable {
}
class AddressInitial extends AddressState {}
class AddressLoadedState extends AddressState{
final List<MainAdress> addresses;
const AddressLoadedState({required this.addresses});
@override
//// LOADED STATE
class AddressLoadedState extends AddressState {
final List<MainAdress> addresses;
const AddressLoadedState({required this.addresses});
@override
List<Object> get props => [addresses];
}
class AddressErrorState extends AddressState{
////ERROR STATE
class AddressErrorState extends AddressState {
final String message;
const AddressErrorState({required this.message});
@override
@override
List<Object> get props => [message];
}
class AddressLoadingState extends AddressState{
//// LOADING STATE
class AddressLoadingState extends AddressState {}
////ADD ADDRESS STATE
class AddAddressState extends AddressState {
final List<Country> countries;
final List<Region> regions;
const AddAddressState(
{
required this.countries,
required this.regions});
@override
List<Object> get props => [countries, regions,];
}
class EditAddressState extends AddressState{
final MainAdress address;
final List<Country> countries;
final List<Region> regions;
const EditAddressState({required this.address, required this.countries, required this.regions});
@override
List<Object> get props => [countries, regions,address];
}

View File

@ -1,8 +1,14 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:unit2/sevices/profile/volunatary_services.dart';
import 'package:unit2/utils/profile_utilities.dart';
import '../../../model/location/country.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';
part 'voluntary_work_event.dart';
part 'voluntary_work_state.dart';
@ -10,6 +16,12 @@ part 'voluntary_work_state.dart';
class VoluntaryWorkBloc extends Bloc<VoluntaryWorkEvent, VoluntaryWorkState> {
VoluntaryWorkBloc() : super(VoluntaryWorkInitial()) {
List<VoluntaryWork> voluntaryWorks = [];
List<Country> globalCountries=[];
List<Category> agencyCategory = [];
List<Region> globalRegions=[];
List<Position> agencyPositions = [];
List<Agency> agencies = [];
////Get Voluntary Works
on<GetVoluntarWorks>((event, emit) async{
emit(VoluntaryWorkLoadingState());
try{
@ -20,5 +32,35 @@ class VoluntaryWorkBloc extends Bloc<VoluntaryWorkEvent, VoluntaryWorkState> {
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});
//// Show Add form Event
on<ShowAddVoluntaryWorks>((event,emit)async{
try{
emit(VoluntaryWorkLoadingState());
if (agencyPositions.isEmpty) {
List<Position> positions =
await ProfileUtilities.instance.getAgencyPosition();
agencyPositions = positions;
}
/////AGENCIES------------------------------------------
if (agencies.isEmpty) {
List<Agency> newAgencies =
await ProfileUtilities.instance.getAgecies();
agencies = newAgencies;
}
/////Category Agency------------------------------------------
if (agencyCategory.isEmpty) {
List<Category> categoryAgencies =
await ProfileUtilities.instance.agencyCategory();
agencyCategory = categoryAgencies;
}
emit(AddVoluntaryWorkState(agencies: agencies,positions: agencyPositions,agencyCategory: agencyCategory,regions: globalRegions,countries: globalCountries));
}catch(e){
emit(VoluntaryWorkErrorState(message: e.toString()));
}
});on<ShowErrorState>((event,emit){
emit(VoluntaryWorkErrorState(message: event.message));
});
}
}

View File

@ -14,3 +14,11 @@ class GetVoluntarWorks extends VoluntaryWorkEvent{
@override
List<Object> get props => [profileId,token];
}
class ShowAddVoluntaryWorks extends VoluntaryWorkEvent{
}
class ShowErrorState extends VoluntaryWorkEvent{
final String message;
const ShowErrorState({required this.message});
}

View File

@ -8,20 +8,33 @@ abstract class VoluntaryWorkState extends Equatable {
}
class VoluntaryWorkInitial extends VoluntaryWorkState {}
////Loaded State
class VoluntaryWorkLoadedState extends VoluntaryWorkState{
final List<VoluntaryWork> voluntaryWorks;
const VoluntaryWorkLoadedState({required this.voluntaryWorks});
@override
List<Object> get props => [voluntaryWorks];
}
////Error State
class VoluntaryWorkErrorState extends VoluntaryWorkState{
final String message;
const VoluntaryWorkErrorState({required this.message});
@override
List<Object> get props => [message];
}
////Loading State
class VoluntaryWorkLoadingState extends VoluntaryWorkState{
}
class AddVoluntaryWorkState extends VoluntaryWorkState{
final List<Position> positions;
final List<Agency> agencies;
final List<Category> agencyCategory;
final List<Country> countries;
final List<Region> regions;
const AddVoluntaryWorkState({required this.agencies,required this.countries, required this.positions, required this.regions,required this.agencyCategory});
@override
List<Object> get props => [positions,agencies,countries,regions];
}

View File

@ -26,7 +26,7 @@ class WorkHistoryBloc extends Bloc<WorkHistorytEvent, WorkHistoryState> {
try {
if (workExperiences.isEmpty) {
List<WorkHistory> works = await WorkHistoryService.instance
.getWorkExperiences(event.profileId!, event.token!);
.getWorkExperiences(event.profileId, event.token);
workExperiences = works;
}

View File

@ -0,0 +1,207 @@
// To parse this JSON data, do
//
// final document = documentFromJson(jsonString);
class Document {
Document({
required this.id,
required this.sk,
required this.dsk,
required this.slug,
required this.files,
required this.title,
required this.agency,
required this.office,
required this.subject,
required this.fileType,
required this.isPublic,
required this.createdAt,
required this.createdBy,
required this.validatedAt,
required this.validatedBy,
required this.documentType,
required this.documentRoutes,
required this.alternateMobile,
required this.attachedDocument,
required this.enableNotification,
required this.createdByPersonId,
});
final int? id;
final String? sk;
final String? dsk;
final String? slug;
final List<FileElement>? files;
final String? title;
final String? agency;
final String? office;
final String? subject;
final FileType? fileType;
final bool? isPublic;
final String? createdAt;
final String? createdBy;
final String? validatedAt;
final String? validatedBy;
final DocumentType? documentType;
final dynamic documentRoutes;
final AlternateMobile? alternateMobile;
final dynamic attachedDocument;
final bool? enableNotification;
final int? createdByPersonId;
factory Document.fromJson(Map<String, dynamic> json) => Document(
id: json["id"],
sk: json["sk"],
dsk: json["dsk"],
slug: json["slug"],
files: List<FileElement>.from(json["files"].map((x) => FileElement.fromJson(x))),
title: json["title"],
agency: json["agency"],
office: json["office"],
subject: json["subject"],
fileType: FileType.fromJson(json["file_type"]),
isPublic: json["is_public"],
createdAt: json["created_at"],
createdBy: json["created_by"],
validatedAt: json["validated_at"],
validatedBy: json["validated_by"],
documentType: DocumentType.fromJson(json["document_type"]),
documentRoutes: json["document_routes"],
alternateMobile: AlternateMobile.fromJson(json["alternate_mobile"]),
attachedDocument: json["attached_document"],
enableNotification: json["enable_notification"],
createdByPersonId: json["created_by_person_id"],
);
Map<String, dynamic> toJson() => {
"id": id,
"sk": sk,
"dsk": dsk,
"slug": slug,
"files": List<dynamic>.from(files!.map((x) => x.toJson())),
"title": title,
"agency": agency,
"office": office,
"subject": subject,
"file_type": fileType?.toJson(),
"is_public": isPublic,
"created_at": createdAt,
"created_by": createdBy,
"validated_at": validatedAt,
"validated_by": validatedBy,
"document_type": documentType?.toJson(),
"document_routes": documentRoutes,
"alternate_mobile": alternateMobile?.toJson(),
"attached_document": attachedDocument,
"enable_notification": enableNotification,
"created_by_person_id": createdByPersonId,
};
}
class AlternateMobile {
AlternateMobile({
required this.id,
required this.mobileNo,
required this.documentId,
});
final dynamic id;
final dynamic mobileNo;
final dynamic documentId;
factory AlternateMobile.fromJson(Map<String, dynamic> json) => AlternateMobile(
id: json["id"],
mobileNo: json["mobile_no"],
documentId: json["document_id"],
);
Map<String, dynamic> toJson() => {
"id": id,
"mobile_no": mobileNo,
"document_id": documentId,
};
}
class DocumentType {
DocumentType({
required this.id,
required this.name,
required this.slug,
required this.categoryId,
required this.priorityNumber,
});
final int id;
final String name;
final dynamic slug;
final int categoryId;
final dynamic priorityNumber;
factory DocumentType.fromJson(Map<String, dynamic> json) => DocumentType(
id: json["id"],
name: json["name"],
slug: json["slug"],
categoryId: json["category_id"],
priorityNumber: json["priority_number"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"slug": slug,
"category_id": categoryId,
"priority_number": priorityNumber,
};
}
class FileType {
FileType({
required this.id,
required this.name,
required this.isActive,
required this.extensions,
});
final int id;
final String name;
final bool isActive;
final List<String> extensions;
factory FileType.fromJson(Map<String, dynamic> json) => FileType(
id: json["id"],
name: json["name"],
isActive: json["is_active"],
extensions: List<String>.from(json["extensions"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"is_active": isActive,
"extensions": List<dynamic>.from(extensions.map((x) => x)),
};
}
class FileElement {
FileElement({
required this.path,
required this.extnsn,
required this.dateTime,
});
final String path;
final String extnsn;
final String dateTime;
factory FileElement.fromJson(Map<String, dynamic> json) => FileElement(
path: json["path"],
extnsn: json["extnsn"],
dateTime: json["date_time"],
);
Map<String, dynamic> toJson() => {
"path": path,
"extnsn": extnsn,
"date_time": dateTime,
};
}

View File

@ -26,7 +26,7 @@ class EducationalBackground {
final String? periodTo;
final dynamic attachments;
final String? periodFrom;
final dynamic unitsEarned;
final int? unitsEarned;
final String? yearGraduated;
factory EducationalBackground.fromJson(Map<String, dynamic> json) => EducationalBackground(

View File

@ -9,10 +9,10 @@ import 'package:unit2/utils/text_container.dart';
import 'package:unit2/widgets/costum_divider.dart';
import 'package:unit2/widgets/text_icon.dart';
import '../../test_data.dart';
import '../../theme-data.dart/btn-style.dart';
import '../../theme-data.dart/form-style.dart';
import '../../utils/global.dart';
import '../../../test_data.dart';
import '../../../theme-data.dart/btn-style.dart';
import '../../../theme-data.dart/form-style.dart';
import '../../../utils/global.dart';
class RequetAutoReceipt extends StatefulWidget {
RequetAutoReceipt({super.key});
@ -124,7 +124,7 @@ class _RequetAutoReceiptState extends State<RequetAutoReceipt> {
height: screenHeight * .06,
child: ElevatedButton(
style: secondaryBtnStyle(
second, Colors.transparent, Colors.white54),
primary, Colors.transparent, Colors.white54),
child: const Text(
requestAutoReceipt,
style: TextStyle(color: Colors.white),

View File

@ -0,0 +1,52 @@
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_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:unit2/bloc/docsms/docsms_bloc.dart';
import 'package:unit2/screens/docsms/components/request_receipt.dart';
import 'package:unit2/widgets/error_state.dart';
class AutoReceiveDocument extends StatefulWidget {
const AutoReceiveDocument({super.key});
@override
State<AutoReceiveDocument> createState() => _AutoReceiveDocumentState();
}
class _AutoReceiveDocumentState extends State<AutoReceiveDocument> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ProgressHUD(
padding: const EdgeInsets.all(24),
backgroundColor: Colors.black87,
indicatorWidget: const SpinKitFadingCircle(
color: Colors.white,
),
child: BlocConsumer<DocsmsBloc, DocsmsState>(
listener: (context, state) {
if (state is DocSmsLoadingState) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait...");
}
if (state is DocSmsErrorState || state is DocumentLoaded) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
},
builder: (context, state) {
if (state is DocumentLoaded) {
return RequetAutoReceipt();
}if(state is DocSmsErrorState){
return SomethingWentWrong(message: state.message.toString(), onpressed: (){});
}
return Container();
},
),
),
);
}
}

View File

@ -0,0 +1,474 @@
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: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/utils/category.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 '../../../../../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';
class AddAddressScreen extends StatefulWidget {
final int profileId;
final String token;
const AddAddressScreen(
{super.key, required this.profileId, required this.token});
@override
State<AddAddressScreen> createState() => _AddAddressScreenState();
}
class _AddAddressScreenState extends State<AddAddressScreen> {
////boolean
bool hasLotandBlock = false;
bool overseas = false;
bool provinceCall = false;
bool cityCall = false;
bool barangayCall = false;
////selected
Region? selectedRegion;
Province? selectedProvince;
CityMunicipality? selectedMunicipality;
Barangay? selectedBarangay;
Country? selectedCountry;
////Lists
final List<Area> areaClass = [
const Area(value: "Rural Area", group: 0),
const Area(value: "Sitio", group: 1),
const Area(value: "Village", group: 1),
const Area(value: "Urban Area", group: 0),
const Area(value: "Town", group: 1),
const Area(value: "City", group: 1),
const Area(value: "Metropolis", group: 1),
const Area(value: "Megacity", group: 1),
];
final List<String> category = ["Permanent", "Residential", "Birthplace"];
List<Province>? provinces;
List<CityMunicipality>? citymuns;
List<Barangay>? barangays;
final formKey = GlobalKey<FormBuilderState>();
@override
Widget build(BuildContext context) {
return BlocBuilder<AddressBloc, AddressState>(
builder: (context, state) {
if (state is AddAddressState) {
return SingleChildScrollView(
child: SizedBox(
height: screenHeight * .90,
child: FormBuilder(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 25, horizontal: 18),
child: Column(
children: [
//// category
FormBuilderDropdown<String>(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration:
normalTextFieldStyle("Category*", "Category"),
name: "category",
onChanged: (String? category) {},
items: category.map<DropdownMenuItem<String>>(
(String category) {
return DropdownMenuItem(
value: category, child: Text(category));
}).toList()),
const SizedBox(
height: 12,
),
////Area Class
FormBuilderDropdown(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration: normalTextFieldStyle(
"Area class *", "Area class"),
name: "area_class",
onChanged: (Area? area) {},
items: areaClass
.map<DropdownMenuItem<Area>>((Area area) {
return area.group == 0
? DropdownMenuItem(
enabled: false,
value: area,
child: Text(area.value.toUpperCase(),
style: const TextStyle(
color: Colors.black38)))
: DropdownMenuItem(
value: area,
enabled: true,
child: Text(
" ${area.value.toUpperCase()}"));
}).toList()),
const SizedBox(
height: 12,
),
////stateful builder
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
////with block & Lot Switch
FormBuilderSwitch(
initialValue: hasLotandBlock,
activeColor: second,
onChanged: (value) {
setState(() {
hasLotandBlock = value!;
});
},
decoration: normalTextFieldStyle(
"With Lot and Block?", 'Graduated?'),
name: 'graudated',
title: Text(hasLotandBlock ? "YES" : "NO"),
),
SizedBox(
height: hasLotandBlock ? 12 : 0,
),
SizedBox(
width: screenWidth,
child: hasLotandBlock
? Row(
children: [
////block #
Flexible(
flex: 1,
child: FormBuilderTextField(
name: "block_number",
decoration:
normalTextFieldStyle(
"Block #*", "Block #"),
)),
const SizedBox(
width: 8,
),
//// lot #
Flexible(
flex: 1,
child: FormBuilderTextField(
name: "lot_number",
decoration:
normalTextFieldStyle(
"Lot #*", "Lot #"),
)),
],
)
: Container(),
),
],
);
}),
const SizedBox(
height: 12,
),
//// Address Line
FormBuilderTextField(
name: "address_line",
decoration: normalTextFieldStyle(
"Address Line *", "Address Line"),
),
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) {
setState(() {
barangayCall = true;
});
selectedMunicipality = city;
getBarangays();
}
},
decoration:
normalTextFieldStyle(
"Municipality*",
"Municipality"),
value: selectedMunicipality,
items: citymuns == null
? []
: citymuns!.map<
DropdownMenuItem<
CityMunicipality>>(
(CityMunicipality c) {
return DropdownMenuItem(
value: c,
child: Text(c
.description!));
}).toList(),
),
),
),
//// BARANGAY
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: barangayCall,
child: DropdownButtonFormField<
Barangay>(
isExpanded: true,
onChanged: (Barangay? baragay) {
selectedBarangay = baragay;
},
decoration:
normalTextFieldStyle(
"Barangay*",
"Barangay"),
value: selectedBarangay,
items: barangays == null
? []
: barangays!.map<
DropdownMenuItem<
Barangay>>(
(Barangay barangay) {
return DropdownMenuItem(
value: barangay,
child: Text(barangay
.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) {},
),
),
),
],
);
}),
////sumit button
const Expanded(child: SizedBox()),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {},
child: const Text(submit)),
),
const SizedBox(
height: 20,
),
],
),
)),
),
);
}
return 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<AddressBloc>().add(CallErrorState());
}
}
Future<void> getCities() async {
try {
List<CityMunicipality> newCities = await LocationUtils.instance
.getCities(code: selectedProvince!.code.toString());
citymuns = newCities;
setState(() {
selectedMunicipality = newCities[0];
cityCall = false;
barangayCall = true;
getBarangays();
});
} catch (e) {
context.read<AddressBloc>().add(CallErrorState());
}
}
Future<void> getBarangays() async {
try {
List<Barangay> newBarangays = await LocationUtils.instance
.getBarangay(code: selectedMunicipality!.code.toString());
barangays = newBarangays;
setState(() {
selectedBarangay = newBarangays[0];
barangayCall = false;
});
} catch (e) {
context.read<AddressBloc>().add(CallErrorState());
}
}
}
class Area {
final int group;
final String value;
const Area({required this.group, required this.value});
}

View File

@ -0,0 +1,474 @@
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: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/utils/category.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 '../../../../../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';
class EditAddressScreen extends StatefulWidget {
final int profileId;
final String token;
const EditAddressScreen(
{super.key, required this.profileId, required this.token});
@override
State<EditAddressScreen> createState() => _EditAddressScreenState();
}
class _EditAddressScreenState extends State<EditAddressScreen> {
////boolean
bool hasLotandBlock = false;
bool overseas = false;
bool provinceCall = false;
bool cityCall = false;
bool barangayCall = false;
////selected
Region? selectedRegion;
Province? selectedProvince;
CityMunicipality? selectedMunicipality;
Barangay? selectedBarangay;
Country? selectedCountry;
////Lists
final List<Area> areaClass = [
const Area(value: "Rural Area", group: 0),
const Area(value: "Sitio", group: 1),
const Area(value: "Village", group: 1),
const Area(value: "Urban Area", group: 0),
const Area(value: "Town", group: 1),
const Area(value: "City", group: 1),
const Area(value: "Metropolis", group: 1),
const Area(value: "Megacity", group: 1),
];
final List<String> category = ["Permanent", "Residential", "Birthplace"];
List<Province>? provinces;
List<CityMunicipality>? citymuns;
List<Barangay>? barangays;
final formKey = GlobalKey<FormBuilderState>();
@override
Widget build(BuildContext context) {
return BlocBuilder<AddressBloc, AddressState>(
builder: (context, state) {
if (state is EditAddressState) {
return SingleChildScrollView(
child: SizedBox(
height: screenHeight * .90,
child: FormBuilder(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 25, horizontal: 18),
child: Column(
children: [
//// category
FormBuilderDropdown<String>(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration:
normalTextFieldStyle("Category*", "Category"),
name: "category",
onChanged: (String? category) {},
items: category.map<DropdownMenuItem<String>>(
(String category) {
return DropdownMenuItem(
value: category, child: Text(category));
}).toList()),
const SizedBox(
height: 12,
),
////Area Class
FormBuilderDropdown(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration: normalTextFieldStyle(
"Area class *", "Area class"),
name: "area_class",
onChanged: (Area? area) {},
items: areaClass
.map<DropdownMenuItem<Area>>((Area area) {
return area.group == 0
? DropdownMenuItem(
enabled: false,
value: area,
child: Text(area.value.toUpperCase(),
style: const TextStyle(
color: Colors.black38)))
: DropdownMenuItem(
value: area,
enabled: true,
child: Text(
" ${area.value.toUpperCase()}"));
}).toList()),
const SizedBox(
height: 12,
),
////stateful builder
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
////with block & Lot Switch
FormBuilderSwitch(
initialValue: hasLotandBlock,
activeColor: second,
onChanged: (value) {
setState(() {
hasLotandBlock = value!;
});
},
decoration: normalTextFieldStyle(
"With Lot and Block?", 'Graduated?'),
name: 'graudated',
title: Text(hasLotandBlock ? "YES" : "NO"),
),
SizedBox(
height: hasLotandBlock ? 12 : 0,
),
SizedBox(
width: screenWidth,
child: hasLotandBlock
? Row(
children: [
////block #
Flexible(
flex: 1,
child: FormBuilderTextField(
name: "block_number",
decoration:
normalTextFieldStyle(
"Block #*", "Block #"),
)),
const SizedBox(
width: 8,
),
//// lot #
Flexible(
flex: 1,
child: FormBuilderTextField(
name: "lot_number",
decoration:
normalTextFieldStyle(
"Lot #*", "Lot #"),
)),
],
)
: Container(),
),
],
);
}),
const SizedBox(
height: 12,
),
//// Address Line
FormBuilderTextField(
name: "address_line",
decoration: normalTextFieldStyle(
"Address Line *", "Address Line"),
),
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) {
setState(() {
barangayCall = true;
});
selectedMunicipality = city;
getBarangays();
}
},
decoration:
normalTextFieldStyle(
"Municipality*",
"Municipality"),
value: selectedMunicipality,
items: citymuns == null
? []
: citymuns!.map<
DropdownMenuItem<
CityMunicipality>>(
(CityMunicipality c) {
return DropdownMenuItem(
value: c,
child: Text(c
.description!));
}).toList(),
),
),
),
//// BARANGAY
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: barangayCall,
child: DropdownButtonFormField<
Barangay>(
isExpanded: true,
onChanged: (Barangay? baragay) {
selectedBarangay = baragay;
},
decoration:
normalTextFieldStyle(
"Barangay*",
"Barangay"),
value: selectedBarangay,
items: barangays == null
? []
: barangays!.map<
DropdownMenuItem<
Barangay>>(
(Barangay barangay) {
return DropdownMenuItem(
value: barangay,
child: Text(barangay
.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) {},
),
),
),
],
);
}),
////sumit button
const Expanded(child: SizedBox()),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {},
child: const Text(submit)),
),
const SizedBox(
height: 20,
),
],
),
)),
),
);
}
return 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<AddressBloc>().add(CallErrorState());
}
}
Future<void> getCities() async {
try {
List<CityMunicipality> newCities = await LocationUtils.instance
.getCities(code: selectedProvince!.code.toString());
citymuns = newCities;
setState(() {
selectedMunicipality = newCities[0];
cityCall = false;
barangayCall = true;
getBarangays();
});
} catch (e) {
context.read<AddressBloc>().add(CallErrorState());
}
}
Future<void> getBarangays() async {
try {
List<Barangay> newBarangays = await LocationUtils.instance
.getBarangay(code: selectedMunicipality!.code.toString());
barangays = newBarangays;
setState(() {
selectedBarangay = newBarangays[0];
barangayCall = false;
});
} catch (e) {
context.read<AddressBloc>().add(CallErrorState());
}
}
}
class Area {
final int group;
final String value;
const Area({required this.group, required this.value});
}

View File

@ -1,10 +1,15 @@
import 'package:app_popup_menu/app_popup_menu.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:fluttericon/font_awesome_icons.dart';
import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/model/profile/basic_information/adress.dart';
import 'package:unit2/screens/profile/components/basic_information/address/add_modal.dart';
import 'package:unit2/screens/profile/components/basic_information/address/edit_modal.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/global.dart';
@ -13,23 +18,37 @@ import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/empty_data.dart';
import 'package:unit2/widgets/error_state.dart';
class AddressScreen extends StatelessWidget {
import '../../../../utils/alerts.dart';
class AddressScreen extends StatelessWidget {
const AddressScreen({super.key});
@override
Widget build(BuildContext context) {
int? profileId;
String? token;
return Scaffold(
appBar: AppBar(
title: const Text(adressScreenTitle),
centerTitle: true,
backgroundColor: primary,
actions: [AddLeading(onPressed: () {})],
actions: [
AddLeading(onPressed: () {
context.read<AddressBloc>().add(ShowAddAddressForm());
})
],
),
body: ProgressHUD(
padding: const EdgeInsets.all(24),
indicatorWidget: const SpinKitFadingCircle(
color: Colors.white,
),
backgroundColor: Colors.black87,
child: BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is UserLoggedIn) {
token = state.userData!.user!.login!.token;
profileId = state.userData!.user!.login!.user!.profileId;
return BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
if (state is ProfileLoaded) {
@ -40,7 +59,9 @@ class AddressScreen extends StatelessWidget {
progress!.showWithText("Please wait...");
}
if (state is AddressLoadedState ||
state is AddressErrorState) {
state is AddressErrorState ||
state is AddAddressState ||
state is EditAddressState) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
@ -48,7 +69,7 @@ class AddressScreen extends StatelessWidget {
builder: (context, state) {
if (state is AddressLoadedState) {
if (state.addresses.isNotEmpty) {
return ListView.builder(
return ListView.builder(
padding: const EdgeInsets.symmetric(
vertical: 8, horizontal: 10),
itemCount: state.addresses.length,
@ -57,25 +78,25 @@ class AddressScreen extends StatelessWidget {
String? subdivision =
state.addresses[index].details ?? '';
String category = state.addresses[index]
.address!
.category!
.name!;
.address!.category!.name!;
String? barangay = state.addresses[index]
.address!
.barangay !=
.address!.barangay !=
null
? '${state.addresses[index].address!.barangay!.description!.toUpperCase()},'
: '';
String cityMunicipality = state.addresses[index]
String cityMunicipality = state
.addresses[index]
.address!
.cityMunicipality!
.description!;
String province = state.addresses[index]
String province = state
.addresses[index]
.address!
.cityMunicipality!
.province!
.description!;
String region = state.addresses[index]
String region = state
.addresses[index]
.address!
.cityMunicipality!
.province!
@ -128,12 +149,59 @@ class AddressScreen extends StatelessWidget {
),
],
)),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
))
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...");
}, "Delete?",
"Confirm Delete?");
}
if (value == 1) {
////edit eligibilty-= = = = = = = = =>>
final progress =
ProgressHUD.of(
context);
progress!.showWithText(
"Loading...");
context
.read<AddressBloc>()
.add(ShowEditAddressForm(
address: state
.addresses[
index]));
}
},
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",
)
]),
),
],
@ -150,6 +218,16 @@ class AddressScreen extends StatelessWidget {
"You don't have address added. Please click + to add.");
}
}
if (state is AddressErrorState) {
return SomethingWentWrong(
message: state.message, onpressed: () {});
}
if (state is AddAddressState) {
return AddAddressScreen(
profileId: profileId!, token: token!);
}if(state is EditAddressState){
return EditAddressScreen(profileId: profileId!, token: token!);
}
return Container();
},
);
@ -163,4 +241,23 @@ class AddressScreen 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

@ -0,0 +1,510 @@
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:form_builder_validators/form_builder_validators.dart';
import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/profile/education/education_bloc.dart';
import 'package:unit2/model/profile/educational_background.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/form-style.dart';
import 'package:unit2/utils/global.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart';
import '../../../../theme-data.dart/btn-style.dart';
import '../../../../theme-data.dart/colors.dart';
import '../../../../utils/text_container.dart';
import '../../shared/add_for_empty_search.dart';
class AddEducationScreen extends StatefulWidget {
final int profileId;
final String token;
const AddEducationScreen(
{super.key, required this.profileId, required this.token});
@override
State<AddEducationScreen> createState() => _AddEducationScreenState();
}
class _AddEducationScreenState extends State<AddEducationScreen> {
final List<EducationLevel> educationLevel = [
const EducationLevel(type: "label", value: "Basic Education", group: 1),
const EducationLevel(type: "level", value: "Elementary", group: 1),
const EducationLevel(type: "level", value: "Secondary (non-K12)", group: 1),
const EducationLevel(type: "level", value: "Junior High", group: 1),
const EducationLevel(type: "level", value: "Senior High", group: 1),
const EducationLevel(type: "label", value: "Higher Education", group: 2),
const EducationLevel(type: "level", value: "Collegiate", group: 2),
const EducationLevel(type: "level", value: "Vocational", group: 2),
const EducationLevel(type: "label", value: "Post Graduate", group: 2),
const EducationLevel(type: "level", value: "Masteral", group: 2),
const EducationLevel(type: "level", value: "Doctorate", group: 2),
];
List<ValueItem> valueItemHonorList = [];
////selected
EducationLevel? selectedLevel;
School? selectedSchool;
Course? selectedProgram;
List<Honor> selectedHonors = [];
List<ValueItem>? selectedValueItem;
final formKey = GlobalKey<FormBuilderState>();
////congrollers
final addProgramController = TextEditingController();
final addSchoolController = TextEditingController();
final fromController = TextEditingController();
final untilController = TextEditingController();
final yearGraduated = TextEditingController();
////focus node
final programFocusNode = FocusNode();
final schoolFocusNode = FocusNode();
final honorFocusNode = FocusNode();
////booleans
bool graduated = true;
int? unitsEarned;
////
@override
Widget build(BuildContext context) {
return BlocBuilder<EducationBloc, EducationState>(
builder: (context, state) {
if (state is AddEducationState) {
valueItemHonorList = state.honors.map((Honor honor) {
return ValueItem(label: honor.name!, value: honor.name);
}).toList();
return Container(
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 18),
child: FormBuilder(
key: formKey,
child: SingleChildScrollView(
child: SizedBox(
height: blockSizeVertical * 85,
child: Column(children: [
const SizedBox(
height: 12,
),
//// LEVEL
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderDropdown(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration:
normalTextFieldStyle("level*", "level"),
name: "education_level",
onChanged: (EducationLevel? level) {
setState(() {
selectedLevel = level;
});
},
items: educationLevel
.map<DropdownMenuItem<EducationLevel>>(
(EducationLevel level) {
return level.type == "label"
? DropdownMenuItem(
enabled: false,
value: level,
child: Text(level.value.toUpperCase(),
style: const TextStyle(
color: Colors.black38)))
: DropdownMenuItem(
value: level,
enabled: true,
child: Text(
" ${level.value.toUpperCase()}"));
}).toList()),
const SizedBox(
height: 12,
),
////school
StatefulBuilder(builder: (context, setState) {
return SearchField(
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.schools
.map((School school) =>
SearchFieldListItem(school.name!,
item: school,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: ListTile(
title: Text(school.name!)),
)))
.toList(),
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
focusNode: schoolFocusNode,
searchInputDecoration:
normalTextFieldStyle("School *", "").copyWith(
suffixIcon:
const Icon(Icons.arrow_drop_down)),
onSuggestionTap: (school) {
setState(() {
selectedSchool = school.item;
schoolFocusNode.unfocus();
});
},
emptyWidget: EmptyWidget(
title: "Add School",
controller: addSchoolController,
onpressed: () {
setState(() {
School newSchool = School(
id: null,
name: addSchoolController.text.toUpperCase());
state.schools.insert(0, newSchool);
addSchoolController.text = "";
Navigator.pop(context);
});
}),
);
}),
const SizedBox(
height: 12,
),
////Programs
Container(
child: selectedLevel != null &&
selectedLevel!.group != 1
? SearchField(
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.programs
.map((Course program) =>
SearchFieldListItem(
program.program!,
item: program,
child: Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 10),
child: ListTile(
title: Text(
program.program!)),
)))
.toList(),
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
focusNode: programFocusNode,
searchInputDecoration:
normalTextFieldStyle(
"Course/Programs *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
onSuggestionTap: (position) {
setState(() {
selectedProgram = position.item;
programFocusNode.unfocus();
});
},
emptyWidget: EmptyWidget(
title: "Add Program",
controller: addProgramController,
onpressed: () {
setState(() {
Course newProgram = Course(
id: null,
program: addProgramController
.text.toUpperCase());
state.programs.insert(0,newProgram);
addProgramController.text = "";
Navigator.pop(context);
});
}),
)
: Container())
],
);
}),
const SizedBox(
height: 12,
),
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
//// GRADUATED SWITCH
FormBuilderSwitch(
initialValue: graduated,
activeColor: second,
onChanged: (value) {
setState(() {
graduated = value!;
if (graduated) {
unitsEarned = null;
} else {
yearGraduated.text = "";
}
});
},
decoration: normalTextFieldStyle(
"Graduated?", 'Graduated?'),
name: 'graudated',
title: Text(graduated ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
////FROM
SizedBox(
width: screenWidth,
child: Row(
children: [
Flexible(
flex: 1,
child: FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This fied is required"),
decoration:
normalTextFieldStyle("from *", "from"),
name: "",
controller: fromController,
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
width: 300,
height: 300,
child: YearPicker(
firstDate: DateTime(
DateTime.now().year - 100,
1),
lastDate: DateTime(
DateTime.now().year + 100,
1),
initialDate: DateTime.now(),
selectedDate: DateTime.now(),
onChanged: (DateTime dateTime) {
fromController.text =
dateTime.year.toString();
Navigator.pop(context);
},
),
),
);
},
);
},
),
),
const SizedBox(
width: 8,
),
////UNTIL
Flexible(
flex: 1,
child: FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This fied is required"),
decoration: normalTextFieldStyle(
"until *", "until"),
name: "",
controller: untilController,
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
width: 300,
height: 300,
child: YearPicker(
firstDate: DateTime(
DateTime.now().year - 100,
1),
lastDate: DateTime(
DateTime.now().year + 100,
1),
initialDate: DateTime.now(),
selectedDate: DateTime.now(),
onChanged: (DateTime dateTime) {
untilController.text =
dateTime.year.toString();
Navigator.pop(context);
},
),
),
);
},
);
},
),
),
const SizedBox(
width: 8,
),
],
),
),
const SizedBox(
height: 12,
),
SizedBox(
child: graduated
////GRADUATED YEAR
? FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This fied is required"),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
width: 300,
height: 300,
child: YearPicker(
firstDate: DateTime(
DateTime.now().year - 100,
1),
lastDate: DateTime(
DateTime.now().year + 100,
1),
initialDate: DateTime.now(),
selectedDate: DateTime.now(),
onChanged: (DateTime dateTime) {
yearGraduated.text =
dateTime.year.toString();
Navigator.pop(context);
},
),
),
);
},
);
},
name: "year_graduated",
controller: yearGraduated,
decoration: normalTextFieldStyle(
"Year Graduated *", "Year Graduated *"),
)
//// HIGHEST UNITS EARNED
: FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This fied is required"),
name: "units_earned",
decoration: normalTextFieldStyle(
"Highest Level/Units Earned *",
"Highest Level/Units Earned *")),
),
],
);
}),
const SizedBox(
height: 12,
),
//// HONORS
MultiSelectDropDown(
onOptionSelected: (List<ValueItem> selectedOptions) {
selectedValueItem = selectedOptions;
},
borderColor: Colors.grey,
borderWidth: 1,
borderRadius: 5,
hint: "Honors",
padding: const EdgeInsets.all(8),
options: valueItemHonorList,
selectionType: SelectionType.multi,
chipConfig: const ChipConfig(wrapType: WrapType.wrap),
dropdownHeight: 300,
optionTextStyle: const TextStyle(fontSize: 16),
selectedOptionIcon: const Icon(Icons.check_circle),
),
////sumit button
const Expanded(child: SizedBox()),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style:
mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
if (formKey.currentState!.saveAndValidate()) {
//// program
if (selectedLevel!.value == "Elementary" ||
selectedLevel!.value ==
"Secondary (non-K12)" ||
selectedLevel!.value == "Junior High" ||
selectedLevel!.value == "Senior High") {
selectedProgram = null;
}
if (!graduated) {
unitsEarned = int.parse(formKey
.currentState!.value['units_earned']);
}
////education
Education newEducation = Education(
id: null,
level: selectedLevel!.value,
course: selectedProgram,
school: selectedSchool);
////honors
if (selectedValueItem != null) {
for (var honor in selectedValueItem!) {
Honor newHonor = state.honors.firstWhere((element) => element.name == honor.value);
selectedHonors.add(newHonor);
}
}
EducationalBackground educationalBackground =
EducationalBackground(
id: null,
honors: null,
education: newEducation,
periodTo: untilController.text,
periodFrom: fromController.text,
yearGraduated:
graduated ? yearGraduated.text : null,
unitsEarned: !graduated ? unitsEarned : null,
attachments: null,
);
final progress = ProgressHUD.of(context);
progress!.showWithText("Loading...");
context.read<EducationBloc>().add(AddEducation(
educationalBackground: educationalBackground,
profileId: widget.profileId,
token: widget.token,
honors: selectedHonors));
}
},
child: const Text(submit)),
),
const SizedBox(
height: 20,
),
]),
),
),
),
);
}
return Container();
},
);
}
}
class EducationLevel {
final String value;
final String type;
final int group;
const EducationLevel(
{required this.type, required this.value, required this.group});
}

View File

@ -0,0 +1,564 @@
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:form_builder_validators/form_builder_validators.dart';
import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/profile/education/education_bloc.dart';
import 'package:unit2/model/profile/educational_background.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/form-style.dart';
import 'package:unit2/utils/global.dart';
import '../../../../theme-data.dart/btn-style.dart';
import '../../../../theme-data.dart/colors.dart';
import '../../../../utils/text_container.dart';
import '../../shared/add_for_empty_search.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart';
class EditEducationScreen extends StatefulWidget {
final int profileId;
final String token;
const EditEducationScreen(
{super.key, required this.profileId, required this.token});
@override
State<EditEducationScreen> createState() => _EditEducationScreenState();
}
class _EditEducationScreenState extends State<EditEducationScreen> {
final List<EducationLevel> educationLevel = [
const EducationLevel(type: "label", value: "Basic Education", group: 1),
const EducationLevel(type: "level", value: "Elementary", group: 1),
const EducationLevel(type: "level", value: "Secondary (non-K12)", group: 1),
const EducationLevel(type: "level", value: "Junior High", group: 1),
const EducationLevel(type: "level", value: "Senior High", group: 1),
const EducationLevel(type: "label", value: "Higher Education", group: 2),
const EducationLevel(type: "level", value: "Collegiate", group: 2),
const EducationLevel(type: "level", value: "Vocational", group: 2),
const EducationLevel(type: "label", value: "Post Graduate", group: 2),
const EducationLevel(type: "level", value: "Masteral", group: 2),
const EducationLevel(type: "level", value: "Doctorate", group: 2),
];
List<ValueItem> valueItemHonorList = [];
List<ValueItem> selectedValueItem = [];
////selected
EducationLevel? selectedLevel;
School? selectedSchool;
Course? selectedProgram;
List<Honor> selectedHonors = [];
final formKey = GlobalKey<FormBuilderState>();
////congrollers
final addProgramController = TextEditingController();
final addSchoolController = TextEditingController();
final fromController = TextEditingController();
final untilController = TextEditingController();
final yearGraduated = TextEditingController();
final currentSchoolController = TextEditingController();
final currentProgramController = TextEditingController();
final unitsController = TextEditingController(); ////focus node
final programFocusNode = FocusNode();
final schoolFocusNode = FocusNode();
final honorFocusNode = FocusNode();
////booleans
bool graduated = true;
@override
Widget build(BuildContext context) {
return BlocBuilder<EducationBloc, EducationState>(
builder: (context, state) {
if (state is EditEducationState) {
////selected level
selectedLevel = educationLevel.firstWhere((element) =>
element.value.toUpperCase() ==
state.educationalBackground.education!.level);
currentSchoolController.text =
state.educationalBackground.education!.school!.name!;
if (selectedLevel != null && selectedLevel!.group != 1) {
currentProgramController.text =
state.educationalBackground.education!.course!.program!;
}
////year grduated and units earned
if (state.educationalBackground.yearGraduated != null) {
graduated = true;
yearGraduated.text = state.educationalBackground.yearGraduated!;
} else {
unitsController.text =
state.educationalBackground.unitsEarned.toString();
graduated = false;
}
fromController.text = state.educationalBackground.periodFrom!;
untilController.text = state.educationalBackground.periodTo!;
////honors
////get all honors
valueItemHonorList = state.honors.map((Honor honor) {
return ValueItem(label: honor.name!, value: honor.name);
}).toList();
return Container(
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 18),
child: FormBuilder(
key: formKey,
child: SingleChildScrollView(
child: SizedBox(
height: blockSizeVertical * 85,
child: Column(children: [
const SizedBox(
height: 12,
),
//// LEVEL
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
FormBuilderDropdown(
initialValue: selectedLevel,
validator: FormBuilderValidators.required(
errorText: "This field is required"),
decoration:
normalTextFieldStyle("level*", "level"),
name: "education_level",
onChanged: (EducationLevel? level) {
setState(() {
selectedLevel = level;
});
},
items: educationLevel
.map<DropdownMenuItem<EducationLevel>>(
(EducationLevel level) {
return level.type == "label"
? DropdownMenuItem(
enabled: false,
value: level,
child: Text(level.value.toUpperCase(),
style: const TextStyle(
color: Colors.black38)))
: DropdownMenuItem(
value: level,
enabled: true,
child: Text(
" ${level.value.toUpperCase()}"));
}).toList()),
const SizedBox(
height: 12,
),
////school
StatefulBuilder(builder: (context, setState) {
return SearchField(
controller: currentSchoolController,
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.schools
.map((School school) =>
SearchFieldListItem(school.name!,
item: school,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10),
child: ListTile(
title: Text(school.name!)),
)))
.toList(),
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
focusNode: schoolFocusNode,
searchInputDecoration:
normalTextFieldStyle("School *", "").copyWith(
suffixIcon:
const Icon(Icons.arrow_drop_down)),
onSuggestionTap: (school) {
setState(() {
selectedSchool = school.item;
schoolFocusNode.unfocus();
});
},
emptyWidget: EmptyWidget(
title: "Add School",
controller: addSchoolController,
onpressed: () {
setState(() {
School newSchool = School(
id: null,
name: addSchoolController.text
.toUpperCase());
state.schools.insert(0, newSchool);
addSchoolController.text = "";
Navigator.pop(context);
});
}),
);
}),
const SizedBox(
height: 12,
),
////Programs
Container(
child: selectedLevel != null &&
selectedLevel!.group != 1
? SearchField(
suggestionAction:
SuggestionAction.unfocus,
controller: currentProgramController,
itemHeight: 50,
suggestionsDecoration: box1(),
suggestions: state.programs
.map((Course program) =>
SearchFieldListItem(
program.program!,
item: program,
child: Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 10),
child: ListTile(
title: Text(
program.program!)),
)))
.toList(),
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
focusNode: programFocusNode,
searchInputDecoration:
normalTextFieldStyle(
"Course/Programs *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
onSuggestionTap: (position) {
setState(() {
selectedProgram = position.item;
programFocusNode.unfocus();
});
},
emptyWidget: EmptyWidget(
title: "Add Program",
controller: addProgramController,
onpressed: () {
setState(() {
Course newProgram = Course(
id: null,
program: addProgramController
.text
.toUpperCase());
state.programs
.insert(0, newProgram);
addProgramController.text = "";
Navigator.pop(context);
});
}),
)
: Container())
],
);
}),
const SizedBox(
height: 12,
),
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
//// GRADUATED SWITCH
FormBuilderSwitch(
initialValue: graduated,
activeColor: second,
onChanged: (value) {
setState(() {
graduated = value!;
if (graduated) {
unitsController.text = "";
} else {
yearGraduated.text = "";
}
});
},
decoration: normalTextFieldStyle(
"Graduated?", 'Graduated?'),
name: 'graudated',
title: Text(graduated ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
////FROM
SizedBox(
width: screenWidth,
child: Row(
children: [
Flexible(
flex: 1,
child: FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This fied is required"),
decoration:
normalTextFieldStyle("from *", "from"),
name: "",
controller: fromController,
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
width: 300,
height: 300,
child: YearPicker(
firstDate: DateTime(
DateTime.now().year - 100,
1),
lastDate: DateTime(
DateTime.now().year + 100,
1),
initialDate: DateTime.now(),
selectedDate: DateTime.now(),
onChanged: (DateTime dateTime) {
fromController.text =
dateTime.year.toString();
Navigator.pop(context);
},
),
),
);
},
);
},
),
),
const SizedBox(
width: 8,
),
////UNTIL
Flexible(
flex: 1,
child: FormBuilderTextField(
validator: FormBuilderValidators.required(
errorText: "This fied is required"),
decoration: normalTextFieldStyle(
"until *", "until"),
name: "",
controller: untilController,
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
width: 300,
height: 300,
child: YearPicker(
firstDate: DateTime(
DateTime.now().year - 100,
1),
lastDate: DateTime(
DateTime.now().year + 100,
1),
initialDate: DateTime.now(),
selectedDate: DateTime.now(),
onChanged: (DateTime dateTime) {
untilController.text =
dateTime.year.toString();
Navigator.pop(context);
},
),
),
);
},
);
},
),
),
const SizedBox(
width: 8,
),
Flexible(
flex: 1,
child: graduated
////GRADUATED YEAR
? FormBuilderTextField(
validator:
FormBuilderValidators.required(
errorText:
"This fied is required"),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: SizedBox(
width: 300,
height: 300,
child: YearPicker(
firstDate: DateTime(
DateTime.now().year -
100,
1),
lastDate: DateTime(
DateTime.now().year +
100,
1),
initialDate:
DateTime.now(),
selectedDate:
DateTime.now(),
onChanged:
(DateTime dateTime) {
yearGraduated.text =
dateTime.year
.toString();
Navigator.pop(context);
},
),
),
);
},
);
},
name: "year_graduated",
controller: yearGraduated,
decoration: normalTextFieldStyle(
"Year Graduated *",
"Year Graduated *"),
)
//// HIGHEST UNITS EARNED
: FormBuilderTextField(
validator:
FormBuilderValidators.required(
errorText:
"This fied is required"),
controller: unitsController,
name: "units_earned",
decoration: normalTextFieldStyle(
"Highest Level/Units Earned *",
"Highest Level/Units Earned *")),
)
],
),
)
],
);
}),
const SizedBox(
height: 12,
),
//// HONORS
StatefulBuilder(builder: (context, setState) {
return MultiSelectDropDown(
onOptionSelected: (List<ValueItem> selectedOptions) {
selectedValueItem = selectedOptions;
},
borderColor: Colors.grey,
borderWidth: 1,
borderRadius: 5,
hint: "Honors",
padding: const EdgeInsets.all(8),
options: valueItemHonorList,
selectionType: SelectionType.multi,
chipConfig: const ChipConfig(wrapType: WrapType.wrap),
dropdownHeight: 300,
optionTextStyle: const TextStyle(fontSize: 16),
selectedOptionIcon: const Icon(Icons.check_circle),
selectedOptions:
(state.educationalBackground.honors!.isNotEmpty &&
state.educationalBackground.honors != null)
? selectedValueItem = state
.educationalBackground.honors!
.map((Honor honor) => ValueItem(
label: honor.name!, value: honor.name))
.toList()
: [],
);
}),
////sumit button
const Expanded(child: SizedBox()),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style:
mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
if (formKey.currentState!.saveAndValidate()) {
//// program
if (selectedLevel!.value == "Elementary" ||
selectedLevel!.value ==
"Secondary (non-K12)" ||
selectedLevel!.value == "Junior High" ||
selectedLevel!.value == "Senior High") {
selectedProgram = null;
}else{
selectedProgram ??= state.educationalBackground.education!.course;
}
selectedSchool ??= state.educationalBackground.education!.school;
////education
Education newEducation = Education(
id: null,
level: selectedLevel!.value,
course: selectedProgram,
school: selectedSchool);
////honors
if (selectedValueItem.isNotEmpty) {
for (var honor in selectedValueItem) {
Honor newHonor = state.honors.firstWhere(
(element) => element.name == honor.value);
selectedHonors.add(newHonor);
}
}
EducationalBackground educationalBackground =
EducationalBackground(
id: state.educationalBackground.id,
honors: null,
education: newEducation,
periodTo: untilController.text,
periodFrom: fromController.text,
yearGraduated:
graduated ? yearGraduated.text : null,
unitsEarned: !graduated
? int.parse(unitsController.text)
: null,
attachments: null,
);
final progress = ProgressHUD.of(context);
progress!.showWithText("Loading...");
context.read<EducationBloc>().add(UpdateEducation(
educationalBackground: educationalBackground,
profileId: widget.profileId,
token: widget.token,
honors: selectedHonors));
}
},
child: const Text(submit)),
),
const SizedBox(
height: 20,
),
]),
),
),
),
);
}
return Container();
},
);
}
}
class EducationLevel {
final String value;
final String type;
final int group;
const EducationLevel(
{required this.type, required this.value, required this.group});
}

View File

@ -1,11 +1,14 @@
import 'package:app_popup_menu/app_popup_menu.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:fluttericon/font_awesome_icons.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/model/profile/educational_background.dart';
import 'package:unit2/screens/profile/components/education/add_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';
@ -14,18 +17,26 @@ import 'package:unit2/widgets/empty_data.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../bloc/profile/education/education_bloc.dart';
import '../../../utils/alerts.dart';
import 'education/edit_modal.dart';
class EducationScreen extends StatelessWidget {
const EducationScreen({super.key});
@override
Widget build(BuildContext context) {
int profileId;
String? token;
return Scaffold(
appBar: AppBar(
title: const Text(educationScreenTitle),
centerTitle: true,
backgroundColor: primary,
actions: [AddLeading(onPressed: () {})],
actions: [
AddLeading(onPressed: () {
context.read<EducationBloc>().add(ShowAddEducationForm());
})
],
),
//userbloc
body: ProgressHUD(
@ -35,6 +46,8 @@ class EducationScreen extends StatelessWidget {
child: BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is UserLoggedIn) {
token = state.userData!.user!.login!.token;
profileId = state.userData!.user!.login!.user!.profileId!;
//profilebloc
return BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
@ -47,10 +60,77 @@ class EducationScreen extends StatelessWidget {
progress!.showWithText("Please wait...");
}
if (state is EducationalBackgroundLoadedState ||
state is EducationalBackgroundErrorState) {
state is EducationalBackgroundErrorState ||
state is AddEducationState ||
state is EditEducationState ||
state is EducationDeletedState || state is EditedEducationState) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
////ADDED STATE
if (state is EducationAddedState) {
if (state.response['success']) {
successAlert(context, "Adding Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
} else {
errorAlert(context, "Adding Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
}
}
////EDITED STATE
if (state is EditedEducationState) {
if (state.response['success']) {
successAlert(context, "Update Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
} else {
errorAlert(context, "Updated Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
}
}
////DELETED STATE
if (state is EducationDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
"Educational Background has been deleted successfully",
() {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
} else {
errorAlert(context, "Deletion Failed",
"Error deleting Education Background", () {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
}
}
},
builder: (context, state) {
if (state is EducationalBackgroundLoadedState) {
@ -181,12 +261,67 @@ class EducationScreen extends StatelessWidget {
),
]),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
))
AppPopupMenu<int>(
offset: const Offset(-10, -10),
elevation: 3,
onSelected: (value) {
////delete -= = = = = = = = =>>
if (value == 2) {
confirmAlert(context, () {
final progress =
ProgressHUD.of(
context);
progress!.showWithText(
"Loading...");
context
.read<EducationBloc>()
.add(DeleteEducation(
educationalBackground:
state.educationalBackground[
index],
profileId:
profileId,
token: token!));
}, "Delete?",
"Confirm Delete?");
}
if (value == 1) {
////edit -= = = = = = = = =>>
final progress =
ProgressHUD.of(context);
progress!.showWithText(
"Loading...");
context
.read<EducationBloc>()
.add(ShowEditEducationForm(
profileId:
profileId,
token: token!,
educationalBackground:
state.educationalBackground[
index]));
}
},
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",
)
],
),
),
@ -206,6 +341,18 @@ class EducationScreen extends StatelessWidget {
return SomethingWentWrong(
message: state.message, onpressed: () {});
}
if (state is AddEducationState) {
return AddEducationScreen(
token: token!,
profileId: profileId,
);
}
if (state is EditEducationState) {
return EditEducationScreen(
token: token!,
profileId: profileId,
);
}
return Container();
},
);
@ -219,4 +366,23 @@ class EducationScreen 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

@ -64,383 +64,399 @@ class _AddEligibilityScreenState extends State<AddEligibilityScreen> {
return SingleChildScrollView(
child: SizedBox(
height: screenHeight * .95,
child: ProgressHUD(
child: Center(
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 25, horizontal: 18),
child: FormBuilder(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
////ELIGIBILITIES DROPDOWN
FormBuilderDropdown<Eligibility>(
onChanged: (Eligibility? eligibility) {
selectedEligibility = eligibility;
},
autovalidateMode:
AutovalidateMode.onUserInteraction,
validator: (value) =>
value == null ? 'required' : null,
items: state.eligibilities
.map<DropdownMenuItem<Eligibility>>(
(Eligibility eligibility) {
return DropdownMenuItem<Eligibility>(
value: eligibility,
child: Text(eligibility.title));
}).toList(),
name: "eligibility",
decoration: normalTextFieldStyle(
"Eligibility", "Eligibility")),
const SizedBox(
height: 8,
),
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 25, horizontal: 18),
child: FormBuilder(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
////ELIGIBILITIES DROPDOWN
FormBuilderDropdown<Eligibility>(
onChanged: (Eligibility? eligibility) {
selectedEligibility = eligibility;
},
autovalidateMode:
AutovalidateMode.onUserInteraction,
validator: (value) =>
value == null ? 'required' : null,
items: state.eligibilities
.map<DropdownMenuItem<Eligibility>>(
(Eligibility eligibility) {
return DropdownMenuItem<Eligibility>(
value: eligibility,
child: Text(eligibility.title));
}).toList(),
name: "eligibility",
decoration: normalTextFieldStyle(
"Eligibility", "Eligibility")),
const SizedBox(
height: 8,
),
SizedBox(
width: screenWidth,
child: Row(
children: [
////LICENSE NUMBER
Flexible(
flex: 1,
child: FormBuilderTextField(
onChanged: (value) {
license = value;
},
name: 'license_number',
decoration: normalTextFieldStyle(
"license number", "license number"),
),
SizedBox(
width: screenWidth,
child: Row(
children: [
////LICENSE NUMBER
Flexible(
flex: 1,
child: FormBuilderTextField(
onChanged: (value) {
license = value;
},
name: 'license_number',
decoration: normalTextFieldStyle(
"license number", "license number"),
),
const SizedBox(
width: 8,
),
const SizedBox(
width: 8,
),
////RATING
Flexible(
flex: 1,
child: FormBuilderTextField(
keyboardType: const TextInputType
.numberWithOptions(),
onChanged: (value) {
rating = value;
},
name: 'rating',
decoration: normalTextFieldStyle(
'rating %', 'rating'),
),
////RATING
Flexible(
flex: 1,
child: FormBuilderTextField(
keyboardType:
const TextInputType.numberWithOptions(),
onChanged: (value) {
rating = value;
},
name: 'rating',
decoration: normalTextFieldStyle(
'rating %', 'rating'),
),
),
],
),
),
],
),
const SizedBox(
height: 8,
),
SizedBox(
width: screenWidth,
child: Row(
children: [
////EXAM DATE
Flexible(
flex: 1,
child: DateTimePicker(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
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", "")
.copyWith(
prefixIcon: const Icon(
Icons.date_range,
color: Colors.black87,
)),
initialValue: null,
)),
const SizedBox(
width: 8,
),
////VALIDITY DATE
Flexible(
),
const SizedBox(
height: 8,
),
SizedBox(
width: screenWidth,
child: Row(
children: [
////EXAM DATE
Flexible(
flex: 1,
child: DateTimePicker(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
controller: validityDateController,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
use24HourFormat: false,
icon: const Icon(Icons.date_range),
controller: examDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
timeHintText:
"Date of Examination/Conferment",
decoration: normalTextFieldStyle(
"Validity date", "Validity date")
"Exam date", "")
.copyWith(
prefixIcon: const Icon(
Icons.date_range,
color: Colors.black87,
)),
initialValue: null,
),
),
],
),
),
const SizedBox(
height: 8,
),
Text(
"Placement of Examination/Conferment",
style: Theme.of(context)
.textTheme
.displaySmall!
.copyWith(fontSize: blockSizeVertical * 2),
),
const SizedBox(
height: 8,
),
////OVERSEAS ADDRESS SWITCH
Column(
children: [
FormBuilderSwitch(
validator: FormBuilderValidators.required(
errorText: 'This field is required'),
initialValue: overseas,
activeColor: second,
onChanged: (value) {
setState(() {
overseas = value;
});
},
decoration: normalTextFieldStyle("", ''),
name: 'overseas',
title: const Text("Overseas Address?"),
),
)),
const SizedBox(
height: 8,
width: 8,
),
////COUNTRY DROPDOWN
SizedBox(
child: overseas == true
? 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;
},
)
: Column(
children: [
////REGION DROPDOWN
FormBuilderDropdown<Region?>(
autovalidateMode: AutovalidateMode
.onUserInteraction,
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
//// region onchange
onChanged: (Region? region) async {
if(selectedRegion != region){
setState(() {
////VALIDITY DATE
Flexible(
flex: 1,
child: DateTimePicker(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
controller: validityDateController,
firstDate: DateTime(1970),
lastDate: DateTime(2100),
decoration: normalTextFieldStyle(
"Validity date", "Validity date")
.copyWith(
prefixIcon: const Icon(
Icons.date_range,
color: Colors.black87,
)),
initialValue: null,
),
),
],
),
),
const SizedBox(
height: 8,
),
Text(
"Placement of Examination/Conferment",
style: Theme.of(context)
.textTheme
.displaySmall!
.copyWith(fontSize: blockSizeVertical * 2),
),
const SizedBox(
height: 8,
),
////OVERSEAS ADDRESS SWITCH
Column(
children: [
FormBuilderSwitch(
validator: FormBuilderValidators.required(
errorText: 'This field is required'),
initialValue: overseas,
activeColor: second,
onChanged: (value) {
setState(() {
overseas = value;
});
},
decoration: normalTextFieldStyle("", ''),
name: 'overseas',
title: const Text("Overseas Address?"),
),
const SizedBox(
height: 8,
),
////COUNTRY DROPDOWN
SizedBox(
child: overseas == true
? 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;
},
)
: Column(
children: [
////REGION DROPDOWN
FormBuilderDropdown<Region?>(
autovalidateMode:
AutovalidateMode
.onUserInteraction,
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
//// region onchange
onChanged:
(Region? region) async {
if (selectedRegion !=
region) {
setState(() {
provinceCall = true;
});
selectedRegion = region;
selectedRegion = region;
getProvinces();
}
},
initialValue: selectedRegion,
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: 70,
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")),
),
),
//// CityMunicipalities dropdown
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: cityCall,
child: DropdownButtonFormField<
CityMunicipality>(
}
},
initialValue: selectedRegion,
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: 70,
child: ModalProgressHUD(
color: Colors.transparent,
inAsyncCall: provinceCall,
child: DropdownButtonFormField<
Province?>(
autovalidateMode:
AutovalidateMode
.onUserInteraction,
validator: (value) =>
value == null
? 'required'
: null,
isExpanded: true,
value: selectedProvince,
onChanged:
(CityMunicipality? city) {
selectedMunicipality = city;
(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(
"Municipality*",
"Municipality"),
value: selectedMunicipality,
items: citymuns == null
? []
: citymuns!.map<
DropdownMenuItem<
CityMunicipality>>(
(CityMunicipality c) {
return DropdownMenuItem(
value: c,
child: Text(c
.description!));
}).toList(),
),
"Province*",
"Province")),
),
),
//// CityMunicipalities dropdown
SizedBox(
height: 60,
child: ModalProgressHUD(
color: Colors.white,
inAsyncCall: cityCall,
child:
DropdownButtonFormField<
CityMunicipality>(
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 Expanded(
child: SizedBox(),
),
const Expanded(
child: SizedBox(),
),
SizedBox(
width: screenWidth,
height: 60,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
//rating
double? rate = rating == null
? null
: double.parse(rating!);
//lisence
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);
SizedBox(
width: screenWidth,
height: 60,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
//rating
double? rate = rating == null
? null
: double.parse(rating!);
//lisence
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()) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Loading...");
context.read<EligibilityBloc>().add(
AddEligibility(
eligibityCert: eligibityCert,
profileId:
widget.profileId.toString(),
token: widget.token));
}
// context.read<ProfileBloc>().add(AddEligibility(eligibityCert: eligibityCert, profileId: profileId, token: token))
},
child: const Text(submit)),
),
const SizedBox(
height: 20,
),
]),
),
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()) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Loading...");
context.read<EligibilityBloc>().add(
AddEligibility(
eligibityCert: eligibityCert,
profileId:
widget.profileId.toString(),
token: widget.token));
}
// context.read<ProfileBloc>().add(AddEligibility(eligibityCert: eligibityCert, profileId: profileId, token: token))
},
child: const Text(submit)),
),
const SizedBox(
height: 20,
),
]),
),
),
),

View File

@ -5,6 +5,7 @@ import 'package:flutter_spinkit/flutter_spinkit.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/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/text_container.dart';
@ -18,12 +19,16 @@ class VolunataryWorkScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
String? token;
int? profileId;
DateFormat dteFormat2 = DateFormat.yMMMMd('en_US');
return Scaffold(
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),
@ -32,6 +37,9 @@ class VolunataryWorkScreen extends StatelessWidget {
child: BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is UserLoggedIn) {
token = state.userData!.user!.login!.token;
profileId =
state.userData!.user!.login!.user!.profileId;
return BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
if (state is ProfileLoaded) {
@ -43,7 +51,7 @@ class VolunataryWorkScreen extends StatelessWidget {
progress!.showWithText("Please wait...");
}
if (state is VoluntaryWorkLoadedState ||
state is VoluntaryWorkErrorState) {
state is VoluntaryWorkErrorState|| state is AddVoluntaryWorkState) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
@ -138,6 +146,8 @@ 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!,);
}
return Container();
},

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@ 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:searchfield/searchfield.dart';
import 'package:unit2/screens/profile/shared/add_for_empty_search.dart';
import '../../../../bloc/profile/profile_bloc.dart';
import '../../../../bloc/profile/workHistory/workHistory_bloc.dart';
import '../../../../bloc/user/user_bloc.dart';
@ -129,84 +130,22 @@ class _EditWorkHistoryScreenState extends State<EditWorkHistoryScreen> {
positionFocusNode.unfocus();
});
},
emptyWidget: Container(
decoration: box1(),
height: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(
height: 20,
),
const Text("No result found..."),
const SizedBox(
height: 10,
),
TextButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
"Add Position?"),
content: SizedBox(
height: 130,
child: Column(
children: [
TextFormField(
controller:
addPositionController,
decoration:
normalTextFieldStyle(
"", ""),
),
const SizedBox(
height: 12,
),
SizedBox(
width:
double.infinity,
height: 50,
child:
ElevatedButton(
style: mainBtnStyle(
primary,
Colors
.transparent,
second),
onPressed:
() {
setState(
() {
Position
newAgencyPosition =
Position(
id: null,
title: addPositionController.text.toUpperCase());
state.agencyPositions.insert(
0,
newAgencyPosition);
selectedPosition =
newAgencyPosition;
addPositionController.text =
"";
Navigator.pop(
context);
});
},
child: const Text(
"Add"))),
],
),
),
);
});
},
child: const Text("Add position"))
]),
),
emptyWidget: EmptyWidget(
controller: addPositionController,
onpressed: () {
setState(() {
Position newAgencyPosition = Position(
id: null,
title: addPositionController.text
.toUpperCase());
state.agencyPositions
.insert(0, newAgencyPosition);
selectedPosition = newAgencyPosition;
addPositionController.text = "";
Navigator.pop(context);
});
},
title: "Add Position"),
validator: (position) {
if (position!.isEmpty) {
return "This field is required";
@ -253,139 +192,77 @@ class _EditWorkHistoryScreenState extends State<EditWorkHistoryScreen> {
return Column(
children: [
SearchField(
controller: oldAgencyController,
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"
: "Government"),
)))
.toList(),
searchInputDecoration: normalTextFieldStyle(
"Agency *", "")
.copyWith(
suffixIcon:
const Icon(Icons.arrow_drop_down)),
onSuggestionTap: (agency) {
setState(() {
selectedAgency = agency.item;
if (selectedAgency!.privateEntity == null) {
showIsPrivateRadio = true;
} else {
showIsPrivateRadio = false;
controller: oldAgencyController,
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"
: "Government"),
)))
.toList(),
searchInputDecoration:
normalTextFieldStyle("Agency *", "")
.copyWith(
suffixIcon: const Icon(
Icons.arrow_drop_down)),
onSuggestionTap: (agency) {
setState(() {
selectedAgency = agency.item;
if (selectedAgency!.privateEntity ==
null) {
showIsPrivateRadio = true;
} else {
showIsPrivateRadio = false;
}
if (selectedAgency!.privateEntity ==
true) {
showSalaryGradeAndSalaryStep = false;
}
if (selectedAgency!.privateEntity ==
false) {
showSalaryGradeAndSalaryStep = true;
}
agencyFocusNode.unfocus();
});
},
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
if (selectedAgency!.privateEntity == true) {
showSalaryGradeAndSalaryStep = false;
}
if (selectedAgency!.privateEntity ==
false) {
showSalaryGradeAndSalaryStep = true;
}
agencyFocusNode.unfocus();
});
},
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
emptyWidget: Container(
decoration: box1(),
height: 100,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
const SizedBox(
height: 20,
),
const Text("No result found"),
const SizedBox(
height: 10,
),
TextButton(
onPressed: () {
showDialog(
context: context,
builder:
(BuildContext context) {
return AlertDialog(
title: const Text(
"Add Position"),
content: SizedBox(
height: 130,
child: Column(
children: [
TextFormField(
controller:
addAgencyController,
decoration:
normalTextFieldStyle(
"", ""),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double
.infinity,
height: 50,
child:
ElevatedButton(
style: mainBtnStyle(
primary,
Colors
.transparent,
second),
onPressed:
() {
setState(
() {
Agency newAgency = Agency(
id: null,
name: addAgencyController.text.toUpperCase(),
category: null,
privateEntity: null);
state.agencies.insert(0,
newAgency);
selectedAgency =
newAgency;
addAgencyController.text =
"";
showAgencyCategory =
true;
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);
selectedAgency = newAgency;
addAgencyController.text = "";
showAgencyCategory = true;
showIsPrivateRadio =
true;
showIsPrivateRadio = true;
Navigator.pop(context);
});
},
child: const Text(
"Add"))),
],
),
),
);
});
},
child: const Text("Add Agency"))
]),
),
),
Navigator.pop(context);
});
},
title: "Add Agency")),
SizedBox(
height: showAgencyCategory ? 12 : 0,

View File

@ -0,0 +1,597 @@
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

@ -0,0 +1,68 @@
import 'package:flutter/material.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';
class EmptyWidget extends StatelessWidget {
final TextEditingController controller;
final Function()? onpressed;
final String title;
const EmptyWidget(
{super.key, required this.controller, required this.onpressed,required this.title});
@override
Widget build(BuildContext context) {
return Container(
decoration: box1(),
height: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(
height: 20,
),
const Text("No result found..."),
const SizedBox(
height: 10,
),
TextButton(
onPressed: () {
////ADD POSITION DIALOG
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: SizedBox(
height: 130,
child: Column(
children: [
TextFormField(
controller: controller,
decoration: normalTextFieldStyle("", ""),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: onpressed,
child: const Text("Add"))),
],
),
),
);
});
},
child: Text(title))
]),
);
}
}

View File

@ -1,97 +1,224 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:unit2/screens/docsms/components/request_receipt.dart';
import 'package:unit2/screens/docsms/index.dart';
import 'package:unit2/screens/unit2/homepage.dart/module-screen.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/global.dart';
import 'package:unit2/utils/global_context.dart';
import 'package:unit2/utils/qr_scanner.dart';
import 'package:unit2/utils/text_container.dart';
import '../../../../bloc/docsms/docsms_bloc.dart';
class DashBoard extends StatelessWidget {
final List<Module> roles;
const DashBoard({super.key, required this.roles});
@override
Widget build(BuildContext context) {
List<String> finishRoles = [];
return Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 24),
height: MediaQuery.of(context).size.height,
//listview builder
////listview builder
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: roles.length,
itemBuilder: (BuildContext context, int index) {
// gridview.count
return SizedBox(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
roles[index].name.toUpperCase(),
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontSize: 12),
),
const SizedBox(
height: 8,
),
GridView.count(
shrinkWrap: true,
crossAxisCount: 4,
crossAxisSpacing: 8,
mainAxisSpacing: 10,
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 5),
children: roles[index].roles.map((role) {
return Container(
padding: const EdgeInsetsDirectional.fromSTEB(8,5,8,13),
alignment: Alignment.center,
decoration:const BoxDecoration(
color: Colors.white,
boxShadow:[ BoxShadow(color: Colors.black12,spreadRadius: 2,blurRadius: 3)],
borderRadius: BorderRadius.all(Radius.circular(8))
),
child: GestureDetector(
onTap: () {
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Icon(
role.icon,
size: 20,
weight: 100,
grade: 100,
color:second,
),
),
const SizedBox(
height: 5,
),
Text(
role.role.name!.toLowerCase() == "establishment point-person"?"Est. point-person":
role.role.name!,
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(
fontSize: blockSizeVertical*1.1,
fontWeight: FontWeight.bold),
),
]),
),
);
}).toList()),
const SizedBox(height: 8,)
],
),
);
//// gridview.count
return roles[index].roles.isNotEmpty
? SizedBox(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
roles[index].name.toUpperCase(),
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontSize: 12),
),
const SizedBox(
height: 8,
),
GridView.count(
shrinkWrap: true,
crossAxisCount: 4,
crossAxisSpacing: 8,
mainAxisSpacing: 10,
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 5),
children: roles[index].roles.map((role) {
//// if role name is qr code && finishRoles not contain security
//// this card will visible if the user has qr code scanner or security role
if (role.role.name!.toLowerCase() ==
'qr code scanner' &&
!finishRoles.contains("security")) {
finishRoles.add('scanner');
//// loop thru module to find unit module exist
for (var element in role.role.modules!) {
if (element!.name!.toLowerCase() == 'unit2') {
for (var element in element.objects!) {
//// loop thru objects to find pass check exist
if (element!.id == 9 &&
//// check if operations contains read and write
element.operations!
.contains("read")) {
//// if all conditions are true return card
return CardLabel(
ontap: () {},
icon: role.icon,
title: "Pass Check",
);
}
}
}
}
return Container();
//// if role name is security
//// this card will visible if the user has qr code scanner or security role
} else if (role.role.name!.toLowerCase() ==
'security guard' &&
!finishRoles.contains('scanner')) {
finishRoles.add('security');
for (var element in role.role.modules!) {
if (element!.name!.toLowerCase() == 'unit2') {
for (var element in element.objects!) {
if (element!.id == 9 &&
element.operations!
.contains("read")) {
return CardLabel(
ontap: () {},
icon: role.icon,
title: "Pass Check",
);
}
}
}
}
return Container();
//// if role name is field surveyor
} else if (role.role.name!.toLowerCase() ==
'field surveyor') {
for (var element in role.role.modules!) {
if (element!.name!.toLowerCase() == 'rpass') {
for (var element in element.objects!) {
if (element!.id == 11 &&
element.operations!
.contains("read")) {
return CardLabel(
ontap: () {},
icon: role.icon,
title: "Field Surveyor",
);
}
}
}
}
return Container();
//// if role name is process server
} else if (role.role.name!.toLowerCase() ==
'process server') {
for (var element in role.role.modules!) {
if (element!.name!.toLowerCase() ==
'document management') {
for (var element in element.objects!) {
if (element!.id == 3 &&
element.operations!
.contains("read")) {
return CardLabel(
ontap: () async {
String? qrBarcode =
await qrScanner();
if (qrBarcode != null) {
Navigator.push(NavigationService.navigatorKey.currentContext!, MaterialPageRoute(builder:
(BuildContext context) {
return BlocProvider(
create: (context) => DocsmsBloc()
..add(LoadDocument(
documentId: qrBarcode)),
child:
const AutoReceiveDocument(),
);
}));
}
},
icon: role.icon,
title: "Process Server",
);
}
}
}
}
return Container();
} else {
return Container();
}
}).toList()),
const SizedBox(
height: 8,
)
],
),
)
: Container();
}),
);
}
}
// ignore: must_be_immutable
class CardLabel extends StatelessWidget {
final String title;
final IconData icon;
final Function()? ontap;
const CardLabel(
{super.key,
required this.icon,
required this.title,
required this.ontap});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: ontap,
child: Container(
padding: const EdgeInsetsDirectional.fromSTEB(8, 5, 8, 13),
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.black12, spreadRadius: 2, blurRadius: 3)
],
borderRadius: BorderRadius.all(Radius.circular(8))),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Icon(
icon,
size: 20,
weight: 100,
grade: 100,
color: second,
),
),
const SizedBox(
height: 5,
),
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.labelLarge!.copyWith(
fontSize: blockSizeVertical * 1.2,
fontWeight: FontWeight.bold),
),
]),
),
);
}
}

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart';
import 'package:fluttericon/font_awesome5_icons.dart';
import 'package:fluttericon/font_awesome_icons.dart';
import 'package:fluttericon/rpg_awesome_icons.dart';
import 'package:fluttericon/typicons_icons.dart';
import 'package:unit2/screens/unit2/homepage.dart/components/dashboard.dart';
import 'package:unit2/theme-data.dart/colors.dart';
@ -21,7 +22,8 @@ class MainScreen extends StatefulWidget {
class _MainScreenState extends State<MainScreen> {
List<Module> roles = [
Module(name: 'UniT2 module operations', roles: []),
Module(name: 'DocSms module operations', roles: [])
Module(name: 'DocSms module operations', roles: []),
Module(name: "RPAss module operations",roles:[] )
];
@override
Widget build(BuildContext context) {
@ -43,6 +45,10 @@ class _MainScreenState extends State<MainScreen> {
IconData iconData = iconGenerator(getRole!.name!);
Roles newRole = Roles(role: getRole, icon: iconData);
roles[1].roles.add(newRole);
} if (module.name!.toLowerCase() == 'rpass') {
IconData iconData = iconGenerator(getRole!.name!);
Roles newRole = Roles(role: getRole, icon: iconData);
roles[2].roles.add(newRole);
}
}
}
@ -97,6 +103,8 @@ class _MainScreenState extends State<MainScreen> {
case 'process server':
iconData = Typicons.doc_text;
break;
case 'field surveyor':
iconData = RpgAwesome.telescope;
}
return iconData!;
}

View File

@ -0,0 +1,36 @@
import 'dart:convert';
import 'package:unit2/utils/request.dart';
import 'package:unit2/utils/urls.dart';
import 'package:http/http.dart' as http;
import '../../model/docsms/document.dart';
class AutoReceiveDocumentServices{
static final AutoReceiveDocumentServices _instance = AutoReceiveDocumentServices();
static AutoReceiveDocumentServices get instance => _instance;
Future<Document?> getDocument(String documentId) async {
String path = Url.instance.getDocument();
Document? document;
Map<String, String> params = {"t1.id": documentId.toString()};
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
try {
http.Response response = await Request.instance.getRequest(param: params,path:path,headers:headers);
if (response.statusCode == 200) {
Map data = json.decode(response.body);
if(data['message'].toString().toLowerCase() == "data successfully fetched."){
document = Document.fromJson(data['data']);
}else{
document = null;
}
}
} catch (e) {
throw (e.toString());
}
return document;
}
}

View File

@ -9,12 +9,12 @@ import 'package:http/http.dart' as http;
class EducationService {
static final EducationService _instance = EducationService();
static EducationService get instace => _instance;
////get educational background
Future<List<EducationalBackground>> getEducationalBackground(
int profileId, String token) async {
List<EducationalBackground> educationalBackgrounds = [];
String authToken = "Token $token";
String path = "${Url.instance.getEducationalBackgrounds()}$profileId/";
String path = "${Url.instance.educationalBackground()}$profileId/";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authToken
@ -38,4 +38,201 @@ class EducationService {
return educationalBackgrounds;
}
////Add
Future<Map<dynamic, dynamic>> add(
{required EducationalBackground educationalBackground,
required String token,
required int profileId,
required List<Honor> honors}) async {
String authtoken = "Token $token";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authtoken
};
String path = '${Url.instance.educationalBackground()}$profileId/';
Map<dynamic, dynamic> statusResponse = {};
Map body = {
"_level": educationalBackground.education!.level,
"_schoolId": educationalBackground.education?.school?.id,
"_schoolName": educationalBackground.education!.school!.name,
"_programId": educationalBackground.education?.course?.id,
"_programName": educationalBackground.education?.course?.program,
"_course": null,
"period_from": educationalBackground.periodFrom.toString(),
"period_to": educationalBackground.periodTo.toString(),
"units_earned": educationalBackground.unitsEarned,
"year_graduated": educationalBackground.yearGraduated,
"honors": honors.isEmpty ? [] : honors,
};
try {
http.Response response = await Request.instance
.postRequest(path: path, param: {}, body: body, headers: headers);
if (response.statusCode == 201) {
Map data = jsonDecode(response.body);
statusResponse = data;
} else {
statusResponse.addAll({'success': false});
}
} catch (e) {
throw e.toString();
}
return statusResponse;
}
////Edit
Future<Map<dynamic, dynamic>> edit(
{required EducationalBackground educationalBackground,
required String token,
required int profileId,
required List<Honor> honors}) async {
String authtoken = "Token $token";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authtoken
};
String path = '${Url.instance.educationalBackground()}$profileId/';
Map<dynamic, dynamic> statusResponse = {};
Map body = {
"id": educationalBackground.id,
"_level": educationalBackground.education!.level,
"_schoolId": educationalBackground.education?.school?.id,
"_schoolName": educationalBackground.education!.school!.name,
"_programId": educationalBackground.education?.course?.id,
"_programName": educationalBackground.education?.course?.program,
"_course": null,
"period_from": educationalBackground.periodFrom.toString(),
"period_to": educationalBackground.periodTo.toString(),
"units_earned": educationalBackground.unitsEarned,
"year_graduated": educationalBackground.yearGraduated,
"honors": honors.isEmpty ? [] : honors,
};
try {
http.Response response = await Request.instance
.putRequest(path: path, param: {}, body: body, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
statusResponse = data;
} else {
statusResponse.addAll({'success': false});
}
} catch (e) {
throw e.toString();
}
return statusResponse;
}
//// delete
Future<bool> delete(
{required int profileId,
required String token,
required EducationalBackground educationalBackground}) async {
String authToken = "Token $token";
String path = "${Url.instance.educationalBackground()}$profileId/";
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authToken
};
bool? success;
Map<String, dynamic> params = {"force_mode": "true"};
Map body = {
"id": educationalBackground.id,
"_level": educationalBackground.education!.level,
"_schoolId": educationalBackground.education!.school!.id,
"education_id": educationalBackground.education!.id,
"period_from": educationalBackground.periodFrom,
"period_to": educationalBackground.periodTo,
"units_earned": educationalBackground.unitsEarned,
"year_graduated": educationalBackground.yearGraduated,
"honors": educationalBackground.honors
};
try {
http.Response response = await Request.instance.deleteRequest(
path: path, headers: headers, body: body, param: params);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
success = data['success'];
} else {
success = false;
}
} catch (e) {
throw e.toString();
}
return success!;
}
//// get schools
Future<List<School>> getSchools() async {
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
List<School> schools = [];
String path = Url.instance.getSchools();
try {
http.Response response = await Request.instance
.getRequest(param: {}, path: path, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
if (data['data'] != null) {
data['data'].forEach((school) {
School newSchool = School.fromJson(school);
schools.add(newSchool);
});
}
}
} catch (e) {
throw e.toString();
}
return schools;
}
Future<List<Course>> getPrograms() async {
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
List<Course> programs = [];
String path = Url.instance.getPrograms();
try {
http.Response response = await Request.instance
.getRequest(param: {}, path: path, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
if (data['data'] != null) {
data['data'].forEach((course) {
Course newCourse = Course.fromJson(course);
programs.add(newCourse);
});
}
}
} catch (e) {
throw e.toString();
}
return programs;
}
////get honors
Future<List<Honor>> getHonors() async {
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
List<Honor> honors = [];
String path = Url.instance.getHonors();
try {
http.Response response = await Request.instance
.getRequest(param: {}, path: path, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
if (data['data'] != null) {
data['data'].forEach((honor) {
Honor newHonor = Honor.fromJson(honor);
honors.add(newHonor);
});
}
}
} catch (e) {
throw e.toString();
}
return honors;
}
}

View File

@ -164,7 +164,7 @@ class WorkHistoryService {
}
//get agency position
////get agency position
Future<List<Position>> getAgencyPosition() async {
List<Position> agencyPositions = [];
String path = Url.instance.getPositions();

View File

@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:unit2/bloc/docsms/docsms_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/sos/sos_bloc.dart';
import 'package:unit2/screens/docsms/index.dart';
import 'package:unit2/screens/sos/index.dart';
import 'package:unit2/screens/unit2/homepage.dart/components/menu.dart';
import 'package:unit2/screens/unit2/login/login.dart';
@ -51,6 +53,7 @@ class AppRouter {
child: const SosScreen(),
);
});
default:
return MaterialPageRoute(builder: (context) {
return Container();

View File

@ -1,4 +1,3 @@
import 'dart:convert';
import 'package:unit2/model/location/country.dart';
@ -11,35 +10,63 @@ import 'package:unit2/utils/urls.dart';
import '../model/profile/basic_information/contact_information.dart';
import '../model/utils/agency.dart';
import '../model/utils/category.dart';
import '../model/utils/position.dart';
class ProfileUtilities {
static final ProfileUtilities _instance = ProfileUtilities();
static ProfileUtilities get instance => _instance;
Future<List<Eligibility>>getEligibilities()async{
List<Eligibility> eligibilities=[];
Future<List<Eligibility>> getEligibilities() async {
List<Eligibility> eligibilities = [];
String path = Url.instance.eligibilities();
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
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){
data['data'].forEach((var eligibility){
Eligibility newEligibilities = Eligibility.fromJson(eligibility);
eligibilities.add(newEligibilities);
});
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) {
data['data'].forEach((var eligibility) {
Eligibility newEligibilities = Eligibility.fromJson(eligibility);
eligibilities.add(newEligibilities);
});
}
}
} catch (e) {
throw (e.toString());
}
}
}catch(e){
throw(e.toString());
}
return eligibilities;
return eligibilities;
}
//get agencies
////get agency position
Future<List<Position>> getAgencyPosition() async {
List<Position> agencyPositions = [];
String path = Url.instance.getPositions();
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
try {
http.Response response = await Request.instance
.getRequest(param: {}, path: path, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
if (data['data'] != null) {
data['data'].forEach((var agencyPosition) {
Position position = Position.fromJson(agencyPosition);
agencyPositions.add(position);
});
}
}
} catch (e) {
throw (e.toString());
}
return agencyPositions;
}
////get agencies
Future<List<Agency>> getAgecies() async {
List<Agency> agencies = [];
String path = Url.instance.getAgencies();
@ -64,8 +91,7 @@ class ProfileUtilities {
return agencies;
}
//get agency category
////get agency category
Future<List<Category>> agencyCategory() async {
List<Category> agencyCategory = [];
String path = Url.instance.getAgencyCategory();
@ -91,28 +117,28 @@ class ProfileUtilities {
}
//// get service type
Future<List<ServiceType>> getServiceType()async{
Future<List<ServiceType>> getServiceType() async {
List<ServiceType> serviceTypes = [];
Map<String, String> headers = {
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
};
String path = Url.instance.getServiceTypes();
try{
http.Response response = await Request.instance.getRequest(param: {},path:path,headers: headers );
if(response.statusCode == 200){
try {
http.Response response = await Request.instance
.getRequest(param: {}, path: path, headers: headers);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
if(data['data'] != null){
for(var element in data['data']){
if (data['data'] != null) {
for (var element in data['data']) {
ServiceType newServiceType = ServiceType.fromJson(element);
serviceTypes.add(newServiceType);
}
}
}
}catch(e){
} catch (e) {
throw e.toString();
}
return serviceTypes;
}
}

View File

@ -0,0 +1,17 @@
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:unit2/utils/scanner.dart';
Future<String?> qrScanner() async {
String? result;
try {
ScanResult afterScan = await QRCodeBarCodeScanner.instance.scanner();
if (afterScan.type == ResultType.Barcode) {
result = afterScan.rawContent;
return result;
}
} catch (e) {
throw e.toString();
}
return null;
}

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() {
@ -27,6 +27,11 @@ class Url {
return "/api/sos_app/sos_request/";
}
//// DOCSMS paths
String getDocument(){
return "/api/web_app/public/document_viewer/";
}
////ELIGIBILITIES PATHS
String eligibilities(){
return "/api/jobnet_app/eligibilities/";
@ -57,17 +62,24 @@ String getAgencies(){
return "/api/jobnet_app/agencies/";
}
String getAgencyCategory(){
return "api/jobnet_app/agency_categories/";
}
////educational background paths
String getEducationalBackgrounds(){
String educationalBackground(){
return "/api/jobnet_app/profile/pds/education/";
}
String getSchools(){
return "/api/jobnet_app/schools/";
}
String getPrograms(){
return "api/jobnet_app/education_programs/";
}
String getHonors(){
return "/api/jobnet_app/honors";
}
//// learning and development paths

View File

@ -677,6 +677,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
location:
dependency: "direct main"
description:
name: location
sha256: "9051959f6f2ccadd887b28b66e9cbbcc25b6838e37cf9e894c421ccc0ebf80b5"
url: "https://pub.dev"
source: hosted
version: "4.4.0"
location_platform_interface:
dependency: transitive
description:
name: location_platform_interface
sha256: "62eeaf1658e92e4459b727f55a3c328eccbac8ba043fa6d262ac5286ad48384c"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
location_web:
dependency: transitive
description:
name: location_web
sha256: "6c08c408a040534c0269c4ff9fe17eebb5a36dea16512fbaf116b9c8bc21545b"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
logging:
dependency: transitive
description:
@ -741,6 +765,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.0"
multi_dropdown:
dependency: "direct main"
description:
name: multi_dropdown
sha256: "65b8f505b251c5173e8eff64c09cd37460d8f8be906c2069a03815ad2641dcd1"
url: "https://pub.dev"
source: hosted
version: "1.0.9"
nested:
dependency: transitive
description:

View File

@ -77,7 +77,7 @@ 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,
dev_dependencies:
flutter_test: