add search functions to superadmin screens

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-10-03 08:33:10 +08:00
parent ba89592496
commit deeca18962
38 changed files with 3517 additions and 2576 deletions

View File

@ -51,10 +51,13 @@ class LearningDevelopmentBloc
attachmentCategories = attachmentCategories =
await AttachmentServices.instance.getCategories(); await AttachmentServices.instance.getCategories();
} }
List<LearningDevelopement> learnings = await LearningDevelopmentServices if(learningsAndDevelopments.isEmpty){
List<LearningDevelopement> learnings = await LearningDevelopmentServices
.instance .instance
.getLearningDevelopments(event.profileId, event.token); .getLearningDevelopments(event.profileId, event.token);
learningsAndDevelopments = learnings; learningsAndDevelopments = learnings;
}
emit(LearningDevelopmentLoadedState( emit(LearningDevelopmentLoadedState(
learningsAndDevelopment: learningsAndDevelopments,attachmentCategory: attachmentCategories)); learningsAndDevelopment: learningsAndDevelopments,attachmentCategory: attachmentCategories));
} catch (e) { } catch (e) {

View File

@ -64,6 +64,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
primaryBasicInformation: globalCurrentProfile!)); primaryBasicInformation: globalCurrentProfile!));
} else { } else {
currentProfileInformation = event.primaryBasicInformation; currentProfileInformation = event.primaryBasicInformation;
globalCurrentProfile = currentProfileInformation;
emit(BasicInformationProfileLoaded( emit(BasicInformationProfileLoaded(
primaryBasicInformation: currentProfileInformation!)); primaryBasicInformation: currentProfileInformation!));
} }
@ -108,7 +109,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
0, ProfileOtherInfo(id: null, name: "NONE", description: null)); 0, ProfileOtherInfo(id: null, name: "NONE", description: null));
} }
emit(BasicInformationEditingState( emit(BasicInformationEditingState(
primaryInformation: currentProfileInformation!, primaryInformation: globalCurrentProfile!,
extensions: nameExtensions, extensions: nameExtensions,
sexes: sexes, sexes: sexes,
bloodTypes: bloodType, bloodTypes: bloodType,

View File

@ -13,9 +13,12 @@ class GetAgencies extends AgencyEvent{
class AddAgency extends AgencyEvent{ class AddAgency extends AgencyEvent{
final Agency agency; final Agency agency;
const AddAgency({required this.agency}); const AddAgency({required this.agency});
List<Object> get props => [agency
];
} }
class GetEstPointPersonAgencies extends AgencyEvent{ class GetEstPointPersonAgencies extends AgencyEvent{
final List<AssignedArea>? assignedAreas; final List<AssignedArea>? assignedAreas;
const GetEstPointPersonAgencies({required this.assignedAreas}); const GetEstPointPersonAgencies({required this.assignedAreas});
} }

View File

@ -60,7 +60,7 @@ class AssignAreaBloc extends Bloc<AssignAreaEvent, AssignAreaState> {
} }
}); });
on<AddAssignArea>((event, emit) async { on<AddAssignArea>((event, emit) async {
// try { try {
emit(AssignAreaLoadingState()); emit(AssignAreaLoadingState());
Map<dynamic, dynamic> response = await RbacAssignedAreaServices.instance Map<dynamic, dynamic> response = await RbacAssignedAreaServices.instance
.add( .add(
@ -77,11 +77,6 @@ class AssignAreaBloc extends Bloc<AssignAreaEvent, AssignAreaState> {
break; break;
} }
} }
// newAssignArea = userAssignedAreas.firstWhere((var element) {
// return element.assignedRole?.role?.id == event.roleId &&
// element.assignedRole?.user?.id == event.userId;
// });
if (newAssignArea?.assignedArea != null) { if (newAssignArea?.assignedArea != null) {
userAssignedAreas.removeWhere((element) => userAssignedAreas.removeWhere((element) =>
element.assignedRole!.role!.id == event.roleId && element.assignedRole!.role!.id == event.roleId &&
@ -120,8 +115,8 @@ class AssignAreaBloc extends Bloc<AssignAreaEvent, AssignAreaState> {
newAreas.add(newArea); newAreas.add(newArea);
} }
} }
newAssignArea?.assignedArea = newAreas; newAssignArea.assignedArea = newAreas;
userAssignedAreas.add(newAssignArea!); userAssignedAreas.add(newAssignArea);
//// purok //// purok
} }
if (event.areaTypeId == 2) { if (event.areaTypeId == 2) {
@ -149,8 +144,8 @@ class AssignAreaBloc extends Bloc<AssignAreaEvent, AssignAreaState> {
newAreas.add(newArea); newAreas.add(newArea);
} }
} }
newAssignArea?.assignedArea = newAreas; newAssignArea.assignedArea = newAreas;
userAssignedAreas.add(newAssignArea!); userAssignedAreas.add(newAssignArea);
} }
////statiom ////statiom
if (event.areaTypeId == 4) { if (event.areaTypeId == 4) {
@ -200,8 +195,8 @@ class AssignAreaBloc extends Bloc<AssignAreaEvent, AssignAreaState> {
newAreas.add(newArea); newAreas.add(newArea);
} }
} }
newAssignArea?.assignedArea = newAreas; newAssignArea.assignedArea = newAreas;
userAssignedAreas.add(newAssignArea!); userAssignedAreas.add(newAssignArea);
} }
////agency ////agency
if (event.areaTypeId == 3) { if (event.areaTypeId == 3) {
@ -231,16 +226,16 @@ class AssignAreaBloc extends Bloc<AssignAreaEvent, AssignAreaState> {
newAreas.add(newArea); newAreas.add(newArea);
} }
} }
newAssignArea?.assignedArea = newAreas; newAssignArea.assignedArea = newAreas;
userAssignedAreas.add(newAssignArea!); userAssignedAreas.add(newAssignArea);
} }
emit(AssignAreaAddedState(response: response)); emit(AssignAreaAddedState(response: response));
} else { } else {
emit(AssignAreaAddedState(response: response)); emit(AssignAreaAddedState(response: response));
} }
// } catch (e) { } catch (e) {
// emit(AssignAreaErorState(message: e.toString())); emit(AssignAreaErorState(message: e.toString()));
// } }
}); });
on<LoadAssignedAreas>((event, emit) async { on<LoadAssignedAreas>((event, emit) async {
emit(AssignedAreaLoadedState( emit(AssignedAreaLoadedState(

View File

@ -11,7 +11,7 @@ part 'role_module_state.dart';
class RoleModuleBloc extends Bloc<RoleModuleEvent, RoleModuleState> { class RoleModuleBloc extends Bloc<RoleModuleEvent, RoleModuleState> {
RoleModuleBloc() : super(RoleModuleInitial()) { RoleModuleBloc() : super(RoleModuleInitial()) {
List<RoleModules> roleModules = []; List<RoleModules> roleModules = [];
List<RBAC> roles = []; List<RBAC> roles = [];
List<RBAC> modules = []; List<RBAC> modules = [];
on<GetRoleModules>((event, emit) async { on<GetRoleModules>((event, emit) async {
emit(RoleModuleLoadingState()); emit(RoleModuleLoadingState());
@ -19,18 +19,19 @@ class RoleModuleBloc extends Bloc<RoleModuleEvent, RoleModuleState> {
if (roleModules.isEmpty) { if (roleModules.isEmpty) {
roleModules = await RbacRoleModuleServices.instance.getRoleModules(); roleModules = await RbacRoleModuleServices.instance.getRoleModules();
} }
if (modules.isEmpty) { if (modules.isEmpty) {
modules = await RbacModuleServices.instance.getRbacModule(); modules = await RbacModuleServices.instance.getRbacModule();
} }
if (roles.isEmpty) { if (roles.isEmpty) {
roles = await RbacRoleServices.instance.getRbacRoles(); roles = await RbacRoleServices.instance.getRbacRoles();
} }
emit(RoleModuleLoadedState(roleModules: roleModules,modules: modules,roles: roles)); emit(RoleModuleLoadedState(
roleModules: roleModules, modules: modules, roles: roles));
} catch (e) { } catch (e) {
emit(RoleModuleErrorState(message: e.toString())); emit(RoleModuleErrorState(message: e.toString()));
} }
}); });
on<AddRoleModule>((event, emit) async { on<AddRoleModule>((event, emit) async {
try { try {
emit(RoleModuleLoadingState()); emit(RoleModuleLoadingState());
Map<dynamic, dynamic> statusResponse = Map<dynamic, dynamic> statusResponse =
@ -40,9 +41,12 @@ class RoleModuleBloc extends Bloc<RoleModuleEvent, RoleModuleState> {
moduleIds: event.moduleIds); moduleIds: event.moduleIds);
if (statusResponse['success']) { if (statusResponse['success']) {
List<int?> ids = roleModules.map((e) => e.id).toList();
statusResponse['data'].forEach((var roleMod) { statusResponse['data'].forEach((var roleMod) {
RoleModules newRoleModule = RoleModules.fromJson(roleMod); RoleModules newRoleModule = RoleModules.fromJson(roleMod);
roleModules.add(newRoleModule); if (!ids.contains(newRoleModule.id)) {
roleModules.add(newRoleModule);
}
emit(RoleModuleAddedState(response: statusResponse)); emit(RoleModuleAddedState(response: statusResponse));
}); });
} else { } else {

View File

@ -36,11 +36,14 @@ class RolesUnderBloc extends Bloc<RolesUnderEvent, RolesUnderState> {
.add(roleId: event.roleId, rolesId: event.roleUnderIds); .add(roleId: event.roleId, rolesId: event.roleUnderIds);
if (statusResponse['success']) { if (statusResponse['success']) {
List<int> ids = rolesUnder.map((e) => e.id).toList();
statusResponse['data'].forEach((var roleMod) { statusResponse['data'].forEach((var roleMod) {
RolesUnder newRoleUnder = RolesUnder.fromJson(roleMod); RolesUnder newRoleUnder = RolesUnder.fromJson(roleMod);
rolesUnder.add(newRoleUnder); if (!ids.contains(newRoleUnder.id)) {
emit(RoleUnderAddedState(response: statusResponse)); rolesUnder.add(newRoleUnder);
}
}); });
emit(RoleUnderAddedState(response: statusResponse));
} else { } else {
emit(RoleUnderAddedState(response: statusResponse)); emit(RoleUnderAddedState(response: statusResponse));
} }

View File

@ -23,9 +23,9 @@ import '../../../../utils/alerts.dart';
class CitizenShipScreen extends StatefulWidget { class CitizenShipScreen extends StatefulWidget {
final int profileId; final int profileId;
final String token; final String token;
final List<Citizenship> citizenships;
const CitizenShipScreen( const CitizenShipScreen(
{super.key, required this.profileId, required this.token}); {super.key, required this.profileId, required this.token , required this.citizenships});
@override @override
State<CitizenShipScreen> createState() => _CitizenShipScreenState(); State<CitizenShipScreen> createState() => _CitizenShipScreenState();
@ -421,7 +421,9 @@ class _CitizenShipScreenState extends State<CitizenShipScreen> {
if (state is CitizenshipErrorState) { if (state is CitizenshipErrorState) {
return Scaffold( return Scaffold(
body: SomethingWentWrong( body: SomethingWentWrong(
message: state.message, onpressed: () {})); message: state.message, onpressed: () {
context.read<CitizenshipBloc>().add(GetCitizenship(citizenship: widget.citizenships));
}));
} }
return Container(); return Container();
}, },

View File

@ -10,6 +10,7 @@ import 'package:unit2/sevices/profile/contact_services.dart';
import 'package:unit2/theme-data.dart/btn-style.dart'; import 'package:unit2/theme-data.dart/btn-style.dart';
import 'package:unit2/theme-data.dart/form-style.dart'; import 'package:unit2/theme-data.dart/form-style.dart';
import 'package:unit2/utils/global.dart'; import 'package:unit2/utils/global.dart';
import 'package:unit2/utils/global_context.dart';
import 'package:unit2/utils/text_container.dart'; import 'package:unit2/utils/text_container.dart';
import '../../../../../theme-data.dart/colors.dart'; import '../../../../../theme-data.dart/colors.dart';
@ -84,7 +85,7 @@ class _AddContactInformationScreenState
serviceTypeId: serviceTypeId:
selectedServiceType!.id!); selectedServiceType!.id!);
} catch (e) { } catch (e) {
context NavigationService.navigatorKey.currentContext!
.read<ContactBloc>() .read<ContactBloc>()
.add(CallErrorEvent(message: e.toString())); .add(CallErrorEvent(message: e.toString()));
} }
@ -129,6 +130,7 @@ class _AddContactInformationScreenState
? selectedServiceType?.id == 2 ? selectedServiceType?.id == 2
//// Landline //// Landline
? FormBuilderTextField( ? FormBuilderTextField(
keyboardType: TextInputType.number,
controller: numberMailController, controller: numberMailController,
inputFormatters: [landLineFormatter], inputFormatters: [landLineFormatter],
name: 'number-mail', name: 'number-mail',
@ -150,7 +152,7 @@ class _AddContactInformationScreenState
errorText: "This field is required"), errorText: "This field is required"),
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Mobile number *", "Mobile number *",
"+63 (9xx) xxx - xxxx"), "+63 (9xx) xxx - xxxx").copyWith(helperText: "Please input your mobile number excluding the 0"),
) )
: selectedServiceType!.id == 4 : selectedServiceType!.id == 4
////Social Media ////Social Media
@ -167,6 +169,7 @@ class _AddContactInformationScreenState
: selectedServiceType!.id == 3 : selectedServiceType!.id == 3
////Email Address ////Email Address
? FormBuilderTextField( ? FormBuilderTextField(
keyboardType: TextInputType.emailAddress,
controller: numberMailController, controller: numberMailController,
name: 'number-mail', name: 'number-mail',
validator: FormBuilderValidators validator: FormBuilderValidators

View File

@ -37,7 +37,7 @@ class _EditContactInformationScreenState
var mobileFormatter = MaskTextInputFormatter( var mobileFormatter = MaskTextInputFormatter(
mask: "+63 (###) ###-####", mask: "+63 (###) ###-####",
filter: {"#": RegExp(r"^[1-9][0-9]*$")}, filter: {"#": RegExp(r'^[0-9][0-9]*$')},
type: MaskAutoCompletionType.lazy, type: MaskAutoCompletionType.lazy,
initialText: "0"); initialText: "0");
@ -149,6 +149,7 @@ class _EditContactInformationScreenState
? selectedServiceType?.id == 2 ? selectedServiceType?.id == 2
//// Landline //// Landline
? FormBuilderTextField( ? FormBuilderTextField(
keyboardType: TextInputType.number,
controller: numberMailController, controller: numberMailController,
name: 'number-mail', name: 'number-mail',
inputFormatters: [landLineFormatter], inputFormatters: [landLineFormatter],
@ -162,6 +163,7 @@ class _EditContactInformationScreenState
selectedServiceType!.id == 19 selectedServiceType!.id == 19
//// Mobile number //// Mobile number
? FormBuilderTextField( ? FormBuilderTextField(
keyboardType: TextInputType.number,
controller: numberMailController, controller: numberMailController,
name: 'number-mail', name: 'number-mail',
inputFormatters: [mobileFormatter], inputFormatters: [mobileFormatter],
@ -172,10 +174,12 @@ class _EditContactInformationScreenState
decoration: normalTextFieldStyle( decoration: normalTextFieldStyle(
"Mobile number *", "Mobile number *",
"+63 (9xx) xxx - xxxx"), "+63 (9xx) xxx - xxxx"),
) )
: selectedServiceType!.id == 4 : selectedServiceType!.id == 4
////Social Media ////Social Media
? FormBuilderTextField( ? FormBuilderTextField(
controller: numberMailController, controller: numberMailController,
name: 'number-mail', name: 'number-mail',
validator: validator:
@ -188,6 +192,7 @@ class _EditContactInformationScreenState
: selectedServiceType!.id == 3 : selectedServiceType!.id == 3
////Email Address ////Email Address
? FormBuilderTextField( ? FormBuilderTextField(
keyboardType: TextInputType.emailAddress,
controller: controller:
numberMailController, numberMailController,
name: 'number-mail', name: 'number-mail',

View File

@ -1,10 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import '../../../../../bloc/profile/family/family_bloc.dart';
import '../../../../../theme-data.dart/btn-style.dart'; import '../../../../../theme-data.dart/btn-style.dart';
import '../../../../../theme-data.dart/colors.dart'; import '../../../../../theme-data.dart/colors.dart';
import '../../../../../theme-data.dart/form-style.dart'; import '../../../../../theme-data.dart/form-style.dart';
@ -26,6 +22,7 @@ class AddMobileNumber extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
FormBuilderTextField( FormBuilderTextField(
keyboardType: TextInputType.number,
name: 'number_mail', name: 'number_mail',
inputFormatters: [mobileFormatter], inputFormatters: [mobileFormatter],
validator: FormBuilderValidators.required( validator: FormBuilderValidators.required(

View File

@ -45,7 +45,7 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
AttachmentCategory? selectedAttachmentCategory; AttachmentCategory? selectedAttachmentCategory;
List<AttachmentCategory> attachmentCategories = []; List<AttachmentCategory> attachmentCategories = [];
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar( appBar: AppBar(
title: context.watch<LearningDevelopmentBloc>().state title: context.watch<LearningDevelopmentBloc>().state
is LearningDevelopmentAddingState is LearningDevelopmentAddingState

View File

@ -48,360 +48,378 @@ import '../unit2/homepage.dart/components/menu.dart';
import 'components/main_menu.dart'; import 'components/main_menu.dart';
import 'components/submenu.dart'; import 'components/submenu.dart';
class ProfileInfo extends StatelessWidget { class ProfileInfo extends StatefulWidget {
const ProfileInfo({super.key}); const ProfileInfo({super.key});
@override
State<ProfileInfo> createState() => _ProfileInfoState();
}
class _ProfileInfoState extends State<ProfileInfo> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
int? profileId; int? profileId;
String? token; String? token;
Profile profile; Profile profile;
return Scaffold( return WillPopScope(
appBar: AppBar( onWillPop: () async{
backgroundColor: primary, setState(() {
centerTitle: true,
title: const Text('Profile'), });
), return true;
body: ProgressHUD( },
padding: const EdgeInsets.all(24), child: Scaffold(
backgroundColor: Colors.black87, appBar: AppBar(
indicatorWidget: const SpinKitFadingCircle(color: Colors.white), backgroundColor: primary,
child: BlocBuilder<UserBloc, UserState>(builder: (context, state) { centerTitle: true,
if (state is UserLoggedIn) { title: const Text('Profile'),
profileId = state.userData!.user!.login!.user!.profileId; ),
token = state.userData!.user!.login!.token!; body: ProgressHUD(
if (globalCurrentProfile == null) { padding: const EdgeInsets.all(24),
profile = state.userData!.employeeInfo!.profile!; backgroundColor: Colors.black87,
} else { indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
profile = globalCurrentProfile!; child: BlocBuilder<UserBloc, UserState>(builder: (context, state) {
if (state is UserLoggedIn) {
profileId = state.userData!.user!.login!.user!.profileId;
token = state.userData!.user!.login!.token!;
if (globalCurrentProfile == null) {
profile = state.userData!.employeeInfo!.profile!;
globalCurrentProfile = profile;
} else {
profile = globalCurrentProfile!;
}
return BlocConsumer<ProfileBloc, ProfileState>(
listener: (
context,
state,
) {
if (state is ProfileLoading) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait...");
}
if (state is ProfileLoaded ||
state is ProfileErrorState ||
state is BasicInformationEditingState) {
final progress = ProgressHUD.of(context);
progress?.dismiss();
}
},
builder: (context, state) {
if (state is ProfileLoaded) {
return Container(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 12),
child: ListView(
children: [
Text(
"View and Update your Profile Information",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge,
),
ExpandableGroup(
collapsedIcon:
const Icon(Icons.keyboard_arrow_down),
expandedIcon: const Icon(Icons.keyboard_arrow_up),
header: const ListTile(
leading: Icon(
Elusive.address_book,
color: primary,
),
title: Text(
"Basic Information",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
items: [
subMenu(Icons.person, "Primary", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider<ProfileBloc>.value(
value: ProfileBloc()
..add(GetPrimaryBasicInfo(
primaryBasicInformation: profile)),
child: PrimaryInfo(
token: token!,
profileId: profileId!,
),
);
}));
}),
subMenu(Icons.home, "Addresses", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => AddressBloc()
..add(GetAddress(
addresses: state.profileInformation
.basicInfo.addresses)),
child: const AddressScreen(),
);
}));
}),
subMenu(Icons.contact_mail, "Identifications",
() {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => IdentificationBloc()
..add(GetIdentifications(
identificationInformation: state
.profileInformation
.basicInfo
.identifications)),
child: const IdentificationsScreen(),
);
}));
}),
subMenu(Icons.contact_phone, "Contact Info",
() {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => ContactBloc()
..add(GetContacts(
contactInformations: state
.profileInformation
.basicInfo
.contactInformation)),
child: const ContactInformationScreen(),
);
}));
}),
subMenu(Icons.flag, "Citizenships", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => CitizenshipBloc()
..add(GetCitizenship(
citizenship: state
.profileInformation
.basicInfo
.citizenships)),
child: CitizenShipScreen(
citizenships: state
.profileInformation
.basicInfo
.citizenships,
profileId: profileId!, token: token!),
);
}));
}),
]),
const Divider(),
MainMenu(
icon: Elusive.group,
title: "Family",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => FamilyBloc()
..add(GetFamilies(
profileId: profileId!, token: token!)),
child: const FamilyBackgroundScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: FontAwesome5.graduation_cap,
title: "Education",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => EducationBloc()
..add(GetEducationalBackground(
profileId: profileId!, token: token!)),
child: const EducationScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: Icons.stars,
title: "Eligibility",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => EligibilityBloc()
..add(GetEligibilities(
profileId: profileId!, token: token!)),
child: const EligibiltyScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: FontAwesome5.shopping_bag,
title: "Work History",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => WorkHistoryBloc()
..add(GetWorkHistories(
profileId: profileId!, token: token!)),
child: const WorkHistoryScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: FontAwesome5.walking,
title: "Voluntary Work & Civic Services",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => VoluntaryWorkBloc()
..add(GetVoluntarWorks(
profileId: profileId!, token: token!)),
child: const VolunataryWorkScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: Elusive.lightbulb,
title: "Learning & Development",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => LearningDevelopmentBloc()
..add(GetLearningDevelopments(
profileId: profileId!, token: token!)),
child: const LearningAndDevelopmentScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: Brandico.codepen,
title: "Personal References",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => ReferencesBloc()
..add(GetReferences(
profileId: profileId!, token: token!)),
child: const ReferencesScreen(),
);
}));
},
),
ExpandableGroup(
collapsedIcon:
const Icon(Icons.keyboard_arrow_down),
expandedIcon: const Icon(Icons.keyboard_arrow_up),
header: const ListTile(
leading: Icon(
Icons.info,
color: primary,
),
title: Text(
"Other Information",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
items: [
subMenu(
Icons.fitness_center, "Skills & Hobbies",
() {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => HoobiesBloc()
..add(GetSkillsHobbies(
profileId: profileId!,
token: token!)),
child: const SkillHobbiesScreen(),
);
}));
}),
subMenu(FontAwesome5.certificate,
"Organization Memberships", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) =>
OrganizationMembershipBloc()
..add(GetOrganizationMembership(
profileId: profileId!,
token: token!)),
child: const OrgMembershipsScreen(),
);
}));
}),
subMenu(Entypo.doc_text,
"Non-Academic Recognitions", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) =>
NonAcademicRecognitionBloc()
..add(GetNonAcademicRecognition(
profileId: profileId!,
token: token!)),
child:
const NonAcademicRecognitionScreen(),
);
}));
}),
]),
ExpandableGroup(
collapsedIcon:
const Icon(Icons.keyboard_arrow_down),
expandedIcon: const Icon(Icons.keyboard_arrow_up),
header: const ListTile(
leading: Icon(
FontAwesome5.laptop_house,
color: primary,
),
title: Text(
"Assets",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
items: [
subMenu(ModernPictograms.home,
"Real Property Tax", () {}),
]),
],
),
);
}
if (state is ProfileLoading) {
return const LoadingScreen();
}
if (state is ProfileErrorState) {
return SomethingWentWrong(
message: state.mesage,
onpressed: () {
BlocProvider.of<ProfileBloc>(context).add(
LoadProfile(token: token!, userID: profileId!));
});
}
return Container();
},
);
} }
print(profile.lastName); return Container();
return BlocConsumer<ProfileBloc, ProfileState>( }),
listener: ( )),
context, );
state,
) {
if (state is ProfileLoading) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait...");
}
if (state is ProfileLoaded ||
state is ProfileErrorState ||
state is BasicInformationEditingState) {
final progress = ProgressHUD.of(context);
progress?.dismiss();
}
},
builder: (context, state) {
if (state is ProfileLoaded) {
return Container(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 12),
child: ListView(
children: [
Text(
"View and Update your Profile Information",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge,
),
ExpandableGroup(
collapsedIcon:
const Icon(Icons.keyboard_arrow_down),
expandedIcon: const Icon(Icons.keyboard_arrow_up),
header: const ListTile(
leading: Icon(
Elusive.address_book,
color: primary,
),
title: Text(
"Basic Information",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
items: [
subMenu(Icons.person, "Primary", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider<ProfileBloc>.value(
value: ProfileBloc()
..add(GetPrimaryBasicInfo(
primaryBasicInformation: profile)),
child: PrimaryInfo(
token: token!,
profileId: profileId!,
),
);
}));
}),
subMenu(Icons.home, "Addresses", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => AddressBloc()
..add(GetAddress(
addresses: state.profileInformation
.basicInfo.addresses)),
child: const AddressScreen(),
);
}));
}),
subMenu(Icons.contact_mail, "Identifications",
() {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => IdentificationBloc()
..add(GetIdentifications(
identificationInformation: state
.profileInformation
.basicInfo
.identifications)),
child: const IdentificationsScreen(),
);
}));
}),
subMenu(Icons.contact_phone, "Contact Info",
() {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => ContactBloc()
..add(GetContacts(
contactInformations: state
.profileInformation
.basicInfo
.contactInformation)),
child: const ContactInformationScreen(),
);
}));
}),
subMenu(Icons.flag, "Citizenships", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => CitizenshipBloc()
..add(GetCitizenship(
citizenship: state
.profileInformation
.basicInfo
.citizenships)),
child: CitizenShipScreen(
profileId: profileId!, token: token!),
);
}));
}),
]),
const Divider(),
MainMenu(
icon: Elusive.group,
title: "Family",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => FamilyBloc()
..add(GetFamilies(
profileId: profileId!, token: token!)),
child: const FamilyBackgroundScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: FontAwesome5.graduation_cap,
title: "Education",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => EducationBloc()
..add(GetEducationalBackground(
profileId: profileId!, token: token!)),
child: const EducationScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: Icons.stars,
title: "Eligibility",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => EligibilityBloc()
..add(GetEligibilities(
profileId: profileId!, token: token!)),
child: const EligibiltyScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: FontAwesome5.shopping_bag,
title: "Work History",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => WorkHistoryBloc()
..add(GetWorkHistories(
profileId: profileId!, token: token!)),
child: const WorkHistoryScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: FontAwesome5.walking,
title: "Voluntary Work & Civic Services",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => VoluntaryWorkBloc()
..add(GetVoluntarWorks(
profileId: profileId!, token: token!)),
child: const VolunataryWorkScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: Elusive.lightbulb,
title: "Learning & Development",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => LearningDevelopmentBloc()
..add(GetLearningDevelopments(
profileId: profileId!, token: token!)),
child: const LearningAndDevelopmentScreen(),
);
}));
},
),
const Divider(),
MainMenu(
icon: Brandico.codepen,
title: "Personal References",
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => ReferencesBloc()
..add(GetReferences(
profileId: profileId!, token: token!)),
child: const ReferencesScreen(),
);
}));
},
),
ExpandableGroup(
collapsedIcon:
const Icon(Icons.keyboard_arrow_down),
expandedIcon: const Icon(Icons.keyboard_arrow_up),
header: const ListTile(
leading: Icon(
Icons.info,
color: primary,
),
title: Text(
"Other Information",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
items: [
subMenu(
Icons.fitness_center, "Skills & Hobbies",
() {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) => HoobiesBloc()
..add(GetSkillsHobbies(
profileId: profileId!,
token: token!)),
child: const SkillHobbiesScreen(),
);
}));
}),
subMenu(FontAwesome5.certificate,
"Organization Memberships", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) =>
OrganizationMembershipBloc()
..add(GetOrganizationMembership(
profileId: profileId!,
token: token!)),
child: const OrgMembershipsScreen(),
);
}));
}),
subMenu(Entypo.doc_text,
"Non-Academic Recognitions", () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BlocProvider(
create: (context) =>
NonAcademicRecognitionBloc()
..add(GetNonAcademicRecognition(
profileId: profileId!,
token: token!)),
child:
const NonAcademicRecognitionScreen(),
);
}));
}),
]),
ExpandableGroup(
collapsedIcon:
const Icon(Icons.keyboard_arrow_down),
expandedIcon: const Icon(Icons.keyboard_arrow_up),
header: const ListTile(
leading: Icon(
FontAwesome5.laptop_house,
color: primary,
),
title: Text(
"Assets",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
items: [
subMenu(ModernPictograms.home,
"Real Property Tax", () {}),
]),
],
),
);
}
if (state is ProfileLoading) {
return const LoadingScreen();
}
if (state is ProfileErrorState) {
return SomethingWentWrong(
message: state.mesage,
onpressed: () {
BlocProvider.of<ProfileBloc>(context).add(
LoadProfile(token: token!, userID: profileId!));
});
}
return Container();
},
);
}
return Container();
}),
));
} }
} }

