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)
|
### 🛠 Installation
|
||||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter development, view the
|
```bash
|
||||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
git clone https://github.com/efrilm/frl-movie.git
|
||||||
samples, guidance on mobile development, and a full API reference.
|
```
|
||||||
|
|
||||||
|
```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
|
sort_unnamed_constructors_first: ignore
|
||||||
invalid_annotation_target: ignore
|
invalid_annotation_target: ignore
|
||||||
use_build_context_synchronously: ignore
|
use_build_context_synchronously: ignore
|
||||||
|
deprecated_member_use: ignore
|
||||||
exclude:
|
exclude:
|
||||||
- test/generated/**
|
- test/generated/**
|
||||||
- "**/**.g.dart"
|
- "**/**.g.dart"
|
||||||
|
|||||||
@ -1,5 +1,66 @@
|
|||||||
part of 'theme.dart';
|
part of 'theme.dart';
|
||||||
|
|
||||||
class AppColor {
|
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';
|
part of 'theme.dart';
|
||||||
|
|
||||||
class AppStyle {
|
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';
|
part of 'theme.dart';
|
||||||
|
|
||||||
class AppValue {
|
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:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../common/theme/theme.dart';
|
||||||
|
import '../components/assets/assets.gen.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class SplashPage extends StatefulWidget {
|
class SplashPage extends StatefulWidget {
|
||||||
const SplashPage({super.key});
|
const SplashPage({super.key});
|
||||||
@ -9,12 +12,160 @@ class SplashPage extends StatefulWidget {
|
|||||||
State<SplashPage> createState() => _SplashPageState();
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: AnimatedBuilder(
|
||||||
child: Text("Splash Page"),
|
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