413 lines
13 KiB
Dart
413 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import '../../core/routing/routes.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import '../providers/userRoleProvider.dart';
|
|
import 'drawerContentWrapper.dart';
|
|
|
|
class DrawerMenu extends ConsumerStatefulWidget {
|
|
const DrawerMenu({super.key});
|
|
@override
|
|
ConsumerState<DrawerMenu> createState() => DrawerMenuState();
|
|
}
|
|
|
|
class DrawerMenuState extends ConsumerState<DrawerMenu> {
|
|
OverlayEntry? _overlayEntry;
|
|
|
|
void _showPopup(
|
|
BuildContext context,
|
|
Offset offset,
|
|
Size size,
|
|
String key,
|
|
dynamic roleId,
|
|
) {
|
|
_hidePopup(); // remove previous popup
|
|
|
|
_overlayEntry = OverlayEntry(
|
|
builder: (_) {
|
|
return Positioned(
|
|
left: offset.dx + size.width - 5,
|
|
top: offset.dy + (size.height / 2) - 20,
|
|
child: MouseRegion(
|
|
onExit: (_) => _hidePopup(), // hide when mouse leaves popup
|
|
child: Material(
|
|
elevation: 4,
|
|
borderRadius: BorderRadius.circular(16),
|
|
child: Container(
|
|
padding: const EdgeInsets.all(10),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(6),
|
|
color: const Color(0xFFDDF5F1),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (key == 'User') ...[
|
|
_buildPopupItem(
|
|
label: "Partner",
|
|
onTap: () => context.go(AppRoutes.agentLst),
|
|
),
|
|
const SizedBox(height: 5),
|
|
_buildPopupItem(
|
|
label: "Staff",
|
|
onTap: () => context.go(AppRoutes.staffLst),
|
|
),
|
|
],
|
|
if (key == 'Reports') ...[
|
|
if (roleId == 'manager' ||
|
|
roleId == 'Accounts' ||
|
|
roleId == 'agent') ...[
|
|
_buildPopupItem(
|
|
label: "Payout List",
|
|
onTap: () => context.go(
|
|
roleId == 'agent'
|
|
? AppRoutes.gridView
|
|
: AppRoutes.gridList,
|
|
),
|
|
),
|
|
const SizedBox(height: 5),
|
|
],
|
|
_buildPopupItem(
|
|
label: "Claims",
|
|
onTap: () => context.go(AppRoutes.claimlist),
|
|
),
|
|
const SizedBox(height: 5),
|
|
_buildPopupItem(
|
|
label: "Endorsement",
|
|
onTap: () => context.go(AppRoutes.Endorsement),
|
|
),
|
|
const SizedBox(height: 5),
|
|
_buildPopupItem(
|
|
label: "Policy",
|
|
onTap: () => context.go(AppRoutes.policylist),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
|
|
Overlay.of(context, rootOverlay: true)?.insert(_overlayEntry!);
|
|
}
|
|
|
|
void _hidePopup() {
|
|
print('Hide');
|
|
_overlayEntry?.remove();
|
|
_overlayEntry = null;
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_hidePopup(); // remove any popup when drawer is disposed
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final roleId = ref.watch(userRoleProvider);
|
|
final currentPath = GoRouterState.of(context).matchedLocation;
|
|
|
|
print('RoleId - $roleId');
|
|
return Container(
|
|
color: const Color(0xFF425B5B),
|
|
padding: const EdgeInsets.all(13.0),
|
|
child: ListView(
|
|
padding: EdgeInsets.zero,
|
|
children: [
|
|
const SizedBox(height: 30),
|
|
|
|
// Dashboard
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: Image.asset(
|
|
"assets/drawer/drawerImg1.png",
|
|
height: 25,
|
|
width: 25,
|
|
),
|
|
label: "Dashboard",
|
|
isActive:
|
|
currentPath == AppRoutes.dashboard ||
|
|
currentPath == AppRoutes.partnerPortalDashboard,
|
|
onTap: () async {
|
|
_hidePopup();
|
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.remove('dashboardKeyProvider');
|
|
await prefs.remove('dashboardStatusProvider');
|
|
await prefs.remove('dashboardStaffIdProvider');
|
|
final dashboardRoute = roleId == 'agent'
|
|
? AppRoutes.partnerPortalDashboard
|
|
: AppRoutes.dashboard;
|
|
context.go(dashboardRoute);
|
|
},
|
|
),
|
|
|
|
// Enquiry
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: Icon(Icons.list_alt_rounded, size: 30, color: Colors.black),
|
|
label: "Enquiry",
|
|
onTap: () async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.remove('dashboardKeyProvider');
|
|
await prefs.remove('dashboardStatusProvider');
|
|
await prefs.remove('dashboardStaffIdProvider');
|
|
_hidePopup();
|
|
if (roleId == 'agent') {
|
|
context.go(AppRoutes.enquiryLst);
|
|
}
|
|
// else if (roleId == 'handler') {
|
|
// context.go(AppRoutes.enquiryHandlerLst);
|
|
// }
|
|
else {
|
|
context.go(AppRoutes.enquiryForStaff);
|
|
}
|
|
},
|
|
),
|
|
|
|
// User (Manager Only)
|
|
if (roleId == 'manager')
|
|
_buildHoverMenu(
|
|
context: context,
|
|
icon: Icon(Icons.person_add_alt, size: 30),
|
|
label: "User",
|
|
popupKey: 'User',
|
|
),
|
|
|
|
// Reports (Not Staff)
|
|
if (roleId != 'staff')
|
|
_buildHoverMenu(
|
|
context: context,
|
|
icon: Image.asset(
|
|
"assets/drawer/drawerImg2.png",
|
|
height: 25,
|
|
width: 25,
|
|
),
|
|
label: "Reports",
|
|
popupKey: 'Reports',
|
|
),
|
|
|
|
|
|
if (roleId == 'manager')
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: Icon(Icons.access_time, size: 30, color: Colors.black),
|
|
label: "Staff Attendance",
|
|
onTap: () {
|
|
context.go(AppRoutes.allStaffAttendance);
|
|
},
|
|
),
|
|
|
|
if (roleId == 'Accounts') ...[
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: const Icon(Icons.payments_outlined, size: 30, color: Colors.black),
|
|
label: "Payout",
|
|
isActive: currentPath == AppRoutes.payoutList,
|
|
onTap: () => context.go(AppRoutes.payoutList),
|
|
),
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: const Icon(Icons.upload_file_outlined, size: 30, color: Colors.black),
|
|
label: "Payout Upload",
|
|
isActive: currentPath == AppRoutes.payoutUpload,
|
|
onTap: () => context.go(AppRoutes.payoutUpload),
|
|
),
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: const Icon(Icons.table_chart_outlined, size: 30, color: Colors.black),
|
|
label: "Payout Report",
|
|
isActive: currentPath == AppRoutes.payoutReport,
|
|
onTap: () => context.go(AppRoutes.payoutReport),
|
|
),
|
|
],
|
|
|
|
if (roleId == 'agent')
|
|
_buildMenuItem(
|
|
context: context,
|
|
icon: const Icon(Icons.table_chart_outlined, size: 30, color: Colors.black),
|
|
label: "Payout Report",
|
|
isActive: currentPath == AppRoutes.payoutReport,
|
|
onTap: () => context.go(AppRoutes.payoutReport),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildMenuItem({
|
|
required BuildContext context,
|
|
required Widget icon,
|
|
required String label,
|
|
bool isActive = false,
|
|
required VoidCallback onTap,
|
|
}) {
|
|
return Column(
|
|
children: [
|
|
GestureDetector(
|
|
onTap: onTap,
|
|
child: MouseRegion(
|
|
onEnter: (_) => _hidePopup(), // hide any popup when hovering
|
|
child: DrawerContentWrapper(child: icon, isActive: isActive),
|
|
),
|
|
),
|
|
DrawerLabel(label, isActive: isActive),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildHoverMenu({
|
|
required BuildContext context,
|
|
required Widget icon,
|
|
required String label,
|
|
required String popupKey,
|
|
}) {
|
|
return Column(
|
|
children: [
|
|
Builder(
|
|
builder: (itemContext) {
|
|
return MouseRegion(
|
|
onEnter: (_) {
|
|
final renderBox = itemContext.findRenderObject() as RenderBox;
|
|
final offset = renderBox.localToGlobal(Offset.zero);
|
|
final size = renderBox.size;
|
|
final roleId = ref.read(userRoleProvider);
|
|
_showPopup(context, offset, size, popupKey, roleId);
|
|
},
|
|
child: DrawerContentWrapper(child: icon),
|
|
);
|
|
},
|
|
),
|
|
DrawerLabel(label),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
// Drawer label widget
|
|
class DrawerLabel extends StatelessWidget {
|
|
final String text;
|
|
final bool isActive;
|
|
const DrawerLabel(this.text, {super.key, this.isActive = false});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Split the text by space (e.g. "Staff Attendance" → ["Staff", "Attendance"])
|
|
final parts = text.split(' ');
|
|
|
|
return Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: parts.map((line) {
|
|
return Text(
|
|
line,
|
|
style: GoogleFonts.inter(
|
|
color: isActive ? const Color(0xFF0ABFA3) : Colors.white,
|
|
fontSize: 11.5,
|
|
fontWeight: isActive ? FontWeight.w700 : FontWeight.w400,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
);
|
|
}).toList(),
|
|
);
|
|
}
|
|
|
|
// Widget build(BuildContext context) {
|
|
// return Row(
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
// children: [
|
|
// SizedBox(
|
|
// width: 70,
|
|
// child: Align(
|
|
// alignment: Alignment.center,
|
|
// child: Text(
|
|
// text,
|
|
// style: GoogleFonts.inter(color: Colors.white, fontSize: 11.5),
|
|
// softWrap: true,
|
|
// maxLines: 2,
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// const SizedBox(height: 20),
|
|
// ],
|
|
// );
|
|
// }
|
|
}
|
|
|
|
// Popup item
|
|
Widget _buildPopupItem({required String label, required VoidCallback onTap}) {
|
|
return _HoverableContainer(
|
|
label: label,
|
|
onTap: onTap,
|
|
normalColor: const Color(0xFFDDF5F1),
|
|
hoverColor: Colors.white,
|
|
);
|
|
}
|
|
|
|
// Hoverable container for popup items
|
|
class _HoverableContainer extends StatefulWidget {
|
|
final String label;
|
|
final VoidCallback onTap;
|
|
final Color normalColor;
|
|
final Color hoverColor;
|
|
|
|
const _HoverableContainer({
|
|
super.key,
|
|
required this.label,
|
|
required this.onTap,
|
|
required this.normalColor,
|
|
required this.hoverColor,
|
|
});
|
|
|
|
@override
|
|
_HoverableContainerState createState() => _HoverableContainerState();
|
|
}
|
|
|
|
class _HoverableContainerState extends State<_HoverableContainer> {
|
|
bool _isHovered = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MouseRegion(
|
|
onEnter: (_) => setState(() => _isHovered = true),
|
|
onExit: (_) => setState(() => _isHovered = false),
|
|
child: GestureDetector(
|
|
onTap: widget.onTap,
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: _isHovered ? widget.hoverColor : widget.normalColor,
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
SizedBox(
|
|
width: 110,
|
|
child: Text(widget.label, style: _cardTextStyle),
|
|
),
|
|
const Icon(
|
|
Icons.arrow_forward_ios_rounded,
|
|
size: 12,
|
|
color: Colors.black,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
TextStyle _cardTextStyle = GoogleFonts.inter(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
);
|