TKK_E32230211/lib/app/modules/register/controllers/register_controller.dart

188 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../../../routes/app_pages.dart';
import '../../../widgets/numpad_nominal_widget.dart';
import '../../../widgets/numpad_pin_widget.dart';
import '../../../widgets/target_celengan_picker.dart';
class RegisterController extends GetxController {
final namaController = TextEditingController();
final emailController = TextEditingController();
final passwordController = TextEditingController();
final targetCelenganController = TextEditingController();
final nominalTargetController = TextEditingController();
final pinController = TextEditingController();
final confirmPinController = TextEditingController();
final isPinVisible = false.obs;
final isConfirmPinVisible = false.obs;
final isLoading = false.obs;
String _activeField = '';
final _auth = FirebaseAuth.instance;
final _firestore = FirebaseFirestore.instance;
@override
void onClose() {
namaController.dispose();
emailController.dispose();
passwordController.dispose();
targetCelenganController.dispose();
nominalTargetController.dispose();
pinController.dispose();
confirmPinController.dispose();
super.onClose();
}
void togglePinVisibility() => isPinVisible.value = !isPinVisible.value;
void toggleConfirmPinVisibility() =>
isConfirmPinVisible.value = !isConfirmPinVisible.value;
void showTargetPicker(BuildContext context) {
TargetCelenganPicker.show(
context,
selected: targetCelenganController.text.isEmpty
? null
: targetCelenganController.text,
onSelected: (label) => targetCelenganController.text = label,
);
}
void showNumpad(BuildContext context, String field) {
_activeField = field;
final activeCtrl = _getController(field);
final isPinField = field == 'pin' || field == 'confirmPin';
if (isPinField) {
NumpadPinInputWidget.show(
context,
controller: activeCtrl,
onKey: _onNumpadKey,
onSimpan: () => Get.back(),
title: field == 'pin' ? 'Masukkan PIN' : 'Ulangi PIN',
);
} else {
NumpadNominalWidget.show(
context,
controller: activeCtrl,
onKey: _onNumpadKey,
onSimpan: () => Get.back(),
);
}
}
TextEditingController _getController(String field) {
if (field == 'pin') return pinController;
if (field == 'confirmPin') return confirmPinController;
return nominalTargetController;
}
void _onNumpadKey(String key) {
final ctrl = _getController(_activeField);
final isPinField = _activeField == 'pin' || _activeField == 'confirmPin';
if (key == 'del') {
if (ctrl.text.isNotEmpty)
ctrl.text = ctrl.text.substring(0, ctrl.text.length - 1);
} else {
if (isPinField && ctrl.text.length >= 6) return;
ctrl.text += key;
}
}
/// Parse nominal dari string seperti "Rp 2.500.000" → 2500000
int _parseNominal(String raw) {
final cleaned = raw.replaceAll(RegExp(r'[^0-9]'), '');
return int.tryParse(cleaned) ?? 0;
}
Future<void> simpan() async {
if (namaController.text.isEmpty ||
emailController.text.isEmpty ||
passwordController.text.isEmpty ||
targetCelenganController.text.isEmpty ||
nominalTargetController.text.isEmpty ||
pinController.text.isEmpty ||
confirmPinController.text.isEmpty) {
Get.snackbar(
'Perhatian',
'Semua field harus diisi!',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.shade100,
);
return;
}
if (pinController.text != confirmPinController.text) {
Get.snackbar(
'Perhatian',
'PIN tidak cocok!',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.shade100,
);
return;
}
try {
isLoading.value = true;
// 1. Buat akun di Firebase Auth
final credential = await _auth.createUserWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
final uid = credential.user!.uid;
final now = FieldValue.serverTimestamp();
// 2. Simpan ke collection 'users'
await _firestore.collection('users').doc(uid).set({
'email': emailController.text.trim(),
'password': 'hashed_password', // Hanya placeholder, auth sudah handle
'createdAt': now,
});
// 3. Simpan ke collection 'profil'
await _firestore.collection('profil').doc(uid).set({
'userId': uid,
'nama': namaController.text.trim(),
'target': targetCelenganController.text.trim(),
'targetNominal': _parseNominal(nominalTargetController.text),
'pin': pinController.text,
'totalSaldo': 0,
'createdAt': now,
});
Get.snackbar(
'Berhasil',
'Akun berhasil dibuat!',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.shade100,
);
Get.offAllNamed(Routes.LOGIN);
} on FirebaseAuthException catch (e) {
String message = 'Registrasi gagal.';
if (e.code == 'email-already-in-use') {
message = 'Email sudah digunakan.';
} else if (e.code == 'weak-password') {
message = 'Password terlalu lemah (min. 6 karakter).';
} else if (e.code == 'invalid-email') {
message = 'Format email tidak valid.';
}
Get.snackbar(
'Registrasi Gagal',
message,
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.shade100,
);
} finally {
isLoading.value = false;
}
}
}