feat: auth

This commit is contained in:
efrilm
2025-08-16 17:48:49 +07:00
parent 255b10d5a9
commit edf067369d
9 changed files with 1006 additions and 79 deletions
+6 -2
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../application/auth/auth_bloc.dart';
import '../application/language/language_bloc.dart';
import '../common/theme/theme.dart';
import '../common/constant/app_constant.dart';
@@ -21,8 +22,11 @@ class _AppWidgetState extends State<AppWidget> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => getIt<LanguageBloc>(),
return MultiBlocProvider(
providers: [
BlocProvider(create: (context) => getIt<LanguageBloc>()),
BlocProvider(create: (context) => getIt<AuthBloc>()),
],
child: BlocBuilder<LanguageBloc, LanguageState>(
builder: (context, state) {
return MaterialApp.router(
+91 -77
View File
@@ -1,7 +1,9 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:package_info_plus/package_info_plus.dart';
import '../../../application/auth/auth_bloc.dart';
import '../../../common/extension/extension.dart';
import '../../../common/theme/theme.dart';
import '../../../injection.dart';
@@ -77,15 +79,10 @@ class _SplashPageState extends State<SplashPage> with TickerProviderStateMixin {
// Navigate to home screen after all animations complete
await Future.delayed(const Duration(milliseconds: 2000));
if (mounted) {
_navigateToHome();
context.read<AuthBloc>().add(const AuthEvent.fetchCurrentUser());
}
}
void _navigateToHome() {
// Uncomment dan sesuaikan dengan route yang ada
context.router.replace(const LoginRoute());
}
@override
void dispose() {
_logoController.dispose();
@@ -97,80 +94,97 @@ class _SplashPageState extends State<SplashPage> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
final packageInfo = getIt<PackageInfo>();
return Scaffold(
body: AnimatedBuilder(
animation: Listenable.merge([
_logoController,
_versionController,
_backgroundController,
]),
builder: (context, child) {
// Clamp values to prevent opacity errors
final logoOpacity = _logoAnimation.value.clamp(0.0, 1.0);
final versionOpacity = _versionAnimation.value.clamp(0.0, 1.0);
final backgroundOpacity = _backgroundAnimation.value.clamp(0.0, 1.0);
return BlocListener<AuthBloc, AuthState>(
listenWhen: (previous, current) => previous.status != current.status,
listener: (context, state) {
if (state.isAuthenticated) {
context.router.replace(const MainRoute());
} else {
context.router.replace(const LoginRoute());
}
},
child: Scaffold(
body: AnimatedBuilder(
animation: Listenable.merge([
_logoController,
_versionController,
_backgroundController,
]),
builder: (context, child) {
// Clamp values to prevent opacity errors
final logoOpacity = _logoAnimation.value.clamp(0.0, 1.0);
final versionOpacity = _versionAnimation.value.clamp(0.0, 1.0);
final backgroundOpacity = _backgroundAnimation.value.clamp(
0.0,
1.0,
);
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppColor.primaryWithOpacity(backgroundOpacity),
AppColor.primaryWithOpacity(backgroundOpacity * 0.8),
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppColor.primaryWithOpacity(backgroundOpacity),
AppColor.primaryWithOpacity(backgroundOpacity * 0.8),
],
),
),
child: Stack(
children: [
// Logo di tengah
Center(
child: Transform.scale(
scale: logoOpacity,
child: Opacity(
opacity: logoOpacity,
child: Container(
width: 150,
height: 150,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 30,
offset: const Offset(0, 15),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
AppValue.radius,
),
child: Assets.images.logo.image(fit: BoxFit.cover),
),
),
),
),
),
// Version di bagian bawah
Positioned(
bottom: 60,
left: 0,
right: 0,
child: Transform.translate(
offset: Offset(0, 20 * (1 - versionOpacity)),
child: Opacity(
opacity: versionOpacity,
child: Text(
'${context.lang.version} ${packageInfo.version}+${packageInfo.buildNumber}',
style: AppStyle.md.copyWith(
color: AppColor.textLight,
),
textAlign: TextAlign.center,
),
),
),
),
],
),
),
child: Stack(
children: [
// Logo di tengah
Center(
child: Transform.scale(
scale: logoOpacity,
child: Opacity(
opacity: logoOpacity,
child: Container(
width: 150,
height: 150,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 30,
offset: const Offset(0, 15),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(AppValue.radius),
child: Assets.images.logo.image(fit: BoxFit.cover),
),
),
),
),
),
// Version di bagian bawah
Positioned(
bottom: 60,
left: 0,
right: 0,
child: Transform.translate(
offset: Offset(0, 20 * (1 - versionOpacity)),
child: Opacity(
opacity: versionOpacity,
child: Text(
'${context.lang.version} ${packageInfo.version}+${packageInfo.buildNumber}',
style: AppStyle.md.copyWith(color: AppColor.textLight),
textAlign: TextAlign.center,
),
),
),
),
],
),
);
},
);
},
),
),
);
}