초기 커밋
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
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<UserManagementScreen> createState() =>
|
||||
_UserManagementScreenState();
|
||||
}
|
||||
|
||||
class _UserManagementScreenState extends ConsumerState<UserManagementScreen> {
|
||||
late PlutoGridStateManager stateManager;
|
||||
|
||||
// Mock 데이터
|
||||
final List<Map<String, dynamic>> _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<PlutoColumn> 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<PlutoRow> 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<void>(
|
||||
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<void> _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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user