320 lines
10 KiB
Dart
320 lines
10 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:marco/helpers/theme/theme_customizer.dart';
|
||
import 'package:marco/helpers/services/storage/local_storage.dart';
|
||
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
|
||
import 'package:marco/helpers/utils/my_shadow.dart';
|
||
import 'package:marco/helpers/widgets/my_card.dart';
|
||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||
import 'package:marco/helpers/widgets/my_text.dart';
|
||
import 'package:flutter_lucide/flutter_lucide.dart';
|
||
import 'package:marco/model/employee_info.dart';
|
||
import 'package:marco/helpers/widgets/avatar.dart';
|
||
|
||
class UserProfileBar extends StatefulWidget {
|
||
final bool isCondensed;
|
||
|
||
const UserProfileBar({super.key, this.isCondensed = false});
|
||
|
||
@override
|
||
_UserProfileBarState createState() => _UserProfileBarState();
|
||
}
|
||
|
||
class _UserProfileBarState extends State<UserProfileBar>
|
||
with SingleTickerProviderStateMixin, UIMixin {
|
||
final ThemeCustomizer customizer = ThemeCustomizer.instance;
|
||
bool isCondensed = false;
|
||
EmployeeInfo? employeeInfo;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_loadEmployeeInfo();
|
||
}
|
||
|
||
void _loadEmployeeInfo() {
|
||
setState(() {
|
||
employeeInfo = LocalStorage.getEmployeeInfo();
|
||
});
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
isCondensed = widget.isCondensed;
|
||
|
||
return MyCard(
|
||
borderRadiusAll: 16,
|
||
paddingAll: 0,
|
||
shadow: MyShadow(position: MyShadowPosition.centerRight, elevation: 4),
|
||
child: AnimatedContainer(
|
||
decoration: BoxDecoration(
|
||
gradient: LinearGradient(
|
||
colors: [
|
||
leftBarTheme.background.withOpacity(0.95),
|
||
leftBarTheme.background.withOpacity(0.85),
|
||
],
|
||
begin: Alignment.topCenter,
|
||
end: Alignment.bottomCenter,
|
||
),
|
||
),
|
||
width: isCondensed ? 90 : 250,
|
||
duration: const Duration(milliseconds: 300),
|
||
curve: Curves.easeInOut,
|
||
child: SafeArea(
|
||
bottom: true,
|
||
top: false,
|
||
left: false,
|
||
right: false,
|
||
child: Column(
|
||
children: [
|
||
userProfileSection(),
|
||
MySpacing.height(8),
|
||
supportAndSettingsMenu(),
|
||
const Spacer(),
|
||
logoutButton(),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget userProfileSection() {
|
||
if (employeeInfo == null) {
|
||
return const Padding(
|
||
padding: EdgeInsets.all(24.0),
|
||
child: Center(child: CircularProgressIndicator()),
|
||
);
|
||
}
|
||
|
||
return Container(
|
||
width: double.infinity,
|
||
padding: MySpacing.xy(58, 68),
|
||
decoration: BoxDecoration(
|
||
color: leftBarTheme.activeItemBackground,
|
||
borderRadius: const BorderRadius.only(
|
||
topLeft: Radius.circular(16),
|
||
topRight: Radius.circular(16),
|
||
),
|
||
),
|
||
child: Column(
|
||
children: [
|
||
Avatar(
|
||
firstName: employeeInfo?.firstName ?? 'First',
|
||
lastName: employeeInfo?.lastName ?? 'Name',
|
||
size: 60,
|
||
),
|
||
MySpacing.height(12),
|
||
MyText.labelLarge(
|
||
"${employeeInfo?.firstName ?? 'First'} ${employeeInfo?.lastName ?? 'Last'}",
|
||
fontWeight: 700,
|
||
color: leftBarTheme.activeItemColor,
|
||
textAlign: TextAlign.center,
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget supportAndSettingsMenu() {
|
||
return Padding(
|
||
padding: MySpacing.xy(16, 16),
|
||
child: Column(
|
||
children: [
|
||
menuItem(icon: LucideIcons.settings, label: "Settings"),
|
||
MySpacing.height(12),
|
||
menuItem(icon: LucideIcons.badge_help, label: "Support"),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget menuItem({required IconData icon, required String label}) {
|
||
return InkWell(
|
||
onTap: () {},
|
||
borderRadius: BorderRadius.circular(10),
|
||
hoverColor: leftBarTheme.activeItemBackground.withOpacity(0.2),
|
||
splashColor: leftBarTheme.activeItemBackground.withOpacity(0.3),
|
||
child: Padding(
|
||
padding: MySpacing.xy(12, 10),
|
||
child: Row(
|
||
children: [
|
||
Icon(icon, size: 20, color: leftBarTheme.onBackground),
|
||
MySpacing.width(12),
|
||
Expanded(
|
||
child: MyText.bodyMedium(
|
||
label,
|
||
color: leftBarTheme.onBackground,
|
||
fontWeight: 500,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget logoutButton() {
|
||
return InkWell(
|
||
onTap: () async {
|
||
bool? confirm = await showDialog<bool>(
|
||
context: context,
|
||
builder: (context) {
|
||
return Dialog(
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(20),
|
||
),
|
||
child: Padding(
|
||
padding:
|
||
const EdgeInsets.symmetric(horizontal: 24, vertical: 28),
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(
|
||
LucideIcons.log_out,
|
||
size: 48,
|
||
color: Colors.redAccent,
|
||
),
|
||
const SizedBox(height: 16),
|
||
Text(
|
||
"Logout Confirmation",
|
||
style: TextStyle(
|
||
fontSize: 20,
|
||
fontWeight: FontWeight.w700,
|
||
color: Theme.of(context).colorScheme.onBackground,
|
||
),
|
||
),
|
||
const SizedBox(height: 12),
|
||
Text(
|
||
"Are you sure you want to logout?\nYou will need to login again to continue.",
|
||
textAlign: TextAlign.center,
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
color: Theme.of(context)
|
||
.colorScheme
|
||
.onSurface
|
||
.withOpacity(0.7),
|
||
),
|
||
),
|
||
const SizedBox(height: 24),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Expanded(
|
||
child: TextButton(
|
||
onPressed: () => Navigator.pop(context, false),
|
||
style: TextButton.styleFrom(
|
||
foregroundColor: Colors.grey.shade700,
|
||
),
|
||
child: const Text("Cancel"),
|
||
),
|
||
),
|
||
const SizedBox(width: 12),
|
||
Expanded(
|
||
child: ElevatedButton(
|
||
onPressed: () async {
|
||
await LocalStorage.logout();
|
||
},
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: Colors.redAccent,
|
||
foregroundColor: Colors.white,
|
||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
),
|
||
child: const Text("Logout"),
|
||
),
|
||
),
|
||
],
|
||
)
|
||
],
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
|
||
if (confirm == true) {
|
||
// Show animated loader dialog
|
||
showDialog(
|
||
context: context,
|
||
barrierDismissible: false,
|
||
builder: (context) => Dialog(
|
||
backgroundColor: Colors.transparent,
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: const [
|
||
CircularProgressIndicator(),
|
||
SizedBox(height: 12),
|
||
Text(
|
||
"Logging you out...",
|
||
style: TextStyle(color: Colors.white),
|
||
)
|
||
],
|
||
),
|
||
),
|
||
);
|
||
|
||
await LocalStorage.logout();
|
||
|
||
if (mounted) {
|
||
Navigator.pop(context);
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Row(
|
||
children: [
|
||
const Icon(LucideIcons.check, color: Colors.green),
|
||
const SizedBox(width: 12),
|
||
const Text("You’ve been logged out successfully."),
|
||
],
|
||
),
|
||
backgroundColor: Colors.grey.shade900,
|
||
behavior: SnackBarBehavior.floating,
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
duration: const Duration(seconds: 3),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
},
|
||
borderRadius: const BorderRadius.only(
|
||
bottomLeft: Radius.circular(16),
|
||
bottomRight: Radius.circular(16),
|
||
),
|
||
hoverColor: leftBarTheme.activeItemBackground.withOpacity(0.2),
|
||
splashColor: leftBarTheme.activeItemBackground.withOpacity(0.3),
|
||
child: AnimatedContainer(
|
||
duration: const Duration(milliseconds: 150),
|
||
curve: Curves.easeInOut,
|
||
width: double.infinity,
|
||
padding: MySpacing.all(16),
|
||
decoration: BoxDecoration(
|
||
color: leftBarTheme.activeItemBackground,
|
||
borderRadius: const BorderRadius.only(
|
||
bottomLeft: Radius.circular(16),
|
||
bottomRight: Radius.circular(16),
|
||
),
|
||
),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
MyText.bodyMedium(
|
||
"Logout",
|
||
color: leftBarTheme.activeItemColor,
|
||
fontWeight: 600,
|
||
),
|
||
MySpacing.width(8),
|
||
Icon(
|
||
LucideIcons.log_out,
|
||
size: 20,
|
||
color: leftBarTheme.activeItemColor,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|