contact refactor and created its own bloc

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-03-07 15:01:56 +08:00
parent 367402b288
commit 5bea76102c
9 changed files with 480 additions and 162 deletions

View File

@ -0,0 +1,22 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import '../../../../model/profile/basic_information/contact_information.dart';
part 'contact_event.dart';
part 'contact_state.dart';
class ContactBloc extends Bloc<ContactEvent, ContactState> {
ContactBloc() : super(ContactInitial()) {
List<ContactInfo> contactInformations = [];
on<GetContacts>((event, emit) {
emit(ContactLoadingState());
try {
contactInformations = event.contactInformations;
emit(ContactLoadedState(contactInformation: contactInformations));
} catch (e) {
emit(ContactErrorState(message: e.toString()));
}
});
}
}

View File

@ -0,0 +1,16 @@
part of 'contact_bloc.dart';
abstract class ContactEvent extends Equatable {
const ContactEvent();
@override
List<Object> get props => [];
}
class GetContacts extends ContactEvent{
final List<ContactInfo> contactInformations;
const GetContacts({required this.contactInformations});
@override
List<Object> get props => [];
}

View File

@ -0,0 +1,27 @@
part of 'contact_bloc.dart';
abstract class ContactState extends Equatable {
const ContactState();
@override
List<Object> get props => [];
}
class ContactInitial extends ContactState {}
class ContactLoadedState extends ContactState{
final List<ContactInfo> contactInformation;
const ContactLoadedState({required this.contactInformation});
@override
List<Object> get props => [];
}
class ContactLoadingState extends ContactState{
}
class ContactErrorState extends ContactState{
final String message;
const ContactErrorState({required this.message});
@override
List<Object> get props => [message];
}

View File

@ -0,0 +1,21 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import '../../../../model/profile/basic_information/identification_information.dart';
part 'identification_event.dart';
part 'identification_state.dart';
class IdentificationBloc extends Bloc<IdentificationEvent, IdentificationState> {
IdentificationBloc() : super(IdentificationInitial()) {
List<Identification> identificationInformations = [];
on<GetIdentifications>((event, emit) {
try{
identificationInformations = event.identificationInformation;
emit(IdentificationLoadedState(identificationInformation: identificationInformations));
}catch(e){
emit(IdenficationErrorState(message: e.toString()));
}
});
}
}

View File

@ -0,0 +1,15 @@
part of 'identification_bloc.dart';
abstract class IdentificationEvent extends Equatable {
const IdentificationEvent();
@override
List<Object> get props => [];
}
class GetIdentifications extends IdentificationEvent{
final List<Identification> identificationInformation;
const GetIdentifications({required this.identificationInformation});
@override
List<Object> get props => [identificationInformation];
}

View File

@ -0,0 +1,28 @@
part of 'identification_bloc.dart';
abstract class IdentificationState extends Equatable {
const IdentificationState();
@override
List<Object> get props => [];
}
class IdentificationInitial extends IdentificationState {}
class IdentificationLoadedState extends IdentificationState{
final List<Identification> identificationInformation;
const IdentificationLoadedState({required this.identificationInformation});
@override
List<Object> get props => [identificationInformation];
}
class IdenficationErrorState extends IdentificationState{
final String message;
const IdenficationErrorState({required this.message});
@override
List<Object> get props => [message];
}
class IdentificationLoadingState extends IdentificationState{
}

View File

