Sistem-Pakar-Diagnosa-Penya.../frontend/lib/admin/user_list_page.dart

482 lines
17 KiB
Dart

import 'package:flutter/material.dart';
import 'package:frontend/api_services/api_services.dart';
class UserListPage extends StatefulWidget {
@override
_UserListPageState createState() => _UserListPageState();
}
class _UserListPageState extends State<UserListPage> {
final ApiService apiService = ApiService();
List<Map<String, dynamic>> users = [];
bool isLoading = true;
final _formKey = GlobalKey<FormState>();
final _nameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _alamatController = TextEditingController();
final _nomorTeleponController = TextEditingController();
@override
void initState() {
super.initState();
_loadUsers();
}
@override
void dispose() {
// Dispose controllers in dispose method
_nameController.dispose();
_emailController.dispose();
_passwordController.dispose();
_alamatController.dispose();
_nomorTeleponController.dispose();
super.dispose();
}
Future<void> _addUser() async {
try {
await apiService.registerUser(
name: _nameController.text,
email: _emailController.text,
password: _passwordController.text,
alamat: _alamatController.text,
nomorTelepon: _nomorTeleponController.text,
);
// Clear form
_nameController.clear();
_emailController.clear();
_passwordController.clear();
_alamatController.clear();
_nomorTeleponController.clear();
// Refresh user list
await _loadUsers();
// Show success message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('User berhasil ditambahkan'),
backgroundColor: Colors.green,
),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Gagal menambahkan user: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
}
}
Future<void> _updateUser(Map<String, dynamic> user) async {
try {
// Hanya kirim password jika diisi
String? newPassword =
_passwordController.text.isEmpty ? null : _passwordController.text;
await apiService.updateUser(
id: user['id'],
name: _nameController.text,
email: _emailController.text,
password: newPassword, // Kirim null jika password kosong
alamat: _alamatController.text,
nomorTelepon: _nomorTeleponController.text,
);
// Clear form
_nameController.clear();
_emailController.clear();
_passwordController.clear();
_alamatController.clear();
_nomorTeleponController.clear();
// Refresh user list
await _loadUsers();
// Show success message with password info
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
newPassword != null
? 'User berhasil diperbarui termasuk password'
: 'User berhasil diperbarui',
),
backgroundColor: Colors.green,
),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Gagal memperbarui user: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
}
}
Future<void> _deleteUser(int userId) async {
try {
await apiService.deleteUser(userId);
await _loadUsers();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('User berhasil dihapus'),
backgroundColor: Colors.green,
),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Gagal menghapus user: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
}
}
void _showDeleteConfirmation(Map<String, dynamic> user) {
showDialog(
context: context,
builder:
(context) => AlertDialog(
title: Text('Konfirmasi Hapus'),
content: Text(
'Apakah Anda yakin ingin menghapus user ${user['name']}?',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Batal'),
),
ElevatedButton(
onPressed: () async {
try {
Navigator.pop(context); // Close dialog first
await apiService.deleteUser(user['id']);
await _loadUsers(); // Refresh the list
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('User berhasil dihapus'),
backgroundColor: Colors.green,
),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Gagal menghapus user: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
}
},
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
child: Text('Hapus'),
),
],
),
);
}
void _showUpdateDialog(Map<String, dynamic> user) {
// Pre-fill form with existing user data
_nameController.text = user['name'] ?? '';
_emailController.text = user['email'] ?? '';
_alamatController.text = user['alamat'] ?? '';
_nomorTeleponController.text = user['nomorTelepon'] ?? '';
_passwordController.text = ''; // Empty for security
showDialog(
context: context,
builder:
(context) => AlertDialog(
title: Text('Update User'),
content: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Nama'),
validator:
(value) =>
value?.isEmpty ?? true
? 'Nama tidak boleh kosong'
: null,
),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value?.isEmpty ?? true)
return 'Email tidak boleh kosong';
if (!value!.contains('@')) return 'Email tidak valid';
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(
labelText: 'Password Baru',
helperText:
'Kosongkan jika tidak ingin mengubah password',
),
obscureText: true,
validator: (value) {
if (value?.isNotEmpty ?? false) {
if (value!.length < 6)
return 'Password minimal 6 karakter';
}
return null;
},
),
TextFormField(
controller: _alamatController,
decoration: InputDecoration(labelText: 'Alamat'),
validator:
(value) =>
value?.isEmpty ?? true
? 'Alamat tidak boleh kosong'
: null,
),
TextFormField(
controller: _nomorTeleponController,
decoration: InputDecoration(labelText: 'Nomor Telepon'),
keyboardType: TextInputType.phone,
validator:
(value) =>
value?.isEmpty ?? true
? 'Nomor telepon tidak boleh kosong'
: null,
),
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Batal'),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.pop(context);
_updateUser(user);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF9DC08D),
),
child: Text('Update'),
),
],
),
);
}
void _showAddUserDialog() {
showDialog(
context: context,
builder:
(context) => AlertDialog(
title: Text('Tambah User Baru'),
content: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Nama'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nama tidak boleh kosong';
}
return null;
},
),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email tidak boleh kosong';
}
if (!value.contains('@')) {
return 'Email tidak valid';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Password tidak boleh kosong';
}
if (value.length < 6) {
return 'Password minimal 6 karakter';
}
return null;
},
),
TextFormField(
controller: _alamatController,
decoration: InputDecoration(labelText: 'Alamat'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Alamat tidak boleh kosong';
}
return null;
},
),
TextFormField(
controller: _nomorTeleponController,
decoration: InputDecoration(labelText: 'Nomor Telepon'),
keyboardType: TextInputType.phone,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nomor telepon tidak boleh kosong';
}
return null;
},
),
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Batal'),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.pop(context);
_addUser();
}
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF9DC08D),
),
child: Text('Simpan'),
),
],
),
);
}
Future<void> _loadUsers() async {
try {
final userList = await apiService.getUsers();
setState(() {
users = userList;
isLoading = false;
});
} catch (e) {
print('Error loading users: $e');
setState(() {
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Daftar Pengguna'),
backgroundColor: Color(0xFF9DC08D),
),
floatingActionButton: FloatingActionButton(
onPressed: _showAddUserDialog,
backgroundColor: Color(0xFF9DC08D),
child: Icon(Icons.add),
),
body:
isLoading
? Center(child: CircularProgressIndicator())
: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
child: DataTable(
columnSpacing: 20,
columns: [
DataColumn(label: Text('Nama')),
DataColumn(label: Text('Email')),
DataColumn(label: Text('Alamat')),
DataColumn(label: Text('No. Telepon')),
DataColumn(label: Text('Role')),
DataColumn(label: Text('Aksi')),
],
rows:
users.map((user) {
return DataRow(
cells: [
DataCell(Text(user['name'] ?? '-')),
DataCell(Text(user['email'] ?? '-')),
DataCell(Text(user['alamat'] ?? '-')),
DataCell(Text(user['nomorTelepon'] ?? '-')),
DataCell(
Container(
padding: EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
decoration: BoxDecoration(
color:
user['role'] == 'admin'
? Colors.blue.withOpacity(0.2)
: Colors.green.withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
),
child: Text(
user['role'] ?? 'user',
style: TextStyle(
color:
user['role'] == 'admin'
? Colors.blue
: Colors.green,
),
),
),
),
DataCell(
Row(
children: [
IconButton(
icon: Icon(Icons.edit),
onPressed: () => _showUpdateDialog(user),
),
IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed:
() => _showDeleteConfirmation(user),
),
],
),
),
],
);
}).toList(),
),
),
),
);
}
}