import 'package:flutter/material.dart'; import 'package:mileograph_flutter/services/apiService.dart'; import 'package:mileograph_flutter/services/authservice.dart'; import 'package:mileograph_flutter/services/dataService.dart'; import 'package:provider/provider.dart'; import 'components/login/login.dart'; import 'components/pages/dashboard.dart'; late ApiService api; void main() { runApp( MultiProvider( providers: [ Provider( create: (_) { api = ApiService(baseUrl: 'https://dev.mileograph.co.uk/api/v1'); return api; }, ), ChangeNotifierProxyProvider( create: (context) => AuthService(api: context.read()), update: (_, api, previous) { return previous ?? AuthService(api: api); }, ), ProxyProvider( update: (_, auth, __) { api.setTokenProvider(() => auth.token); }, ), ChangeNotifierProxyProvider( create: (context) => DataService(api: context.read()), update: (_, api, previous) => previous ?? DataService(api: api), ), ], child: MyApp(), ), ); } class AppRoot extends StatelessWidget { const AppRoot({super.key}); @override Widget build(BuildContext context) { return Consumer( builder: (context, auth, child) { return auth.isLoggedIn ? MyHomePage() : LoginScreen(); }, ); } } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( useMaterial3: true, // This is the theme of your application. // // TRY THIS: Try running your application with "flutter run". You'll see // the application has a purple toolbar. Then, without quitting the app, // try changing the seedColor in the colorScheme below to Colors.green // and then invoke "hot reload" (save your changes or press the "hot // reload" button in a Flutter-supported IDE, or press "r" if you used // the command line to start the app). //fullPage // Notice that the counter didn't reset back to zero; the application // state is not lost during the reload. To reset the state, use hot // restart instead. // // This works for code too, not just values: Most code changes can be // tested with just a hot reload. colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey), ), darkTheme: ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: Colors.blueGrey, brightness: Brightness.dark, ), ), themeMode: ThemeMode.system, home: AppRoot(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); // This widget is the home page of your application. It is stateful, meaning // that it has a State object (defined below) that contains fields that affect // how it looks. // This class is the configuration for the state. It holds the values (in this // case the title) provided by the parent (in this case the App widget) and // used by the build method of the State. Fields in a Widget subclass are // always marked "final". @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { int pageIndex = 0; final List contentPages = [ Dashboard(), Center(child: Text("Calculator Page")), Center(child: Text("Entries Page")), Center(child: Text("Traction Page")), Center(child: Text("Trips Page")), ]; bool loggedIn = false; bool _fetched = false; @override void didChangeDependencies() { super.didChangeDependencies(); if (!_fetched) { _fetched = true; WidgetsBinding.instance.addPostFrameCallback((_) { final data = context.read(); final auth = context.read(); api.setTokenProvider(() => auth.token); if (data.homepageStats == null) { data.fetchHomepageStats(); } }); } } @override Widget build(BuildContext context) { Widget currentPage; final data = context.watch(); final auth = context.read(); if (data.homepageStats != null) { currentPage = contentPages[pageIndex]; } else { currentPage = Center( child: FilledButton( onPressed: data.fetchHomepageStats, child: Text("Fetch"), ), ); } // This method is rerun every time setState is called, for instance as done // by the _incrementCounter method above. // // The Flutter framework has been optimized to make rerunning build methods // fast, so that you can just rebuild anything that needs updating rather // than having to individually change instances of widgets. return Scaffold( appBar: AppBar( // TRY THIS: Try changing the color here to a specific color (to // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar // change color while the other colors stay the same. backgroundColor: Theme.of(context).colorScheme.inversePrimary, // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. title: Text.rich( TextSpan( children: [ TextSpan(text: "Mile"), TextSpan( text: "O", style: TextStyle(color: Colors.red), ), TextSpan(text: "graph"), ], style: TextStyle( decoration: TextDecoration.none, color: Colors.white, fontFamily: "Tomatoes", ), ), ), actions: [ IconButton(onPressed: null, icon: Icon(Icons.account_circle)), IconButton(onPressed: auth.logout, icon: Icon(Icons.logout)), ], ), bottomNavigationBar: NavigationBar( selectedIndex: pageIndex, onDestinationSelected: (int index) { setState(() { pageIndex = index; }); }, destinations: [ NavigationDestination(icon: Icon(Icons.home), label: "Home"), NavigationDestination(icon: Icon(Icons.route), label: "Calculator"), NavigationDestination(icon: Icon(Icons.list), label: "Entries"), NavigationDestination(icon: Icon(Icons.train), label: "Traction"), NavigationDestination(icon: Icon(Icons.book), label: "Trips"), ], ), body: currentPage, floatingActionButton: FloatingActionButton( onPressed: null, tooltip: 'New Entry', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }