Files
bumrent_app/lib/app/modules/auth/views/registration_view.dart
2025-07-09 16:01:10 +07:00

1278 lines
46 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/auth_controller.dart';
import '../../../theme/app_colors.dart';
import 'package:intl/intl.dart';
class RegistrationView extends GetView<AuthController> {
const RegistrationView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
// Reset all registration fields when leaving the page
controller.resetRegistrationFields();
return true;
},
child: Scaffold(
body: Stack(
children: [
// Background gradient - same as login page
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
AppColors.primaryLight.withOpacity(0.1),
AppColors.background,
AppColors.accentLight.withOpacity(0.1),
],
),
),
),
// Pattern overlay - same as login page
Opacity(
opacity: 0.03,
child: Container(
decoration: BoxDecoration(
color: Colors.blue[50], // Temporary solid color
),
),
),
// Accent circles - same as login page
Positioned(
top: -40,
right: -20,
child: Container(
width: 150,
height: 150,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColors.primary.withOpacity(0.2),
Colors.transparent,
],
),
),
),
),
Positioned(
bottom: -50,
left: -30,
child: Container(
width: 180,
height: 180,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColors.accent.withOpacity(0.2),
Colors.transparent,
],
),
),
),
),
// Main content
SafeArea(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
_buildBackButton(),
const SizedBox(height: 20),
_buildHeader(),
const SizedBox(height: 30),
_buildRegistrationCard(),
_buildLoginLink(),
_buildCheckStatusLink(),
const SizedBox(height: 30),
],
),
),
),
),
],
),
),
);
}
Widget _buildBackButton() {
return Align(
alignment: Alignment.topLeft,
child: InkWell(
onTap: () {
// Reset all registration fields when going back
controller.resetRegistrationFields();
Get.back();
},
borderRadius: BorderRadius.circular(50),
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: AppColors.shadow,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Icon(Icons.arrow_back, size: 20, color: AppColors.primary),
),
),
);
}
Widget _buildHeader() {
return Center(
child: Hero(
tag: 'logo',
child: Image.asset(
'assets/images/logo.png',
width: 150,
height: 150,
errorBuilder: (context, error, stackTrace) {
return Icon(
Icons.apartment_rounded,
size: 120,
color: AppColors.primary,
);
},
),
),
);
}
Widget _buildRegistrationCard() {
return Card(
elevation: 4,
shadowColor: AppColors.shadow,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
child: Padding(
padding: const EdgeInsets.all(28.0),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Welcome text
Text(
'Daftar Akun',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
),
),
const SizedBox(height: 8),
Text(
'Lengkapi data berikut untuk mendaftar',
style: TextStyle(
fontSize: 14,
color: AppColors.textSecondary,
fontWeight: FontWeight.w400,
),
),
const SizedBox(height: 24),
// Account Credentials Section
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.primaryLight.withOpacity(0.05),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: AppColors.primaryLight.withOpacity(0.2),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.account_circle_outlined,
color: AppColors.primary,
size: 20,
),
const SizedBox(width: 8),
Text(
'Informasi Akun',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
),
],
),
const SizedBox(height: 16),
// Email field
_buildInputLabel('Email'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Masukkan email anda',
prefixIcon: Icons.email_outlined,
keyboardType: TextInputType.emailAddress,
onChanged: (value) => controller.email.value = value,
validator: controller.validateEmail,
),
const SizedBox(height: 16),
// Password field
_buildInputLabel('Password'),
const SizedBox(height: 8),
Obx(
() => _buildTextField(
hintText: 'Masukkan password anda',
prefixIcon: Icons.lock_outline,
obscureText: !controller.isPasswordVisible.value,
onChanged: (value) => controller.password.value = value,
validator: controller.validatePassword,
suffixIcon: IconButton(
icon: Icon(
controller.isPasswordVisible.value
? Icons.visibility
: Icons.visibility_off,
color: AppColors.iconGrey,
),
onPressed: controller.togglePasswordVisibility,
),
),
),
const SizedBox(height: 16),
// Confirm Password field
_buildInputLabel('Konfirmasi Password'),
const SizedBox(height: 8),
Obx(
() => _buildTextField(
controller: controller.confirmPasswordController,
hintText: 'Masukkan ulang password anda',
prefixIcon: Icons.lock_outline,
obscureText: !controller.isConfirmPasswordVisible.value,
validator: controller.validateConfirmPassword,
suffixIcon: IconButton(
icon: Icon(
controller.isConfirmPasswordVisible.value
? Icons.visibility
: Icons.visibility_off,
color: AppColors.iconGrey,
),
onPressed: controller.toggleConfirmPasswordVisibility,
),
),
),
],
),
),
const SizedBox(height: 24),
// Personal Data Section
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.accentLight.withOpacity(0.05),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: AppColors.accentLight.withOpacity(0.2),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.person_outline,
color: AppColors.accent,
size: 20,
),
const SizedBox(width: 8),
Text(
'Data Diri',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppColors.accent,
),
),
],
),
const SizedBox(height: 16),
// Name field
_buildInputLabel('Nama Lengkap'),
const SizedBox(height: 8),
_buildTextField(
controller: controller.nameController,
hintText: 'Masukkan nama lengkap anda',
prefixIcon: Icons.person_outline,
validator: controller.validateName,
),
const SizedBox(height: 16),
// NIK field
_buildInputLabel('NIK'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Masukkan NIK anda',
prefixIcon: Icons.credit_card_outlined,
keyboardType: TextInputType.number,
onChanged: (value) => controller.nik.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'NIK tidak boleh kosong';
}
if (value.length != 16) {
return 'NIK harus 16 digit';
}
if (!RegExp(r'^[0-9]+$').hasMatch(value)) {
return 'NIK hanya boleh berisi angka';
}
return null;
},
),
const SizedBox(height: 16),
// Tanggal Lahir field
_buildInputLabel('Tanggal Lahir'),
const SizedBox(height: 8),
Builder(builder: (context) => _buildDateField(context)),
const SizedBox(height: 16),
// Phone field
_buildInputLabel('No HP'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Masukkan nomor HP anda',
prefixIcon: Icons.phone_outlined,
keyboardType: TextInputType.phone,
onChanged:
(value) => controller.phoneNumber.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'No HP tidak boleh kosong';
}
if (!value.startsWith('08')) {
return 'Nomor HP harus diawali dengan 08';
}
if (value.length < 10 || value.length > 13) {
return 'Nomor HP harus antara 10-13 digit';
}
if (!RegExp(r'^[0-9]+$').hasMatch(value)) {
return 'Nomor HP hanya boleh berisi angka';
}
return null;
},
),
const SizedBox(height: 16),
// RT/RW field
_buildInputLabel('RT/RW'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Contoh: 001/002',
prefixIcon: Icons.home_work_outlined,
onChanged: (value) => controller.rtRw.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'RT/RW tidak boleh kosong';
}
if (!RegExp(r'^\d{1,3}\/\d{1,3}$').hasMatch(value)) {
return 'Format RT/RW tidak valid (contoh: 001/002)';
}
return null;
},
),
const SizedBox(height: 16),
// Kelurahan/Desa field
_buildInputLabel('Kelurahan/Desa'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Masukkan kelurahan/desa anda',
prefixIcon: Icons.location_city_outlined,
onChanged: (value) => controller.kelurahan.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Kelurahan/Desa tidak boleh kosong';
}
if (value.length < 3) {
return 'Kelurahan/Desa minimal 3 karakter';
}
return null;
},
),
const SizedBox(height: 16),
// Kecamatan field
_buildInputLabel('Kecamatan'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Masukkan kecamatan anda',
prefixIcon: Icons.location_on_outlined,
onChanged: (value) => controller.kecamatan.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Kecamatan tidak boleh kosong';
}
if (value.length < 3) {
return 'Kecamatan minimal 3 karakter';
}
return null;
},
),
const SizedBox(height: 16),
// Address field
_buildInputLabel('Alamat Lengkap'),
const SizedBox(height: 8),
_buildTextField(
hintText: 'Masukkan alamat lengkap anda',
prefixIcon: Icons.home_outlined,
onChanged:
(value) => controller.alamatLengkap.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Alamat lengkap tidak boleh kosong';
}
if (value.length < 5) {
return 'Alamat terlalu pendek, minimal 5 karakter';
}
return null;
},
),
],
),
),
const SizedBox(height: 24),
// Important info
_buildImportantInfo(),
const SizedBox(height: 24),
// Register button
Obx(
() => SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton(
onPressed:
controller.isLoading.value
? null
: controller.registerUser,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primary,
foregroundColor: AppColors.buttonText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: controller.isLoading.value ? 0 : 2,
shadowColor: AppColors.primary.withOpacity(0.4),
),
child:
controller.isLoading.value
? const SizedBox(
height: 24,
width: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Daftar',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
letterSpacing: 0.5,
),
),
const SizedBox(width: 8),
const Icon(Icons.arrow_forward, size: 18),
],
),
),
),
),
// Error message
Obx(
() =>
controller.errorMessage.value.isNotEmpty
? Container(
margin: const EdgeInsets.only(top: 16),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColors.errorLight,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Icon(
Icons.error_outline,
color: AppColors.error,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
controller.errorMessage.value,
style: TextStyle(
color: AppColors.error,
fontSize: 13,
),
),
),
],
),
)
: const SizedBox.shrink(),
),
],
),
),
),
);
}
Widget _buildInputLabel(String label) {
return Text(
label,
style: TextStyle(
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
fontSize: 15,
),
);
}
Widget _buildTextField({
TextEditingController? controller,
required String hintText,
required IconData prefixIcon,
TextInputType keyboardType = TextInputType.text,
bool obscureText = false,
Widget? suffixIcon,
Function(String)? onChanged,
String? Function(String?)? validator,
}) {
return TextFormField(
controller: controller,
keyboardType: keyboardType,
obscureText: obscureText,
onChanged: onChanged,
validator: validator,
style: TextStyle(fontSize: 16, color: AppColors.textPrimary),
decoration: InputDecoration(
hintText: hintText,
hintStyle: TextStyle(color: AppColors.textLight),
prefixIcon: Icon(prefixIcon, color: AppColors.iconGrey, size: 22),
suffixIcon: suffixIcon,
filled: true,
fillColor: AppColors.inputBackground,
contentPadding: const EdgeInsets.symmetric(vertical: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: AppColors.primary, width: 1.5),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: AppColors.error, width: 1.5),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: AppColors.error, width: 1.5),
),
),
);
}
Widget _buildImportantInfo() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.warningLight,
borderRadius: BorderRadius.circular(14),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.info_outline, size: 20, color: AppColors.warning),
const SizedBox(width: 12),
Expanded(
child: Text(
'Setelah melakukan pendaftaran, silahkan simpan kode registrasi untuk cek status pendaftaran',
style: TextStyle(
fontSize: 13,
color: AppColors.textPrimary,
height: 1.4,
),
),
),
],
),
);
}
Widget _buildLoginLink() {
return Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Sudah punya akun?",
style: TextStyle(color: AppColors.textSecondary),
),
TextButton(
onPressed: () {
// Reset all registration fields when going back to login
controller.resetRegistrationFields();
Get.back();
},
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
),
child: Text(
'Masuk',
style: TextStyle(
fontWeight: FontWeight.bold,
color: AppColors.primary,
),
),
),
],
),
);
}
// Add button to check registration status
Widget _buildCheckStatusLink() {
return Center(
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextButton(
onPressed: () => _showCheckStatusDialog(Get.context!),
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.search, size: 18, color: AppColors.accent),
const SizedBox(width: 8),
Text(
'Cek Status Pendaftaran',
style: TextStyle(
fontWeight: FontWeight.bold,
color: AppColors.accent,
fontSize: 14,
),
),
],
),
),
),
);
}
// Show dialog to check registration status
void _showCheckStatusDialog(BuildContext context) {
final TextEditingController codeController = TextEditingController();
final TextEditingController emailController = TextEditingController();
final authController = Get.find<AuthController>();
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Dialog header
Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppColors.accent.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(
Icons.search,
color: AppColors.accent,
size: 20,
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
'Cek Status Pendaftaran',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
),
),
),
IconButton(
icon: const Icon(Icons.close, size: 20),
onPressed: () => Navigator.pop(context),
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
splashRadius: 24,
),
],
),
const SizedBox(height: 16),
// Registration code field
Text(
'Kode Registrasi',
style: TextStyle(
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
fontSize: 14,
),
),
const SizedBox(height: 8),
TextField(
controller: codeController,
decoration: InputDecoration(
hintText: 'Masukkan kode registrasi',
hintStyle: TextStyle(color: AppColors.textLight),
prefixIcon: Icon(
Icons.confirmation_number_outlined,
color: AppColors.iconGrey,
size: 22,
),
filled: true,
fillColor: AppColors.inputBackground,
contentPadding: const EdgeInsets.symmetric(vertical: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(
color: AppColors.accent,
width: 1.5,
),
),
),
),
const SizedBox(height: 16),
// Email field
Text(
'Email',
style: TextStyle(
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
fontSize: 14,
),
),
const SizedBox(height: 8),
TextField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Masukkan email yang terdaftar',
hintStyle: TextStyle(color: AppColors.textLight),
prefixIcon: Icon(
Icons.email_outlined,
color: AppColors.iconGrey,
size: 22,
),
filled: true,
fillColor: AppColors.inputBackground,
contentPadding: const EdgeInsets.symmetric(vertical: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(
color: AppColors.accent,
width: 1.5,
),
),
),
),
const SizedBox(height: 24),
// Submit button
SizedBox(
width: double.infinity,
height: 48,
child: ElevatedButton(
onPressed: () async {
// Validasi input
if (codeController.text.isEmpty ||
emailController.text.isEmpty) {
Get.snackbar(
'Error',
'Kode registrasi dan Email harus diisi',
snackPosition: SnackPosition.TOP,
backgroundColor: AppColors.errorLight,
colorText: AppColors.error,
icon: Icon(
Icons.error_outline,
color: AppColors.error,
),
duration: const Duration(seconds: 3),
);
return;
}
// Simpan nilai input untuk digunakan nanti
final String registerId = codeController.text.trim();
final String email = emailController.text.trim();
print(
'Checking registration status for ID: $registerId, Email: $email',
);
// Tutup dialog input
Navigator.pop(context);
// Tampilkan loading indicator
Get.dialog(
const Center(child: CircularProgressIndicator()),
barrierDismissible: false,
);
try {
// Cek status pendaftaran
final result = await authController
.checkRegistrationStatus(registerId, email);
// Debug log
print('Registration status check result: $result');
// Tutup dialog loading
Get.back();
// Periksa hasil query
if (result != null && result.isNotEmpty) {
print('Valid result found, showing status dialog');
// Tambahkan delay kecil untuk memastikan UI diperbarui dengan benar
// Ini membantu memastikan dialog status muncul setelah dialog loading ditutup
Future.delayed(const Duration(milliseconds: 100), () {
_showRegistrationStatusDialog(result);
});
} else {
print('No result found or empty result');
// Tampilkan pesan error
Get.snackbar(
'Tidak Ditemukan',
'Data pendaftaran tidak ditemukan. Pastikan kode registrasi dan email yang dimasukkan benar.',
snackPosition: SnackPosition.TOP,
backgroundColor: AppColors.errorLight,
colorText: AppColors.error,
icon: Icon(
Icons.error_outline,
color: AppColors.error,
),
duration: const Duration(seconds: 4),
);
}
} catch (e) {
// Tutup dialog loading jika terjadi error
Get.back();
print('Error checking registration status: $e');
// Tampilkan pesan error
Get.snackbar(
'Error',
'Terjadi kesalahan saat memeriksa status. Silakan coba lagi nanti.',
snackPosition: SnackPosition.TOP,
backgroundColor: AppColors.errorLight,
colorText: AppColors.error,
icon: Icon(
Icons.error_outline,
color: AppColors.error,
),
duration: const Duration(seconds: 4),
);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.accent,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
elevation: 0,
),
child: const Text(
'Cek Status',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
},
);
}
// Show dialog with registration status details
void _showRegistrationStatusDialog(Map<String, dynamic> data) {
// Log data yang diterima untuk debugging
print('Showing registration status dialog with data: $data');
// Validasi data
if (data.isEmpty) {
print('Error: Empty data received in _showRegistrationStatusDialog');
Get.snackbar(
'Error',
'Data status pendaftaran tidak valid',
snackPosition: SnackPosition.TOP,
backgroundColor: AppColors.errorLight,
colorText: AppColors.error,
duration: const Duration(seconds: 3),
);
return;
}
final String status = data['status'] ?? 'unknown';
final String namaLengkap = data['nama_lengkap'] ?? '';
final String keterangan = data['keterangan'] ?? '';
print('Processing status: $status, nama: $namaLengkap');
// Define status color and message based on status
Color statusColor;
String statusMessage;
IconData statusIcon;
switch (status) {
case 'pending':
statusColor = AppColors.warning;
statusMessage =
keterangan.isNotEmpty
? keterangan
: 'Pendaftaran Anda sedang dalam proses verifikasi oleh petugas. Mohon tunggu konfirmasi lebih lanjut.';
statusIcon = Icons.hourglass_top;
break;
case 'active':
statusColor = AppColors.success;
statusMessage =
keterangan.isNotEmpty
? keterangan
: 'Pendaftaran Anda telah disetujui. Anda dapat login menggunakan email dan password yang telah didaftarkan.';
statusIcon = Icons.check_circle;
break;
case 'dibatalkan':
statusColor = AppColors.error;
statusMessage =
keterangan.isNotEmpty
? keterangan
: 'Maaf, pendaftaran Anda ditolak. Silakan hubungi admin untuk informasi lebih lanjut.';
statusIcon = Icons.cancel;
break;
case 'suspended':
statusColor = AppColors.error;
statusMessage =
keterangan.isNotEmpty
? keterangan
: 'Akun Anda saat ini dinonaktifkan. Silakan hubungi admin untuk informasi lebih lanjut.';
statusIcon = Icons.block;
break;
default:
statusColor = AppColors.textSecondary;
statusMessage =
keterangan.isNotEmpty
? keterangan
: 'Status pendaftaran tidak diketahui. Silakan hubungi admin untuk informasi lebih lanjut.';
statusIcon = Icons.help;
}
print('Preparing to show dialog with status: $status, color: $statusColor');
// Gunakan Get.dialog sebagai pengganti showDialog untuk menghindari masalah context
Get.dialog(
Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: statusColor.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(statusIcon, color: statusColor, size: 40),
),
const SizedBox(height: 24),
Text(
'Status Pendaftaran',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
),
),
const SizedBox(height: 8),
Text(
namaLengkap,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: AppColors.textSecondary,
),
),
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
decoration: BoxDecoration(
color: statusColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(30),
),
child: Text(
status.toUpperCase(),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: statusColor,
),
),
),
const SizedBox(height: 24),
Text(
statusMessage,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
color: AppColors.textSecondary,
height: 1.5,
),
),
// Tampilkan informasi tambahan jika ada
if (data.containsKey('tanggal_update') &&
data['tanggal_update'] != null) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColors.infoLight.withOpacity(0.3),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.info_outline,
size: 16,
color: AppColors.info,
),
const SizedBox(width: 8),
Text(
'Informasi Tambahan',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: AppColors.info,
),
),
],
),
const SizedBox(height: 8),
Text(
'Terakhir diperbarui: ${_formatDate(data['tanggal_update'])}',
style: TextStyle(
fontSize: 13,
color: AppColors.textSecondary,
),
),
],
),
),
],
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => Get.back(),
style: ElevatedButton.styleFrom(
backgroundColor: statusColor,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
padding: const EdgeInsets.symmetric(vertical: 12),
),
child: const Text(
'Tutup',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
barrierDismissible: true,
);
print('Dialog setup completed');
}
// New method to build date picker field
Widget _buildDateField(BuildContext context) {
return GestureDetector(
onTap: () async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now().subtract(
const Duration(days: 365 * 18),
), // Default to 18 years ago
firstDate: DateTime(1940),
lastDate: DateTime.now(),
builder: (BuildContext context, Widget? child) {
return Theme(
data: ThemeData.light().copyWith(
colorScheme: ColorScheme.light(
primary: AppColors.primary,
onPrimary: Colors.white,
surface: Colors.white,
onSurface: AppColors.textPrimary,
),
dialogBackgroundColor: Colors.white,
),
child: child!,
);
},
);
if (picked != null) {
controller.tanggalLahir.value = picked;
}
},
child: Obx(() {
final selectedDate = controller.tanggalLahir.value;
final displayText =
selectedDate != null
? '${selectedDate.day.toString().padLeft(2, '0')}-${selectedDate.month.toString().padLeft(2, '0')}-${selectedDate.year}'
: 'Pilih tanggal lahir';
return Container(
padding: const EdgeInsets.symmetric(vertical: 16),
decoration: BoxDecoration(
color: AppColors.inputBackground,
borderRadius: BorderRadius.circular(14),
),
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Icon(
Icons.calendar_today_outlined,
color: AppColors.iconGrey,
size: 22,
),
),
Text(
displayText,
style: TextStyle(
fontSize: 16,
color:
selectedDate != null
? AppColors.textPrimary
: AppColors.textLight,
),
),
],
),
);
}),
);
}
String _formatDate(dynamic date) {
if (date is String) {
try {
final DateTime parsedDate = DateTime.parse(date);
return DateFormat('dd MMM yyyy, HH:mm').format(parsedDate);
} catch (e) {
return date;
}
} else if (date is num) {
final DateTime parsedDate = DateTime.fromMillisecondsSinceEpoch(
date.toInt() * 1000,
);
return DateFormat('dd MMM yyyy, HH:mm').format(parsedDate);
} else if (date is DateTime) {
return DateFormat('dd MMM yyyy, HH:mm').format(date);
} else {
return "Format tanggal tidak diketahui";
}
}
}