QueenFruits/Mobile Operasional/lib/features/auth/presentation/screens/registration_screen.dart

418 lines
15 KiB
Dart

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<RegistrationScreen> createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends ConsumerState<RegistrationScreen> {
final _formKey = GlobalKey<FormState>();
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<void> _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<void> _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<void> _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,
),
),
],
),
),
),
),
),
);
},
);
}
}