326 lines
13 KiB
Dart
326 lines
13 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../../app/constant.dart';
|
|
import '../../app/route.dart';
|
|
import '../../models/auth_model.dart';
|
|
import '../../provider/current_user_provider.dart';
|
|
import '../../widget/sas_textfield.dart';
|
|
import 'login_provider.dart';
|
|
|
|
class LoginScreen extends HookConsumerWidget {
|
|
const LoginScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final isPasswordObscured = useState<bool>(true);
|
|
final ctrlUsername = useTextEditingController(text: "");
|
|
final ctrlPassword = useTextEditingController(text: "");
|
|
final focusNodeUsername = useFocusNode();
|
|
final focusNodePassword = useFocusNode();
|
|
|
|
final usernamehasFocus = useState(false);
|
|
final passwordhasFocus = useState(false);
|
|
|
|
final isRememberMe = useState(false);
|
|
final errorMessage = useState("");
|
|
final isLoading = useState(false);
|
|
final isSuccess = useState(false);
|
|
final isValidEntry = useState(false);
|
|
|
|
final usernameFromSharePref = useState("");
|
|
final passwordFromSharePref = useState("");
|
|
|
|
focusNodeUsername.addListener(() {
|
|
if (focusNodeUsername.hasFocus) {
|
|
usernamehasFocus.value = true;
|
|
passwordhasFocus.value = false;
|
|
} else {
|
|
usernamehasFocus.value = false;
|
|
}
|
|
});
|
|
|
|
focusNodePassword.addListener(() {
|
|
if (focusNodePassword.hasFocus) {
|
|
usernamehasFocus.value = false;
|
|
passwordhasFocus.value = true;
|
|
} else {
|
|
passwordhasFocus.value = false;
|
|
}
|
|
});
|
|
|
|
// aksi login
|
|
ref.listen(loginProvider, (prev, next) async {
|
|
if (next is LoginStateLoading) {
|
|
isLoading.value = true;
|
|
} else if (next is LoginStateError) {
|
|
isLoading.value = false;
|
|
errorMessage.value = next.message ?? "";
|
|
// print(errorMessage.value);
|
|
Timer(const Duration(seconds: 3), () {
|
|
errorMessage.value = "";
|
|
});
|
|
} else if (next is LoginStateDone) {
|
|
isLoading.value = false;
|
|
isSuccess.value = true;
|
|
Navigator.of(context)
|
|
.pushNamedAndRemoveUntil(menuRoute, (route) => false);
|
|
}
|
|
});
|
|
|
|
ctrlUsername.addListener(
|
|
() {
|
|
if (ctrlUsername.text.isEmpty || ctrlPassword.text.isEmpty) {
|
|
isValidEntry.value = false;
|
|
} else {
|
|
isValidEntry.value = true;
|
|
}
|
|
},
|
|
);
|
|
|
|
ctrlPassword.addListener(
|
|
() {
|
|
if (ctrlUsername.text.isEmpty || ctrlPassword.text.isEmpty) {
|
|
isValidEntry.value = false;
|
|
} else {
|
|
isValidEntry.value = true;
|
|
}
|
|
},
|
|
);
|
|
|
|
return GestureDetector(
|
|
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
|
child: Scaffold(
|
|
resizeToAvoidBottomInset: true,
|
|
backgroundColor: Constant.backgroundWhite,
|
|
body: SizedBox(
|
|
width: Constant.getActualX(context: context, x: 390),
|
|
height: Constant.getActualY(context: context, y: 844),
|
|
child: ListView(
|
|
children: [
|
|
// bg login
|
|
Padding(
|
|
padding: EdgeInsets.only(
|
|
top: Constant.getActualY(context: context, y: 80),
|
|
left: Constant.getActualX(context: context, x: 16),
|
|
right: Constant.getActualX(context: context, x: 16),
|
|
),
|
|
child: Image.asset(
|
|
"assets/bg_login.png",
|
|
// fit: BoxFit.fill,
|
|
// scale: 1,
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 10),
|
|
),
|
|
|
|
// Error From Backend Start
|
|
if (errorMessage.value != "")
|
|
Padding(
|
|
padding: EdgeInsets.only(
|
|
top: Constant.getActualY(context: context, y: 27),
|
|
left: Constant.getActualX(context: context, x: 38),
|
|
right: Constant.getActualX(context: context, x: 32),
|
|
),
|
|
child: Align(
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
"Peringatan : ${errorMessage.value}",
|
|
style: Constant.body1(context: context)
|
|
.copyWith(color: Constant.primaryRed),
|
|
),
|
|
),
|
|
),
|
|
// Error From Backend End
|
|
|
|
// loading
|
|
if (isLoading.value)
|
|
Padding(
|
|
padding: EdgeInsets.only(
|
|
top: Constant.getActualY(context: context, y: 10),
|
|
left: Constant.getActualX(context: context, x: 38),
|
|
right: Constant.getActualX(context: context, x: 32),
|
|
),
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: Constant.getActualX(context: context, x: 40),
|
|
height: Constant.getActualY(context: context, y: 40),
|
|
child: CircularProgressIndicator(
|
|
color: Constant.primaryBlue,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 10),
|
|
),
|
|
|
|
Padding(
|
|
padding: EdgeInsets.only(
|
|
top: Constant.getActualY(context: context, y: 27),
|
|
left: Constant.getActualX(context: context, x: 38),
|
|
right: Constant.getActualX(context: context, x: 32),
|
|
),
|
|
child: SizedBox(
|
|
width: Constant.getActualX(context: context, x: 320),
|
|
height: Constant.getActualY(context: context, y: 412),
|
|
// color: Colors.amber,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Login",
|
|
style: Constant.heading2(context: context).copyWith(
|
|
color: Constant.textPrimary,
|
|
fontWeight: FontWeight.w600),
|
|
),
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 20),
|
|
),
|
|
SasTextField(
|
|
hintText: "Username",
|
|
labelText: "Username",
|
|
controller: ctrlUsername,
|
|
focusNode: focusNodeUsername,
|
|
hasFocus: usernamehasFocus.value,
|
|
style: Constant.body1(context: context)
|
|
.copyWith(color: Constant.textBlack),
|
|
),
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 16),
|
|
),
|
|
SasTextFieldPassword(
|
|
hintText: "Password",
|
|
labelText: "Password",
|
|
controller: ctrlPassword,
|
|
focusNode: focusNodePassword,
|
|
hasFocus: passwordhasFocus.value,
|
|
onToggle: () {
|
|
isPasswordObscured.value = !isPasswordObscured.value;
|
|
},
|
|
obscureText:
|
|
(isPasswordObscured.value == true) ? true : false,
|
|
),
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 16),
|
|
),
|
|
SizedBox(
|
|
width: Constant.getActualX(context: context, x: 320),
|
|
height: Constant.getActualY(context: context, y: 20),
|
|
// color: Colors.green,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Checkbox(
|
|
value: isRememberMe.value,
|
|
onChanged: (value) {
|
|
if (value != null) {
|
|
isRememberMe.value = value;
|
|
// checkIsLogin(isRememberMe.value);
|
|
}
|
|
},
|
|
),
|
|
const SizedBox(width: 8.0),
|
|
Text(
|
|
"Ingat saya",
|
|
style:
|
|
Constant.caption1(context: context).copyWith(
|
|
color: Constant.textPrimary,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 32),
|
|
),
|
|
// button login
|
|
SizedBox(
|
|
width: Constant.getActualX(context: context, x: 320),
|
|
height: Constant.getActualY(context: context, y: 48),
|
|
child: ElevatedButton(
|
|
onPressed: (isLoading.value == true)
|
|
? null
|
|
: () {
|
|
if (ctrlUsername.text.isEmpty ||
|
|
ctrlPassword.text.isEmpty) {
|
|
isLoading.value = false;
|
|
errorMessage.value = 'Inputan harus diisi';
|
|
Timer(const Duration(seconds: 3), () {
|
|
isLoading.value = false;
|
|
errorMessage.value = "";
|
|
});
|
|
} else {
|
|
ref.read(loginProvider.notifier).login(
|
|
username: ctrlUsername.text,
|
|
password: ctrlPassword.text,
|
|
isRememberMe: isRememberMe.value,
|
|
);
|
|
}
|
|
},
|
|
style: ButtonStyle(
|
|
backgroundColor: MaterialStateColor.resolveWith(
|
|
(st) => Constant.primaryMain),
|
|
shape: MaterialStateProperty.all<
|
|
RoundedRectangleBorder>(
|
|
RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
// side: BorderSide(color: Colors.red),
|
|
),
|
|
),
|
|
shadowColor: MaterialStateProperty.all(
|
|
const Color(0xffff48423d)),
|
|
elevation: MaterialStateProperty.all(4.0),
|
|
),
|
|
child: Align(
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
'Login',
|
|
style: Constant.buttonLarge(context: context)
|
|
.copyWith(
|
|
color: Constant.backgroundWhite,
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: Constant.getActualY(context: context, y: 16),
|
|
),
|
|
// Center(
|
|
// child: InkWell(
|
|
// onTap: () {
|
|
// Navigator.of(context).pushNamedAndRemoveUntil(
|
|
// problemLoginRoute,
|
|
// (route) => true,
|
|
// );
|
|
// },
|
|
// child: Text(
|
|
// "Problem login",
|
|
// style: Constant.caption1(context: context).copyWith(
|
|
// color: Constant.errorDark,
|
|
// fontWeight: FontWeight.w400),
|
|
// ),
|
|
// ),
|
|
// ),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|