This commit is contained in:
efrilm
2025-10-24 01:16:50 +07:00
parent 5d9197c986
commit ca5d2a58e7
45 changed files with 3820 additions and 50 deletions
@@ -0,0 +1,106 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../application/auth/bloc/login_form_bloc.dart';
import '../../../../common/constant/app_constant.dart';
import '../../../../common/theme/theme.dart';
import '../../../../injection.dart';
import '../../../components/assets/assets.gen.dart';
import '../../../components/button/button.dart';
import '../../../components/spaces/space.dart';
import '../../../components/toast/flushbar.dart';
import 'widgets/email_field.dart';
import 'widgets/password_field.dart';
@RoutePage()
class LoginPage extends StatelessWidget implements AutoRouteWrapper {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return BlocListener<LoginFormBloc, LoginFormState>(
listenWhen: (previous, current) =>
previous.failureOrLoginOption != current.failureOrLoginOption,
listener: (context, state) {
state.failureOrLoginOption.fold(
() => null,
(either) => either.fold(
(f) => AppFlushbar.showAuthFailureToast(context, f),
(data) {
if (context.mounted) {
AppFlushbar.showSuccess(
context,
'Login berhasil! Selamat datang, ${data.user.name}.',
);
// context.read<AuthBloc>().add(AuthEvent.fetchCurrentUser());
// context.router.replace(const MainRoute());
}
},
),
);
},
child: Scaffold(
body: BlocBuilder<LoginFormBloc, LoginFormState>(
builder: (context, state) {
return Form(
autovalidateMode: state.showErrorMessages
? AutovalidateMode.always
: AutovalidateMode.disabled,
child: ListView(
padding: const EdgeInsets.symmetric(
horizontal: 260.0,
vertical: 20.0,
),
children: [
const SpaceHeight(60.0),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 130.0),
child: Assets.images.logo.image(width: 100, height: 100),
),
const SpaceHeight(16.0),
Center(
child: Text(
AppConstant.appName,
style: AppStyle.lg.copyWith(fontWeight: FontWeight.w700),
),
),
const SpaceHeight(8.0),
Center(
child: Text(
'Akses Login Kasir Resto',
style: AppStyle.sm.copyWith(
color: AppColor.textSecondary,
),
),
),
const SpaceHeight(20.0),
LoginEmailField(),
const SpaceHeight(12.0),
LoginPasswordField(),
const SpaceHeight(24.0),
AppElevatedButton.filled(
onPressed: state.isSubmitting
? null
: () => context.read<LoginFormBloc>().add(
LoginFormEvent.submitted(),
),
textColor: state.isSubmitting
? AppColor.primary
: Colors.white,
label: 'Masuk',
isLoading: state.isSubmitting,
),
],
),
);
},
),
),
);
}
@override
Widget wrappedRoute(BuildContext context) =>
BlocProvider(create: (context) => getIt<LoginFormBloc>(), child: this);
}
@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../application/auth/bloc/login_form_bloc.dart';
import '../../../../../common/validator/validator.dart';
import '../../../../components/field/field.dart';
class LoginEmailField extends StatelessWidget {
const LoginEmailField({super.key});
@override
Widget build(BuildContext context) {
return AppTextFormField(
label: 'Email',
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
validator: (value) =>
AppValidator.validateEmail(context.read<LoginFormBloc>().state.email),
onChanged: (value) =>
context.read<LoginFormBloc>().add(LoginFormEvent.emailChanged(value)),
);
}
}
@@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../../application/auth/bloc/login_form_bloc.dart';
import '../../../../../common/validator/validator.dart';
import '../../../../components/field/field.dart';
class LoginPasswordField extends StatelessWidget {
const LoginPasswordField({super.key});
@override
Widget build(BuildContext context) {
return AppPasswordTextFormField(
label: 'Password',
keyboardType: TextInputType.visiblePassword,
textInputAction: TextInputAction.done,
validator: (value) => AppValidator.validatePassword(
context.read<LoginFormBloc>().state.password,
),
onChanged: (value) => context.read<LoginFormBloc>().add(
LoginFormEvent.passwordChanged(value),
),
);
}
}
+25 -1
View File
@@ -1,6 +1,9 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import '../../components/assets/assets.gen.dart';
import '../../router/app_router.gr.dart';
@RoutePage()
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@@ -10,8 +13,29 @@ class SplashPage extends StatefulWidget {
}
class _SplashPageState extends State<SplashPage> {
_startDelay() => Future.delayed(const Duration(seconds: 2), _goNext);
_goNext() => context.router.replace(const LoginRoute());
@override
void initState() {
_startDelay();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text("Splash Page")));
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(20),
child: Assets.images.logo.image(
width: 100,
height: 100,
fit: BoxFit.contain,
),
),
),
);
}
}