bharat_erp/lib/modules/users/presentation/screens/user_detail_screen.dart

199 lines
7.4 KiB
Dart

import '../../../../shared/widgets/app_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../../core/utils/formatters.dart';
import '../../../../core/errors/failure.dart';
import '../../../../shared/models/user_management_models.dart';
import '../../../../shared/widgets/app_button.dart';
import '../../../../shared/widgets/app_confirmation_dialog.dart';
import '../../../../shared/widgets/app_loading_view.dart';
import '../../../../shared/widgets/app_status_chip.dart';
import '../../../../shared/widgets/detail_overview_widgets.dart';
import '../../../../shared/widgets/error_view.dart';
import '../../../../shared/widgets/page_header.dart';
import '../providers/users_provider.dart';
import '../../../../shared/widgets/app_toast.dart';
class UserDetailScreen extends ConsumerStatefulWidget {
const UserDetailScreen({super.key, required this.userId});
final String userId;
@override
ConsumerState<UserDetailScreen> createState() => _UserDetailScreenState();
}
class _UserDetailScreenState extends ConsumerState<UserDetailScreen> {
bool _requestedFreshLoad = false;
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_requestedFreshLoad) return;
_requestedFreshLoad = true;
// Always hit GET user-by-id when opening view.
ref.invalidate(userDetailProvider(widget.userId));
}
@override
void didUpdateWidget(covariant UserDetailScreen oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.userId != widget.userId) {
ref.invalidate(userDetailProvider(widget.userId));
}
}
@override
Widget build(BuildContext context) {
final userId = widget.userId;
final userAsync = ref.watch(userDetailProvider(userId));
return Padding(
padding: const EdgeInsets.all(24),
child: userAsync.when(
loading: () => const AppLoadingView(message: 'Loading user details...'),
error: (error, _) => ErrorView.fromFailure(
error is Failure ? error : Failure.unknown(message: error.toString()),
onRetry: () => ref.invalidate(userDetailProvider(userId)),
),
data: (user) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
PageHeader(
title: user.fullName,
subtitle: user.employeeCode,
actions: [
OutlinedButton.icon(
onPressed: () => context.push('/users/$userId/edit'),
icon: const Icon(Icons.edit_outlined),
label: const Text('Edit'),
),
const SizedBox(width: 8),
AppButton(
label: 'Deactivate',
expand: false,
onPressed: () => _deactivate(context),
),
],
),
const SizedBox(height: 24),
AppCard(
child: Padding(
padding: const EdgeInsets.all(24),
child: DetailOverviewCard(
title: 'User Details',
children: [
DetailOverviewSection(
title: 'Summary',
child: DetailSummaryStrip(
metrics: [
DetailSummaryMetric(
icon: Icons.flag_outlined,
label: 'Status',
accent: Theme.of(context).colorScheme.secondary,
child: AppStatusChip(
status: user.status,
compact: true,
),
),
DetailSummaryMetric(
icon: Icons.badge_outlined,
label: 'Employee Code',
child: Text(
user.employeeCode,
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(fontWeight: FontWeight.w700),
),
),
DetailSummaryMetric(
icon: Icons.admin_panel_settings_outlined,
label: 'Role',
child: Text(
user.roleLabel,
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(fontWeight: FontWeight.w700),
),
),
DetailSummaryMetric(
icon: Icons.apartment_outlined,
label: 'Department',
child: Text(
user.departmentLabel,
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(fontWeight: FontWeight.w700),
),
),
],
),
),
DetailOverviewSection(
title: 'Contact',
child: DetailInfoGrid(
items: [
DetailInfoItem('Email', user.email),
DetailInfoItem('Mobile', user.mobile),
],
),
),
DetailOverviewSection(
title: 'Account',
showDivider: false,
child: DetailInfoGrid(
items: [
DetailInfoItem('Role', user.roleLabel),
DetailInfoItem('Department', user.departmentLabel),
if (user.createdAt != null)
DetailInfoItem(
'Created',
DateFormatter.displayDateTime(user.createdAt),
),
if (user.updatedAt != null)
DetailInfoItem(
'Updated',
DateFormatter.displayDateTime(user.updatedAt),
),
],
),
),
],
),
),
),
],
),
),
);
}
Future<void> _deactivate(BuildContext context) async {
final confirmed = await showAppConfirmationDialog(
context: context,
title: 'Deactivate user',
message: 'Are you sure you want to deactivate this user?',
confirmLabel: 'Deactivate',
isDestructive: true,
);
if (confirmed != true || !context.mounted) return;
final success =
await ref.read(userDetailProvider(widget.userId).notifier).deactivate();
if (!context.mounted) return;
showAppToastFromSnackBar(
context,
SnackBar(
content: Text(success ? 'User deactivated' : 'Failed to deactivate'),
),
);
if (success) context.pop();
}
}