fix
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../../core/di/providers.dart';
|
||||
|
||||
/// Drawer for warehouse selection page
|
||||
/// Contains app settings and sync options
|
||||
class WarehouseDrawer extends ConsumerWidget {
|
||||
const WarehouseDrawer({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = Theme.of(context);
|
||||
final authState = ref.watch(authProvider);
|
||||
final usersState = ref.watch(usersProvider);
|
||||
final user = authState.user;
|
||||
|
||||
return Drawer(
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
// Header with user info
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 32,
|
||||
backgroundColor: theme.colorScheme.primary,
|
||||
child: Icon(
|
||||
Icons.person,
|
||||
size: 32,
|
||||
color: theme.colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
user?.username ?? 'User',
|
||||
style: theme.textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: theme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Quản lý kho',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onPrimaryContainer.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Menu items
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
children: [
|
||||
// Sync Users button
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.sync,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
title: const Text('Đồng bộ người dùng'),
|
||||
subtitle: Text(
|
||||
usersState.users.isEmpty
|
||||
? 'Chưa có dữ liệu'
|
||||
: '${usersState.users.length} người dùng',
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
trailing: usersState.isLoading
|
||||
? const SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cloud_download,
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
onTap: usersState.isLoading
|
||||
? null
|
||||
: () async {
|
||||
// Close drawer first
|
||||
Navigator.of(context).pop();
|
||||
|
||||
// Show loading indicator
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Text('Đang đồng bộ...'),
|
||||
],
|
||||
),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
|
||||
// Sync users from API
|
||||
await ref.read(usersProvider.notifier).syncUsers();
|
||||
|
||||
// Show success or error message
|
||||
if (context.mounted) {
|
||||
final error = ref.read(usersProvider).error;
|
||||
if (error != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
const Icon(Icons.error, color: Colors.white),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(child: Text('Lỗi: $error')),
|
||||
],
|
||||
),
|
||||
backgroundColor: Colors.red,
|
||||
action: SnackBarAction(
|
||||
label: 'OK',
|
||||
textColor: Colors.white,
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final count = ref.read(usersProvider).users.length;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
const Icon(Icons.check_circle, color: Colors.white),
|
||||
const SizedBox(width: 16),
|
||||
Text('Đã đồng bộ $count người dùng'),
|
||||
],
|
||||
),
|
||||
backgroundColor: Colors.green,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
|
||||
// Settings (placeholder)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.settings),
|
||||
title: const Text('Cài đặt'),
|
||||
subtitle: const Text('Tùy chỉnh ứng dụng'),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
// TODO: Navigate to settings page
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Tính năng đang phát triển'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// About (placeholder)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.info_outline),
|
||||
title: const Text('Thông tin'),
|
||||
subtitle: const Text('Về ứng dụng'),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
showAboutDialog(
|
||||
context: context,
|
||||
applicationName: 'Quản lý kho',
|
||||
applicationVersion: '1.0.0',
|
||||
applicationIcon: const Icon(Icons.warehouse, size: 48),
|
||||
children: [
|
||||
const Text('Hệ thống quản lý kho và theo dõi sản phẩm.'),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Logout button at bottom
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.logout,
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
title: Text(
|
||||
'Đăng xuất',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.error,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
onTap: () async {
|
||||
// Capture references BEFORE closing drawer (drawer will be disposed)
|
||||
final authNotifier = ref.read(authProvider.notifier);
|
||||
final navigator = Navigator.of(context);
|
||||
final router = GoRouter.of(context);
|
||||
|
||||
navigator.pop(); // Close drawer
|
||||
|
||||
// Show logout confirmation dialog and get result
|
||||
final shouldLogout = await _showLogoutDialog(context);
|
||||
|
||||
// If user confirmed, logout and navigate to login
|
||||
if (shouldLogout == true) {
|
||||
await authNotifier.logout();
|
||||
|
||||
// Navigate to login screen using captured router
|
||||
router.go('/login');
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool?> _showLogoutDialog(BuildContext context) {
|
||||
return showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Đăng xuất'),
|
||||
content: const Text('Bạn có chắc chắn muốn đăng xuất?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('Hủy'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
child: const Text('Đăng xuất'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user