Perbarui model Pengaduan dengan menambahkan getter isUang untuk memeriksa jenis bantuan. Modifikasi tampilan dan controller di modul donatur dan petugas desa untuk meningkatkan pengalaman pengguna, termasuk penggantian ikon dan penyesuaian format tampilan jumlah bantuan. Hapus kode yang tidak diperlukan untuk menjaga kebersihan kode.

This commit is contained in:
Khafidh Fuadi
2025-04-10 14:25:41 +07:00
parent 3f78514175
commit ca6c28f3d6
40 changed files with 3103 additions and 2270 deletions

View File

@ -537,62 +537,114 @@ class AuthController extends GetxController {
}
isLoading.value = true;
try {
// Proses registrasi donatur dengan role_id 3
await _authProvider.signUpDonatur(
email: emailController.text,
password: passwordController.text,
namaLengkap: namaController.text,
alamat: alamatController.text,
noHp: noHpController.text,
jenis: jenisController.text.isEmpty ? 'Individu' : jenisController.text,
);
Get.snackbar(
'Sukses',
'Registrasi donatur berhasil! Silakan login dengan akun Anda.',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green,
colorText: Colors.white,
duration: const Duration(seconds: 5),
);
// Kita akan mencoba maksimal 2 kali jika terjadi error
int maxAttempts = 2;
int attempt = 0;
bool success = false;
Exception? lastError;
// Bersihkan form
clearDonaturRegistrationForm();
while (attempt < maxAttempts && !success) {
attempt++;
print(
'DEBUG: Mencoba pendaftaran donatur (percobaan ke-$attempt dari $maxAttempts)');
// Arahkan ke halaman login
Get.offAllNamed(Routes.login);
} catch (e) {
print('Error registrasi donatur: $e');
try {
print('DEBUG: Validasi form berhasil, melanjutkan proses registrasi');
print('DEBUG: Email: ${emailController.text}');
print('DEBUG: Nama: ${namaController.text}');
print('DEBUG: Alamat: ${alamatController.text}');
print('DEBUG: No HP: ${noHpController.text}');
print(
'DEBUG: Jenis: ${jenisController.text.isEmpty ? 'Individu' : jenisController.text}');
String errorMessage = 'Gagal melakukan registrasi';
// Proses registrasi donatur
await _authProvider.signUpDonatur(
email: emailController.text,
password: passwordController.text,
namaLengkap: namaController.text,
alamat: alamatController.text,
noHp: noHpController.text,
jenis:
jenisController.text.isEmpty ? 'Individu' : jenisController.text,
);
// Tangani error sesuai jenisnya
if (e.toString().contains('email konfirmasi')) {
errorMessage =
'Gagal mengirim email konfirmasi. Mohon periksa alamat email Anda dan coba lagi nanti.';
} else if (e.toString().contains('Email sudah terdaftar')) {
errorMessage =
'Email sudah terdaftar. Silakan gunakan email lain atau login dengan email tersebut.';
} else if (e.toString().contains('weak-password')) {
errorMessage =
'Password terlalu lemah. Gunakan kombinasi huruf, angka, dan simbol.';
} else if (e.toString().contains('invalid-email')) {
errorMessage = 'Format email tidak valid.';
} else {
errorMessage = 'Gagal melakukan registrasi: ${e.toString()}';
print('DEBUG: Registrasi donatur berhasil');
success = true;
Get.snackbar(
'Sukses',
'Registrasi donatur berhasil! Silakan login dengan akun Anda.',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green,
colorText: Colors.white,
duration: const Duration(seconds: 5),
);
// Bersihkan form
clearDonaturRegistrationForm();
// Arahkan ke halaman login
Get.offAllNamed(Routes.login);
} catch (e) {
lastError = e is Exception ? e : Exception(e.toString());
print('ERROR: Error registrasi donatur (percobaan ke-$attempt): $e');
print('ERROR Detail: ${e.runtimeType} - ${e.toString()}');
// Cek apakah bisa dicoba lagi atau tidak
bool canRetry = false;
if (e.toString().contains('Database error saving new user')) {
canRetry = true; // Error database bisa dicoba lagi
print('DEBUG: Error database, akan mencoba lagi');
// Delay sedikit sebelum mencoba lagi
await Future.delayed(const Duration(seconds: 1));
} else if (e.toString().contains('User already registered')) {
// Jangan coba lagi jika email sudah terdaftar
canRetry = false;
}
if (!canRetry || attempt >= maxAttempts) {
// Jika tidak bisa retry atau sudah maksimal, tampilkan error
String errorMessage = 'Gagal melakukan registrasi';
// Tangani error sesuai jenisnya
if (e.toString().contains('email konfirmasi')) {
errorMessage =
'Gagal mengirim email konfirmasi. Mohon periksa alamat email Anda dan coba lagi nanti.';
} else if (e.toString().contains('Email sudah terdaftar')) {
errorMessage =
'Email sudah terdaftar. Silakan gunakan email lain atau login dengan email tersebut.';
} else if (e.toString().contains('weak-password')) {
errorMessage =
'Password terlalu lemah. Gunakan kombinasi huruf, angka, dan simbol.';
} else if (e.toString().contains('invalid-email')) {
errorMessage = 'Format email tidak valid.';
} else if (e.toString().contains('Database error')) {
errorMessage =
'Terjadi kesalahan pada database. Silakan coba lagi nanti atau hubungi administrator.';
} else {
errorMessage = 'Gagal melakukan registrasi: ${e.toString()}';
}
Get.snackbar(
'Error',
errorMessage,
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red,
colorText: Colors.white,
duration: const Duration(seconds: 7),
);
break; // Keluar dari loop
}
}
}
Get.snackbar(
'Error',
errorMessage,
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red,
colorText: Colors.white,
duration: const Duration(seconds: 5),
);
} finally {
isLoading.value = false;
isLoading.value = false;
// Jika gagal setelah mencoba beberapa kali
if (!success && lastError != null) {
print('ERROR: Pendaftaran gagal setelah $attempt percobaan');
// Error sudah ditampilkan di dalam loop
}
}

View File

@ -3,6 +3,7 @@ import 'package:get/get.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart';
import 'package:penyaluran_app/app/routes/app_pages.dart';
import 'package:penyaluran_app/app/theme/app_theme.dart';
class RegisterDonaturView extends GetView<AuthController> {
const RegisterDonaturView({super.key});
@ -13,7 +14,7 @@ class RegisterDonaturView extends GetView<AuthController> {
appBar: AppBar(
title: const Text('Daftar Donatur'),
centerTitle: true,
backgroundColor: Colors.blue,
backgroundColor: AppTheme.primaryColor,
foregroundColor: Colors.white,
elevation: 0,
shape: const RoundedRectangleBorder(
@ -22,436 +23,469 @@ class RegisterDonaturView extends GetView<AuthController> {
),
),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Form(
key: controller.registerDonaturFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 10),
// Header dengan icon dan judul
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
Image.asset(
'assets/images/logo-disalurkita.png',
width: 120,
height: 120,
),
const Text(
'Daftar Sebagai Donatur',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFFE3F2FD), Colors.white],
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Form(
key: controller.registerDonaturFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 10),
// Header dengan icon dan judul
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: AppTheme.primaryColor.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 2),
),
),
const SizedBox(height: 4),
const Text(
'Bergabunglah dengan kami untuk membantu mereka yang membutuhkan',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.blueGrey,
],
),
child: Column(
children: [
Image.asset(
'assets/images/logo-disalurkita.png',
width: 120,
height: 120,
),
),
],
),
),
const SizedBox(height: 20),
// Step indicator
const Row(
children: [
Icon(Icons.person_add, color: Colors.blue),
SizedBox(width: 10),
Text(
'Informasi Akun',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
],
),
const SizedBox(height: 15),
const Divider(),
const SizedBox(height: 10),
// Nama Lengkap
TextFormField(
controller: controller.namaController,
keyboardType: TextInputType.name,
decoration: InputDecoration(
labelText: 'Nama Lengkap',
hintText: 'Masukkan nama lengkap Anda',
prefixIcon: const Icon(Icons.person, color: Colors.blue),
filled: true,
fillColor: Colors.grey.shade100,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
const BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateDonaturNama,
),
const SizedBox(height: 15),
// Email
TextFormField(
controller: controller.emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
hintText: 'contoh@email.com',
prefixIcon: const Icon(Icons.email, color: Colors.blue),
filled: true,
fillColor: Colors.grey.shade100,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
const BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateEmail,
),
const SizedBox(height: 15),
// Password
Obx(() => TextFormField(
controller: controller.passwordController,
obscureText: controller.isPasswordHidden.value,
decoration: InputDecoration(
labelText: 'Password',
hintText: 'Minimal 8 karakter',
prefixIcon:
const Icon(Icons.lock, color: Colors.blue),
suffixIcon: IconButton(
icon: Icon(
controller.isPasswordHidden.value
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
Text(
'Daftar Sebagai Donatur',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppTheme.primaryColor,
),
onPressed: () =>
controller.togglePasswordVisibility(),
),
filled: true,
fillColor: Colors.grey.shade100,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
const BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validatePassword,
)),
const SizedBox(height: 15),
// Confirm Password
Obx(() => TextFormField(
controller: controller.confirmPasswordController,
obscureText: controller.isConfirmPasswordHidden.value,
decoration: InputDecoration(
labelText: 'Konfirmasi Password',
hintText: 'Masukkan password yang sama',
prefixIcon: const Icon(Icons.lock_outline,
color: Colors.blue),
suffixIcon: IconButton(
icon: Icon(
controller.isConfirmPasswordHidden.value
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
const SizedBox(height: 4),
Text(
'Bergabunglah dengan kami untuk membantu mereka yang membutuhkan',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: const Color(0xFF546E7A),
),
onPressed: () =>
controller.toggleConfirmPasswordVisibility(),
),
filled: true,
fillColor: Colors.grey.shade100,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
const BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateConfirmPassword,
)),
const SizedBox(height: 15),
// Section heading
const Row(
children: [
Icon(Icons.person_pin_circle, color: Colors.blue),
SizedBox(width: 10),
Text(
'Informasi Profil',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
],
),
const SizedBox(height: 15),
const Divider(),
const SizedBox(height: 10),
// No HP
TextFormField(
controller: controller.noHpController,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'Nomor HP',
hintText: 'Masukkan nomor HP aktif',
prefixIcon: const Icon(Icons.phone, color: Colors.blue),
filled: true,
fillColor: Colors.grey.shade100,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
const BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
],
),
),
validator: controller.validateDonaturNoHp,
),
const SizedBox(height: 15),
// Alamat
TextFormField(
controller: controller.alamatController,
keyboardType: TextInputType.streetAddress,
maxLines: 2,
decoration: InputDecoration(
labelText: 'Alamat Lengkap',
hintText: 'Masukkan alamat lengkap Anda',
prefixIcon: const Icon(Icons.home, color: Colors.blue),
filled: true,
fillColor: Colors.grey.shade100,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
const BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateDonaturAlamat,
),
const SizedBox(height: 15),
// Jenis Donatur (Dropdown)
Container(
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade300),
),
child: DropdownButtonFormField<String>(
value: controller.jenisController.text.isEmpty
? 'Individu'
: controller.jenisController.text,
decoration: InputDecoration(
labelText: 'Jenis Donatur',
prefixIcon:
const Icon(Icons.category, color: Colors.blue),
border: InputBorder.none,
contentPadding:
const EdgeInsets.symmetric(horizontal: 10),
),
items: const [
DropdownMenuItem(
value: 'Individu', child: Text('Individu')),
DropdownMenuItem(
value: 'Organisasi', child: Text('Organisasi')),
DropdownMenuItem(
value: 'Perusahaan', child: Text('Perusahaan')),
DropdownMenuItem(
value: 'Lainnya', child: Text('Lainnya')),
],
onChanged: (value) {
controller.jenisController.text = value ?? 'Individu';
},
),
),
const SizedBox(height: 25),
// Catatan Informasi
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue.shade200),
),
child: Row(
const SizedBox(height: 20),
// Step indicator
Row(
children: [
const Icon(Icons.info_outline, color: Colors.blue),
Icon(Icons.person_add, color: AppTheme.primaryColor),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Informasi',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
),
Text(
'Informasi Akun',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppTheme.primaryColor,
),
),
],
),
const SizedBox(height: 15),
const Divider(),
const SizedBox(height: 10),
// Nama Lengkap
TextFormField(
controller: controller.namaController,
keyboardType: TextInputType.name,
decoration: InputDecoration(
labelText: 'Nama Lengkap',
hintText: 'Masukkan nama lengkap Anda',
prefixIcon:
Icon(Icons.person, color: AppTheme.primaryColor),
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: AppTheme.primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateDonaturNama,
),
const SizedBox(height: 15),
// Email
TextFormField(
controller: controller.emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
hintText: 'contoh@email.com',
prefixIcon:
Icon(Icons.email, color: AppTheme.primaryColor),
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: AppTheme.primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateEmail,
),
const SizedBox(height: 15),
// Password
Obx(() => TextFormField(
controller: controller.passwordController,
obscureText: controller.isPasswordHidden.value,
decoration: InputDecoration(
labelText: 'Password',
hintText: 'Minimal 8 karakter',
prefixIcon:
Icon(Icons.lock, color: AppTheme.primaryColor),
suffixIcon: IconButton(
icon: Icon(
controller.isPasswordHidden.value
? Icons.visibility_off
: Icons.visibility,
color: AppTheme.primaryColor,
),
SizedBox(height: 5),
Text(
'Data Anda akan terverifikasi dan terlindungi. Kami menjaga privasi dan keamanan data Anda.',
style: TextStyle(
fontSize: 14,
color: Colors.blueGrey,
onPressed: () =>
controller.togglePasswordVisibility(),
),
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: AppTheme.primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validatePassword,
)),
const SizedBox(height: 15),
// Confirm Password
Obx(() => TextFormField(
controller: controller.confirmPasswordController,
obscureText: controller.isConfirmPasswordHidden.value,
decoration: InputDecoration(
labelText: 'Konfirmasi Password',
hintText: 'Masukkan password yang sama',
prefixIcon: Icon(Icons.lock_outline,
color: AppTheme.primaryColor),
suffixIcon: IconButton(
icon: Icon(
controller.isConfirmPasswordHidden.value
? Icons.visibility_off
: Icons.visibility,
color: AppTheme.primaryColor,
),
onPressed: () =>
controller.toggleConfirmPasswordVisibility(),
),
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide:
BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: AppTheme.primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateConfirmPassword,
)),
const SizedBox(height: 15),
// Section heading
Row(
children: [
Icon(Icons.person_pin_circle,
color: AppTheme.primaryColor),
const SizedBox(width: 10),
Text(
'Informasi Profil',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppTheme.primaryColor,
),
),
],
),
const SizedBox(height: 15),
const Divider(),
const SizedBox(height: 10),
// No HP
TextFormField(
controller: controller.noHpController,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'Nomor HP',
hintText: 'Masukkan nomor HP aktif',
prefixIcon:
Icon(Icons.phone, color: AppTheme.primaryColor),
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: AppTheme.primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateDonaturNoHp,
),
const SizedBox(height: 15),
// Alamat
TextFormField(
controller: controller.alamatController,
keyboardType: TextInputType.streetAddress,
maxLines: 2,
decoration: InputDecoration(
labelText: 'Alamat Lengkap',
hintText: 'Masukkan alamat lengkap Anda',
prefixIcon:
Icon(Icons.home, color: AppTheme.primaryColor),
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: AppTheme.primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.red),
),
),
validator: controller.validateDonaturAlamat,
),
const SizedBox(height: 15),
// Jenis Donatur (Dropdown)
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade300),
),
child: DropdownButtonFormField<String>(
value: controller.jenisController.text.isEmpty
? 'Individu'
: controller.jenisController.text,
decoration: InputDecoration(
labelText: 'Jenis Donatur',
labelStyle: TextStyle(color: AppTheme.primaryColor),
prefixIcon: Icon(Icons.category,
color: AppTheme.primaryColor),
border: InputBorder.none,
contentPadding:
const EdgeInsets.symmetric(horizontal: 10),
),
items: const [
DropdownMenuItem(
value: 'Individu', child: Text('Individu')),
DropdownMenuItem(
value: 'Organisasi', child: Text('Organisasi')),
DropdownMenuItem(
value: 'Perusahaan', child: Text('Perusahaan')),
DropdownMenuItem(
value: 'Lainnya', child: Text('Lainnya')),
],
onChanged: (value) {
controller.jenisController.text = value ?? 'Individu';
},
dropdownColor: Colors.white,
icon: Icon(Icons.arrow_drop_down,
color: AppTheme.primaryColor),
),
),
const SizedBox(height: 25),
// Catatan Informasi
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: const Color(0xFFF1F8E9),
borderRadius: BorderRadius.circular(15),
border: Border.all(color: const Color(0xFFAED581)),
),
child: Row(
children: [
const Icon(Icons.info_outline,
color: Color(0xFF558B2F)),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Informasi',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color(0xFF558B2F),
),
),
SizedBox(height: 5),
Text(
'Data Anda akan terverifikasi dan terlindungi. Kami menjaga privasi dan keamanan data Anda.',
style: TextStyle(
fontSize: 14,
color: Color(0xFF33691E),
),
),
],
),
),
],
),
),
const SizedBox(height: 25),
// Register Button
Obx(() => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: AppTheme.primaryColor.withOpacity(0.3),
spreadRadius: 1,
blurRadius: 3,
offset: const Offset(0, 2),
),
],
),
),
],
),
),
const SizedBox(height: 25),
// Register Button
Obx(() => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.blue.withOpacity(0.3),
spreadRadius: 1,
blurRadius: 3,
offset: const Offset(0, 2),
child: ElevatedButton(
onPressed: controller.isLoading.value
? null
: controller.registerDonatur,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 15),
backgroundColor: AppTheme.primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 0,
),
],
),
child: ElevatedButton(
onPressed: controller.isLoading.value
? null
: controller.registerDonatur,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 15),
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 0,
),
child: controller.isLoading.value
? const SpinKitThreeBounce(
color: Colors.white,
size: 24,
)
: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.how_to_reg, color: Colors.white),
SizedBox(width: 10),
Text(
'DAFTAR SEKARANG',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
child: controller.isLoading.value
? const SpinKitThreeBounce(
color: Colors.white,
size: 24,
)
: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.how_to_reg,
color: Colors.white),
SizedBox(width: 10),
Text(
'DAFTAR SEKARANG',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 1,
),
),
),
],
),
),
)),
const SizedBox(height: 20),
],
),
),
)),
const SizedBox(height: 20),
// Login Link
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.grey.shade50,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade200),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Sudah punya akun?',
style: TextStyle(color: Colors.grey),
),
TextButton(
onPressed: () => Get.offAllNamed(Routes.login),
child: const Text(
'Masuk',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
// Login Link
Container(
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade200),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Sudah punya akun?',
style: TextStyle(color: Color(0xFF546E7A)),
),
TextButton(
onPressed: () => Get.offAllNamed(Routes.login),
style: TextButton.styleFrom(
foregroundColor: AppTheme.primaryColor,
),
child: const Text(
'Masuk',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
],
],
),
),
),
const SizedBox(height: 20),
],
const SizedBox(height: 20),
],
),
),
),
),