Files
bumrent_app/lib/app/modules/auth/views/registration_view.dart
Andreas Malvino 8284c93aa5 fitur petugas
2025-06-22 09:25:58 +07:00

484 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/auth_controller.dart';
import '../../../theme/app_colors.dart';
class RegistrationView extends GetView<AuthController> {
const RegistrationView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.background,
body: SafeArea(
child: Stack(
children: [
// Background gradient
Positioned(
top: -100,
right: -100,
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColors.primaryLight.withOpacity(0.2),
AppColors.background.withOpacity(0),
],
stops: const [0.0, 1.0],
),
),
),
),
Positioned(
bottom: -80,
left: -80,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColors.accent.withOpacity(0.15),
AppColors.background.withOpacity(0),
],
stops: const [0.0, 1.0],
),
),
),
),
// Content
SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildBackButton(),
const SizedBox(height: 20),
_buildHeader(),
const SizedBox(height: 24),
_buildRegistrationForm(),
const SizedBox(height: 32),
_buildRegisterButton(),
const SizedBox(height: 24),
_buildImportantInfo(),
const SizedBox(height: 24),
_buildLoginLink(),
],
),
),
),
],
),
),
);
}
Widget _buildBackButton() {
return Align(
alignment: Alignment.topLeft,
child: InkWell(
onTap: () => Get.back(),
borderRadius: BorderRadius.circular(50),
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: AppColors.surface,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: AppColors.shadow,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: const Icon(
Icons.arrow_back,
size: 20,
color: AppColors.primary,
),
),
),
);
}
Widget _buildHeader() {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Hero(
tag: 'logo',
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: AppColors.primarySoft,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: AppColors.primary.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Icon(
Icons.apartment_rounded,
size: 40,
color: AppColors.primary,
),
),
),
const SizedBox(height: 24),
Text(
'Daftar Akun',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
),
),
const SizedBox(height: 10),
Text(
'Lengkapi data berikut untuk mendaftar',
style: TextStyle(fontSize: 16, color: AppColors.textSecondary),
textAlign: TextAlign.center,
),
],
);
}
Widget _buildImportantInfo() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.warningLight,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.warning.withOpacity(0.3)),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppColors.warning.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Icon(Icons.info_outline, size: 20, color: AppColors.warning),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Informasi Penting',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: AppColors.warning,
),
),
const SizedBox(height: 4),
Text(
'Setelah pendaftaran lengkapi data diri untuk dapat melakukan sewa',
style: TextStyle(
fontSize: 13,
color: AppColors.textPrimary,
height: 1.4,
),
),
],
),
),
],
),
);
}
Widget _buildRegistrationForm() {
return Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildInputLabel('Email'),
_buildEmailField(),
const SizedBox(height: 16),
_buildInputLabel('Password'),
_buildPasswordField(),
const SizedBox(height: 16),
_buildInputLabel('Konfirmasi Password'),
_buildConfirmPasswordField(),
const SizedBox(height: 16),
_buildInputLabel('Nama Lengkap'),
_buildNameField(),
const SizedBox(height: 16),
_buildInputLabel('No HP'),
_buildPhoneField(),
const SizedBox(height: 16),
_buildInputLabel('Alamat Lengkap'),
_buildAlamatField(),
const SizedBox(height: 16),
// Removed: NIK, No HP, and Dropdown Daftar Sebagai
],
),
);
}
Widget _buildInputLabel(String label) {
return Text(
label,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
),
);
}
Widget _buildEmailField() {
return Container(
decoration: BoxDecoration(
color: AppColors.surface,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: AppColors.shadow,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: TextField(
onChanged: (value) => controller.email.value = value,
keyboardType: TextInputType.emailAddress,
style: TextStyle(fontSize: 16, color: AppColors.textPrimary),
decoration: InputDecoration(
hintText: 'Masukkan email anda',
hintStyle: TextStyle(color: AppColors.textLight),
prefixIcon: Icon(Icons.email_outlined, color: AppColors.primary),
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 16),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(color: AppColors.primary, width: 1.5),
),
),
),
);
}
Widget _buildPasswordField() {
return Obx(
() => Container(
decoration: BoxDecoration(
color: AppColors.surface,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: AppColors.shadow,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: TextField(
onChanged: (value) => controller.password.value = value,
obscureText: !controller.isPasswordVisible.value,
style: TextStyle(fontSize: 16, color: AppColors.textPrimary),
decoration: InputDecoration(
hintText: 'Masukkan password anda',
hintStyle: TextStyle(color: AppColors.textLight),
prefixIcon: Icon(Icons.lock_outlined, color: AppColors.primary),
suffixIcon: IconButton(
icon: Icon(
controller.isPasswordVisible.value
? Icons.visibility
: Icons.visibility_off,
color: AppColors.iconGrey,
),
onPressed: controller.togglePasswordVisibility,
),
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(vertical: 16),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide(color: AppColors.primary, width: 1.5),
),
),
),
),
);
}
Widget _buildConfirmPasswordField() {
return Obx(
() => TextFormField(
controller: controller.confirmPasswordController,
obscureText: !controller.isConfirmPasswordVisible.value,
decoration: InputDecoration(
hintText: 'Masukkan ulang password anda',
suffixIcon: IconButton(
icon: Icon(
controller.isConfirmPasswordVisible.value
? Icons.visibility
: Icons.visibility_off,
),
onPressed: controller.toggleConfirmPasswordVisibility,
),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Konfirmasi password tidak boleh kosong';
}
if (value != controller.passwordController.text) {
return 'Password tidak cocok';
}
return null;
},
),
);
}
Widget _buildNameField() {
return TextFormField(
controller: controller.nameController,
decoration: InputDecoration(
hintText: 'Masukkan nama lengkap anda',
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nama lengkap tidak boleh kosong';
}
return null;
},
);
}
Widget _buildPhoneField() {
return TextFormField(
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: 'Masukkan nomor HP anda',
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
),
onChanged: (value) => controller.phoneNumber.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'No HP tidak boleh kosong';
}
if (!value.startsWith('08') || value.length < 10) {
return 'Nomor HP tidak valid (harus diawali 08 dan minimal 10 digit)';
}
return null;
},
);
}
Widget _buildAlamatField() {
return TextFormField(
decoration: InputDecoration(
hintText: 'Masukkan alamat lengkap anda',
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 14,
),
),
onChanged: (value) => controller.alamatLengkap.value = value,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Alamat lengkap tidak boleh kosong';
}
return null;
},
);
}
Widget _buildRegisterButton() {
return Obx(
() => ElevatedButton(
onPressed: controller.isLoading.value ? null : controller.registerUser,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primary,
foregroundColor: AppColors.buttonText,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 0,
disabledBackgroundColor: AppColors.primary.withOpacity(0.6),
),
child:
controller.isLoading.value
? const SizedBox(
height: 24,
width: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Text(
'Daftar',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
);
}
Widget _buildLoginLink() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Sudah punya akun? ',
style: TextStyle(color: AppColors.textSecondary, fontSize: 14),
),
GestureDetector(
onTap: () {
Get.back(); // Back to login page
},
child: Text(
'Masuk',
style: TextStyle(
color: AppColors.primary,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
),
],
);
}
}