ambil data stok bantuan

This commit is contained in:
Khafidh Fuadi
2025-03-11 12:44:32 +07:00
parent d24832ea82
commit eec06ba79d
57 changed files with 4306 additions and 1590 deletions

View File

@ -0,0 +1,11 @@
import 'package:get/get.dart';
import 'package:penyaluran_app/app/modules/profile/controllers/profile_controller.dart';
class ProfileBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<ProfileController>(
() => ProfileController(),
);
}
}

View File

@ -0,0 +1,157 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:penyaluran_app/app/data/models/user_model.dart';
import 'package:penyaluran_app/app/services/auth_service.dart';
class ProfileController extends GetxController {
final AuthService _authService = Get.find<AuthService>();
final Rx<User?> user = Rx<User?>(null);
final RxBool isLoading = true.obs;
final RxBool isEditing = false.obs;
// Form controllers
late TextEditingController nameController;
late TextEditingController emailController;
late TextEditingController phoneController;
@override
void onInit() {
super.onInit();
nameController = TextEditingController();
emailController = TextEditingController();
phoneController = TextEditingController();
loadUserData();
}
@override
void onClose() {
nameController.dispose();
emailController.dispose();
phoneController.dispose();
super.onClose();
}
Future<void> loadUserData() async {
isLoading.value = true;
try {
// Mendapatkan data user dari service
final userData = await _authService.getCurrentUser();
user.value = userData;
// Mengisi form controllers dengan data user
if (userData != null) {
nameController.text = userData.name ?? '';
emailController.text = userData.email ?? '';
phoneController.text = userData.phone ?? '';
}
} catch (e) {
Get.snackbar(
'Error',
'Gagal memuat data profil: ${e.toString()}',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
} finally {
isLoading.value = false;
}
}
void toggleEditMode() {
isEditing.value = !isEditing.value;
}
Future<void> updateProfile() async {
if (nameController.text.isEmpty) {
Get.snackbar(
'Error',
'Nama tidak boleh kosong',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
return;
}
isLoading.value = true;
try {
// Update user data
final updatedUser = User(
id: user.value?.id,
name: nameController.text,
email: emailController.text,
phone: phoneController.text,
role: user.value?.role,
token: user.value?.token,
);
// Panggil API untuk update profil
await _authService.updateProfile(updatedUser);
// Refresh data
await loadUserData();
// Keluar dari mode edit
isEditing.value = false;
Get.snackbar(
'Sukses',
'Profil berhasil diperbarui',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
colorText: Colors.white,
);
} catch (e) {
Get.snackbar(
'Error',
'Gagal memperbarui profil: ${e.toString()}',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
} finally {
isLoading.value = false;
}
}
Future<void> changePassword(String currentPassword, String newPassword,
String confirmPassword) async {
if (newPassword != confirmPassword) {
Get.snackbar(
'Error',
'Konfirmasi password tidak sesuai',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
return;
}
isLoading.value = true;
try {
// Panggil API untuk ganti password
await _authService.changePassword(currentPassword, newPassword);
Get.back(); // Tutup dialog
Get.snackbar(
'Sukses',
'Password berhasil diubah',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
colorText: Colors.white,
);
} catch (e) {
Get.snackbar(
'Error',
'Gagal mengubah password: ${e.toString()}',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
} finally {
isLoading.value = false;
}
}
}

View File

@ -0,0 +1,233 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:penyaluran_app/app/modules/profile/controllers/profile_controller.dart';
import 'package:penyaluran_app/app/theme/app_theme.dart';
class ProfileView extends GetView<ProfileController> {
const ProfileView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Profil'),
actions: [
Obx(() {
if (controller.isEditing.value) {
return IconButton(
icon: const Icon(Icons.save),
onPressed: controller.updateProfile,
);
} else {
return IconButton(
icon: const Icon(Icons.edit),
onPressed: controller.toggleEditMode,
);
}
}),
],
),
body: Obx(() {
if (controller.isLoading.value) {
return const Center(child: CircularProgressIndicator());
}
return SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildProfileHeader(),
const SizedBox(height: 24),
_buildProfileForm(),
const SizedBox(height: 24),
_buildPasswordSection(context),
],
),
);
}),
);
}
Widget _buildProfileHeader() {
return Center(
child: Column(
children: [
const CircleAvatar(
radius: 50,
backgroundColor: AppTheme.primaryColor,
child: Icon(
Icons.person,
size: 60,
color: Colors.white,
),
),
const SizedBox(height: 16),
Obx(() => Text(
controller.user.value?.name ?? 'Pengguna',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
)),
const SizedBox(height: 4),
Obx(() => Text(
controller.user.value?.role?.toUpperCase() ?? 'PENGGUNA',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
fontWeight: FontWeight.w500,
),
)),
],
),
);
}
Widget _buildProfileForm() {
return Obx(() {
final isEditing = controller.isEditing.value;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Informasi Pribadi',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
// Nama
TextField(
controller: controller.nameController,
decoration: InputDecoration(
labelText: 'Nama Lengkap',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person),
enabled: isEditing,
),
),
const SizedBox(height: 16),
// Email
TextField(
controller: controller.emailController,
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.email),
enabled: isEditing,
),
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 16),
// Nomor Telepon
TextField(
controller: controller.phoneController,
decoration: InputDecoration(
labelText: 'Nomor Telepon',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.phone),
enabled: isEditing,
),
keyboardType: TextInputType.phone,
),
],
);
});
}
Widget _buildPasswordSection(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Keamanan',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: () => _showChangePasswordDialog(context),
icon: const Icon(Icons.lock),
label: const Text('Ubah Password'),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.primaryColor,
foregroundColor: Colors.white,
minimumSize: const Size(double.infinity, 50),
),
),
],
);
}
void _showChangePasswordDialog(BuildContext context) {
final currentPasswordController = TextEditingController();
final newPasswordController = TextEditingController();
final confirmPasswordController = TextEditingController();
Get.dialog(
AlertDialog(
title: const Text('Ubah Password'),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: currentPasswordController,
decoration: const InputDecoration(
labelText: 'Password Saat Ini',
border: OutlineInputBorder(),
),
obscureText: true,
),
const SizedBox(height: 16),
TextField(
controller: newPasswordController,
decoration: const InputDecoration(
labelText: 'Password Baru',
border: OutlineInputBorder(),
),
obscureText: true,
),
const SizedBox(height: 16),
TextField(
controller: confirmPasswordController,
decoration: const InputDecoration(
labelText: 'Konfirmasi Password Baru',
border: OutlineInputBorder(),
),
obscureText: true,
),
],
),
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text('Batal'),
),
ElevatedButton(
onPressed: () {
controller.changePassword(
currentPasswordController.text,
newPasswordController.text,
confirmPasswordController.text,
);
},
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.primaryColor,
),
child: const Text('Simpan'),
),
],
),
);
}
}