199 lines
5.5 KiB
Dart
199 lines
5.5 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
|
||
|
|
class ValidatorProvider extends ChangeNotifier {
|
||
|
|
final Map<String, String?> _errors = {};
|
||
|
|
final Map<String, bool> _obscureFields = {};
|
||
|
|
final Map<String, FocusNode?> _focusNodes = {};
|
||
|
|
final Map<String, TextEditingController> _controllers = {};
|
||
|
|
String? _password;
|
||
|
|
|
||
|
|
bool validateAllFields() {
|
||
|
|
bool isValid = true;
|
||
|
|
|
||
|
|
// Validasi email
|
||
|
|
final emailError = emailValidator(_controllers['email']?.text);
|
||
|
|
_errors['email'] = emailError;
|
||
|
|
if (emailError != null) isValid = false;
|
||
|
|
|
||
|
|
// Validasi nama lengkap
|
||
|
|
final fullNameError = fullNameValidator(_controllers['fullname']?.text);
|
||
|
|
_errors['fullname'] = fullNameError;
|
||
|
|
if (fullNameError != null) isValid = false;
|
||
|
|
|
||
|
|
// Validasi password (jika ada)
|
||
|
|
if (_controllers.containsKey('password')) {
|
||
|
|
final passwordError = passwordValidator(_controllers['password']?.text);
|
||
|
|
_errors['password'] = passwordError;
|
||
|
|
if (passwordError != null) isValid = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validasi konfirmasi password (jika ada)
|
||
|
|
if (_controllers.containsKey('confirmPassword')) {
|
||
|
|
final confirmPasswordError =
|
||
|
|
confirmPasswordValidator(_controllers['confirmPassword']?.text);
|
||
|
|
_errors['confirmPassword'] = confirmPasswordError;
|
||
|
|
if (confirmPasswordError != null) isValid = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validasi NISN (jika ada)
|
||
|
|
if (_controllers.containsKey('nisn')) {
|
||
|
|
final nisnError = nisnValidator(_controllers['nisn']?.text);
|
||
|
|
_errors['nisn'] = nisnError;
|
||
|
|
if (nisnError != null) isValid = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
notifyListeners();
|
||
|
|
return isValid;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Mengambil error untuk field tertentu
|
||
|
|
String? getError(String field) => _errors[field];
|
||
|
|
|
||
|
|
// Memeriksa apakah field tertentu sedang disembunyikan (obscure)
|
||
|
|
bool isObscure(String field) => _obscureFields[field] ?? true;
|
||
|
|
|
||
|
|
// Mengambil FocusNode untuk field tertentu
|
||
|
|
FocusNode? getFocusNode(String field) => _focusNodes[field];
|
||
|
|
|
||
|
|
// Toggle visibility untuk field tertentu
|
||
|
|
void toggleVisibility(String field) {
|
||
|
|
_obscureFields[field] = !(isObscure(field));
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Mengatur FocusNode untuk field tertentu
|
||
|
|
void setFocusNode(String field, FocusNode focusNode) {
|
||
|
|
_focusNodes[field] = focusNode;
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validasi field tertentu dengan validator yang diberikan
|
||
|
|
void validateField(String field, String? value,
|
||
|
|
{String? Function(String?)? validator}) {
|
||
|
|
// Jika validator tidak null, gunakan untuk memvalidasi nilai field
|
||
|
|
final error = validator != null ? validator(value) : null;
|
||
|
|
_errors[field] = error;
|
||
|
|
|
||
|
|
// Simpan password jika field adalah 'password'
|
||
|
|
if (field == 'password') {
|
||
|
|
_password = value;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validasi confirm password jika field adalah 'confirmPassword'
|
||
|
|
if (field == 'confirmPassword') {
|
||
|
|
_errors[field] = confirmPasswordValidator(value);
|
||
|
|
}
|
||
|
|
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reset the fields and clear errors
|
||
|
|
void resetFields() {
|
||
|
|
_errors.clear();
|
||
|
|
_obscureFields.clear();
|
||
|
|
_password = null;
|
||
|
|
|
||
|
|
for (final controller in _controllers.values) {
|
||
|
|
controller.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set TextEditingController for a field
|
||
|
|
void setController(String field, TextEditingController controller) {
|
||
|
|
_controllers[field] = controller;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remove TextEditingController when not needed anymore
|
||
|
|
void removeController(String field) {
|
||
|
|
_controllers.remove(field);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void dispose() {
|
||
|
|
// Dispose controllers and focus nodes
|
||
|
|
for (final controller in _controllers.values) {
|
||
|
|
controller.dispose();
|
||
|
|
}
|
||
|
|
for (final focusNode in _focusNodes.values) {
|
||
|
|
focusNode?.dispose();
|
||
|
|
}
|
||
|
|
_controllers.clear();
|
||
|
|
_focusNodes.clear();
|
||
|
|
super.dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validator email
|
||
|
|
String? emailValidator(String? value) {
|
||
|
|
if (value == null || value.isEmpty) {
|
||
|
|
return 'Email cannot be empty';
|
||
|
|
}
|
||
|
|
const emailRegex = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$";
|
||
|
|
if (!RegExp(emailRegex).hasMatch(value)) {
|
||
|
|
return 'Invalid email format (e.g. example@gmail.com)';
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validator password
|
||
|
|
String? passwordValidator(String? value) {
|
||
|
|
if (value == null || value.isEmpty) {
|
||
|
|
return 'Password cannot be empty';
|
||
|
|
} else if (value.length < 8) {
|
||
|
|
return 'Password must be at least 8 characters long';
|
||
|
|
}
|
||
|
|
_password = value;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validator untuk konfirmasi password
|
||
|
|
String? confirmPasswordValidator(String? value) {
|
||
|
|
if (value == null || value.isEmpty) {
|
||
|
|
return 'Please confirm your password';
|
||
|
|
} else if (value != _password) {
|
||
|
|
return 'Passwords do not match';
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validator NISN
|
||
|
|
String? nisnValidator(String? value) {
|
||
|
|
if (value == null || value.isEmpty) {
|
||
|
|
return 'NISN cannot be empty';
|
||
|
|
} else if (value.length != 10 || !RegExp(r'^\d{10}$').hasMatch(value)) {
|
||
|
|
return 'NISN must be exactly 10 digits';
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validator nama lengkap
|
||
|
|
String? fullNameValidator(String? value) {
|
||
|
|
if (value == null || value.isEmpty) {
|
||
|
|
return 'Full name cannot be empty';
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Menghapus error dari field tertentu
|
||
|
|
void clearError(String field) {
|
||
|
|
_errors[field] = null;
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Menghapus semua error
|
||
|
|
void clearErrors() {
|
||
|
|
_errors.clear();
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Menghapus FocusNode saat tidak diperlukan lagi
|
||
|
|
void disposeFocusNodes() {
|
||
|
|
for (final focusNode in _focusNodes.values) {
|
||
|
|
focusNode?.dispose();
|
||
|
|
}
|
||
|
|
_focusNodes.clear();
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
}
|