@ -1,5 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:unit2/model/profile/basic_information/contact_information.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/profile/primary_information/contact/contact_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart'; import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/text_container.dart'; import 'package:unit2/utils/text_container.dart';
@ -7,73 +12,178 @@ import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/empty_data.dart'; import 'package:unit2/widgets/empty_data.dart';
class ContactInformationScreen extends StatelessWidget { class ContactInformationScreen extends StatelessWidget {
final List<ContactInfo> contacts; const ContactInformationScreen({
const ContactInformationScreen({super.key, required this.contacts}); super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text(contactScreenTitle), title: const Text(contactScreenTitle),
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
actions: [AddLeading(onPressed: (){})], actions: [AddLeading(onPressed: () {})],
), ),
body: contacts.isNotEmpty? ListView.builder( body: ProgressHUD(
padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 10), padding: const EdgeInsets.all(24),
itemCount: contacts.length, backgroundColor: Colors.black87,
itemBuilder: (BuildContext context, int index) { indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
String numberMail = contacts[index].numbermail!; child: BlocBuilder<UserBloc, UserState>(
String commService = contacts[index].commService!.serviceProvider!.alias!; builder: (context, state) {
return Column( if (state is UserLoggedIn) {
mainAxisAlignment: MainAxisAlignment.start, return BlocBuilder<ProfileBloc, ProfileState>(
crossAxisAlignment: CrossAxisAlignment.start, builder: (context, state) {
children: [ if (state is ProfileLoaded) {
Container( return BlocConsumer<ContactBloc, ContactState>(
decoration: box1(), listener: (context, state) {
padding: const EdgeInsets.symmetric(horizontal: 12,vertical: 8), if (state is ContactLoadingState) {
child: Row( final progress = ProgressHUD.of(context);
children: [ progress!.showWithText("Please wait...");
Expanded( }
child: Column( if (state is ContactLoadedState ||
mainAxisAlignment: MainAxisAlignment.start, state is ContactErrorState) {
crossAxisAlignment: CrossAxisAlignment.start, final progress = ProgressHUD.of(context);
children: [ progress!.dismiss();
Text(numberMail,style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500)), }
const Divider(), },
const SizedBox(height: 5,), builder: (context, state) {
Row( if (state is ContactLoadedState) {
children: [ if (state.contactInformation.isNotEmpty) {
Expanded( return ListView.builder(
child: Text(commService padding: const EdgeInsets.symmetric(
.toString(),style: Theme.of(context).textTheme.titleSmall,), vertical: 8, horizontal: 10),
), itemCount: state.contactInformation.length,
itemBuilder:
contacts[index].active==true? const Badge(backgroundColor: Colors.green, label: Text("Active",),):const SizedBox(), (BuildContext context, int index) {
const SizedBox(width: 5), String numberMail = state
contacts[index].primary==true? const Badge(backgroundColor: Colors.blue, label: Text("Primary"),):const SizedBox() .contactInformation[index]
], .numbermail!;
), String commService = state
const SizedBox(height: 5,), .contactInformation[index]
Text(contacts[index].commService! .commService!
.serviceProvider!.agency!.name .serviceProvider!
.toString()), .alias!;
return Column(
]), mainAxisAlignment:
), MainAxisAlignment.start,
IconButton(onPressed: (){}, icon: const Icon(Icons.more_vert,color: Colors.grey,)) crossAxisAlignment:
], CrossAxisAlignment.start,
), children: [
), Container(
const SizedBox(height: 5,), decoration: box1(),
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
child: Row(
], children: [
); Expanded(
}):const EmptyData(message: "You don't have contact information added. Please click + to add"), child: Column(
), mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(numberMail,
style: Theme.of(
context)
.textTheme
.titleMedium!
.copyWith(
fontWeight:
FontWeight
.w500)),
const Divider(),
const SizedBox(
height: 5,
),
Row(
children: [
Expanded(
child: Text(
commService
.toString(),
style: Theme.of(
context)
.textTheme
.titleSmall,
),
),
state.contactInformation[index]
.active ==
true
? const Badge(
backgroundColor:
Colors
.green,
label: Text(
"Active",
),
)
: const SizedBox(),
const SizedBox(
width: 5),
state.contactInformation[index]
.primary ==
true
? const Badge(
backgroundColor:
Colors
.blue,
label: Text(
"Primary"),
)
: const SizedBox()
],
),
const SizedBox(
height: 5,
),
Text(state
.contactInformation[
index]
.commService!
.serviceProvider!
.agency!
.name
.toString()),
]),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
))
],
),
),
const SizedBox(
height: 5,
),
],
);
});
} else {
const EmptyData(
message:
"You don't have contact information added. Please click + to add");
}
}
return Container();
},
);
}
return Container();
},
);
}
return Container();
},
),
)),
); );
} }
} }

View File

