kz_educa/lib/main.dart

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,
),
),
),
);
}
}