View File

@ -5,6 +5,7 @@ import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:fluttericon/font_awesome_icons.dart'; import 'package:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:search_page/search_page.dart';
import 'package:searchfield/searchfield.dart'; import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/rbac/rbac_operations/agency/agency_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/agency/agency_bloc.dart';
import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart';
@ -28,6 +29,7 @@ class RbacAgencyScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
List<Agency> agencies = [];
List<Category> agencyCategory = []; List<Category> agencyCategory = [];
Category? selectedAgencyCategory; Category? selectedAgencyCategory;
bool? isPrivate; bool? isPrivate;
@ -38,7 +40,37 @@ class RbacAgencyScreen extends StatelessWidget {
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Agencies"), title: const Text("Agencies"),
actions: [ actions: context.watch<AgencyBloc>().state is AgencyLoadingState || context.watch<AgencyBloc>().state is AgencyErrorState || context.watch<AgencyBloc>().state is AgencyAddesState?[]:[
IconButton(
onPressed: () {
showSearch(
context: context,
delegate: SearchPage(
barTheme: ThemeData(cardColor: primary),
builder: (Agency rbac) {
return Column(
children: [
ListTile(
title: Text(rbac.name!),
),
const Divider(),
],
);
},
filter: (Agency rbac) {
return [rbac.name];
},
failure: const Center(
child: Text("No Agency found :("),
),
items: agencies,
searchLabel: "Search Agency",
suggestion: const Center(
child: Text("Search agency by name"),
)),
);
},
icon: const Icon(Icons.search)),
AddLeading(onPressed: () { AddLeading(onPressed: () {
parent = context; parent = context;
showDialog( showDialog(
@ -220,6 +252,7 @@ class RbacAgencyScreen extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
final parent = context; final parent = context;
if (state is AgenciesLoaded) { if (state is AgenciesLoaded) {
agencies = state.agencies;
agencyCategory = state.agencyCategory; agencyCategory = state.agencyCategory;
if (state.agencies.isNotEmpty) { if (state.agencies.isNotEmpty) {
return ListView.builder( return ListView.builder(
@ -262,7 +295,7 @@ class RbacAgencyScreen extends StatelessWidget {
}); });
} else { } else {
return const EmptyData( return const EmptyData(
message: "No Object available. Please click + to add."); message: "No Agency available. Please click + to add.");
} }
}if (state is AgencyErrorState) { }if (state is AgencyErrorState) {
return SomethingWentWrong( return SomethingWentWrong(

View File

@ -82,7 +82,7 @@ class _RbacAssignedAreaScreenState extends State<RbacAssignedAreaScreen> {
areaType = null; areaType = null;
return AlertDialog( return AlertDialog(
title: const Text("Add New Role"), title: const Text("Add New Assigned area"),
content: FormBuilder( content: FormBuilder(
key: formKey, key: formKey,
child: StatefulBuilder(builder: (context, setState) { child: StatefulBuilder(builder: (context, setState) {
@ -1005,7 +1005,7 @@ class _RbacAssignedAreaScreenState extends State<RbacAssignedAreaScreen> {
if (state is AssignedAreaDeletedState) { if (state is AssignedAreaDeletedState) {
if (state.success) { if (state.success) {
successAlert(context, "Delete Successfull!", successAlert(context, "Delete Successfull!",
"Role Module Deleted Successfully", () { "Assign Area Deleted Successfully", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context context
.read<AssignAreaBloc>() .read<AssignAreaBloc>()
@ -1013,7 +1013,7 @@ class _RbacAssignedAreaScreenState extends State<RbacAssignedAreaScreen> {
}); });
} else { } else {
errorAlert( errorAlert(
context, "Delete Failed", "Role Module Delete Failed", context, "Delete Failed", "Assign Area Deletion Failed",
() { () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context context

View File

@ -5,7 +5,9 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:search_page/search_page.dart';
import 'package:unit2/bloc/rbac/rbac_operations/module/module_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/module/module_bloc.dart';
import 'package:unit2/model/rbac/rbac.dart';
import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart';
import 'package:unit2/widgets/Leadings/add_leading.dart'; import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/error_state.dart'; import 'package:unit2/widgets/error_state.dart';
@ -23,83 +25,283 @@ class RbacModuleScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
final bloc = BlocProvider.of<ModuleBloc>(context);
List<RBAC> modules = [];
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Module Screen"), title: const Text("Module Screen"),
actions: [ actions:
AddLeading(onPressed: () { context.watch<ModuleBloc>().state is ModuleLoadingState ||
BuildContext parent = context; context.watch<ModuleBloc>().state is ModuleErrorState ||
showDialog( context.watch<ModuleBloc>().state is ModuleAddedState ||
context: context, context.watch<ModuleBloc>().state is ModuleDeletedState ||
builder: (BuildContext context) { context.watch<ModuleBloc>().state is ModuleAddedState ||
return AlertDialog( context.watch<ModuleBloc>().state is ModuleUpdatedState
title: const Text("Add New Module"), ? []
content: FormBuilder( : [
key: formKey, IconButton(
child: Column( onPressed: () {
mainAxisSize: MainAxisSize.min, showSearch(
children: [ context: context,
FormBuilderTextField( delegate: SearchPage(
name: "object_name", barTheme: ThemeData(cardColor: Colors.white),
decoration: normalTextFieldStyle( builder: (RBAC rbac) {
"Module name *", "Module name "), return Column(
validator: FormBuilderValidators.required( children: [
errorText: "This field is required"), Container(
), width: screenWidth,
const SizedBox( decoration: box1(),
height: 8, padding: const EdgeInsets.symmetric(
), horizontal: 12, vertical: 8),
FormBuilderTextField( child: Row(
name: "slug", children: [
decoration: normalTextFieldStyle("Slug ", "Slug"), const SizedBox(
), width: 12,
const SizedBox( ),
height: 8, Expanded(
), child: Text(rbac.name!,
FormBuilderTextField( style: Theme.of(context)
validator: FormBuilderValidators.maxLength(50, .textTheme
errorText: "Max characters only 50"), .titleMedium!
name: "shorthand", .copyWith(
decoration: fontWeight:
normalTextFieldStyle("Shorthand ", "Shorthand"), FontWeight.w500,
), color: primary)),
const SizedBox( ),
height: 12, AppPopupMenu<int>(
), offset: const Offset(-10, -10),
SizedBox( elevation: 3,
width: double.infinity, onSelected: (value) {
height: 50, if (value == 2) {
child: ElevatedButton( showDialog(
style: mainBtnStyle( context: context,
primary, Colors.transparent, second), builder: (BuildContext
onPressed: () { context) {
if (formKey.currentState! return AlertDialog(
.saveAndValidate()) { title: const Text(
String name = formKey "Update Module"),
.currentState!.value['object_name']; content: FormBuilder(
String? slug = key: formKey,
formKey.currentState!.value['slug']; child: Column(
String? short = formKey mainAxisSize:
.currentState!.value['shorthand']; MainAxisSize
parent.read<ModuleBloc>().add( .min,
AddRbacModule( children: [
id: id, FormBuilderTextField(
name: name, initialValue:
shorthand: short, rbac.name,
slug: slug)); name:
Navigator.pop(context); "object_name",
} decoration: normalTextFieldStyle(
}, "Module name *",
child: const Text("Add"))), "Module name "),
], validator: FormBuilderValidators
), .required(
), errorText:
); "This field is required"),
}); ),
}) const SizedBox(
], height: 8,
),
FormBuilderTextField(
initialValue:
rbac.slug,
name: "slug",
decoration:
normalTextFieldStyle(
"Slug ",
"Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
initialValue:
rbac.shorthand,
validator: FormBuilderValidators
.maxLength(
50,
errorText:
"Max characters only 50"),
name:
"shorthand",
decoration: normalTextFieldStyle(
"Shorthand ",
"Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double
.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
if (formKey
.currentState!
.saveAndValidate()) {
Navigator.pop(context);
String
name =
formKey.currentState!.value['object_name'];
String?
slug =
formKey.currentState!.value['slug'];
String?
short =
formKey.currentState!.value['shorthand'];
////Update
bloc.add(UpdateRbacModule(
moduleId: rbac.id!,
name: name,
slug: slug,
short: short,
createdBy: rbac.createdBy?.id,
updatedBy: id));
Navigator.pop(context);
}
},
child: const Text("Update"))),
],
),
),
);
});
}
if (value == 1) {
////delete
Navigator.pop(context);
confirmAlert(context, () {
context
.read<ModuleBloc>()
.add(DeleteRbacModule(
moduleId:
rbac.id!));
}, "Delete?",
"Confirm Delete?");
}
},
menuItems: [
popMenuItem(
text: "Update",
value: 2,
icon: Icons.edit),
popMenuItem(
text: "Remove",
value: 1,
icon: Icons.delete),
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
),
],
),
),
const SizedBox(
height: 5,
)
],
);
},
filter: (RBAC rbac) {
return [rbac.name];
},
failure: const Center(
child: Text("No Module found :("),
),
items: modules,
searchLabel: "Search Module",
suggestion: const Center(
child: Text("Search module by name"),
)),
);
},
icon: const Icon(Icons.search)),
AddLeading(onPressed: () {
BuildContext parent = context;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text("Add New Module"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderTextField(
name: "object_name",
decoration: normalTextFieldStyle(
"Module name *", "Module name "),
validator: FormBuilderValidators.required(
errorText: "This field is required"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
name: "slug",
decoration:
normalTextFieldStyle("Slug ", "Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
validator:
FormBuilderValidators.maxLength(50,
errorText:
"Max characters only 50"),
name: "shorthand",
decoration: normalTextFieldStyle(
"Shorthand ", "Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate()) {
String name = formKey
.currentState!
.value['object_name'];
String? slug = formKey
.currentState!
.value['slug'];
String? short = formKey
.currentState!
.value['shorthand'];
parent.read<ModuleBloc>().add(
AddRbacModule(
id: id,
name: name,
shorthand: short,
slug: slug));
Navigator.pop(context);
}
},
child: const Text("Add"))),
],
),
),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -162,7 +364,7 @@ class RbacModuleScreen extends StatelessWidget {
context.read<ModuleBloc>().add(GetModule()); context.read<ModuleBloc>().add(GetModule());
}); });
} else { } else {
errorAlert(context, "Delete Failed", "Module Delete Failed", errorAlert(context, "Delete Failed", "Module Deletion Failed",
() { () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<ModuleBloc>().add(GetModule()); context.read<ModuleBloc>().add(GetModule());
@ -174,6 +376,7 @@ class RbacModuleScreen extends StatelessWidget {
final parent = context; final parent = context;
if (state is ModuleLoaded) { if (state is ModuleLoaded) {
if (state.module.isNotEmpty) { if (state.module.isNotEmpty) {
modules = state.module;
return ListView.builder( return ListView.builder(
padding: padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 10), const EdgeInsets.symmetric(vertical: 8, horizontal: 10),
@ -190,18 +393,22 @@ class RbacModuleScreen extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: Row( child: Row(
children: [ children: [
CircleAvatar(child: Text('${index+1}'),), CircleAvatar(
const SizedBox(width: 12,), child: Text('${index + 1}'),
Text(state.module[index].name!, ),
style: Theme.of(context) const SizedBox(
.textTheme width: 12,
.titleMedium! ),
.copyWith( Text(state.module[index].name!,
fontWeight: FontWeight.w500, style: Theme.of(context)
color: primary)), .textTheme
], .titleMedium!
)), .copyWith(
fontWeight: FontWeight.w500,
color: primary)),
],
)),
AppPopupMenu<int>( AppPopupMenu<int>(
offset: const Offset(-10, -10), offset: const Offset(-10, -10),
elevation: 3, elevation: 3,
@ -211,7 +418,8 @@ class RbacModuleScreen extends StatelessWidget {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: const Text("Update Module"), title:
const Text("Update Module"),
content: FormBuilder( content: FormBuilder(
key: formKey, key: formKey,
child: Column( child: Column(
@ -355,7 +563,7 @@ class RbacModuleScreen extends StatelessWidget {
}); });
} else { } else {
return const EmptyData( return const EmptyData(
message: "No Role available. Please click + to add."); message: "No Module available. Please click + to add.");
} }
} }
if (state is ModuleErrorState) { if (state is ModuleErrorState) {

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart';
@ -33,106 +32,121 @@ class RbacModuleObjectsScreen extends StatelessWidget {
List<ValueItem> selectedValueItemObjects = []; List<ValueItem> selectedValueItemObjects = [];
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
elevation: 0, elevation: 0,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Module Object Screen"), title: const Text("Module Object Screen"),
actions: [ actions: context.watch<ModuleObjectsBloc>().state
AddLeading(onPressed: () { is ModuleObjectLoadingState ||
showDialog( context.watch<ModuleObjectsBloc>().state
context: NavigationService.navigatorKey.currentState!.context, is ModuleObjectsErrorState ||
builder: (BuildContext context) { context.watch<ModuleObjectsBloc>().state
valueItemObjects = objects.map((e) { is ModuleObjectAddedState ||
return ValueItem(label: e.name!, value: e.name); context.watch<ModuleObjectsBloc>().state
}).toList(); is ModuleObjectDeletedState
return AlertDialog( ? []
title: const Text("Add New Module Object"), : [
content: FormBuilder( AddLeading(onPressed: () {
key: formKey, showDialog(
child: Column( context:
mainAxisSize: MainAxisSize.min, NavigationService.navigatorKey.currentState!.context,
children: [ builder: (BuildContext context) {
FormBuilderDropdown<RBAC>( valueItemObjects = objects.map((e) {
validator: FormBuilderValidators.required( return ValueItem(label: e.name!, value: e.name);
errorText: "This field is required"), }).toList();
name: "module", return AlertDialog(
decoration: title: const Text("Add New Module Object"),
normalTextFieldStyle("Module", "Module"), content: FormBuilder(
items: modules.isEmpty key: formKey,
? [] child: Column(
: modules.map((e) { mainAxisSize: MainAxisSize.min,
return DropdownMenuItem( children: [
value: e, child: Text(e.name!)); FormBuilderDropdown<RBAC>(
}).toList(), validator: FormBuilderValidators.required(
onChanged: (RBAC? object) { errorText: "This field is required"),
selectedModule = object; name: "module",
}, decoration: normalTextFieldStyle(
), "Module", "Module"),
const SizedBox( items: modules.isEmpty
height: 12, ? []
), : modules.map((e) {
MultiSelectDropDown( return DropdownMenuItem(
onOptionSelected: value: e, child: Text(e.name!));
(List<ValueItem> selectedOptions) { }).toList(),
selectedValueItemObjects = selectedOptions; onChanged: (RBAC? object) {
}, selectedModule = object;
borderColor: Colors.grey, },
borderWidth: 1, ),
borderRadius: 5, const SizedBox(
hint: "Objects", height: 12,
padding: const EdgeInsets.all(8), ),
options: valueItemObjects, MultiSelectDropDown(
selectionType: SelectionType.multi, onOptionSelected:
chipConfig: (List<ValueItem> selectedOptions) {
const ChipConfig(wrapType: WrapType.wrap), selectedValueItemObjects =
dropdownHeight: 300, selectedOptions;
optionTextStyle: const TextStyle(fontSize: 16), },
selectedOptionIcon: borderColor: Colors.grey,
const Icon(Icons.check_circle), borderWidth: 1,
), borderRadius: 5,
const SizedBox( hint: "Objects",
height: 12, padding: const EdgeInsets.all(8),
), options: valueItemObjects,
SizedBox( selectionType: SelectionType.multi,
height: 50, chipConfig: const ChipConfig(
width: double.maxFinite, wrapType: WrapType.wrap),
child: ElevatedButton( dropdownHeight: 300,
style: mainBtnStyle( optionTextStyle:
primary, Colors.transparent, second), const TextStyle(fontSize: 16),
onPressed: () { selectedOptionIcon:
if (formKey.currentState! const Icon(Icons.check_circle),
.saveAndValidate() && ),
selectedValueItemObjects.isNotEmpty) { const SizedBox(
int assignerId = id; height: 12,
int moduleId = selectedModule!.id!; ),
List<int> objectId = []; SizedBox(
for (var object in objects) { height: 50,
selectedValueItemObjects width: double.maxFinite,
.forEach((element) { child: ElevatedButton(
if (element.label.toLowerCase() == style: mainBtnStyle(primary,
object.name?.toLowerCase()) { Colors.transparent, second),
objectId.add(object.id!); onPressed: () {
if (formKey.currentState!
.saveAndValidate() &&
selectedValueItemObjects
.isNotEmpty) {
int assignerId = id;
int moduleId = selectedModule!.id!;
List<int> objectId = [];
for (var object in objects) {
selectedValueItemObjects
.forEach((element) {
if (element.label
.toLowerCase() ==
object.name
?.toLowerCase()) {
objectId.add(object.id!);
}
});
}
Navigator.of(context).pop();
parent
.read<ModuleObjectsBloc>()
.add(AddRbacModuleObjects(
assignerId: assignerId,
moduleId: moduleId,
objectsId: objectId));
} }
}); },
} child: const Text("Submit")),
Navigator.of(context).pop(); )
parent.read<ModuleObjectsBloc>().add( ],
AddRbacModuleObjects( )),
assignerId: assignerId, );
moduleId: moduleId, });
objectsId: objectId)); })
} ],
},
child: const Text("Submit")),
)
],
)),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -140,7 +154,6 @@ class RbacModuleObjectsScreen extends StatelessWidget {
indicatorWidget: const SpinKitFadingCircle(color: Colors.white), indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
child: BlocConsumer<ModuleObjectsBloc, ModuleObjectsState>( child: BlocConsumer<ModuleObjectsBloc, ModuleObjectsState>(
listener: (context, state) { listener: (context, state) {
if (state is ModuleObjectLoadingState) { if (state is ModuleObjectLoadingState) {
final progress = ProgressHUD.of(context); final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait..."); progress!.showWithText("Please wait...");
@ -157,13 +170,13 @@ class RbacModuleObjectsScreen extends StatelessWidget {
if (state is ModuleObjectDeletedState) { if (state is ModuleObjectDeletedState) {
if (state.success) { if (state.success) {
successAlert( successAlert(
context, "Delete Successfull!", "Role Deleted Successfully", context, "Delete Successfull!", "Module Object Deleted Successfully",
() { () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<ModuleObjectsBloc>().add(GetModuleObjects()); context.read<ModuleObjectsBloc>().add(GetModuleObjects());
}); });
} else { } else {
errorAlert(context, "Delete Failed", "Role Delete Failed", () { errorAlert(context, "Delete Failed", "Module Object Deletion Failed", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<ModuleObjectsBloc>().add(GetModuleObjects()); context.read<ModuleObjectsBloc>().add(GetModuleObjects());
}); });
@ -270,20 +283,23 @@ class RbacModuleObjectsScreen extends StatelessWidget {
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.titleMedium! .titleMedium!
.copyWith(color: primary,fontWeight: FontWeight.bold), .copyWith(
color: primary, fontWeight: FontWeight.bold),
), ),
); );
}, },
); );
} else { } else {
return const EmptyData( return const EmptyData(
message: "No Role available. Please click + to add."); message:
"No Module Object available. Please click + to add.");
} }
} }
if (state is ModuleObjectsErrorState) { if (state is ModuleObjectsErrorState) {
return SomethingWentWrong( return SomethingWentWrong(
message: state.message, onpressed: () { message: state.message,
parent.read<ModuleObjectsBloc>().add(GetModuleObjects()); onpressed: () {
parent.read<ModuleObjectsBloc>().add(GetModuleObjects());
}); });
} }
return Container(); return Container();

View File

@ -5,7 +5,9 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:search_page/search_page.dart';
import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/object/object_bloc.dart';
import 'package:unit2/model/rbac/rbac.dart';
import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart';
import 'package:unit2/widgets/error_state.dart'; import 'package:unit2/widgets/error_state.dart';
import '../../../theme-data.dart/box_shadow.dart'; import '../../../theme-data.dart/box_shadow.dart';
@ -24,83 +26,274 @@ class RbacObjectScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
final bloc = BlocProvider.of<ObjectBloc>(context);
List<RBAC> objects = [];
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Objects Screen"), title: const Text("Objects Screen"),
actions: [ actions:
AddLeading(onPressed: () { context.watch<ObjectBloc>().state is ObjectLoadingState ||
BuildContext parent = context; context.watch<ObjectBloc>().state is ObjectAddedState ||
showDialog( context.watch<ObjectBloc>().state is ObjectErrorState ||
context: context, context.watch<ObjectBloc>().state is ObjectDeletedState ||
builder: (BuildContext context) { context.watch<ObjectBloc>().state is ObjectUpdatedState
return AlertDialog( ? []
title: const Text("Add New Object"), : [
content: FormBuilder( IconButton(
key: formKey, onPressed: () {
child: Column( showSearch(
mainAxisSize: MainAxisSize.min, context: context,
children: [ delegate: SearchPage(
FormBuilderTextField( barTheme: ThemeData(cardColor: Colors.white),
name: "object_name", builder: (RBAC rbac) {
decoration: normalTextFieldStyle( return Column(
"Object name *", "Object name "), children: [
validator: FormBuilderValidators.required( Container(
errorText: "This field is required"), width: screenWidth,
), decoration: box1(),
const SizedBox( padding: const EdgeInsets.symmetric(
height: 8, horizontal: 12, vertical: 8),
), child: Row(
FormBuilderTextField( children: [
name: "slug", Expanded(
decoration: normalTextFieldStyle("Slug ", "Slug"), child: Text(rbac.name!,
), style: Theme.of(context)
const SizedBox( .textTheme
height: 8, .titleMedium!
), .copyWith(
FormBuilderTextField( fontWeight:
validator: FormBuilderValidators.maxLength(50, FontWeight.w500,
errorText: "Max characters only 50"), color: primary)),
name: "shorthand", ),
decoration: AppPopupMenu<int>(
normalTextFieldStyle("Shorthand ", "Shorthand"), offset: const Offset(-10, -10),
), elevation: 3,
const SizedBox( onSelected: (value) {
height: 12, if (value == 2) {
), showDialog(
SizedBox( context: context,
width: double.infinity, builder: (BuildContext
height: 50, context) {
child: ElevatedButton( return AlertDialog(
style: mainBtnStyle( title: const Text(
primary, Colors.transparent, second), "Update Object"),
onPressed: () { content: FormBuilder(
if (formKey.currentState! key: formKey,
.saveAndValidate()) { child: Column(
String name = formKey mainAxisSize:
.currentState!.value['object_name']; MainAxisSize
String? slug = .min,
formKey.currentState!.value['slug']; children: [
String? short = formKey FormBuilderTextField(
.currentState!.value['shorthand']; initialValue:
parent.read<ObjectBloc>().add( rbac.name,
AddRbacObject( name:
id: id, "object_name",
name: name, decoration: normalTextFieldStyle(
shorthand: short, "Object name *",
slug: slug)); "Object name "),
Navigator.pop(context); validator: FormBuilderValidators
} .required(
}, errorText:
child: const Text("Add"))), "This field is required"),
], ),
), const SizedBox(
), height: 8,
); ),
}); FormBuilderTextField(
}) initialValue:
], rbac.slug,
name: "slug",
decoration:
normalTextFieldStyle(
"Slug ",
"Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
initialValue:
rbac.shorthand,
validator: FormBuilderValidators
.maxLength(
50,
errorText:
"Max characters only 50"),
name:
"shorthand",
decoration: normalTextFieldStyle(
"Shorthand ",
"Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double
.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
if (formKey
.currentState!
.saveAndValidate()) {
Navigator.pop(context);
String
name =
formKey.currentState!.value['object_name'];
String?
slug =
formKey.currentState!.value['slug'];
String?
short =
formKey.currentState!.value['shorthand'];
bloc.add(UpdateRbacObject(
objectId: rbac.id!,
name: name,
slug: slug,
short: short,
createdBy: rbac.createdBy?.id,
updatedBy: id));
Navigator.pop(context);
}
},
child: const Text("Update"))),
],
),
),
);
});
}
if (value == 1) {
confirmAlert(context, () {
Navigator.pop(context);
bloc.add(DeleteRbacObject(
objectId: rbac.id!));
}, "Delete?",
"Confirm Delete?");
}
},
menuItems: [
popMenuItem(
text: "Update",
value: 2,
icon: Icons.edit),
popMenuItem(
text: "Remove",
value: 1,
icon: Icons.delete),
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
),
],
),
),
const SizedBox(
height: 5,
)
],
);
},
filter: (RBAC rbac) {
return [rbac.name];
},
failure: const Center(
child: Text("No Role found :("),
),
items: objects,
searchLabel: "Search Object",
suggestion: const Center(
child: Text("Search object by name"),
)),
);
},
icon: const Icon(Icons.search)),
AddLeading(onPressed: () {
BuildContext parent = context;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text("Add New Object"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderTextField(
name: "object_name",
decoration: normalTextFieldStyle(
"Object name *", "Object name "),
validator: FormBuilderValidators.required(
errorText: "This field is required"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
name: "slug",
decoration:
normalTextFieldStyle("Slug ", "Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
validator:
FormBuilderValidators.maxLength(50,
errorText:
"Max characters only 50"),
name: "shorthand",
decoration: normalTextFieldStyle(
"Shorthand ", "Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate()) {
String name = formKey
.currentState!
.value['object_name'];
String? slug = formKey
.currentState!
.value['slug'];
String? short = formKey
.currentState!
.value['shorthand'];
parent.read<ObjectBloc>().add(
AddRbacObject(
id: id,
name: name,
shorthand: short,
slug: slug));
Navigator.pop(context);
}
},
child: const Text("Add"))),
],
),
),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -162,7 +355,7 @@ class RbacObjectScreen extends StatelessWidget {
context.read<ObjectBloc>().add(GetObjects()); context.read<ObjectBloc>().add(GetObjects());
}); });
} else { } else {
errorAlert(context, "Delete Failed", "Object Delete Failed", errorAlert(context, "Delete Failed", "Object Deletion Failed",
() { () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<ObjectBloc>().add(GetObjects()); context.read<ObjectBloc>().add(GetObjects());
@ -174,6 +367,7 @@ class RbacObjectScreen extends StatelessWidget {
final parent = context; final parent = context;
if (state is ObjectLoaded) { if (state is ObjectLoaded) {
if (state.objects.isNotEmpty) { if (state.objects.isNotEmpty) {
objects = state.objects;
return ListView.builder( return ListView.builder(
padding: padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 10), const EdgeInsets.symmetric(vertical: 8, horizontal: 10),

View File

@ -5,7 +5,9 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:search_page/search_page.dart';
import 'package:unit2/bloc/rbac/rbac_operations/operation/operation_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/operation/operation_bloc.dart';
import 'package:unit2/model/rbac/rbac.dart';
import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart';
import 'package:unit2/widgets/error_state.dart'; import 'package:unit2/widgets/error_state.dart';
import '../../../theme-data.dart/box_shadow.dart'; import '../../../theme-data.dart/box_shadow.dart';
@ -24,82 +26,276 @@ class RbacOperationScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
final bloc = BlocProvider.of<OperationBloc>(context);
List<RBAC> operations = [];
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: primary, backgroundColor: primary,
title: const Text("Operations Screen"), title: const Text("Operations Screen"),
actions: [ centerTitle: true,
AddLeading(onPressed: () { actions: context.watch<OperationBloc>().state
BuildContext parent = context; is OperationLoadingState ||
showDialog( context.watch<OperationBloc>().state is OperationErrorState ||
context: context, context.watch<OperationBloc>().state is OperationAddedState ||
builder: (BuildContext context) { context.watch<OperationBloc>().state is OperationDeletedState ||
return AlertDialog( context.watch<OperationBloc>().state is OperationUpdatedState
title: const Text("Add New Operation"), ? []
content: FormBuilder( : [
key: formKey, IconButton(
child: Column( onPressed: () {
mainAxisSize: MainAxisSize.min, showSearch(
children: [ context: context,
FormBuilderTextField( delegate: SearchPage(
name: "object_name", barTheme: ThemeData(cardColor: Colors.white),
decoration: normalTextFieldStyle( builder: (RBAC rbac) {
"Operation name *", "Operation name "), return Column(
validator: FormBuilderValidators.required( children: [
errorText: "This field is required"), Container(
width: screenWidth,
decoration: box1(),
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
child: Row(
children: [
Expanded(
child: Text(rbac.name!,
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(
fontWeight:
FontWeight.w500,
color: primary)),
),
AppPopupMenu<int>(
offset: const Offset(-10, -10),
elevation: 3,
onSelected: (value) {
if (value == 2) {
showDialog(
context: context,
builder:
(BuildContext context) {
return AlertDialog(
title: const Text(
"Update Operation"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize:
MainAxisSize.min,
children: [
FormBuilderTextField(
initialValue:
rbac.name,
name:
"object_name",
decoration: normalTextFieldStyle(
"Operation name *",
"Operation name "),
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
initialValue:
rbac.slug,
name: "slug",
decoration:
normalTextFieldStyle(
"Slug ",
"Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
initialValue: rbac
.shorthand,
validator: FormBuilderValidators
.maxLength(50,
errorText:
"Max characters only 50"),
name: "shorthand",
decoration:
normalTextFieldStyle(
"Shorthand ",
"Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double
.infinity,
height: 50,
child:
ElevatedButton(
style: mainBtnStyle(
primary,
Colors
.transparent,
second),
onPressed:
() {
if (formKey
.currentState!
.saveAndValidate()) {
Navigator.pop(context);
String
name =
formKey.currentState!.value['object_name'];
String?
slug =
formKey.currentState!.value['slug'];
String?
short =
formKey.currentState!.value['shorthand'];
bloc.add(UpdateRbacOperation(
operationId: rbac.id!,
name: name,
slug: slug,
short: short,
createdBy: rbac.createdBy?.id,
updatedBy: id));
Navigator.pop(context);
}
},
child: const Text(
"Update"))),
],
),
),
);
});
}
if (value == 1) {
confirmAlert(context, () {
Navigator.pop(context);
context
.read<OperationBloc>()
.add(DeleteRbacOperation(
operationId: rbac.id!));
}, "Delete?", "Confirm Delete?");
}
},
menuItems: [
popMenuItem(
text: "Update",
value: 2,
icon: Icons.edit),
popMenuItem(
text: "Remove",
value: 1,
icon: Icons.delete),
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
),
],
),
),
const SizedBox(
height: 5,
)
],
);
},
filter: (RBAC rbac) {
return [rbac.name];
},
failure: const Center(
child: Text("No Operation found :("),
),
items: operations,
searchLabel: "Search Operation",
suggestion: const Center(
child: Text("Search operation by name"),
)),
);
},
icon: const Icon(Icons.search)),
AddLeading(onPressed: () {
BuildContext parent = context;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text("Add New Operation"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderTextField(
name: "object_name",
decoration: normalTextFieldStyle(
"Operation name *", "Operation name "),
validator: FormBuilderValidators.required(
errorText: "This field is required"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
name: "slug",
decoration:
normalTextFieldStyle("Slug ", "Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
validator: FormBuilderValidators.maxLength(50,
errorText: "Max characters only 50"),
name: "shorthand",
decoration: normalTextFieldStyle(
"Shorthand ", "Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate()) {
String name = formKey.currentState!
.value['object_name'];
String? slug = formKey
.currentState!.value['slug'];
String? short = formKey
.currentState!
.value['shorthand'];
parent.read<OperationBloc>().add(
AddRbacOperation(
id: id,
name: name,
shorthand: short,
slug: slug));
Navigator.pop(context);
}
},
child: const Text("Add"))),
],
),
), ),
const SizedBox( );
height: 8, });
), })
FormBuilderTextField( ],
name: "slug",
decoration: normalTextFieldStyle("Slug ", "Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
validator: FormBuilderValidators.maxLength(50,
errorText: "Max characters only 50"),
name: "shorthand",
decoration:
normalTextFieldStyle("Shorthand ", "Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate()) {
String name = formKey
.currentState!.value['object_name'];
String? slug =
formKey.currentState!.value['slug'];
String? short = formKey
.currentState!.value['shorthand'];
parent.read<OperationBloc>().add(
AddRbacOperation(
id: id,
name: name,
shorthand: short,
slug: slug));
Navigator.pop(context);
}
},
child: const Text("Add"))),
],
),
),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -162,8 +358,8 @@ class RbacOperationScreen extends StatelessWidget {
context.read<OperationBloc>().add(GetOperations()); context.read<OperationBloc>().add(GetOperations());
}); });
} else { } else {
errorAlert(context, "Delete Failed", "Operation Delete Failed", errorAlert(
() { context, "Delete Failed", "Operation Deletion Failed", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<OperationBloc>().add(GetOperations()); context.read<OperationBloc>().add(GetOperations());
}); });
@ -174,6 +370,7 @@ class RbacOperationScreen extends StatelessWidget {
final parent = context; final parent = context;
if (state is OperationsLoaded) { if (state is OperationsLoaded) {
if (state.operations.isNotEmpty) { if (state.operations.isNotEmpty) {
operations = state.operations;
return ListView.builder( return ListView.builder(
padding: padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 10), const EdgeInsets.symmetric(vertical: 8, horizontal: 10),
@ -190,18 +387,22 @@ class RbacOperationScreen extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: Row( child: Row(
children: [ children: [
CircleAvatar(child: Text('${index+1}'),), CircleAvatar(
const SizedBox(width: 12,), child: Text('${index + 1}'),
Text(state.operations[index].name!, ),
style: Theme.of(context) const SizedBox(
.textTheme width: 12,
.titleMedium! ),
.copyWith( Text(state.operations[index].name!,
fontWeight: FontWeight.w500, style: Theme.of(context)
color: primary)), .textTheme
], .titleMedium!
)), .copyWith(
fontWeight: FontWeight.w500,
color: primary)),
],
)),
AppPopupMenu<int>( AppPopupMenu<int>(
offset: const Offset(-10, -10), offset: const Offset(-10, -10),
elevation: 3, elevation: 3,
@ -211,7 +412,8 @@ class RbacOperationScreen extends StatelessWidget {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: const Text("Update Operation"), title: const Text(
"Update Operation"),
content: FormBuilder( content: FormBuilder(
key: formKey, key: formKey,
child: Column( child: Column(
@ -355,7 +557,7 @@ class RbacOperationScreen extends StatelessWidget {
}); });
} else { } else {
return const EmptyData( return const EmptyData(
message: "No Role available. Please click + to add."); message: "No Operation available. Please click + to add.");
} }
} }
if (state is OperationErrorState) { if (state is OperationErrorState) {

View File

@ -7,7 +7,9 @@ import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart'; import 'package:multi_dropdown/multiselect_dropdown.dart';
import 'package:search_page/search_page.dart';
import 'package:unit2/bloc/rbac/rbac_operations/permission/permission_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/permission/permission_bloc.dart';
import 'package:unit2/model/rbac/permission.dart';
import 'package:unit2/model/rbac/rbac.dart'; import 'package:unit2/model/rbac/rbac.dart';
import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart'; import 'package:unit2/screens/superadmin/role/shared_pop_up_menu.dart';
import 'package:unit2/theme-data.dart/btn-style.dart'; import 'package:unit2/theme-data.dart/btn-style.dart';
@ -32,6 +34,8 @@ class RbacPermissionScreen extends StatelessWidget {
List<RBAC> operations = []; List<RBAC> operations = [];
List<ValueItem> valueItemOperations = []; List<ValueItem> valueItemOperations = [];
List<ValueItem> selectedValueItemOperations = []; List<ValueItem> selectedValueItemOperations = [];
List<RBACPermission> permissions = [];
final bloc = BlocProvider.of<PermissionBloc>(context);
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
BuildContext? parent; BuildContext? parent;
return Scaffold( return Scaffold(
@ -39,103 +43,189 @@ class RbacPermissionScreen extends StatelessWidget {
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Permissions Screen"), title: const Text("Permissions Screen"),
actions: [ actions: context.watch<PermissionBloc>().state is PermissonLoadingState ||
AddLeading(onPressed: () { context.watch<PermissionBloc>().state is PermissionErrorState ||
showDialog( context.watch<PermissionBloc>().state is PermissionDeletedState ||
context: NavigationService.navigatorKey.currentState!.context, context.watch<PermissionBloc>().state is PermissionAddedState
builder: (BuildContext context) { ? []
valueItemOperations = operations.map((e) { : [
return ValueItem(label: e.name!, value: e.name); IconButton(
}).toList(); onPressed: () {
return AlertDialog( showSearch(
title: const Text("Add Permission"), context: context,
content: FormBuilder( delegate: SearchPage(
key: formKey, barTheme: ThemeData(cardColor: Colors.white),
child: Column( builder: (RBACPermission rbac) {
mainAxisSize: MainAxisSize.min, return Column(
children: [ children: [
FormBuilderDropdown<RBAC>( Container(
validator: FormBuilderValidators.required( width: screenWidth,
errorText: "This field is required"), decoration: box1(),
name: "object", padding: const EdgeInsets.symmetric(
decoration: horizontal: 12, vertical: 8),
normalTextFieldStyle("Permission", "Permission"), child: Row(
items: objects.isEmpty children: [
? [] Expanded(
: objects.map((e) { child: Text(
return DropdownMenuItem( "${rbac.object?.name} - ${rbac.operation?.name}",
value: e, child: Text(e.name!)); style: Theme.of(context)
}).toList(), .textTheme
onChanged: (RBAC? object) { .titleMedium!
selectedObject = object; .copyWith(
}, fontWeight:
FontWeight.w500,
color: primary)),
),
AppPopupMenu<int>(
offset: const Offset(-10, -10),
elevation: 3,
onSelected: (value) {
if (value == 1) {
confirmAlert(context, () {
Navigator.pop(context);
bloc.add(DeleteRbacPermission(
permissionId: rbac.id!));
}, "Delete?", "Confirm Delete?");
}
},
menuItems: [
popMenuItem(
text: "Remove",
value: 1,
icon: Icons.delete),
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
),
],
),
),
const SizedBox(
height: 5,
)
],
);
},
filter: (RBACPermission rbac) {
return [
rbac.object!.name! + rbac.operation!.name!
];
},
failure: const Center(
child: Text("No permission found :("),
), ),
const SizedBox( items: permissions,
height: 12, searchLabel: "Search Permission",
), suggestion: const Center(
MultiSelectDropDown( child: Text("Search permission by name"),
onOptionSelected: )),
(List<ValueItem> selectedOptions) { );
selectedValueItemOperations = selectedOptions; },
}, icon: const Icon(Icons.search)),
borderColor: Colors.grey, AddLeading(onPressed: () {
borderWidth: 1, showDialog(
borderRadius: 5, context:
hint: "Operations", NavigationService.navigatorKey.currentState!.context,
padding: const EdgeInsets.all(8), builder: (BuildContext context) {
options: valueItemOperations, valueItemOperations = operations.map((e) {
selectionType: SelectionType.multi, return ValueItem(label: e.name!, value: e.name);
chipConfig: }).toList();
const ChipConfig(wrapType: WrapType.wrap), return AlertDialog(
dropdownHeight: 300, title: const Text("Add Permission"),
optionTextStyle: const TextStyle(fontSize: 16), content: FormBuilder(
selectedOptionIcon: key: formKey,
const Icon(Icons.check_circle), child: Column(
), mainAxisSize: MainAxisSize.min,
const SizedBox( children: [
height: 12, FormBuilderDropdown<RBAC>(
), validator: FormBuilderValidators.required(
SizedBox( errorText: "This field is required"),
height: 50, name: "object",
width: double.maxFinite, decoration: normalTextFieldStyle(
child: ElevatedButton( "Permission", "Permission"),
style: mainBtnStyle( items: objects.isEmpty
primary, Colors.transparent, second), ? []
onPressed: () { : objects.map((e) {
if (formKey.currentState! return DropdownMenuItem(
.saveAndValidate() && value: e, child: Text(e.name!));
selectedValueItemOperations }).toList(),
.isNotEmpty) { onChanged: (RBAC? object) {
int assignerId = id; selectedObject = object;
int objectId = selectedObject!.id!; },
),
const SizedBox(
height: 12,
),
MultiSelectDropDown(
onOptionSelected:
(List<ValueItem> selectedOptions) {
selectedValueItemOperations =
selectedOptions;
},
borderColor: Colors.grey,
borderWidth: 1,
borderRadius: 5,
hint: "Operations",
padding: const EdgeInsets.all(8),
options: valueItemOperations,
selectionType: SelectionType.multi,
chipConfig: const ChipConfig(
wrapType: WrapType.wrap),
dropdownHeight: 300,
optionTextStyle:
const TextStyle(fontSize: 16),
selectedOptionIcon:
const Icon(Icons.check_circle),
),
const SizedBox(
height: 12,
),
SizedBox(
height: 50,
width: double.maxFinite,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate() &&
selectedValueItemOperations
.isNotEmpty) {
int assignerId = id;
int objectId = selectedObject!.id!;
List<int> opIds = []; List<int> opIds = [];
for (var operation in operations) { for (var operation in operations) {
selectedValueItemOperations selectedValueItemOperations
.forEach((element) { .forEach((element) {
if (element.label.toLowerCase() == if (element.label
operation.name?.toLowerCase()) { .toLowerCase() ==
opIds.add(operation.id!); operation.name
?.toLowerCase()) {
opIds.add(operation.id!);
}
});
}
Navigator.pop(context);
parent!.read<PermissionBloc>().add(
AddRbacPermission(
assignerId: assignerId,
objectId: objectId,
operationIds: opIds));
} }
}); },
} child: const Text("Submit")),
)
Navigator.pop(context); ],
parent!.read<PermissionBloc>().add( )),
AddRbacPermission( );
assignerId: assignerId, });
objectId: objectId, })
operationIds: opIds)); ],
}
},
child: const Text("Submit")),
)
],
)),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -179,8 +269,8 @@ class RbacPermissionScreen extends StatelessWidget {
context.read<PermissionBloc>().add(GetPermissions()); context.read<PermissionBloc>().add(GetPermissions());
}); });
} else { } else {
errorAlert(context, "Delete Failed", "Permission Delete Failed", errorAlert(
() { context, "Delete Failed", "Permission Deletion Failed", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<PermissionBloc>().add(GetPermissions()); context.read<PermissionBloc>().add(GetPermissions());
}); });
@ -193,6 +283,7 @@ class RbacPermissionScreen extends StatelessWidget {
objects = state.objects; objects = state.objects;
operations = state.operations; operations = state.operations;
if (state.permissions.isNotEmpty) { if (state.permissions.isNotEmpty) {
permissions = state.permissions;
return ListView.builder( return ListView.builder(
padding: padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 10), const EdgeInsets.symmetric(vertical: 8, horizontal: 10),
@ -209,41 +300,39 @@ class RbacPermissionScreen extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: Row( child: Row(
children: [ children: [
CircleAvatar( CircleAvatar(
child: Text('${index + 1}'), child: Text('${index + 1}'),
), ),
const SizedBox( const SizedBox(
width: 12, width: 12,
), ),
Flexible( Flexible(
child: Text( child: Text(
"${state.permissions[index].object?.name} - ${state.permissions[index].operation?.name}", "${state.permissions[index].object?.name} - ${state.permissions[index].operation?.name}",
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.titleMedium! .titleMedium!
.copyWith( .copyWith(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: primary)), color: primary)),
), ),
], ],
)), )),
AppPopupMenu<int>( AppPopupMenu<int>(
offset: const Offset(-10, -10), offset: const Offset(-10, -10),
elevation: 3, elevation: 3,
onSelected: (value) { onSelected: (value) {
if (value == 1) { if (value == 1) {
confirmAlert(context, () { confirmAlert(context, () {
context.read<PermissionBloc>().add( context.read<PermissionBloc>().add(
DeleteRbacPermission( DeleteRbacPermission(
permissionId: state.permissions[index].id!)); permissionId: state
.permissions[index].id!));
}, "Delete?", "Confirm Delete?"); }, "Delete?", "Confirm Delete?");
} }
}, },
menuItems: [ menuItems: [
popMenuItem( popMenuItem(
text: "Remove", text: "Remove",
value: 1, value: 1,
@ -271,8 +360,9 @@ class RbacPermissionScreen extends StatelessWidget {
} }
if (state is PermissionErrorState) { if (state is PermissionErrorState) {
return SomethingWentWrong( return SomethingWentWrong(
message: state.message, onpressed: () { message: state.message,
parent!.read<PermissionBloc>().add(GetPermissions()); onpressed: () {
parent!.read<PermissionBloc>().add(GetPermissions());
}); });
} }
return Container(); return Container();

View File

@ -5,9 +5,7 @@ import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:group_list_view/group_list_view.dart'; import 'package:group_list_view/group_list_view.dart';
import 'package:multi_dropdown/models/value_item.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart'; import 'package:multi_dropdown/multiselect_dropdown.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:unit2/bloc/rbac/rbac_operations/permission_assignment/permission_assignment_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/permission_assignment/permission_assignment_bloc.dart';
import 'package:unit2/model/rbac/permission.dart'; import 'package:unit2/model/rbac/permission.dart';
import 'package:unit2/model/rbac/rbac.dart'; import 'package:unit2/model/rbac/rbac.dart';
@ -15,7 +13,6 @@ import 'package:unit2/theme-data.dart/btn-style.dart';
import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/theme-data.dart/form-style.dart'; import 'package:unit2/theme-data.dart/form-style.dart';
import 'package:unit2/utils/alerts.dart'; import 'package:unit2/utils/alerts.dart';
import 'package:unit2/utils/global_context.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 'package:unit2/widgets/error_state.dart'; import 'package:unit2/widgets/error_state.dart';
@ -40,91 +37,111 @@ class RbacPermissionAssignmentScreen extends StatelessWidget {
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Permission Assignment"), title: const Text("Permission Assignment"),
actions: [ actions: context.watch<PermissionAssignmentBloc>().state
AddLeading(onPressed: () { is PermissionAssignmentLoadingScreen ||
showDialog( context.watch<PermissionAssignmentBloc>().state
context: context, is PermissionAssignmentErrorState ||
builder: (BuildContext context) { context.watch<PermissionAssignmentBloc>().state
valueItemPermission = permissions.map((e) { is PermissionAssignmentAddedState ||
return ValueItem( context.watch<PermissionAssignmentBloc>().state
label: "${e.object!.name} - ${e.operation!.name}", is PermissionAssignmentDeletedState
value: e.id.toString()); ? []
}).toList(); : [
return AlertDialog( AddLeading(onPressed: () {
title: const Text("Add Permission"), showDialog(
content: FormBuilder( context: context,
key: formKey, builder: (BuildContext context) {
child: Column( valueItemPermission = permissions.map((e) {
mainAxisSize: MainAxisSize.min, return ValueItem(
children: [ label: "${e.object!.name} - ${e.operation!.name}",
FormBuilderDropdown<RBAC>( value: e.id.toString());
validator: FormBuilderValidators.required( }).toList();
errorText: "This field is required"), return AlertDialog(
name: "role", title: const Text("Add Permission"),
decoration: normalTextFieldStyle("Role", "Role"), content: FormBuilder(
items: roles.isEmpty key: formKey,
? [] child: Column(
: roles.map((e) { mainAxisSize: MainAxisSize.min,
return DropdownMenuItem( children: [
value: e, child: Text(e.name!)); FormBuilderDropdown<RBAC>(
}).toList(), validator: FormBuilderValidators.required(
onChanged: (RBAC? role) { errorText: "This field is required"),
selectedRole = role; name: "role",
}, decoration:
), normalTextFieldStyle("Role", "Role"),
const SizedBox( items: roles.isEmpty
height: 12, ? []
), : roles.map((e) {
MultiSelectDropDown( return DropdownMenuItem(
onOptionSelected: (List<ValueItem> selectedOptions) { value: e, child: Text(e.name!));
selectedValueItemPermission = selectedOptions; }).toList(),
}, onChanged: (RBAC? role) {
borderColor: Colors.grey, selectedRole = role;
borderWidth: 1, },
borderRadius: 5, ),
hint: "Operations", const SizedBox(
padding: const EdgeInsets.all(8), height: 12,
options: valueItemPermission, ),
selectionType: SelectionType.multi, MultiSelectDropDown(
chipConfig: const ChipConfig(wrapType: WrapType.wrap), onOptionSelected:
dropdownHeight: 300, (List<ValueItem> selectedOptions) {
optionTextStyle: const TextStyle(fontSize: 16), selectedValueItemPermission =
selectedOptionIcon: const Icon(Icons.check_circle), selectedOptions;
), },
const SizedBox( borderColor: Colors.grey,
height: 12, borderWidth: 1,
), borderRadius: 5,
SizedBox( hint: "Operations",
height: 50, padding: const EdgeInsets.all(8),
width: double.maxFinite, options: valueItemPermission,
child: ElevatedButton( selectionType: SelectionType.multi,
style: mainBtnStyle( chipConfig: const ChipConfig(
primary, Colors.transparent, second), wrapType: WrapType.wrap),
onPressed: () { dropdownHeight: 300,
if (formKey.currentState!.saveAndValidate() && optionTextStyle:
selectedValueItemPermission.isNotEmpty) { const TextStyle(fontSize: 16),
int assignerId = id; selectedOptionIcon:
int roleId = selectedRole!.id!; const Icon(Icons.check_circle),
List<int> opIds = ),
selectedValueItemPermission.map((e) { const SizedBox(
return int.parse(e.value!); height: 12,
}).toList(); ),
Navigator.pop(context); SizedBox(
parent.read<PermissionAssignmentBloc>().add( height: 50,
AddPersmissionAssignment( width: double.maxFinite,
assignerId: assignerId, child: ElevatedButton(
opsId: opIds, style: mainBtnStyle(primary,
roleId: roleId)); Colors.transparent, second),
} onPressed: () {
}, if (formKey.currentState!
child: const Text("Submit")), .saveAndValidate() &&
) selectedValueItemPermission
], .isNotEmpty) {
)), int assignerId = id;
); int roleId = selectedRole!.id!;
}); List<int> opIds =
}) selectedValueItemPermission
], .map((e) {
return int.parse(e.value!);
}).toList();
Navigator.pop(context);
parent
.read<
PermissionAssignmentBloc>()
.add(AddPersmissionAssignment(
assignerId: assignerId,
opsId: opIds,
roleId: roleId));
}
},
child: const Text("Submit")),
)
],
)),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -183,7 +200,6 @@ class RbacPermissionAssignmentScreen extends StatelessWidget {
} }
}, },
builder: (context, state) { builder: (context, state) {
if (state is PermissionAssignmentLoadedState) { if (state is PermissionAssignmentLoadedState) {
if (state.permissionAssignments.isNotEmpty) { if (state.permissionAssignments.isNotEmpty) {
permissions = state.permissions; permissions = state.permissions;

View File

@ -25,6 +25,7 @@ class RbacRoleScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bloc = BlocProvider.of<RoleBloc>(context);
final formKey = GlobalKey<FormBuilderState>(); final formKey = GlobalKey<FormBuilderState>();
List<RBAC> roles = []; List<RBAC> roles = [];
return Scaffold( return Scaffold(
@ -32,102 +33,274 @@ class RbacRoleScreen extends StatelessWidget {
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Role Screen"), title: const Text("Role Screen"),
actions: [ actions:
IconButton( context.watch<RoleBloc>().state is RoleLoadingState ||
onPressed: () { context.watch<RoleBloc>().state is RoleErrorState ||
showSearch( context.watch<RoleBloc>().state is RoleDeletedState? ||
context: context, context.watch<RoleBloc>().state is RoleAddedState? ||
delegate: SearchPage( context.watch<RoleBloc>().state is RoleUpdatedState
barTheme: ThemeData(cardColor: primary), ? []
builder: (RBAC rbac) { : [
return ListTile( IconButton(
title: Text(rbac.name!), onPressed: () {
); showSearch(
}, context: context,
filter: (RBAC rbac) { delegate: SearchPage(
return [rbac.name]; barTheme: ThemeData(cardColor: Colors.white),
}, builder: (RBAC rbac) {
failure: const Center( return Column(
child: Text("No Role found :("), children: [
), Container(
items: roles, width: screenWidth,
searchLabel: "Search Role", decoration: box1(),
suggestion: const Center( padding: const EdgeInsets.symmetric(
child: Text("Search role by name"), horizontal: 12, vertical: 8),
)), child: Row(
); children: [
}, Expanded(
icon: const Icon(Icons.search)), child: Row(
AddLeading(onPressed: () { children: [
BuildContext parent = context; Flexible(
showDialog( child: Text(rbac.name!,
context: context, style: Theme.of(context)
builder: (BuildContext context) { .textTheme
return AlertDialog( .titleMedium!
title: const Text("Add New Role"), .copyWith(
content: FormBuilder( fontWeight:
key: formKey, FontWeight
child: Column( .w500,
mainAxisSize: MainAxisSize.min, color: primary)),
children: [ ),
FormBuilderTextField( ],
name: "object_name", )),
decoration: normalTextFieldStyle( AppPopupMenu<int>(
"Role name *", "Role name "), offset: const Offset(-10, -10),
validator: FormBuilderValidators.required( elevation: 3,
errorText: "This field is required"), onSelected: (value) {
), if (value == 2) {
const SizedBox( showDialog(
height: 8, context: context,
), builder: (BuildContext
FormBuilderTextField( context) {
name: "slug", return AlertDialog(
decoration: normalTextFieldStyle("Slug ", "Slug"), title: const Text(
), "Update Role"),
const SizedBox( content: FormBuilder(
height: 8, key: formKey,
), child: Column(
FormBuilderTextField( mainAxisSize:
validator: FormBuilderValidators.maxLength(50, MainAxisSize
errorText: "Max characters only 50"), .min,
name: "shorthand", children: [
decoration: FormBuilderTextField(
normalTextFieldStyle("Shorthand ", "Shorthand"), initialValue:
), rbac.name,
const SizedBox( name:
height: 12, "object_name",
), decoration: normalTextFieldStyle(
SizedBox( "Role name *",
width: double.infinity, "Role name "),
height: 50, validator: FormBuilderValidators
child: ElevatedButton( .required(
style: mainBtnStyle( errorText:
primary, Colors.transparent, second), "This field is required"),
onPressed: () { ),
if (formKey.currentState! const SizedBox(
.saveAndValidate()) { height: 8,
String name = formKey ),
.currentState!.value['object_name']; FormBuilderTextField(
String? slug = initialValue:
formKey.currentState!.value['slug']; rbac.slug,
String? short = formKey name: "slug",
.currentState!.value['shorthand']; decoration:
parent.read<RoleBloc>().add(AddRbacRole( normalTextFieldStyle(
id: id, "Slug ",
name: name, "Slug"),
shorthand: short, ),
slug: slug)); const SizedBox(
Navigator.pop(context); height: 8,
} ),
}, FormBuilderTextField(
child: const Text("Add"))), initialValue:
], rbac.shorthand,
), validator: FormBuilderValidators
), .maxLength(
); 50,
}); errorText:
}) "Max characters only 50"),
], name:
"shorthand",
decoration: normalTextFieldStyle(
"Shorthand ",
"Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double
.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
if (formKey
.currentState!
.saveAndValidate()) {
Navigator.pop(context);
String
name =
formKey.currentState!.value['object_name'];
String?
slug =
formKey.currentState!.value['slug'];
String?
short =
formKey.currentState!.value['shorthand'];
bloc.add(UpdateRbacRole(
roleId: rbac.id!,
name: name,
slug: slug,
short: short,
createdBy: rbac.createdBy?.id,
updatedBy: id));
Navigator.pop(context);
}
},
child: const Text("Update"))),
],
),
),
);
});
}
if (value == 1) {
confirmAlert(context, () {
Navigator.pop(context);
bloc
.add(DeleteRbacRole(
roleId: rbac.id!));
}, "Delete?",
"Confirm Delete?");
}
},
menuItems: [
popMenuItem(
text: "Update",
value: 2,
icon: Icons.edit),
popMenuItem(
text: "Remove",
value: 1,
icon: Icons.delete),
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
),
],
),
),
const SizedBox(
height: 5,
)
],
);
},
filter: (RBAC rbac) {
return [rbac.name];
},
failure: const Center(
child: Text("No Role found :("),
),
items: roles,
searchLabel: "Search Role",
suggestion: const Center(
child: Text("Search role by name"),
)),
);
},
icon: const Icon(Icons.search)),
AddLeading(onPressed: () {
BuildContext parent = context;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text("Add New Role"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderTextField(
name: "object_name",
decoration: normalTextFieldStyle(
"Role name *", "Role name "),
validator: FormBuilderValidators.required(
errorText: "This field is required"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
name: "slug",
decoration:
normalTextFieldStyle("Slug ", "Slug"),
),
const SizedBox(
height: 8,
),
FormBuilderTextField(
validator:
FormBuilderValidators.maxLength(50,
errorText:
"Max characters only 50"),
name: "shorthand",
decoration: normalTextFieldStyle(
"Shorthand ", "Shorthand"),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate()) {
String name = formKey
.currentState!
.value['object_name'];
String? slug = formKey
.currentState!
.value['slug'];
String? short = formKey
.currentState!
.value['shorthand'];
parent.read<RoleBloc>().add(
AddRbacRole(
id: id,
name: name,
shorthand: short,
slug: slug));
Navigator.pop(context);
}
},
child: const Text("Add"))),
],
),
),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),

View File

@ -36,7 +36,7 @@ class RbacRoleAssignment extends StatelessWidget {
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("User Roles Screens"), title: const Text("User Roles Screens"),
actions: [ actions: context.watch<RoleAssignmentBloc>().state is RoleAssignmentLoadingState || context.watch<RoleAssignmentBloc>().state is RoleAssignmentErrorState || context.watch<RoleAssignmentBloc>().state is UserNotExistError || context.watch<RoleAssignmentBloc>().state is RoleAddedState? []: [
AddLeading(onPressed: () { AddLeading(onPressed: () {
BuildContext parent = context; BuildContext parent = context;
showDialog( showDialog(
@ -131,13 +131,13 @@ class RbacRoleAssignment extends StatelessWidget {
if (state is AssignedRoleDeletedState) { if (state is AssignedRoleDeletedState) {
if (state.success) { if (state.success) {
successAlert(context, "Delete Successfull!", successAlert(context, "Delete Successfull!",
"Role Module Deleted Successfully", () { "Role Deleted Successfully", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<RoleAssignmentBloc>().add(LoadAssignedRole()); context.read<RoleAssignmentBloc>().add(LoadAssignedRole());
}); });
} else { } else {
errorAlert( errorAlert(
context, "Delete Failed", "Role Module Delete Failed", () { context, "Delete Failed", "Role Deletion Failed", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<RoleAssignmentBloc>().add(LoadAssignedRole()); context.read<RoleAssignmentBloc>().add(LoadAssignedRole());
}); });

View File

@ -36,7 +36,7 @@ class RbacRoleExtendScreen extends StatelessWidget {
elevation: 0, elevation: 0,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Role Extend"), title: const Text("Role Extend"),
actions: [ actions: context.watch<RoleExtendBloc>().state is RoleExtendLoadingState || context.watch<RoleExtendBloc>().state is RoleExtendErrorState || context.watch<RoleExtendBloc>().state is RoleExtendAddedState || context.watch<RoleExtendBloc>().state is RoleExtendDeletedState? []:[
AddLeading(onPressed: () { AddLeading(onPressed: () {
showDialog( showDialog(
context: NavigationService.navigatorKey.currentState!.context, context: NavigationService.navigatorKey.currentState!.context,

View File

@ -34,100 +34,114 @@ class RbacRoleModuleScreen extends StatelessWidget {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: primary, backgroundColor: primary,
title: const Text("Role Modules Screen"), title: const Text("Role Module Screen" ),
actions: [ centerTitle: true,
AddLeading(onPressed: () { actions: context.watch<RoleModuleBloc>().state
showDialog( is RoleModuleLoadingState ||
context: NavigationService.navigatorKey.currentState!.context, context.watch<RoleModuleBloc>().state is RoleModuleErrorState ||
builder: (BuildContext context) { context.watch<RoleModuleBloc>().state is RoleModuleAddedState ||
valueItemModules = modules.map((e) { context.watch<RoleModuleBloc>().state is RoleModuleDeletedState
return ValueItem(label: e.name!, value: e.name); ? []
}).toList(); : [
return AlertDialog( AddLeading(onPressed: () {
title: const Text("Add Role Module"), showDialog(
content: FormBuilder( context:
key: formKey, NavigationService.navigatorKey.currentState!.context,
child: Column( builder: (BuildContext context) {
mainAxisSize: MainAxisSize.min, valueItemModules = modules.map((e) {
children: [ return ValueItem(label: e.name!, value: e.name);
FormBuilderDropdown<RBAC>( }).toList();
validator: FormBuilderValidators.required( return AlertDialog(
errorText: "This field is required"), title: const Text("Add Role Module"),
name: "role", content: FormBuilder(
decoration: normalTextFieldStyle("Role", "Role"), key: formKey,
items: roles.isEmpty child: Column(
? [] mainAxisSize: MainAxisSize.min,
: roles.map((e) { children: [
return DropdownMenuItem( FormBuilderDropdown<RBAC>(
value: e, child: Text(e.name!)); validator: FormBuilderValidators.required(
}).toList(), errorText: "This field is required"),
onChanged: (RBAC? role) { name: "role",
selectedRole = role; decoration:
}, normalTextFieldStyle("Role", "Role"),
), items: roles.isEmpty
const SizedBox( ? []
height: 12, : roles.map((e) {
), return DropdownMenuItem(
MultiSelectDropDown( value: e, child: Text(e.name!));
onOptionSelected: }).toList(),
(List<ValueItem> selectedOptions) { onChanged: (RBAC? role) {
selectedValueItemModules = selectedOptions; selectedRole = role;
}, },
borderColor: Colors.grey, ),
borderWidth: 1, const SizedBox(
borderRadius: 5, height: 12,
hint: "Modules", ),
padding: const EdgeInsets.all(8), MultiSelectDropDown(
options: valueItemModules, onOptionSelected:
selectionType: SelectionType.multi, (List<ValueItem> selectedOptions) {
chipConfig: selectedValueItemModules =
const ChipConfig(wrapType: WrapType.wrap), selectedOptions;
dropdownHeight: 300, },
optionTextStyle: const TextStyle(fontSize: 16), borderColor: Colors.grey,
selectedOptionIcon: borderWidth: 1,
const Icon(Icons.check_circle), borderRadius: 5,
), hint: "Modules",
const SizedBox( padding: const EdgeInsets.all(8),
height: 12, options: valueItemModules,
), selectionType: SelectionType.multi,
SizedBox( chipConfig: const ChipConfig(
height: 50, wrapType: WrapType.wrap),
width: double.maxFinite, dropdownHeight: 300,
child: ElevatedButton( optionTextStyle:
style: mainBtnStyle( const TextStyle(fontSize: 16),
primary, Colors.transparent, second), selectedOptionIcon:
onPressed: () { const Icon(Icons.check_circle),
if (formKey.currentState! ),
.saveAndValidate() && const SizedBox(
selectedValueItemModules.isNotEmpty) { height: 12,
int assignerId = id; ),
int roleId = selectedRole!.id!; SizedBox(
List<int> modulesId = []; height: 50,
for (var module in modules) { width: double.maxFinite,
selectedValueItemModules child: ElevatedButton(
.forEach((element) { style: mainBtnStyle(primary,
if (element.label.toLowerCase() == Colors.transparent, second),
module.name?.toLowerCase()) { onPressed: () {
modulesId.add(module.id!); if (formKey.currentState!
.saveAndValidate() &&
selectedValueItemModules
.isNotEmpty) {
int assignerId = id;
int roleId = selectedRole!.id!;
List<int> modulesId = [];
for (var module in modules) {
selectedValueItemModules
.forEach((element) {
if (element.label
.toLowerCase() ==
module.name
?.toLowerCase()) {
modulesId.add(module.id!);
}
});
}
Navigator.of(context).pop();
parent.read<RoleModuleBloc>().add(
AddRoleModule(
assignerId: assignerId,
roleId: roleId,
moduleIds: modulesId));
} }
}); },
} child: const Text("Submit")),
Navigator.of(context).pop(); )
parent.read<RoleModuleBloc>().add( ],
AddRoleModule( )),
assignerId: assignerId, );
roleId: roleId, });
moduleIds: modulesId)); })
} ],
},
child: const Text("Submit")),
)
],
)),
);
});
})
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -156,7 +170,7 @@ class RbacRoleModuleScreen extends StatelessWidget {
}); });
} else { } else {
errorAlert( errorAlert(
context, "Delete Failed", "Role Module Delete Failed", () { context, "Delete Failed", "Role Module Deletion Failed", () {
Navigator.of(context).pop(); Navigator.of(context).pop();
context.read<RoleModuleBloc>().add(GetRoleModules()); context.read<RoleModuleBloc>().add(GetRoleModules());
}); });
@ -258,20 +272,22 @@ class RbacRoleModuleScreen extends StatelessWidget {
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.titleMedium! .titleMedium!
.copyWith(color: primary,fontWeight: FontWeight.bold), .copyWith(
color: primary, fontWeight: FontWeight.bold),
), ),
); );
}, },
); );
} else { } else {
return const EmptyData( return const EmptyData(
message: "No Role available. Please click + to add."); message: "No Role Module available. Please click + to add.");
} }
} }
if (state is RoleModuleErrorState) { if (state is RoleModuleErrorState) {
return SomethingWentWrong( return SomethingWentWrong(
message: state.message, onpressed: () { message: state.message,
context.read<RoleModuleBloc>().add(GetRoleModules()); onpressed: () {
context.read<RoleModuleBloc>().add(GetRoleModules());
}); });
} }
return Container(); return Container();

View File

@ -0,0 +1,307 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:group_list_view/group_list_view.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart';
import 'package:unit2/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart';
import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../model/rbac/rbac.dart';
import '../../../theme-data.dart/btn-style.dart';
import '../../../theme-data.dart/colors.dart';
import '../../../theme-data.dart/form-style.dart';
import '../../../utils/alerts.dart';
import '../../../utils/global_context.dart';
import '../../../widgets/empty_data.dart';
class RbacRoleUnderScreen extends StatelessWidget {
final int id;
const RbacRoleUnderScreen({super.key, required this.id});
@override
Widget build(BuildContext context) {
final parent = context;
Map<String, List<Content>> rolesUnder = {};
List<RBAC> roles = [];
RBAC? selectedRole;
List<ValueItem> valueItemRoles = [];
List<ValueItem> selectedValueItemRoles = [];
final formKey = GlobalKey<FormBuilderState>();
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: primary,
title: const Text("Assignable Roles"),
actions: context.watch<RolesUnderBloc>().state
is RoleUnderLoadingState? ||
context.watch<RolesUnderBloc>().state is RoleUnderErrorState ||
context.watch<RolesUnderBloc>().state
is RoleUnderDeletedState ||
context.watch<RolesUnderBloc>().state is RoleUnderAddedState
? []
: [
AddLeading(onPressed: () {
showDialog(
context:
NavigationService.navigatorKey.currentState!.context,
builder: (BuildContext context) {
valueItemRoles = roles.map((e) {
return ValueItem(label: e.name!, value: e.name);
}).toList();
return AlertDialog(
title: const Text("Add Role Under"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderDropdown<RBAC>(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
name: "role",
decoration: normalTextFieldStyle(
"Main Role", "Main Role"),
items: roles.isEmpty
? []
: roles.map((e) {
return DropdownMenuItem(
value: e, child: Text(e.name!));
}).toList(),
onChanged: (RBAC? role) {
selectedRole = role;
},
),
const SizedBox(
height: 12,
),
MultiSelectDropDown(
onOptionSelected:
(List<ValueItem> selectedOptions) {
selectedValueItemRoles = selectedOptions;
},
borderColor: Colors.grey,
borderWidth: 1,
borderRadius: 5,
hint: "Roles Under",
padding: const EdgeInsets.all(8),
options: valueItemRoles,
selectionType: SelectionType.multi,
chipConfig: const ChipConfig(
wrapType: WrapType.wrap),
dropdownHeight: 300,
optionTextStyle:
const TextStyle(fontSize: 16),
selectedOptionIcon:
const Icon(Icons.check_circle),
),
const SizedBox(
height: 12,
),
SizedBox(
height: 50,
width: double.maxFinite,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate() &&
selectedValueItemRoles
.isNotEmpty) {
int assignerId = id;
int roleId = selectedRole!.id!;
List<int> rolesId = [];
for (var role in roles) {
selectedValueItemRoles
.forEach((element) {
if (element.label
.toLowerCase() ==
role.name?.toLowerCase()) {
rolesId.add(role.id!);
}
});
}
Navigator.of(context).pop();
parent.read<RolesUnderBloc>().add(
AddRoleUnder(
roleId: roleId,
roleUnderIds: rolesId));
}
},
child: const Text("Submit")),
)
],
)),
);
});
})
],
),
body: ProgressHUD(
padding: const EdgeInsets.all(24),
backgroundColor: Colors.black87,
indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
child: BlocConsumer<RolesUnderBloc, RolesUnderState>(
listener: (context, state) {
if (state is RoleUnderLoadingState) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait...");
}
if (state is RoleUnderLoadedState ||
state is RoleUnderErrorState ||
state is RoleUnderDeletedState ||
state is RoleUnderAddedState) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
////Deleted State
if (state is RoleUnderDeletedState) {
if (state.success) {
successAlert(
context, "Delete Successfull!", "Role Deleted Successfully",
() {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
} else {
errorAlert(
context, "Delete Failed", "Role Module Delete Failed", () {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
}
}
////Added State
if (state is RoleUnderAddedState) {
if (state.response['success']) {
successAlert(
context, "Adding Successfull!", state.response['message'],
() {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
} else {
errorAlert(context, "Adding Failed", state.response['message'],
() {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
}
}
},
builder: (context, state) {
if (state is RoleUnderLoadedState) {
rolesUnder = {};
roles = state.roles;
if (state.rolesUnder.isNotEmpty) {
for (var roleUnder in state.rolesUnder) {
if (!rolesUnder.keys
.contains(roleUnder.roleUnderMain.name!.toLowerCase())) {
rolesUnder.addAll(
{roleUnder.roleUnderMain.name!.toLowerCase(): []});
rolesUnder[roleUnder.roleUnderMain.name!.toLowerCase()]!
.add(Content(
id: roleUnder.id,
name: roleUnder.roleUnderChild.name!));
} else {
rolesUnder[roleUnder.roleUnderMain.name!.toLowerCase()]!
.add(Content(
id: roleUnder.id,
name: roleUnder.roleUnderChild.name!));
}
}
}
if (state.rolesUnder.isNotEmpty) {
return GroupListView(
sectionsCount: rolesUnder.keys.toList().length,
countOfItemInSection: (int section) {
return rolesUnder.values.toList()[section].length;
},
itemBuilder: (BuildContext context, IndexPath index) {
return ListTile(
trailing: IconButton(
color: Colors.grey.shade500,
icon: const Icon(Icons.delete),
onPressed: () {
confirmAlert(context,(){
context.read<RolesUnderBloc>().add(DeleteRoleUnder(roleUnderId:rolesUnder.values .toList()[index.section][index.index].id));
}, "Delete", "Delete Role?");
},
),
title: Row(
children: [
CircleAvatar(
child: Text("${index.index + 1}",
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(color: Colors.white))),
const SizedBox(
width: 20,
),
Expanded(
child: Text(
rolesUnder.values
.toList()[index.section][index.index]
.name
.toUpperCase(),
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(
fontWeight: FontWeight.w500,
color: primary)),
),
],
),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
groupHeaderBuilder: (BuildContext context, int section) {
return ListTile(
tileColor: Colors.white,
dense: true,
title: Text(
rolesUnder.keys.toList()[section].toUpperCase(),
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(
color: primary, fontWeight: FontWeight.bold),
),
);
},
);
} else {
return const EmptyData(
message: "No Role available. Please click + to add.");
}
}
if (state is RoleUnderErrorState) {
return SomethingWentWrong(
message: state.message,
onpressed: () {
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
}
return Container();
},
),
),
);
}
}
class Content {
final int id;
final String name;
const Content({required this.id, required this.name});
}

View File

@ -1,296 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:group_list_view/group_list_view.dart';
import 'package:multi_dropdown/multiselect_dropdown.dart';
import 'package:unit2/bloc/rbac/rbac_operations/roles_under/roles_under_bloc.dart';
import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../model/rbac/rbac.dart';
import '../../../theme-data.dart/btn-style.dart';
import '../../../theme-data.dart/colors.dart';
import '../../../theme-data.dart/form-style.dart';
import '../../../utils/alerts.dart';
import '../../../utils/global_context.dart';
import '../../../widgets/empty_data.dart';
class RbacRoleUnderScreen extends StatelessWidget {
final int id;
const RbacRoleUnderScreen({super.key, required this.id});
@override
Widget build(BuildContext context) {
final parent = context;
Map<String, List<Content>> rolesUnder = {};
List<RBAC> roles = [];
RBAC? selectedRole;
List<ValueItem> valueItemRoles = [];
List<ValueItem> selectedValueItemRoles = [];
final formKey = GlobalKey<FormBuilderState>();
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: primary,
title: const Text("Assignable Roles"),
actions: [
AddLeading(onPressed: () {
showDialog(
context: NavigationService.navigatorKey.currentState!.context,
builder: (BuildContext context) {
valueItemRoles = roles.map((e) {
return ValueItem(label: e.name!, value: e.name);
}).toList();
return AlertDialog(
title: const Text("Add Role Under"),
content: FormBuilder(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderDropdown<RBAC>(
validator: FormBuilderValidators.required(
errorText: "This field is required"),
name: "role",
decoration: normalTextFieldStyle(
"Main Role", "Main Role"),
items: roles.isEmpty
? []
: roles.map((e) {
return DropdownMenuItem(
value: e, child: Text(e.name!));
}).toList(),
onChanged: (RBAC? role) {
selectedRole = role;
},
),
const SizedBox(
height: 12,
),
MultiSelectDropDown(
onOptionSelected:
(List<ValueItem> selectedOptions) {
selectedValueItemRoles = selectedOptions;
},
borderColor: Colors.grey,
borderWidth: 1,
borderRadius: 5,
hint: "Roles Under",
padding: const EdgeInsets.all(8),
options: valueItemRoles,
selectionType: SelectionType.multi,
chipConfig:
const ChipConfig(wrapType: WrapType.wrap),
dropdownHeight: 300,
optionTextStyle: const TextStyle(fontSize: 16),
selectedOptionIcon:
const Icon(Icons.check_circle),
),
const SizedBox(
height: 12,
),
SizedBox(
height: 50,
width: double.maxFinite,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
if (formKey.currentState!
.saveAndValidate() &&
selectedValueItemRoles.isNotEmpty) {
int assignerId = id;
int roleId = selectedRole!.id!;
List<int> rolesId = [];
for (var role in roles) {
selectedValueItemRoles
.forEach((element) {
if (element.label.toLowerCase() ==
role.name?.toLowerCase()) {
rolesId.add(role.id!);
}
});
}
Navigator.of(context).pop();
parent.read<RolesUnderBloc>().add(
AddRoleUnder(
roleId: roleId,
roleUnderIds: rolesId));
}
},
child: const Text("Submit")),
)
],
)),
);
});
})
],
),
body: ProgressHUD(
padding: const EdgeInsets.all(24),
backgroundColor: Colors.black87,
indicatorWidget: const SpinKitFadingCircle(color: Colors.white),
child: BlocConsumer<RolesUnderBloc, RolesUnderState>(
listener: (context, state) {
if (state is RoleUnderLoadingState) {
final progress = ProgressHUD.of(context);
progress!.showWithText("Please wait...");
}
if (state is RoleUnderLoadedState ||
state is RoleUnderErrorState ||
state is RoleUnderDeletedState ||
state is RoleUnderAddedState) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
////Deleted State
if (state is RoleUnderDeletedState) {
if (state.success) {
successAlert(context, "Delete Successfull!",
"Role Deleted Successfully", () {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
} else {
errorAlert(
context, "Delete Failed", "Role Module Delete Failed", () {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
}
}
////Added State
if (state is RoleUnderAddedState) {
if (state.response['success']) {
successAlert(
context, "Adding Successfull!", state.response['message'],
() {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
} else {
errorAlert(context, "Adding Failed", state.response['message'],
() {
Navigator.of(context).pop();
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
}
}
},
builder: (context, state) {
if (state is RoleUnderLoadedState) {
rolesUnder = {};
roles = state.roles;
if (state.rolesUnder.isNotEmpty) {
for (var roleUnder in state.rolesUnder) {
if (!rolesUnder.keys
.contains(roleUnder.roleUnderMain.name!.toLowerCase())) {
rolesUnder.addAll(
{roleUnder.roleUnderMain.name!.toLowerCase(): []});
rolesUnder[roleUnder.roleUnderMain.name!.toLowerCase()]!
.add(Content(
id: roleUnder.id,
name: roleUnder.roleUnderChild.name!));
} else {
rolesUnder[roleUnder.roleUnderMain.name!.toLowerCase()]!
.add(Content(
id: roleUnder.id,
name: roleUnder.roleUnderChild.name!));
}
}
}
if (state.rolesUnder.isNotEmpty) {
return GroupListView(
sectionsCount: rolesUnder.keys.toList().length,
countOfItemInSection: (int section) {
return rolesUnder.values.toList()[section].length;
},
itemBuilder: (BuildContext context, IndexPath index) {
return ListTile(
trailing: IconButton(
color: Colors.grey.shade500,
icon: const Icon(Icons.delete),
onPressed: () {
context.read<RolesUnderBloc>().add(DeleteRoleUnder(
roleUnderId: rolesUnder.values
.toList()[index.section][index.index]
.id));
},
),
title: Row(
children: [
CircleAvatar(
child: Text("${index.index + 1}",
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(color: Colors.white))),
const SizedBox(
width: 20,
),
Expanded(
child: Text(
rolesUnder.values
.toList()[index.section][index.index]
.name
.toUpperCase(),
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(
fontWeight: FontWeight.w500,
color: primary)
),
),
],
),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
groupHeaderBuilder: (BuildContext context, int section) {
return ListTile(
tileColor: Colors.white,
dense: true,
title: Text(
rolesUnder.keys.toList()[section].toUpperCase(),
style: Theme.of(context)
.textTheme
.titleMedium!
.copyWith(color: primary,fontWeight: FontWeight.bold),
),
);
},
);
} else {
return const EmptyData(
message: "No Role available. Please click + to add.");
}
}
if (state is RoleUnderErrorState) {
return SomethingWentWrong(
message: state.message, onpressed: () {
context.read<RolesUnderBloc>().add(GetRolesUnder());
});
}
return Container();
},
),
),
);
}
}
class Content {
final int id;
final String name;
const Content({required this.id, required this.name});
}

View File

@ -5,7 +5,6 @@ import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:searchfield/searchfield.dart'; import 'package:searchfield/searchfield.dart';
import 'package:unit2/bloc/rbac/rbac_operations/role/role_bloc.dart';
import 'package:unit2/bloc/rbac/rbac_operations/station/station_bloc.dart'; import 'package:unit2/bloc/rbac/rbac_operations/station/station_bloc.dart';
import 'package:unit2/model/rbac/rbac_station.dart'; import 'package:unit2/model/rbac/rbac_station.dart';
import 'package:unit2/model/utils/agency.dart'; import 'package:unit2/model/utils/agency.dart';
@ -62,436 +61,469 @@ class _RbacStationScreenState extends State<RbacStationScreen> {
centerTitle: true, centerTitle: true,
backgroundColor: primary, backgroundColor: primary,
title: const Text("Station Screen"), title: const Text("Station Screen"),
actions: [ actions: context.watch<StationBloc>().state is StationLoadingState ||
AddLeading(onPressed: () { context.watch<StationBloc>().state is StationErrorState ||
BuildContext parent = context; context.watch<StationBloc>().state is RbacStationAddedState ||
mainParentStations = []; context.watch<StationBloc>().state is FilterStationState
mainParent = stations.isEmpty ? true : false; ? []
for (RbacStation station in stations) { : [
if (station.hierarchyOrderNo == 1) { AddLeading(onPressed: () {
mainParentStations.add(station); BuildContext parent = context;
} mainParentStations = [];
} mainParent = stations.isEmpty ? true : false;
for (RbacStation station in stations) {
if (station.hierarchyOrderNo == 1) {
mainParentStations.add(station);
}
}
/////Add new tation /////Add new tation
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: const Text("Add New Station"), title: const Text("Add New Station"),
content: SingleChildScrollView( content: SingleChildScrollView(
child: FormBuilder( child: FormBuilder(
key: formKey, key: formKey,
child: StatefulBuilder(builder: (context, setState) { child:
return Column( StatefulBuilder(builder: (context, setState) {
mainAxisSize: MainAxisSize.min, return Column(
children: [ mainAxisSize: MainAxisSize.min,
////is main parent children: [
FormBuilderSwitch( ////is main parent
initialValue: mainParent, FormBuilderSwitch(
activeColor: second, initialValue: mainParent,
onChanged: (value) { activeColor: second,
setState(() { onChanged: (value) {
mainParent = !mainParent; setState(() {
}); mainParent = !mainParent;
}, });
decoration: normalTextFieldStyle(
"is Main Parent?", 'is Main Parent?'),
name: 'main-parent',
title: Text(mainParent ? "YES" : "NO"),
validator: FormBuilderValidators.required(
errorText: "This field is required"),
),
SizedBox(
height: mainParent ? 0 : 8,
),
//// selected main parent
SizedBox(
child: mainParent == true
? const SizedBox.shrink()
: FormBuilderDropdown<RbacStation>(
decoration: normalTextFieldStyle(
"Main Parent Station",
"Main Parent Station"),
name: "parent-stations",
items: mainParentStations.isEmpty
? []
: mainParentStations.map((e) {
return DropdownMenuItem(
value: e,
child: Text(e.stationName!),
);
}).toList(),
onChanged: (RbacStation? e) {
setState(() {
selectedMainParentStation = e;
parentStations = [];
for (RbacStation station
in stations) {
if (station.mainParentStation ==
selectedMainParentStation!
.id) {
parentStations.add(station);
}
}
parentStations.add(
selectedMainParentStation!);
});
},
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
),
),
SizedBox(
height: mainParent ? 0 : 8,
),
////parent station
SizedBox(
child: mainParent == true
? const SizedBox.shrink()
: FormBuilderDropdown<RbacStation>(
decoration: normalTextFieldStyle(
"Parent Station", "Parent Station"),
name: "parent-stations",
onChanged: (RbacStation? e) {
setState(() {
selectedParentStation = e;
});
},
items: parentStations.isEmpty
? []
: parentStations.map((e) {
return DropdownMenuItem(
value: e,
child: Text(e.stationName!),
);
}).toList(),
validator:
FormBuilderValidators.required(
errorText:
"This field is required"),
),
),
const SizedBox(
height: 12,
),
////Station Type
SearchField(
itemHeight: 50,
suggestionsDecoration: searchFieldDecoration(),
suggestions: stationTypes
.map((StationType stationType) =>
SearchFieldListItem(
stationType.typeName!,
item: stationType,
child: Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 10),
child: ListTile(
title: Text(
stationType.typeName!,
overflow: TextOverflow.visible,
)),
)))
.toList(),
validator: (station) {
if (station!.isEmpty) {
return "This field is required";
}
return null;
},
focusNode: stationTypeFocusNode,
searchInputDecoration:
normalTextFieldStyle("Station Type *", "")
.copyWith(
suffixIcon: GestureDetector(
onTap: () => stationTypeFocusNode.unfocus(),
child: const Icon(Icons.arrow_drop_down),
)),
onSuggestionTap: (position) {
setState(() {
selectedStationType = position.item!;
stationTypeFocusNode.unfocus();
});
},
emptyWidget: EmptyWidget(
title: "Add StationType",
controller: addStationTypeController,
onpressed: () {
setState(() {
StationType stationType = StationType(
id: null,
typeName:
addStationTypeController.text,
color: null,
order: null,
isActive: null,
group: null);
stationTypes.add(stationType);
Navigator.pop(context);
});
}),
),
const SizedBox(
height: 12,
),
////Position title
FormBuilderDropdown(
decoration: normalTextFieldStyle(
"Head Position", "Head Position"),
name: "head-position",
items: positions.map((e) {
return DropdownMenuItem(
value: e,
child: Text(e.title!),
);
}).toList(),
onChanged: (title) {
selectedPositiontitle = title;
},
),
const SizedBox(
height: 12,
),
////is within parent
FormBuilderSwitch(
initialValue: true,
activeColor: second,
onChanged: (value) {
setState(() {
isWithinParent = value!;
});
},
decoration: normalTextFieldStyle(
"Location of the station within this parent?",
'Location of the station within this parent?'),
name: 'isWithinParent',
title: Text(isWithinParent ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
Row(
//// Station Name
children: [
Flexible(
child: FormBuilderTextField(
validator:
FormBuilderValidators.required(
errorText:
"This Field is required"),
decoration: normalTextFieldStyle(
"Station name", "Station name"),
name: "station-name"),
),
const SizedBox(
width: 12,
),
//// Acronym
Flexible(
child: FormBuilderTextField(
validator:
FormBuilderValidators.required(
errorText:
"This Field is required"),
decoration: normalTextFieldStyle(
"Acronym", "Acronym"),
name: "acronym"),
),
],
),
const SizedBox(
height: 12,
),
FormBuilderTextField(
////Description
decoration: normalTextFieldStyle(
"Station description",
"Station description"),
name: "station-description"),
const SizedBox(
height: 12,
),
Row(
children: [
Flexible(
////Code
child: FormBuilderTextField(
decoration: normalTextFieldStyle(
"Code", "Code"),
name: "code"),
),
const SizedBox(
width: 12,
),
Flexible(
//// Full Code
child: FormBuilderTextField(
decoration: normalTextFieldStyle(
"Full Code", "Full Code"),
name: "fullcode"),
),
],
),
const SizedBox(
height: 12,
),
////is Hospital
FormBuilderSwitch(
initialValue: isHospital,
activeColor: second,
onChanged: (value) {
setState(() {
isHospital = !isHospital;
});
},
decoration:
normalTextFieldStyle("Is Hospital", ''),
name: 'isHospital',
title: Text(isHospital == true ? "YES" : "NO"),
),
const SizedBox(
height: 20,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
onPressed: () {
RbacStation? newStation;
if (formKey.currentState!
.saveAndValidate()) {
String? stationName = formKey
.currentState!
.value['station-name'];
String? acronym = formKey
.currentState!.value['acronym'];
String? code = formKey
.currentState!.value['code'];
String? fullcode = formKey
.currentState!.value['fullcode'];
String? description = formKey
.currentState!
.value['station-description'];
newStation = RbacStation(
id: null,
stationName: stationName,
stationType: selectedStationType,
hierarchyOrderNo: mainParent
? 1
: selectedParentStation!
.hierarchyOrderNo! +
1,
headPosition:
selectedPositiontitle?.title,
governmentAgency:
GovernmentAgency(
agencyid:
selectedAgencyId,
agencyname: null,
agencycatid: null,
privateEntity: null,
contactinfoid: null),
acronym: acronym,
parentStation: mainParent
? null
: selectedParentStation!.id!,
code: code,
fullcode: fullcode,
childStationInfo: null,
islocationUnderParent:
isWithinParent,
mainParentStation: mainParent
? null
: selectedMainParentStation!
.id!,
description: description,
ishospital: isHospital,
isactive: true,
sellingStation: null);
Navigator.pop(context);
rbacStationBloc.add(AddRbacStation(
station: newStation));
}
}, },
child: const Text("Add"))), decoration: normalTextFieldStyle(
], "is Main Parent?", 'is Main Parent?'),
); name: 'main-parent',
}), title: Text(mainParent ? "YES" : "NO"),
), validator: FormBuilderValidators.required(
), errorText: "This field is required"),
); ),
}); SizedBox(
}), height: mainParent ? 0 : 8,
////Filter ),
IconButton( //// selected main parent
onPressed: () { SizedBox(
showDialog( child: mainParent == true
context: context, ? const SizedBox.shrink()
builder: (BuildContext context) { : FormBuilderDropdown<RbacStation>(
return AlertDialog( decoration: normalTextFieldStyle(
title: const Text( "Main Parent Station",
"Select agency to filter stations", "Main Parent Station"),
textAlign: TextAlign.center, name: "parent-stations",
), items: mainParentStations.isEmpty
content: SizedBox( ? []
child: // //// Filter Agencies : mainParentStations.map((e) {
Padding( return DropdownMenuItem(
padding: const EdgeInsets.all(8), value: e,
child: SearchField( child: Text(
inputFormatters: [UpperCaseTextFormatter()], e.stationName!),
itemHeight: 100, );
focusNode: agencyFocusNode, }).toList(),
suggestions: agencies onChanged: (RbacStation? e) {
.map((Agency agency) => setState(() {
SearchFieldListItem(agency.name!, selectedMainParentStation = e;
item: agency, parentStations = [];
child: ListTile( for (RbacStation station
title: Text( in stations) {
agency.name!, if (station
overflow: TextOverflow.visible, .mainParentStation ==
), selectedMainParentStation!
))) .id) {
.toList(), parentStations
searchInputDecoration: .add(station);
normalTextFieldStyle("Filter", "").copyWith( }
suffixIcon: IconButton( }
icon: const Icon(Icons.arrow_drop_down), parentStations.add(
onPressed: () { selectedMainParentStation!);
agencyFocusNode.unfocus(); });
}, },
)), validator: FormBuilderValidators
onSuggestionTap: (agency) { .required(
agencyFocusNode.unfocus(); errorText:
"This field is required"),
selectedAgencyId = agency.item!.id!; ),
print(selectedAgencyId); ),
Navigator.pop(context); SizedBox(
rbacStationBloc.add(FilterStation( height: mainParent ? 0 : 8,
agencyId: selectedAgencyId)); ),
}, ////parent station
validator: (agency) { SizedBox(
if (agency!.isEmpty) { child: mainParent == true
return "This field is required"; ? const SizedBox.shrink()
} : FormBuilderDropdown<RbacStation>(
return null; decoration: normalTextFieldStyle(
}, "Parent Station",
emptyWidget: const Center( "Parent Station"),
child: Text("No result found..."), name: "parent-stations",
)), onChanged: (RbacStation? e) {
setState(() {
selectedParentStation = e;
});
},
items: parentStations.isEmpty
? []
: parentStations.map((e) {
return DropdownMenuItem(
value: e,
child: Text(
e.stationName!),
);
}).toList(),
validator: FormBuilderValidators
.required(
errorText:
"This field is required"),
),
),
const SizedBox(
height: 12,
),
////Station Type
SearchField(
itemHeight: 50,
suggestionsDecoration:
searchFieldDecoration(),
suggestions: stationTypes
.map((StationType stationType) =>
SearchFieldListItem(
stationType.typeName!,
item: stationType,
child: Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 10),
child: ListTile(
title: Text(
stationType.typeName!,
overflow:
TextOverflow.visible,
)),
)))
.toList(),
validator: (station) {
if (station!.isEmpty) {
return "This field is required";
}
return null;
},
focusNode: stationTypeFocusNode,
searchInputDecoration:
normalTextFieldStyle(
"Station Type *", "")
.copyWith(
suffixIcon: GestureDetector(
onTap: () =>
stationTypeFocusNode.unfocus(),
child:
const Icon(Icons.arrow_drop_down),
)),
onSuggestionTap: (position) {
setState(() {
selectedStationType = position.item!;
stationTypeFocusNode.unfocus();
});
},
emptyWidget: EmptyWidget(
title: "Add StationType",
controller: addStationTypeController,
onpressed: () {
setState(() {
StationType stationType =
StationType(
id: null,
typeName:
addStationTypeController
.text,
color: null,
order: null,
isActive: null,
group: null);
stationTypes.add(stationType);
Navigator.pop(context);
});
}),
),
const SizedBox(
height: 12,
),
////Position title
FormBuilderDropdown(
decoration: normalTextFieldStyle(
"Head Position", "Head Position"),
name: "head-position",
items: positions.map((e) {
return DropdownMenuItem(
value: e,
child: Text(e.title!),
);
}).toList(),
onChanged: (title) {
selectedPositiontitle = title;
},
),
const SizedBox(
height: 12,
),
////is within parent
FormBuilderSwitch(
initialValue: true,
activeColor: second,
onChanged: (value) {
setState(() {
isWithinParent = value!;
});
},
decoration: normalTextFieldStyle(
"Location of the station within this parent?",
'Location of the station within this parent?'),
name: 'isWithinParent',
title:
Text(isWithinParent ? "YES" : "NO"),
),
const SizedBox(
height: 12,
),
Row(
//// Station Name
children: [
Flexible(
child: FormBuilderTextField(
validator: FormBuilderValidators
.required(
errorText:
"This Field is required"),
decoration: normalTextFieldStyle(
"Station name",
"Station name"),
name: "station-name"),
),
const SizedBox(
width: 12,
),
//// Acronym
Flexible(
child: FormBuilderTextField(
validator: FormBuilderValidators
.required(
errorText:
"This Field is required"),
decoration: normalTextFieldStyle(
"Acronym", "Acronym"),
name: "acronym"),
),
],
),
const SizedBox(
height: 12,
),
FormBuilderTextField(
////Description
decoration: normalTextFieldStyle(
"Station description",
"Station description"),
name: "station-description"),
const SizedBox(
height: 12,
),
Row(
children: [
Flexible(
////Code
child: FormBuilderTextField(
decoration: normalTextFieldStyle(
"Code", "Code"),
name: "code"),
),
const SizedBox(
width: 12,
),
Flexible(
//// Full Code
child: FormBuilderTextField(
decoration: normalTextFieldStyle(
"Full Code", "Full Code"),
name: "fullcode"),
),
],
),
const SizedBox(
height: 12,
),
////is Hospital
FormBuilderSwitch(
initialValue: isHospital,
activeColor: second,
onChanged: (value) {
setState(() {
isHospital = !isHospital;
});
},
decoration: normalTextFieldStyle(
"Is Hospital", ''),
name: 'isHospital',
title: Text(
isHospital == true ? "YES" : "NO"),
),
const SizedBox(
height: 20,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary,
Colors.transparent, second),
onPressed: () {
RbacStation? newStation;
if (formKey.currentState!
.saveAndValidate()) {
String? stationName = formKey
.currentState!
.value['station-name'];
String? acronym = formKey
.currentState!
.value['acronym'];
String? code = formKey
.currentState!
.value['code'];
String? fullcode = formKey
.currentState!
.value['fullcode'];
String? description =
formKey.currentState!.value[
'station-description'];
newStation = RbacStation(
id: null,
stationName: stationName,
stationType:
selectedStationType,
hierarchyOrderNo: mainParent
? 1
: selectedParentStation!
.hierarchyOrderNo! +
1,
headPosition:
selectedPositiontitle
?.title,
governmentAgency:
GovernmentAgency(
agencyid:
selectedAgencyId,
agencyname: null,
agencycatid: null,
privateEntity: null,
contactinfoid:
null),
acronym: acronym,
parentStation:
mainParent
? null
: selectedParentStation!
.id!,
code: code,
fullcode: fullcode,
childStationInfo: null,
islocationUnderParent:
isWithinParent,
mainParentStation: mainParent
? null
: selectedMainParentStation!
.id!,
description: description,
ishospital: isHospital,
isactive: true,
sellingStation: null);
Navigator.pop(context);
rbacStationBloc.add(
AddRbacStation(
station: newStation));
}
},
child: const Text("Add"))),
],
);
}),
),
), ),
), );
); });
}); }),
}, ////Filter
icon: const Icon(Icons.filter_list)) IconButton(
], onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
"Select agency to filter stations",
textAlign: TextAlign.center,
),
content: SizedBox(
child: // //// Filter Agencies
Padding(
padding: const EdgeInsets.all(8),
child: SearchField(
inputFormatters: [
UpperCaseTextFormatter()
],
itemHeight: 100,
focusNode: agencyFocusNode,
suggestions: agencies
.map((Agency agency) =>
SearchFieldListItem(agency.name!,
item: agency,
child: ListTile(
title: Text(
agency.name!,
overflow:
TextOverflow.visible,
),
)))
.toList(),
searchInputDecoration:
normalTextFieldStyle("Filter", "")
.copyWith(
suffixIcon: IconButton(
icon: const Icon(Icons.arrow_drop_down),
onPressed: () {
agencyFocusNode.unfocus();
},
)),
onSuggestionTap: (agency) {
agencyFocusNode.unfocus();
selectedAgencyId = agency.item!.id!;
print(selectedAgencyId);
Navigator.pop(context);
rbacStationBloc.add(FilterStation(
agencyId: selectedAgencyId));
},
validator: (agency) {
if (agency!.isEmpty) {
return "This field is required";
}
return null;
},
emptyWidget: const Center(
child: Text("No result found..."),
)),
),
),
);
});
},
icon: const Icon(Icons.filter_list))
],
), ),
body: ProgressHUD( body: ProgressHUD(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@ -643,7 +675,7 @@ class _RbacStationScreenState extends State<RbacStationScreen> {
boxShadow: []), boxShadow: []),
padding: padding:
const EdgeInsets const EdgeInsets
.only( .only(
left: 30), left: 30),
child: Row( child: Row(
children: [ children: [
@ -652,7 +684,8 @@ class _RbacStationScreenState extends State<RbacStationScreen> {
children: [ children: [
Padding( Padding(
padding: padding:
const EdgeInsets.all( const EdgeInsets
.all(
6), 6),
child: child:
Text( Text(
@ -720,7 +753,7 @@ class _RbacStationScreenState extends State<RbacStationScreen> {
box1() box1()
.copyWith(boxShadow: []), .copyWith(boxShadow: []),
padding: const EdgeInsets padding: const EdgeInsets
.only( .only(
left: left:
50), 50),
child: child:
@ -873,7 +906,9 @@ class _RbacStationScreenState extends State<RbacStationScreen> {
return SomethingWentWrong( return SomethingWentWrong(
message: state.message, message: state.message,
onpressed: () { onpressed: () {
context.read<StationBloc>().add(GetStations(agencyId: selectedAgencyId)); context
.read<StationBloc>()
.add(GetStations(agencyId: selectedAgencyId));
}); });
} }

View File

@ -1,7 +1,8 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart'; import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttericon/font_awesome5_icons.dart'; import 'package:fluttericon/font_awesome5_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
@ -44,45 +45,45 @@ class BasicInfo extends StatelessWidget {
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
const CoverImage(), const CoverImage(),
// Positioned( Positioned(
// top: blockSizeVertical * 15.5, top: blockSizeVertical * 15.5,
// child: Stack( child: Stack(
// alignment: Alignment.center, alignment: Alignment.center,
// children: [ children: [
// CachedNetworkImage( CachedNetworkImage(
// imageUrl: fileUrl, imageUrl: fileUrl,
// imageBuilder: (context, imageProvider) => imageBuilder: (context, imageProvider) =>
// Container( Container(
// width: 160, width: 160,
// height: 160, height: 160,
// decoration: BoxDecoration( decoration: BoxDecoration(
// border: Border.all( border: Border.all(
// color: Colors.black26, width: 3), color: Colors.black26, width: 3),
// shape: BoxShape.circle, shape: BoxShape.circle,
// image: DecorationImage( image: DecorationImage(
// image: imageProvider, image: imageProvider,
// fit: BoxFit.cover), fit: BoxFit.cover),
// ), ),
// ), ),
// placeholder: (context, url) => placeholder: (context, url) =>
// const CircularProgressIndicator(), const CircularProgressIndicator(),
// errorWidget: (context, url, error) => errorWidget: (context, url, error) =>
// Container( Container(
// width: 160, width: 160,
// height: 160, height: 160,
// decoration: BoxDecoration( decoration: BoxDecoration(
// border: Border.all( border: Border.all(
// color: Colors.white, width: 3), color: Colors.white, width: 3),
// shape: BoxShape.circle, shape: BoxShape.circle,
// ), ),
// child: SvgPicture.asset( child: SvgPicture.asset(
// 'assets/svgs/male.svg', 'assets/svgs/male.svg',
// ), ),
// ), ),
// ), ),
// ], ],
// ), ),
// ), ),
Positioned( Positioned(
top: 10, top: 10,
left: 20, left: 20,
@ -135,13 +136,14 @@ class BuildInformation extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
DateFormat dteFormat2 = DateFormat.yMMMMd('en_US'); DateFormat dteFormat2 = DateFormat.yMMMMd('en_US');
globalFistname = globalFistname ?? userData.user!.login!.user!.firstName!.toUpperCase(); globalFistname =
globalLastname =globalLastname ?? userData.user!.login!.user!.lastName!.toUpperCase(); globalFistname ?? userData.employeeInfo!.profile!.firstName!.toUpperCase();
globalMiddleName = globalMiddleName == null globalLastname =
? (userData.employeeInfo == null globalLastname ?? userData.employeeInfo!.profile!.lastName!.toUpperCase();
globalMiddleName = globalMiddleName ??
(userData.employeeInfo == null
? '' ? ''
: userData.employeeInfo!.profile?.middleName?.toUpperCase()) : userData.employeeInfo!.profile?.middleName?.toUpperCase());
: '';
globalSex = globalSex ?? userData.employeeInfo!.profile!.sex!.toUpperCase(); globalSex = globalSex ?? userData.employeeInfo!.profile!.sex!.toUpperCase();
globalBday = globalBday ?? userData.employeeInfo!.profile!.birthdate; globalBday = globalBday ?? userData.employeeInfo!.profile!.birthdate;
final uuid = userData.employeeInfo!.uuid; final uuid = userData.employeeInfo!.uuid;

View File

@ -26,7 +26,7 @@ import 'package:unit2/screens/superadmin/permission_assignment/permission_assign
import 'package:unit2/screens/superadmin/role/role_screen.dart'; import 'package:unit2/screens/superadmin/role/role_screen.dart';
import 'package:unit2/screens/superadmin/role_assignment.dart/role_assignment_screen.dart'; import 'package:unit2/screens/superadmin/role_assignment.dart/role_assignment_screen.dart';
import 'package:unit2/screens/superadmin/role_extend/role_extend_screen.dart'; import 'package:unit2/screens/superadmin/role_extend/role_extend_screen.dart';
import 'package:unit2/screens/superadmin/roles_under/roles_under_screen.dart'; import 'package:unit2/screens/superadmin/roles_under/assignable_roles.dart';
import 'package:unit2/screens/superadmin/stations/stations_screen.dart'; import 'package:unit2/screens/superadmin/stations/stations_screen.dart';
import 'package:unit2/screens/unit2/homepage.dart/module-screen.dart'; import 'package:unit2/screens/unit2/homepage.dart/module-screen.dart';
import 'package:unit2/theme-data.dart/btn-style.dart'; import 'package:unit2/theme-data.dart/btn-style.dart';

View File

@ -18,9 +18,9 @@ class _MenuScreenState extends State<MenuScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final String firstName =globalFistname?? final String firstName =globalFistname??
widget.userData!.user!.login!.user!.firstName!.toUpperCase(); widget.userData!.employeeInfo!.profile!.firstName!.toUpperCase();
final String lastname = globalLastname?? final String lastname = globalLastname??
widget.userData!.user!.login!.user!.lastName!.toUpperCase(); widget.userData!.employeeInfo!.profile!.lastName!.toUpperCase();
return Drawer( return Drawer(
child: SizedBox( child: SizedBox(
height: screenHeight, height: screenHeight,

View File

@ -1,5 +1,6 @@
import 'package:assets_audio_player/assets_audio_player.dart'; import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:audioplayers/audioplayers.dart'; import 'package:audioplayers/audioplayers.dart';
import 'package:awesome_dialog/awesome_dialog.dart';
import 'package:cool_alert/cool_alert.dart'; import 'package:cool_alert/cool_alert.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -35,13 +36,13 @@ class _QRCodeScannerState extends State<QRCodeScanner> {
player = AudioPlayer(); player = AudioPlayer();
super.initState(); super.initState();
} }
@override @override
void dispose() { void dispose() {
player?.dispose(); player?.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -73,83 +74,86 @@ class _QRCodeScannerState extends State<QRCodeScanner> {
progress!.dismiss(); progress!.dismiss();
} }
if (state is ScanSuccess) { if (state is ScanSuccess) {
Future.delayed(const Duration(seconds: 1), () async{ Future.delayed(const Duration(seconds: 1), () async {
await player?.play(AssetSource("success.mp3")); await player?.play(AssetSource("success.mp3"));
}); });
context.read<PassCheckBloc>().add(ScanQr(token: state.token)); context.read<PassCheckBloc>().add(ScanQr(token: state.token));
} }
if (state is QRInvalid) { if (state is QRInvalid) {
Future.delayed(const Duration(seconds: 1), ()async { Future.delayed(const Duration(seconds: 1), () async {
await player?.play(AssetSource("invalid.mp3")); await player?.play(AssetSource("invalid.mp3"));
}); });
context.read<PassCheckBloc>().add(ScanQr(token: state.token)); context.read<PassCheckBloc>().add(ScanQr(token: state.token));
} }
if (state is ScanFailed) { if (state is ScanFailed) {
Future.delayed(const Duration(seconds: 1), ()async { Future.delayed(const Duration(seconds: 1), () async {
await player?.play(AssetSource("fail.mp3")); await player?.play(AssetSource("fail.mp3"));
}); });
context.read<PassCheckBloc>().add(ScanQr(token: state.token)); context.read<PassCheckBloc>().add(ScanQr(token: state.token));
} }
if (state is IncomingScanState) { if (state is IncomingScanState) {
CoolAlert.show( AwesomeDialog(
barrierDismissible: false, dismissOnBackKeyPress: false,
context: context, context: context,
type: CoolAlertType.loading, dialogType: DialogType.info,
text: "Enter Temperature", dismissOnTouchOutside: false,
widget: Padding( body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 24),
child: FormBuilder( child: FormBuilder(
key: formKey, key: formKey,
child: Column( child: Column(
children: [ children: [
const SizedBox( const Text("Enter Temperature",style: TextStyle(color: Colors.black),),
height: 24, const SizedBox(
height: 24,
),
FormBuilderTextField(
keyboardType: TextInputType.number,
name: "temp",
decoration:
normalTextFieldStyle("Temperature", ""),
validator: numericRequired),
const SizedBox(
height: 12,
),
SizedBox(
height: 50,
width: double.infinity,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
child: const Text(submit),
onPressed: () {
if (formKey.currentState!.saveAndValidate()) {
double temperature = double.parse(
formKey.currentState!.value['temp']);
context.read<PassCheckBloc>().add(
PerformIncomingPostLog(
temp: temperature));
Navigator.of(context).pop();
}
},
), ),
FormBuilderTextField( )
keyboardType: TextInputType.number, ],
name: "temp", )),
decoration: ),
normalTextFieldStyle("Temperature", ""), ).show();
validator: numericRequired),
const SizedBox(
height: 12,
),
SizedBox(
height: 50,
width: double.infinity,
child: ElevatedButton(
style: mainBtnStyle(
primary, Colors.transparent, second),
child: const Text(submit),
onPressed: () {
if (formKey.currentState!.saveAndValidate()) {
double temperature = double.parse(
formKey.currentState!.value['temp']);
context.read<PassCheckBloc>().add(
PerformIncomingPostLog(
temp: temperature));
Navigator.of(context).pop();
}
},
),
)
],
)),
));
} }
if (state is OutGoingScanState) { if (state is OutGoingScanState) {
CoolAlert.show( AwesomeDialog(
barrierDismissible: false, dismissOnBackKeyPress: false,
context: context, context: context,
type: CoolAlertType.loading, dialogType: DialogType.info,
text: "Enter Destination", dismissOnTouchOutside: false,
widget: Padding( body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24), padding: const EdgeInsets.symmetric(horizontal: 24,vertical: 24),
child: FormBuilder( child: FormBuilder(
key: formKey, key: formKey,
child: Column( child: Column(
children: [ children: [
const Text("Enter Destination"),
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
@ -185,7 +189,8 @@ class _QRCodeScannerState extends State<QRCodeScanner> {
) )
], ],
)), )),
)); )).show();
} }
}, },
builder: (context, state) { builder: (context, state) {
@ -302,28 +307,56 @@ class _QRCodeScannerState extends State<QRCodeScanner> {
children: [ children: [
SelectedState( SelectedState(
//TODO add api data //TODO add api data
title: state.roleIdRoleName.roleName.toLowerCase() == "41" || title: state.roleIdRoleName.roleName
state.roleIdRoleName.roleName.toLowerCase() == 'qr code scanner' || .toLowerCase() ==
state.roleIdRoleName.roleName.toLowerCase() == 'office/branch chief' || "41" ||
state.roleIdRoleName.roleName.toLowerCase() == 'registration in-charge' state.roleIdRoleName.roleName
.toLowerCase() ==
'qr code scanner' ||
state.roleIdRoleName.roleName
.toLowerCase() ==
'office/branch chief' ||
state.roleIdRoleName.roleName
.toLowerCase() ==
'registration in-charge'
? state.assignedArea.stationName ? state.assignedArea.stationName
: state.roleIdRoleName.roleName.toLowerCase() == 'barangay chairperson' : state.roleIdRoleName.roleName
.toLowerCase() ==
'barangay chairperson'
? state.assignedArea.brgydesc ? state.assignedArea.brgydesc
: state.roleIdRoleName.roleName.toLowerCase() == 'purok president' : state.roleIdRoleName.roleName
.toLowerCase() ==
'purok president'
? state.assignedArea.purokdesc ? state.assignedArea.purokdesc
: state.roleIdRoleName.roleName.toLowerCase() == 'establishment point-person' : state.roleIdRoleName.roleName
.toLowerCase() ==
'establishment point-person'
? "Agency" ? "Agency"
: "", : "",
subtitle: state.roleIdRoleName.roleName.toLowerCase() == "41" || subtitle: state.roleIdRoleName.roleName
state.roleIdRoleName.roleName.toLowerCase() == 'qr code scanner' || .toLowerCase() ==
state.roleIdRoleName.roleName.toLowerCase() == 'office/branch chief' || "41" ||
state.roleIdRoleName.roleName.toLowerCase() == 'registration in-charge' state.roleIdRoleName.roleName
.toLowerCase() ==
'qr code scanner' ||
state.roleIdRoleName.roleName
.toLowerCase() ==
'office/branch chief' ||
state.roleIdRoleName.roleName
.toLowerCase() ==
'registration in-charge'
? "Station" ? "Station"
: state.roleIdRoleName.roleName.toLowerCase() == 'barangay chairperson' : state.roleIdRoleName.roleName
.toLowerCase() ==
'barangay chairperson'
? "Barangay" ? "Barangay"
: state.roleIdRoleName.roleName.toLowerCase() == 'purok president' : state.roleIdRoleName.roleName
.toLowerCase() ==
'purok president'
? "Purok" ? "Purok"
: state.roleIdRoleName.roleName.toLowerCase() == 'establishment point-person' : state.roleIdRoleName.roleName
.toLowerCase() ==
'establishment point-person'
? "Agency" ? "Agency"
: "", : "",
), ),

View File

@ -14,7 +14,7 @@ class AgencyServices {
'X-Client-Key': xClientKey, 'X-Client-Key': xClientKey,
'X-Client-Secret': xClientSecret 'X-Client-Secret': xClientSecret
}; };
String path = Url.instance.postAgencies(); String path = Url.instance.agencies();
Future<List<Agency>> getAgencies() async { Future<List<Agency>> getAgencies() async {
List<Agency> agencies = []; List<Agency> agencies = [];

View File

@ -111,7 +111,6 @@ class RbacModuleServices {
Future<bool> deleteRbacModule({required int moduleId}) async { Future<bool> deleteRbacModule({required int moduleId}) async {
bool success = false; bool success = false;
String path = "${Url.instance.getModules()}$moduleId/";
try { try {
http.Response response = await Request.instance http.Response response = await Request.instance
.deleteRequest(path: '${path+moduleId.toString()}/', headers: headers, body: {}, param: {}); .deleteRequest(path: '${path+moduleId.toString()}/', headers: headers, body: {}, param: {});

View File

@ -67,7 +67,6 @@ class RbacRoleExtendServices {
Future<bool> delete({required int roleExtendId}) async { Future<bool> delete({required int roleExtendId}) async {
bool success = false; bool success = false;
String path = "${Url.instance.getRoleExtend()}$roleExtendId/";
try { try {
http.Response response = await Request.instance.deleteRequest( http.Response response = await Request.instance.deleteRequest(
path: '${path + roleExtendId.toString()}/', path: '${path + roleExtendId.toString()}/',

View File

@ -3,7 +3,8 @@ import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
var mobileFormatter = MaskTextInputFormatter( var mobileFormatter = MaskTextInputFormatter(
mask: "+63 (###) ###-####", mask: "+63 (###) ###-####",
filter: {"#": RegExp(r"^[1-9][0-9]*$")}, filter: {"#": RegExp(r'^[0-9][0-9]*$')
},
type: MaskAutoCompletionType.lazy, type: MaskAutoCompletionType.lazy,
initialText: "0"); initialText: "0");

View File

@ -18,7 +18,7 @@ class Request {
Map<String, String>? param}) async { Map<String, String>? param}) async {
Response response; Response response;
try { try {
response = await get(Uri.http(host, path!, param), headers: headers) response = await get(Uri.https(host, path!, param), headers: headers)
.timeout(Duration(seconds: requestTimeout)); .timeout(Duration(seconds: requestTimeout));
} on TimeoutException catch (_) { } on TimeoutException catch (_) {
// Fluttertoast.showToast( // Fluttertoast.showToast(
@ -60,7 +60,7 @@ class Request {
Map<String, String>? param}) async { Map<String, String>? param}) async {
Response response; Response response;
try { try {
response = await post(Uri.http(host, path!, param), response = await post(Uri.https(host, path!, param),
headers: headers, body: jsonEncode(body)) headers: headers, body: jsonEncode(body))
.timeout(Duration(seconds: requestTimeout)); .timeout(Duration(seconds: requestTimeout));
} on TimeoutException catch (_) { } on TimeoutException catch (_) {
@ -103,7 +103,7 @@ class Request {
required Map<String, dynamic>? param}) async { required Map<String, dynamic>? param}) async {
Response response; Response response;
try { try {
response = await put(Uri.http(host, path, param), response = await put(Uri.https(host, path, param),
headers: headers, body: jsonEncode(body)); headers: headers, body: jsonEncode(body));
} on TimeoutException catch (_) { } on TimeoutException catch (_) {
// Fluttertoast.showToast( // Fluttertoast.showToast(
@ -187,7 +187,7 @@ class Request {
required Map<String, dynamic>? param}) async { required Map<String, dynamic>? param}) async {
Response response; Response response;
try { try {
response = await delete(Uri.http(host, path, param), response = await delete(Uri.https(host, path, param),
headers: headers, body: jsonEncode(body)) headers: headers, body: jsonEncode(body))
.timeout(Duration(seconds: requestTimeout)); .timeout(Duration(seconds: requestTimeout));
} on TimeoutException catch (_) { } on TimeoutException catch (_) {

View File

@ -5,8 +5,8 @@ class Url {
String host() { String host() {
// return '192.168.10.183:3000'; // return '192.168.10.183:3000';
// return 'agusandelnorte.gov.ph'; return 'agusandelnorte.gov.ph';
return "192.168.10.219:3000"; // return "192.168.10.219:3000";
// return "192.168.10.241"; // return "192.168.10.241";
// return "192.168.10.221:3004"; // return "192.168.10.221:3004";
// return "playweb.agusandelnorte.gov.ph"; // return "playweb.agusandelnorte.gov.ph";
@ -15,8 +15,8 @@ class Url {
} }
String prefixHost() { String prefixHost() {
// return "https"; return "https";
return "http"; // return "http";
} }
String authentication() { String authentication() {