Efril 7137cd2335
Some checks are pending
Build & Deploy iOS to TestFlight / build-and-deploy (push) Waiting to run
feat: update ui splash
2026-06-23 21:40:08 +07:00

199 lines
6.5 KiB
Dart

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../application/auth/auth_bloc.dart';
import '../../../common/theme/theme.dart';
import '../../components/assets/assets.gen.dart';
import '../../router/app_router.gr.dart';
@RoutePage()
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@override
State<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> with TickerProviderStateMixin {
late AnimationController _logoController;
late AnimationController _taglineController;
late AnimationController _poweredByController;
late Animation<double> _logoFadeAnimation;
late Animation<double> _logoScaleAnimation;
late Animation<double> _taglineFadeAnimation;
late Animation<Offset> _taglineSlideAnimation;
late Animation<double> _poweredByFadeAnimation;
@override
void initState() {
super.initState();
_logoController = AnimationController(
duration: const Duration(milliseconds: 1000),
vsync: this,
);
_taglineController = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
);
_poweredByController = AnimationController(
duration: const Duration(milliseconds: 600),
vsync: this,
);
_logoFadeAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(parent: _logoController, curve: Curves.easeOut));
_logoScaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
CurvedAnimation(parent: _logoController, curve: Curves.easeOutBack),
);
_taglineFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: _taglineController, curve: Curves.easeOut),
);
_taglineSlideAnimation =
Tween<Offset>(begin: const Offset(0, 0.3), end: Offset.zero).animate(
CurvedAnimation(parent: _taglineController, curve: Curves.easeOut),
);
_poweredByFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: _poweredByController, curve: Curves.easeIn),
);
_startAnimations();
}
void _startAnimations() async {
await Future.delayed(const Duration(milliseconds: 300));
if (mounted) _logoController.forward();
await Future.delayed(const Duration(milliseconds: 600));
if (mounted) _taglineController.forward();
await Future.delayed(const Duration(milliseconds: 400));
if (mounted) _poweredByController.forward();
await Future.delayed(const Duration(milliseconds: 1500));
if (mounted) {
context.read<AuthBloc>().add(const AuthEvent.fetchCurrentUser());
}
}
@override
void dispose() {
_logoController.dispose();
_taglineController.dispose();
_poweredByController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
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: Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFFE81E1E), Color(0xFFC40202)],
),
),
child: SafeArea(
child: Column(
children: [
// Main content - Logo & Tagline di tengah
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Logo
AnimatedBuilder(
animation: _logoController,
builder: (context, child) {
return Opacity(
opacity: _logoFadeAnimation.value.clamp(0.0, 1.0),
child: Transform.scale(
scale: _logoScaleAnimation.value,
child: child,
),
);
},
child: SizedBox(
width: 180,
child: Assets.images.logo.image(fit: BoxFit.contain),
),
),
const SizedBox(height: 32),
// Tagline
SlideTransition(
position: _taglineSlideAnimation,
child: FadeTransition(
opacity: _taglineFadeAnimation,
child: Text(
'Pantau kondisi bisnismu, dari genggaman',
style: AppStyle.lg.copyWith(
color: AppColor.white.withOpacity(0.9),
fontWeight: FontWeight.w400,
letterSpacing: 0.3,
),
textAlign: TextAlign.center,
),
),
),
],
),
),
// Powered by di bawah
FadeTransition(
opacity: _poweredByFadeAnimation,
child: Padding(
padding: const EdgeInsets.only(bottom: 24),
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: AppStyle.sm.copyWith(
color: AppColor.white.withOpacity(0.7),
),
children: [
const TextSpan(text: 'powered by '),
TextSpan(
text: 'PT Selalu Ada Keberuntungan',
style: AppStyle.sm.copyWith(
color: AppColor.white,
fontWeight: FontWeight.w700,
),
),
],
),
),
),
),
],
),
),
),
),
);
}
}