253 lines
8.7 KiB
Dart
Executable File
253 lines
8.7 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'dart:async';
|
|
import 'dart:math';
|
|
|
|
import 'package:hive/hive.dart';
|
|
import 'package:hive_flutter/hive_flutter.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:cloud_firestore/cloud_firestore.dart'; // <-- Importação necessária
|
|
|
|
import 'firebase_options.dart';
|
|
|
|
import 'package:kzeduca_app/services/i18n_service.dart';
|
|
import 'package:kzeduca_app/services/firebase_service.dart';
|
|
import 'services/toast_service.dart';
|
|
import 'package:kzeduca_app/screens/auth_screen.dart';
|
|
import 'package:kzeduca_app/screens/dashboard_screen.dart';
|
|
import 'package:kzeduca_app/screens/add_transaction_screen.dart';
|
|
import 'package:kzeduca_app/screens/statistics_screen.dart';
|
|
import 'package:kzeduca_app/screens/budget_screen.dart';
|
|
import 'package:kzeduca_app/screens/create_budget_screen.dart';
|
|
import 'package:kzeduca_app/screens/savings_calculator_screen.dart';
|
|
import 'package:kzeduca_app/screens/settings_screen.dart';
|
|
import 'package:kzeduca_app/screens/financial_agent_screen.dart';
|
|
import 'package:kzeduca_app/services/user_state_service.dart';
|
|
import 'package:kzeduca_app/models/transaction.dart' as app;
|
|
import 'package:kzeduca_app/models/budget.dart';
|
|
import 'package:kzeduca_app/services/hive_service.dart';
|
|
import 'package:kzeduca_app/services/transaction_list_notifier.dart';
|
|
|
|
// Importação necessária para o GameStateProvider
|
|
import 'package:kzeduca_app/providers/game_state_provider.dart';
|
|
|
|
void main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
await Hive.initFlutter();
|
|
Hive.registerAdapter(app.TransactionTypeAdapter());
|
|
Hive.registerAdapter(app.TransactionCategoryAdapter());
|
|
Hive.registerAdapter(app.TransactionAdapter());
|
|
Hive.registerAdapter(BudgetPeriodAdapter());
|
|
Hive.registerAdapter(BudgetAdapter());
|
|
await Hive.openBox<app.Transaction>('transactions');
|
|
await Hive.openBox<Budget>('budgets');
|
|
|
|
await Firebase.initializeApp(
|
|
options: DefaultFirebaseOptions.currentPlatform,
|
|
);
|
|
|
|
// Ativa o cache offline do Firestore
|
|
FirebaseFirestore.instance.settings = const Settings(
|
|
persistenceEnabled: true,
|
|
);
|
|
|
|
runApp(
|
|
MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider(create: (_) => I18nService()),
|
|
ChangeNotifierProvider(create: (_) => UserStateService()),
|
|
ChangeNotifierProvider(create: (_) => TransactionListNotifier()),
|
|
ChangeNotifierProvider(create: (_) => GameStateProvider()), // <-- AGORA ADICIONADO!
|
|
Provider(
|
|
create: (context) => FirebaseService(
|
|
Provider.of<UserStateService>(context, listen: false),
|
|
),
|
|
),
|
|
Provider(create: (_) => HiveService()),
|
|
],
|
|
child: const KzEducaApp(),
|
|
),
|
|
);
|
|
}
|
|
|
|
class KzEducaApp extends StatefulWidget {
|
|
const KzEducaApp({super.key});
|
|
|
|
@override
|
|
State<KzEducaApp> createState() => _KzEducaAppState();
|
|
}
|
|
|
|
class _KzEducaAppState extends State<KzEducaApp> {
|
|
late final Future<void> _appInitializationFuture;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// Atraso a inicialização para garantir que o SplashScreen seja visível
|
|
_appInitializationFuture = _initializeApp();
|
|
}
|
|
|
|
Future<void> _initializeApp() async {
|
|
// Tarefas de inicialização do aplicativo
|
|
final initializationTasks = Future.microtask(() async {
|
|
final i18nService = Provider.of<I18nService>(context, listen: false);
|
|
await i18nService.setLocale(i18nService.locale);
|
|
await Provider.of<UserStateService>(context, listen: false).recalculateBalanceFromHive();
|
|
await Provider.of<TransactionListNotifier>(context, listen: false).loadTransactions();
|
|
});
|
|
|
|
// Atraso mínimo para garantir que o splash screen seja exibido
|
|
const minimumSplashDuration = Duration(seconds: 4);
|
|
final splashFuture = Future.delayed(minimumSplashDuration);
|
|
|
|
// Aguarda a conclusão de ambas as tarefas
|
|
await Future.wait([initializationTasks, splashFuture]);
|
|
}
|
|
|
|
void _changeCurrency(String newCurrencySymbol) {}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final i18n = Provider.of<I18nService>(context);
|
|
|
|
return MaterialApp(
|
|
debugShowCheckedModeBanner: false,
|
|
title: i18n.t('app_name'),
|
|
theme: ThemeData(
|
|
primarySwatch: Colors.blue,
|
|
fontFamily: 'Inter',
|
|
visualDensity: VisualDensity.adaptivePlatformDensity,
|
|
inputDecorationTheme: InputDecorationTheme(
|
|
filled: true,
|
|
fillColor: Colors.white.withOpacity(0.8),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
borderSide: const BorderSide(color: Colors.blueAccent, width: 2.0),
|
|
),
|
|
contentPadding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 20.0),
|
|
),
|
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
|
style: ElevatedButton.styleFrom(
|
|
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
|
|
elevation: 5,
|
|
shadowColor: Colors.black.withOpacity(0.2),
|
|
),
|
|
),
|
|
),
|
|
locale: i18n.locale,
|
|
localizationsDelegates: const [
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
],
|
|
supportedLocales: i18n.supportedLocales,
|
|
home: FutureBuilder(
|
|
future: _appInitializationFuture,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const SplashScreen();
|
|
}
|
|
|
|
if (snapshot.hasError) {
|
|
return Center(child: Text('Erro ao inicializar: ${snapshot.error}'));
|
|
}
|
|
|
|
return StreamBuilder<User?>(
|
|
stream: FirebaseAuth.instance.authStateChanges(),
|
|
builder: (context, authSnapshot) {
|
|
// A verificação de loading na tela de auth é desnecessária agora,
|
|
// já que o FutureBuilder do SplashScreen já tratou do estado de espera inicial.
|
|
if (authSnapshot.hasData) {
|
|
final userStateService = Provider.of<UserStateService>(context, listen: false);
|
|
userStateService.fetchUserData(authSnapshot.data!.uid);
|
|
|
|
return const DashboardScreen();
|
|
}
|
|
|
|
return const AuthScreen();
|
|
},
|
|
);
|
|
},
|
|
),
|
|
routes: {
|
|
'/add_transaction': (context) => const AddTransactionScreen(),
|
|
'/budget': (context) => const BudgetScreen(),
|
|
'/statistics': (context) => const StatisticsScreen(),
|
|
'/savings_calculator': (context) => const SavingsCalculatorScreen(),
|
|
'/create_budget': (context) => const CreateBudgetScreen(),
|
|
'/settings': (context) => SettingsScreen(
|
|
onLocaleChanged: (locale) {},
|
|
onCurrencyChanged: _changeCurrency,
|
|
),
|
|
'/financial_agent': (context) => const MainMenuScreen(),
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class SplashScreen extends StatefulWidget {
|
|
const SplashScreen({super.key});
|
|
|
|
@override
|
|
State<SplashScreen> createState() => _SplashScreenState();
|
|
}
|
|
|
|
class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
late Animation<double> _logoOpacity;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(seconds: 4),
|
|
)..forward();
|
|
|
|
_logoOpacity = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: const Interval(0.0, 0.6, curve: Curves.easeIn),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: const Color(0xFF1E1C3A),
|
|
body: Center(
|
|
child: FadeTransition(
|
|
opacity: _logoOpacity,
|
|
child: Image.asset(
|
|
'assets/images/kzeduca_logo.png', // Verifique se o caminho da imagem está correto
|
|
width: 200,
|
|
height: 200,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |