import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:toastification/toastification.dart'; import '../../app/route.dart'; import '../../app/constant.dart'; import '../../provider/current_user_provider.dart'; import 'login_provider.dart'; class LoginScreen extends HookConsumerWidget { const LoginScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [ SystemUiOverlay.bottom, ]); final usernameCtr = useTextEditingController( text: "", ); final passwordCtr = useTextEditingController( text: "", ); final hostCtr = useTextEditingController( text: "", ); final isLoading = useState(false); final isSuccess = useState(false); ToastificationItem? toastItem; void showLongToast( String title, String message, String typeToast, Duration waktu, ) { if (typeToast == "success") { toastItem = toastification.show( context: context, title: Text(title), description: Text(message), autoCloseDuration: waktu, type: ToastificationType.success, ); } else if (typeToast == "error") { toastItem = toastification.show( context: context, title: Text(title), description: Text(message), autoCloseDuration: waktu, type: ToastificationType.error, style: ToastificationStyle.fillColored, ); } } void hideToast() { if (toastItem != null) { toastification.dismissAll(); } } // proses login ref.listen(loginProvider, (prev, next) { if (next is LoginStateLoading) { isLoading.value = true; } else if (next is LoginStateError) { isLoading.value = false; // errorMessage.value = next.message; showLongToast( 'Error', next.message, 'error', Duration(seconds: 3), ); } else if (next is LoginStateDone) { hideToast(); isLoading.value = false; isSuccess.value = true; ref.read(currentUserProvider.notifier).state = next.model; Navigator.of(context) .pushNamedAndRemoveUntil(homeRoute, (route) => false); } }); void login() { if (usernameCtr.text.isEmpty || passwordCtr.text.isEmpty || hostCtr.text.isEmpty) { showLongToast( 'Error', 'Inputan wajib diisi', 'error', Duration(seconds: 3), ); } else { // print('proses login'); ref.read(loginProvider.notifier).login( username: usernameCtr.text, host: hostCtr.text, password: passwordCtr.text, ); } } return GestureDetector( onTap: () { FocusManager.instance.primaryFocus!.unfocus(); }, child: Scaffold( resizeToAvoidBottomInset: true, backgroundColor: Constant.textWhite, body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // atas Image.asset( 'images/vektoratas.png', width: double.infinity, fit: BoxFit.cover, ), SizedBox( height: Constant.getActualYPhone( context: context, y: 40, ), ), // konten didalamnya Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: Text( 'Selamat Datang', style: Constant.title_700(context: context).copyWith( color: Constant.textBlack, ), ), ), Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: Text( 'Silahkan masuk untuk mengakses akun Anda', style: Constant.title_400(context: context).copyWith( color: Constant.textBlack, ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 64, ), ), // inputan Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: Text( 'Username', style: Constant.title_400(context: context).copyWith( color: Constant.inputanGrey, ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 16, ), ), Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: TextField( controller: usernameCtr, decoration: InputDecoration( hintText: "Masukkan Username", enabledBorder: const OutlineInputBorder( borderSide: BorderSide( color: Colors.grey, width: 1, ), ), focusedBorder: const OutlineInputBorder( borderSide: BorderSide( color: Colors.blue, width: 2, ), ), ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 20, ), ), Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: Text( 'Password', style: Constant.title_400(context: context).copyWith( color: Constant.inputanGrey, ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 16, ), ), Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: TextField( controller: passwordCtr, obscureText: true, decoration: InputDecoration( hintText: "Masukkan Password", enabledBorder: const OutlineInputBorder( borderSide: BorderSide( color: Colors.grey, width: 1, ), ), focusedBorder: const OutlineInputBorder( borderSide: BorderSide( color: Colors.blue, width: 2, ), ), ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 20, ), ), Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: Text( 'Host', style: Constant.title_400(context: context).copyWith( color: Constant.inputanGrey, ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 16, ), ), Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: TextField( controller: hostCtr, decoration: InputDecoration( hintText: "Masukkan Host", enabledBorder: const OutlineInputBorder( borderSide: BorderSide( color: Colors.grey, width: 1, ), ), focusedBorder: const OutlineInputBorder( borderSide: BorderSide( color: Colors.blue, width: 2, ), ), ), ), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 64, ), ), // inputan // button login Padding( padding: EdgeInsets.only( left: Constant.getActualXPhone( context: context, x: 20, ), right: Constant.getActualXPhone( context: context, x: 20, ), ), child: SizedBox( width: double.infinity, height: Constant.getActualYPhone( context: context, y: 48, ), child: ElevatedButton( onPressed: () async { (isLoading.value || (isSuccess.value == true)) ? null : login(); }, style: ElevatedButton.styleFrom( backgroundColor: Constant.bgButton, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 8, shadowColor: Constant.bgButton.withOpacity(0.24), ), child: Text( (isLoading.value) ? 'Loading...' : 'LOGIN', style: Constant.titleButton500(context: context).copyWith( color: Constant.textWhite, ), ), ), ), ), // konten didalamnya SizedBox( height: Constant.getActualYPhone( context: context, y: 60, ), ), ], ), ), ), ); } }