feat: splash page
This commit is contained in:
parent
cb5250459e
commit
afc8476701
43
README.md
43
README.md
@ -1,16 +1,39 @@
|
||||
# apskel_owner_flutter
|
||||
# Apskel Owner App
|
||||
|
||||
A new Flutter project.
|
||||
A Flutter-based Point of Sale (POS) application designed specifically for business owners.
|
||||
Helps manage sales, products, inventory, and business reports in real-time with a simple, easy-to-use interface.
|
||||
|
||||
## Getting Started
|
||||
## 🚀 Getting Started
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
### ✅ Prerequisites
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
- [Flutter](https://flutter.dev/docs/get-started/install) 3.32.8 or newer
|
||||
- Dart 3.8.1 or newer
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
### 🛠 Installation
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
```bash
|
||||
git clone https://github.com/efrilm/frl-movie.git
|
||||
```
|
||||
|
||||
```bash
|
||||
cd app-path
|
||||
```
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
```bash
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Running
|
||||
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -13,6 +13,7 @@ analyzer:
|
||||
sort_unnamed_constructors_first: ignore
|
||||
invalid_annotation_target: ignore
|
||||
use_build_context_synchronously: ignore
|
||||
deprecated_member_use: ignore
|
||||
exclude:
|
||||
- test/generated/**
|
||||
- "**/**.g.dart"
|
||||
|
||||
@ -1,5 +1,66 @@
|
||||
part of 'theme.dart';
|
||||
|
||||
class AppColor {
|
||||
// TODO: define color
|
||||
// Primary Colors
|
||||
static const Color primary = Color(0xFF36175e);
|
||||
static const Color primaryLight = Color(0xFF5a2d85);
|
||||
static const Color primaryDark = Color(0xFF1e0d35);
|
||||
|
||||
// Secondary Colors
|
||||
static const Color secondary = Color(0xFF4CAF50);
|
||||
static const Color secondaryLight = Color(0xFF81C784);
|
||||
static const Color secondaryDark = Color(0xFF388E3C);
|
||||
|
||||
// Background Colors
|
||||
static const Color background = Color(0xFFF5F5F5);
|
||||
static const Color backgroundLight = Color(0xFFFFFFFF);
|
||||
static const Color backgroundDark = Color(0xFF1A1A1A);
|
||||
static const Color surface = Color(0xFFFFFFFF);
|
||||
static const Color surfaceDark = Color(0xFF2D2D2D);
|
||||
|
||||
// Text Colors
|
||||
static const Color textPrimary = Color(0xFF212121);
|
||||
static const Color textSecondary = Color(0xFF757575);
|
||||
static const Color textLight = Color(0xFFBDBDBD);
|
||||
static const Color textWhite = Color(0xFFFFFFFF);
|
||||
|
||||
// Status Colors
|
||||
static const Color success = Color(0xFF4CAF50);
|
||||
static const Color error = Color(0xFFE53E3E);
|
||||
static const Color warning = Color(0xFFFF9800);
|
||||
static const Color info = Color(0xFF2196F3);
|
||||
|
||||
// Border Colors
|
||||
static const Color border = Color(0xFFE0E0E0);
|
||||
static const Color borderLight = Color(0xFFF0F0F0);
|
||||
static const Color borderDark = Color(0xFFBDBDBD);
|
||||
|
||||
// Basic Color
|
||||
static const Color white = Color(0xFFFFFFFF);
|
||||
static const Color black = Color(0xFF000000);
|
||||
|
||||
// Gradient Colors
|
||||
static const List<Color> primaryGradient = [
|
||||
Color(0xFF36175e),
|
||||
Color(0xFF5a2d85),
|
||||
];
|
||||
|
||||
static const List<Color> successGradient = [
|
||||
Color(0xFF4CAF50),
|
||||
Color(0xFF81C784),
|
||||
];
|
||||
|
||||
static const List<Color> backgroundGradient = [
|
||||
Color(0xFFF5F5F5),
|
||||
Color(0xFFE8E8E8),
|
||||
];
|
||||
|
||||
// Opacity Variations
|
||||
static Color primaryWithOpacity(double opacity) =>
|
||||
primary.withOpacity(opacity);
|
||||
static Color successWithOpacity(double opacity) =>
|
||||
success.withOpacity(opacity);
|
||||
static Color errorWithOpacity(double opacity) => error.withOpacity(opacity);
|
||||
static Color warningWithOpacity(double opacity) =>
|
||||
warning.withOpacity(opacity);
|
||||
}
|
||||
|
||||
@ -1,5 +1,27 @@
|
||||
part of 'theme.dart';
|
||||
|
||||
class AppStyle {
|
||||
// TODO: define style
|
||||
static TextStyle xs = TextStyle(color: AppColor.textPrimary, fontSize: 11);
|
||||
|
||||
static TextStyle sm = TextStyle(color: AppColor.textPrimary, fontSize: 12);
|
||||
|
||||
static TextStyle md = TextStyle(color: AppColor.textPrimary, fontSize: 14);
|
||||
|
||||
static TextStyle lg = TextStyle(color: AppColor.textPrimary, fontSize: 18);
|
||||
|
||||
static TextStyle xl = TextStyle(color: AppColor.textPrimary, fontSize: 20);
|
||||
|
||||
static TextStyle xxl = TextStyle(color: AppColor.textPrimary, fontSize: 22);
|
||||
|
||||
static TextStyle h6 = TextStyle(color: AppColor.textPrimary, fontSize: 24);
|
||||
|
||||
static TextStyle h5 = TextStyle(color: AppColor.textPrimary, fontSize: 26);
|
||||
|
||||
static TextStyle h4 = TextStyle(color: AppColor.textPrimary, fontSize: 28);
|
||||
|
||||
static TextStyle h3 = TextStyle(color: AppColor.textPrimary, fontSize: 30);
|
||||
|
||||
static TextStyle h2 = TextStyle(color: AppColor.textPrimary, fontSize: 32);
|
||||
|
||||
static TextStyle h1 = TextStyle(color: AppColor.textPrimary, fontSize: 34);
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
part of 'theme.dart';
|
||||
|
||||
class AppValue {
|
||||
// TODO: define value
|
||||
static const double padding = 16.0;
|
||||
static const double radius = 8.0;
|
||||
static const double elevation = 4.0;
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../common/theme/theme.dart';
|
||||
import '../components/assets/assets.gen.dart';
|
||||
|
||||
@RoutePage()
|
||||
class SplashPage extends StatefulWidget {
|
||||
const SplashPage({super.key});
|
||||
@ -9,12 +12,160 @@ class SplashPage extends StatefulWidget {
|
||||
State<SplashPage> createState() => _SplashPageState();
|
||||
}
|
||||
|
||||
class _SplashPageState extends State<SplashPage> {
|
||||
class _SplashPageState extends State<SplashPage> with TickerProviderStateMixin {
|
||||
late AnimationController _logoController;
|
||||
late AnimationController _versionController;
|
||||
late AnimationController _backgroundController;
|
||||
|
||||
late Animation<double> _logoAnimation;
|
||||
late Animation<double> _versionAnimation;
|
||||
late Animation<double> _backgroundAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Initialize animation controllers
|
||||
_logoController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1200),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_versionController = AnimationController(
|
||||
duration: const Duration(milliseconds: 800),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_backgroundController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1500),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
// Create animations
|
||||
_logoAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _logoController, curve: Curves.elasticOut),
|
||||
);
|
||||
|
||||
_versionAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _versionController, curve: Curves.easeInOut),
|
||||
);
|
||||
|
||||
_backgroundAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _backgroundController, curve: Curves.easeInOut),
|
||||
);
|
||||
|
||||
// Start animations
|
||||
_startAnimations();
|
||||
}
|
||||
|
||||
void _startAnimations() async {
|
||||
// Start background animation immediately
|
||||
_backgroundController.forward();
|
||||
|
||||
// Wait a bit, then start logo animation
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
if (mounted) _logoController.forward();
|
||||
|
||||
// Start version animation after logo starts
|
||||
await Future.delayed(const Duration(milliseconds: 600));
|
||||
if (mounted) _versionController.forward();
|
||||
|
||||
// Navigate to home screen after all animations complete
|
||||
await Future.delayed(const Duration(milliseconds: 2000));
|
||||
if (mounted) {
|
||||
_navigateToHome();
|
||||
}
|
||||
}
|
||||
|
||||
void _navigateToHome() {
|
||||
// Uncomment dan sesuaikan dengan route yang ada
|
||||
// context.router.replace(const HomeRoute());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_logoController.dispose();
|
||||
_versionController.dispose();
|
||||
_backgroundController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Text("Splash Page"),
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
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(
|
||||
'Version 1.0.0',
|
||||
style: AppStyle.md.copyWith(color: AppColor.textLight),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user