import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:niogu_app/core/constants/app_asset.dart'; import 'package:niogu_app/core/constants/app_color.dart'; import 'package:niogu_app/core/constants/app_font_size.dart'; import 'package:niogu_app/core/errors/exceptions.dart'; import 'package:niogu_app/core/providers/app_provider.dart'; import 'package:niogu_app/core/router/app_route.dart'; import 'package:niogu_app/core/utils/log_message.dart'; import 'package:niogu_app/core/system/system_setting.dart'; import 'package:niogu_app/core/widgets/custom_snackbar.dart'; import 'package:niogu_app/core/widgets/custom_text_form_field.dart'; import 'package:niogu_app/features/auth/domain/entities/user.dart'; import 'package:niogu_app/features/auth/presentation/providers/auth_provider.dart'; import 'package:sizer/sizer.dart'; class RegistrationScreen extends ConsumerStatefulWidget { const RegistrationScreen({super.key}); @override ConsumerState createState() => _RegistrationScreenState(); } class _RegistrationScreenState extends ConsumerState { final _formKey = GlobalKey(); final _businessNameController = TextEditingController(); final _nameController = TextEditingController(); final _phoneNumberController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _passwordConfirmController = TextEditingController(); bool _obscurePassword = true; bool _obscurePasswordConfirm = true; @override void initState() { // TODO: implement initState super.initState(); } @override void dispose() { // TODO: implement dispose _businessNameController.dispose(); _nameController.dispose(); _phoneNumberController.dispose(); _emailController.dispose(); _passwordController.dispose(); _passwordConfirmController.dispose(); super.dispose(); } String? _validation({ String? value, String? message, bool isEmail = false, bool isPassword = false, bool isPasswordConfirm = false, }) { if (value == null || value.isEmpty) { return message; } final _emailRegex = RegExp( r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', ); if (isEmail && !_emailRegex.hasMatch(value)) { return "Email tidak valid"; } if (isPassword) { if (value.length < 8) { return "Password minimal harus 8 karakter"; } final passwordRegExp = RegExp( r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&#])[A-Za-z\d@$!%*?&#]{8,}$', ); if (!passwordRegExp.hasMatch(value)) { return "Gunakan huruf besar, kecil, angka, dan simbol"; } } if (isPasswordConfirm && value != _passwordController.text.trim()) { return "Konfirmasi password tidak sesuai"; } return null; } Future _setCurrentOutlet() async { final currentOutletId = await SystemSetting.getCurrentOutletId(); final currentOutletName = await SystemSetting.getCurrentOutletName(); ref.read(currentOutletIdProvider.notifier).state = currentOutletId; ref.read(currentOutletNameProvider.notifier).state = currentOutletName; } Future _setCurrentUser() async { final currentUserId = await SystemSetting.getCurrentUserId(); final currentUserName = await SystemSetting.getCurrentUserName(); final currentUserEmail = await SystemSetting.getCurrentUserEmail(); final currentUserRole = await SystemSetting.getCurrentUserRole(); final outletIdByOwner = await SystemSetting.getOutletIdByOwner(); ref.read(currentUserIdProvider.notifier).state = currentUserId; ref.read(currentUserNameProvider.notifier).state = currentUserName; ref.read(currentUserEmailProvider.notifier).state = currentUserEmail; ref.read(currentUserRoleProvider.notifier).state = currentUserRole; ref.read(outletIdByOwnerProvider.notifier).state = outletIdByOwner; ref.read(currentStatusLoginProvider.notifier).state = true; } Future _register() async { if (!_formKey.currentState!.validate()) return; try { await ref .read(authControllerProvider.notifier) .register( RegisterUser( businessName: _businessNameController.text.trim(), ownerName: _nameController.text.trim(), phoneNumber: _phoneNumberController.text.trim(), email: _emailController.text.trim(), password: _passwordController.text.trim(), passwordConfirmation: _passwordConfirmController.text.trim(), ), ); await ref .read(authControllerProvider.notifier) .login( LoginUser( identifier: _phoneNumberController.text.trim(), password: _passwordController.text.trim(), ), ); if (!mounted) return; await _setCurrentOutlet(); await _setCurrentUser(); CustomSnackbar.showSuccess(context, "Berhasil login"); context.goNamed(AppRoute.homeScreen); } on ServerException catch (e) { if (!mounted) ; CustomSnackbar.showError(context, e.message); } catch (e, st) { LogMessage.log.e(e.toString(), error: e, stackTrace: st); CustomSnackbar.showError(context, "Ups, terjadi kesalahan"); } } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final bool isTablet = 100.w >= 600; final authControllerState = ref.watch(authControllerProvider); final isLoading = authControllerState.isLoading; return SafeArea( top: false, bottom: true, right: false, left: false, child: Scaffold( backgroundColor: Colors.white, body: SafeArea( child: SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 5.h), child: Form( key: _formKey, child: Column( children: [ Image.asset(AppAsset.LOGO_UPDATE, height: 12.h), SizedBox(height: 2.5.h), Text( "Daftar Akun", style: TextStyle( fontSize: AppFontSize.large.sp, fontWeight: FontWeight.bold, color: AppColor.primaryColor, ), ), SizedBox(height: 1.h), Text( "Setiap hal besar selalu dimulai dengan hal kecil. perkuat pondasi bisnimu dan gunakan strategi terbaik", textAlign: TextAlign.center, style: TextStyle( fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, color: Colors.grey, ), ), SizedBox(height: 4.h), CustomTextFormField( label: "Nama Usaha/Perusahaan", hint: "Contoh: Ayam Gepok Pojok", controller: _businessNameController, prefixIcon: Icons.business_center_outlined, validator: (value) => _validation( value: value, message: "Nama usaha belum diisi", ), readOnly: isLoading, ), SizedBox(height: 2.5.h), CustomTextFormField( label: "Nama Pemilik", hint: "John Doe", controller: _nameController, prefixIcon: Icons.person_outline, validator: (value) => _validation( value: value, message: "Nama pemilik belum diisi", ), readOnly: isLoading, ), SizedBox(height: 2.5.h), CustomTextFormField( label: "No. Whatsapp", hint: "Contoh:081234xxxxxx", keyboardType: TextInputType.phone, controller: _phoneNumberController, prefixIcon: Icons.phone_outlined, validator: (value) => _validation( value: value, message: "No. Whatsapp belum diisi", ), readOnly: isLoading, ), SizedBox(height: 2.5.h), CustomTextFormField( label: "Email", hint: "Opsional (Disarankan)", keyboardType: TextInputType.emailAddress, controller: _emailController, prefixIcon: Icons.mail_outline_outlined, validator: (value) => _validation(value: value, isEmail: true), readOnly: isLoading, ), SizedBox(height: 2.5.h), CustomTextFormField( label: "Password", hint: "••••••••", controller: _passwordController, prefixIcon: Icons.lock_outline, isObscure: _obscurePassword, suffixIcon: _obscurePassword ? Icons.visibility_off : Icons.visibility, suffixPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, validator: (value) => _validation( value: value, message: "Password belum diisi", isPassword: true, ), readOnly: isLoading, ), SizedBox(height: 2.5.h), CustomTextFormField( label: "Konfirmasi Password", hint: "••••••••", controller: _passwordConfirmController, prefixIcon: Icons.lock_outline, isObscure: _obscurePasswordConfirm, suffixIcon: _obscurePasswordConfirm ? Icons.visibility_off : Icons.visibility, suffixPressed: () { setState(() { _obscurePasswordConfirm = !_obscurePasswordConfirm; }); }, validator: (value) => _validation( value: value, message: "Konfirmasi password belum diisi", isPasswordConfirm: true, ), readOnly: isLoading, ), SizedBox(height: 2.5.h), ElevatedButton( onPressed: isLoading ? null : _register, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, minimumSize: Size(double.infinity, 7.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(3.w), ), elevation: 2, disabledBackgroundColor: Colors.grey.shade300, ), child: Text( "Daftar Sekarang", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: AppFontSize.medium.sp, ), ), ), SizedBox(height: 4.h), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Sudah punya akun? ", style: TextStyle( fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, ), ), GestureDetector( onTap: () => context.canPop() ? context.pop() : context.goNamed(AppRoute.ownerLoginScreen), child: Text( "Masuk", style: TextStyle( color: AppColor.primaryColor, fontWeight: FontWeight.bold, fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, ), ), ), ], ), SizedBox(height: 2.5.h), Text( "Powered By P.T. Niaga Nusantara", style: TextStyle( color: Colors.grey.shade600, fontWeight: FontWeight.w500, fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, ), ), SizedBox(height: 0.75.h), Text( "Versi 1.0.0", style: TextStyle( color: Colors.grey, fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp, ), ), ], ), ), ), ), ), ); }, ); } }