@ -1,4 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:unit2/bloc/profile/primary_information/identification/identification_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/model/profile/basic_information/identification_information.dart'; import 'package:unit2/model/profile/basic_information/identification_information.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart'; import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/theme-data.dart/colors.dart';
@ -7,76 +10,140 @@ import 'package:unit2/utils/text_container.dart';
import 'package:unit2/widgets/Leadings/add_leading.dart'; import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/empty_data.dart'; import 'package:unit2/widgets/empty_data.dart';
import '../../../../bloc/user/user_bloc.dart';
class IdentificationsScreen extends StatelessWidget { class IdentificationsScreen extends StatelessWidget {
final List<Identification> identities; const IdentificationsScreen({super.key});
const IdentificationsScreen({super.key, required this.identities});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text(identificationScreenTitle), title: const Text(identificationScreenTitle),
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
actions: [AddLeading(onPressed: (){})], actions: [AddLeading(onPressed: () {})],
), ),
body:identities.isNotEmpty? ListView.builder( body: BlocBuilder<UserBloc, UserState>(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), builder: (context, state) {
itemCount: identities.length, if (state is UserLoggedIn) {
itemBuilder: (BuildContext context, int index) { return BlocBuilder<ProfileBloc, ProfileState>(
String agency = identities[index].agency!.name!; builder: (context, state) {
String idNumber = identities[index].identificationNumber!; if (state is ProfileLoaded) {
bool government = identities[index].agency!.privateEntity!; return BlocConsumer<IdentificationBloc,
String issuedAt = "${identities[index].issuedAt!.cityMunicipality!.description!} ${identities[index].issuedAt!.cityMunicipality!.province!.description}"; IdentificationState>(
return Column( listener: (context, state) {},
mainAxisAlignment: MainAxisAlignment.start, builder: (context, state) {
crossAxisAlignment: CrossAxisAlignment.start, if (state is IdentificationLoadedState) {
children: [ if (state.identificationInformation.isNotEmpty) {
Container( return ListView.builder(
width: screenWidth, padding: const EdgeInsets.symmetric(
decoration: box1(), vertical: 8, horizontal: 10),
padding: itemCount: state.identificationInformation.length,
const EdgeInsets.symmetric(horizontal: 12, vertical: 8), itemBuilder: (BuildContext context, int index) {
child: Row( String agency =
children: [ state.identificationInformation[index].agency!.name!;
Expanded( String idNumber =
child: Column( state.identificationInformation[index].identificationNumber!;
mainAxisAlignment: MainAxisAlignment.start, bool government =
crossAxisAlignment: CrossAxisAlignment.start, state.identificationInformation[index].agency!.privateEntity!;
children: [ String issuedAt =
Expanded(child: Text(agency,style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w400))), "${state.identificationInformation[index].issuedAt!.cityMunicipality!.description!} ${state.identificationInformation[index].issuedAt!.cityMunicipality!.province!.description}";
const Divider(), return Column(
const SizedBox(height: 5,), mainAxisAlignment: MainAxisAlignment.start,
Expanded( crossAxisAlignment:
child: Text( CrossAxisAlignment.start,
"$idNumberText : $idNumber",style: Theme.of(context).textTheme.titleSmall, children: [
), Container(
), decoration: box1(),
padding: const EdgeInsets.symmetric(
Badge( horizontal: 12, vertical: 8),
child: Row(
backgroundColor: success2, children: [
label: Text( Expanded(
government == child: Column(
true mainAxisAlignment:
? privateText.toUpperCase() MainAxisAlignment.start,
:governmentText.toUpperCase(), crossAxisAlignment:
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.white),)), CrossAxisAlignment.start,
const SizedBox(height: 5,), children: [
Text(issuedAt), Text(agency,
]), style: Theme.of(context)
), .textTheme
IconButton( .titleMedium!
onPressed: () {}, icon: const Icon(Icons.more_vert,color: Colors.grey,)) .copyWith(
], fontWeight:
), FontWeight
), .w400)),
const SizedBox( const Divider(),
height: 5, const SizedBox(
), height: 5,
], ),
); Row(children: [
}):const EmptyData(message: "You don't have identifications added. Please click + to add."), Expanded(
); child: Text(
"$idNumberText : $idNumber",
style:
Theme.of(context)
.textTheme
.titleSmall,
),
),
Badge(
backgroundColor:
success2,
label: Text(
government == true
? privateText
.toUpperCase()
: governmentText
.toUpperCase(),
style: Theme.of(
context)
.textTheme
.bodySmall!
.copyWith(
color: Colors
.white),
))
]),
const SizedBox(
height: 5,
),
Text(issuedAt),
]),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
))
],
),
),
const SizedBox(
height: 5,
),
],
);
});
} else {
const EmptyData(
message:
"You don't have identifications added. Please click + to add.");
}
}
return Container();
},
);
}
return Container();
},
);
}
return Container();
},
));
} }
} }

