232 lines
7.7 KiB
Dart
232 lines
7.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:dynamic_color/dynamic_color.dart';
|
|
import 'package:mileograph_flutter/components/pages/calculator.dart';
|
|
import 'package:mileograph_flutter/components/pages/traction.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:mileograph_flutter/components/pages/legs.dart';
|
|
import 'package:mileograph_flutter/services/apiService.dart';
|
|
import 'package:mileograph_flutter/services/authservice.dart';
|
|
import 'package:mileograph_flutter/services/dataService.dart';
|
|
|
|
import 'components/login/login.dart';
|
|
import 'components/pages/dashboard.dart';
|
|
import 'components/dashboard/topTractionPanel.dart';
|
|
|
|
late ApiService api;
|
|
|
|
void main() {
|
|
runApp(
|
|
MultiProvider(
|
|
providers: [
|
|
Provider<ApiService>(
|
|
create: (_) {
|
|
api = ApiService(baseUrl: 'https://dev.mileograph.co.uk/api/v1');
|
|
return api;
|
|
},
|
|
),
|
|
ChangeNotifierProxyProvider<ApiService, AuthService>(
|
|
create: (context) => AuthService(api: context.read<ApiService>()),
|
|
update: (_, api, previous) {
|
|
return previous ?? AuthService(api: api);
|
|
},
|
|
),
|
|
ProxyProvider<AuthService, void>(
|
|
update: (_, auth, __) {
|
|
api.setTokenProvider(() => auth.token);
|
|
},
|
|
),
|
|
ChangeNotifierProxyProvider<ApiService, DataService>(
|
|
create: (context) => DataService(api: context.read<ApiService>()),
|
|
update: (_, api, previous) => previous ?? DataService(api: api),
|
|
),
|
|
],
|
|
child: MyApp(),
|
|
),
|
|
);
|
|
}
|
|
|
|
class AppRoot extends StatelessWidget {
|
|
const AppRoot({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Consumer<AuthService>(
|
|
builder: (context, auth, child) {
|
|
return auth.isLoggedIn ? MyHomePage() : LoginScreen();
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
MyApp({super.key});
|
|
|
|
final ColorScheme defaultLight = ColorScheme.fromSeed(seedColor: Colors.red);
|
|
final ColorScheme defaultDark = ColorScheme.fromSeed(
|
|
seedColor: Colors.red,
|
|
brightness: Brightness.dark,
|
|
);
|
|
// This widget is the root of your application.
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return DynamicColorBuilder(
|
|
builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
|
|
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: lightDynamic ?? defaultLight,
|
|
),
|
|
darkTheme: ThemeData(
|
|
useMaterial3: true,
|
|
colorScheme: darkDynamic ?? defaultDark,
|
|
),
|
|
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<MyHomePage> createState() => _MyHomePageState();
|
|
}
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
|
int pageIndex = 0;
|
|
final List<Widget> contentPages = [
|
|
Dashboard(),
|
|
CalculatorPage(),
|
|
LegsPage(),
|
|
TractionPage(),
|
|
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<DataService>();
|
|
final auth = context.read<AuthService>();
|
|
api.setTokenProvider(() => auth.token);
|
|
if (data.homepageStats == null) {
|
|
data.fetchHomepageStats();
|
|
}
|
|
if (data.legs.isEmpty) {
|
|
data.fetchLegs();
|
|
}
|
|
if (data.traction.isEmpty) {
|
|
data.fetchHadTraction();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Widget currentPage;
|
|
|
|
final data = context.watch<DataService>();
|
|
final auth = context.read<AuthService>();
|
|
|
|
if (data.homepageStats != null) {
|
|
currentPage = contentPages[pageIndex];
|
|
} else {
|
|
currentPage = Center(child: CircularProgressIndicator());
|
|
}
|
|
// 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.
|
|
);
|
|
}
|
|
}
|