TKK_E32231115MAULANA/lib/features/account/presentation/pages/manage_account_page.dart

327 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:monitoring_jamur/core/theme/app_theme.dart';
import 'package:monitoring_jamur/core/session/user_session.dart';
import 'package:monitoring_jamur/features/auth/data/user_repository.dart';
import 'package:monitoring_jamur/features/auth/presentation/pages/login_page.dart';
class ManageAccountPage extends StatefulWidget {
const ManageAccountPage({super.key});
@override
State<ManageAccountPage> createState() => _ManageAccountPageState();
}
class _ManageAccountPageState extends State<ManageAccountPage> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final UserRepository _userRepository = UserRepository();
bool _isLoading = false;
bool _obscurePassword = true;
@override
void initState() {
super.initState();
_usernameController.text = UserSession.username ?? '';
}
Future<void> _updateUsername() async {
final newUsername = _usernameController.text.trim();
if (newUsername.isEmpty) return;
if (newUsername == UserSession.username) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Username baru harus berbeda dari yang lama')),
);
return;
}
setState(() => _isLoading = true);
final success = await _userRepository.updateUsername(UserSession.username!, newUsername);
setState(() => _isLoading = false);
if (success) {
await UserSession.saveSession(newUsername);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Username berhasil diperbarui')),
);
}
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Gagal memperbarui username')),
);
}
}
}
Future<void> _updatePassword() async {
final newPassword = _passwordController.text.trim();
if (newPassword.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Password tidak boleh kosong')),
);
return;
}
setState(() => _isLoading = true);
final success = await _userRepository.updatePassword(UserSession.username!, newPassword);
setState(() => _isLoading = false);
if (success) {
_passwordController.clear();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Password berhasil diperbarui')),
);
}
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Gagal memperbarui password')),
);
}
}
}
Future<void> _deleteAccount() async {
final confirm = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Hapus Akun'),
content: const Text('Apakah Anda yakin ingin menghapus akun ini? Tindakan ini tidak dapat dibatalkan.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Batal'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
style: TextButton.styleFrom(foregroundColor: Colors.red),
child: const Text('Hapus'),
),
],
),
);
if (confirm != true) return;
setState(() => _isLoading = true);
final success = await _userRepository.deleteUser(UserSession.username!);
setState(() => _isLoading = false);
if (success) {
await UserSession.logout();
if (mounted) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const LoginPage()),
(route) => false,
);
}
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Gagal menghapus akun')),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.backgroundBeige,
appBar: AppBar(
title: const Text('Kelola Akun'),
backgroundColor: Colors.transparent,
elevation: 0,
foregroundColor: AppTheme.textDark,
),
body: Stack(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: Column(
children: [
// Username Update Section
_buildSection(
title: 'Ganti Username',
child: Column(
children: [
_buildTextField(
controller: _usernameController,
label: 'Username baru',
icon: Icons.person_outline,
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _updateUsername,
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.primaryGreen,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
child: const Text('Simpan Username'),
),
),
],
),
),
const SizedBox(height: 24),
// Password Update Section
_buildSection(
title: 'Ganti Password',
child: Column(
children: [
_buildTextField(
controller: _passwordController,
label: 'Password baru',
icon: Icons.lock_outline,
isPassword: true,
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _updatePassword,
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.primaryGreen,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
child: const Text('Simpan Password'),
),
),
],
),
),
const SizedBox(height: 48),
// Delete Account Section
_buildSection(
title: 'Zona Berbahaya',
isDestructive: true,
child: Column(
children: [
const Text(
'Menghapus akun akan menghapus semua data Anda secara permanen.',
style: TextStyle(color: AppTheme.textLight, fontSize: 13),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: _isLoading ? null : _deleteAccount,
style: OutlinedButton.styleFrom(
foregroundColor: Colors.red,
side: const BorderSide(color: Colors.red),
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
child: const Text('Hapus Akun Saya'),
),
),
],
),
),
],
),
),
if (_isLoading)
Container(
color: Colors.black26,
child: const Center(
child: CircularProgressIndicator(color: AppTheme.primaryGreen),
),
),
],
),
);
}
Widget _buildSection({required String title, required Widget child, bool isDestructive = false}) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: AppTheme.surfaceWhite,
borderRadius: BorderRadius.circular(24),
border: isDestructive ? Border.all(color: Colors.red.withOpacity(0.3)) : null,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: isDestructive ? Colors.red : AppTheme.textDark,
),
),
const SizedBox(height: 16),
child,
],
),
);
}
Widget _buildTextField({
required TextEditingController controller,
required String label,
required IconData icon,
bool isPassword = false,
}) {
return TextField(
controller: controller,
obscureText: isPassword ? _obscurePassword : false,
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(icon, color: AppTheme.primaryGreen),
suffixIcon: isPassword
? IconButton(
icon: Icon(
_obscurePassword ? Icons.visibility_off : Icons.visibility,
color: AppTheme.primaryGreen.withOpacity(0.7),
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
)
: null,
filled: true,
fillColor: AppTheme.backgroundBeige.withOpacity(0.5),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
),
);
}
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
}