View File

@ -9,6 +9,8 @@ import 'package:fluttericon/entypo_icons.dart';
import 'package:fluttericon/font_awesome5_icons.dart'; import 'package:fluttericon/font_awesome5_icons.dart';
import 'package:fluttericon/modern_pictograms_icons.dart'; import 'package:fluttericon/modern_pictograms_icons.dart';
import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart'; import 'package:unit2/bloc/profile/primary_information/address/address_bloc.dart';
import 'package:unit2/bloc/profile/primary_information/contact/contact_bloc.dart';
import 'package:unit2/bloc/profile/primary_information/identification/identification_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/screens/profile/components/basic_information/address_screen.dart'; import 'package:unit2/screens/profile/components/basic_information/address_screen.dart';
import 'package:unit2/screens/profile/components/basic_information/citizenship_screen.dart'; import 'package:unit2/screens/profile/components/basic_information/citizenship_screen.dart';
@ -117,35 +119,43 @@ class _ProfileInfoState extends State<ProfileInfo> {
})); }));
}), }),
subMenu(Icons.home, "Home Addresses", () { subMenu(Icons.home, "Home Addresses", () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => AddressBloc() create: (context) => AddressBloc()
..add(GetAddress( ..add(GetAddress(
addresses: state.profileInformation.basicInfo.addresses)), addresses: state.profileInformation
child: const AddressScreen(), .basicInfo.addresses)),
); child: const AddressScreen(),
})); );
}));
}), }),
subMenu(Icons.contact_mail, "Identifications", subMenu(Icons.contact_mail, "Identifications",
() { () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) { builder: (BuildContext context) {
return IdentificationsScreen( return BlocProvider(
identities: state.profileInformation create: (context) => IdentificationBloc()
.basicInfo.identifications); ..add(GetIdentifications(
identificationInformation: state
.profileInformation
.basicInfo
.identifications)),
child: const IdentificationsScreen(),
);
})); }));
}), }),
subMenu(Icons.contact_phone, "Contact Info", subMenu(Icons.contact_phone, "Contact Info",
() { () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) { builder: (BuildContext context) {
return ContactInformationScreen( return BlocProvider(
contacts: state.profileInformation create: (context) => ContactBloc()
.basicInfo.contactInformation, ..add(GetContacts(
); contactInformations: state.profileInformation.basicInfo.contactInformation)),
})); child: ContactInformationScreen(),
);
}));
}), }),
subMenu(Icons.flag, "Citizenships", () { subMenu(Icons.flag, "Citizenships", () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
@ -162,7 +172,7 @@ class _ProfileInfoState extends State<ProfileInfo> {
icon: Elusive.group, icon: Elusive.group,
title: "Family", title: "Family",
onTap: () { onTap: () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => FamilyBloc() create: (context) => FamilyBloc()
@ -300,28 +310,30 @@ class _ProfileInfoState extends State<ProfileInfo> {
}), }),
subMenu(FontAwesome5.certificate, subMenu(FontAwesome5.certificate,
"Organization Memberships", () { "Organization Memberships", () {
Navigator.push(context, MaterialPageRoute( Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => OrganizationMembershipBloc() create: (context) =>
..add(GetOrganizationMembership( OrganizationMembershipBloc()
profileId: profileId!, ..add(GetOrganizationMembership(
token: token!)), profileId: profileId!,
token: token!)),
child: const OrgMembershipsScreen(), child: const OrgMembershipsScreen(),
); );
})); }));
}), }),
subMenu(Entypo.doc_text, subMenu(Entypo.doc_text,
"Non-Academic Recognitions", () { "Non-Academic Recognitions", () {
Navigator.push(context, MaterialPageRoute(
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => NonAcademicRecognitionBloc() create: (context) =>
..add(GetNonAcademicRecognition( NonAcademicRecognitionBloc()
profileId: profileId!, ..add(GetNonAcademicRecognition(
token: token!)), profileId: profileId!,
child: const NonAcademicRecognitionScreen(), token: token!)),
child:
const NonAcademicRecognitionScreen(),
); );
})); }));
}), }),