import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:gap/gap.dart'; import 'package:pluto_grid/pluto_grid.dart'; import '../../../../core/utils/extensions.dart'; import '../../../../shared/widgets/confirm_dialog.dart'; class UserManagementScreen extends ConsumerStatefulWidget { const UserManagementScreen({super.key}); @override ConsumerState createState() => _UserManagementScreenState(); } class _UserManagementScreenState extends ConsumerState { late PlutoGridStateManager stateManager; // Mock 데이터 final List> _mockUsers = List.generate( 20, (i) => { 'id': '${i + 1}', 'name': '사용자 ${i + 1}', 'email': 'user${i + 1}@example.com', 'role': i == 0 ? 'admin' : 'user', 'status': i % 5 == 0 ? '비활성' : '활성', 'created_at': '2025-01-${(i + 1).toString().padLeft(2, '0')}', }, ); List get _columns => [ PlutoColumn( title: 'ID', field: 'id', type: PlutoColumnType.text(), width: 60, enableEditingMode: false, ), PlutoColumn( title: '이름', field: 'name', type: PlutoColumnType.text(), width: 150, ), PlutoColumn( title: '이메일', field: 'email', type: PlutoColumnType.text(), width: 250, ), PlutoColumn( title: '역할', field: 'role', type: PlutoColumnType.select(['admin', 'user']), width: 100, ), PlutoColumn( title: '상태', field: 'status', type: PlutoColumnType.select(['활성', '비활성']), width: 100, ), PlutoColumn( title: '가입일', field: 'created_at', type: PlutoColumnType.text(), width: 150, enableEditingMode: false, ), ]; List get _rows => _mockUsers .map( (user) => PlutoRow( cells: { 'id': PlutoCell(value: user['id']), 'name': PlutoCell(value: user['name']), 'email': PlutoCell(value: user['email']), 'role': PlutoCell(value: user['role']), 'status': PlutoCell(value: user['status']), 'created_at': PlutoCell(value: user['created_at']), }, ), ) .toList(); void _showCreateUserDialog() { final nameController = TextEditingController(); final emailController = TextEditingController(); showDialog( context: context, builder: (context) => AlertDialog( title: const Text('새 사용자 추가'), content: SizedBox( width: 400, child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: nameController, decoration: const InputDecoration( labelText: '이름', hintText: '사용자 이름 입력', ), ), const Gap(16), TextField( controller: emailController, decoration: const InputDecoration( labelText: '이메일', hintText: 'email@example.com', ), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('취소'), ), FilledButton( onPressed: () { // TODO: API 연동 Navigator.pop(context); if (mounted) { context.showSnackBar('사용자가 추가되었습니다'); } }, child: const Text('추가'), ), ], ), ); } Future _deleteUser(PlutoRow row) async { final confirmed = await ConfirmDialog.show( context, title: '사용자 삭제', message: '정말로 이 사용자를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.', confirmLabel: '삭제', isDestructive: true, ); if (confirmed == true) { stateManager.removeRows([row]); if (mounted) { context.showSnackBar('사용자가 삭제되었습니다'); } } } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 헤더 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '사용자 관리', style: context.textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const Gap(4), Text( '사용자를 조회하고 관리하세요', style: context.textTheme.bodyMedium?.copyWith( color: context.colorScheme.onSurfaceVariant, ), ), ], ), FilledButton.icon( onPressed: _showCreateUserDialog, icon: const Icon(Icons.person_add), label: const Text('새 사용자'), ), ], ), const Gap(24), // 데이터 그리드 Expanded( child: Card( clipBehavior: Clip.antiAlias, child: PlutoGrid( columns: _columns, rows: _rows, onLoaded: (event) { stateManager = event.stateManager; }, onRowDoubleTap: (event) { // TODO: 사용자 상세 정보 다이얼로그 }, configuration: PlutoGridConfiguration( style: PlutoGridStyleConfig( gridBackgroundColor: context.colorScheme.surface, rowColor: context.colorScheme.surface, activatedColor: context.colorScheme.primaryContainer, activatedBorderColor: context.colorScheme.primary, gridBorderColor: context.colorScheme.outlineVariant, borderColor: context.colorScheme.outlineVariant, cellTextStyle: context.textTheme.bodyMedium!, columnTextStyle: context.textTheme.titleSmall!.copyWith( fontWeight: FontWeight.bold, ), ), columnSize: const PlutoGridColumnSizeConfig( autoSizeMode: PlutoAutoSizeMode.scale, ), ), ), ), ), ], ), ); } }