UI elements using the new structs #8
@@ -2,6 +2,7 @@ import 'package:fast_network_navigation/modules/trips_overview.dart';
 | 
				
			|||||||
import 'package:fast_network_navigation/pages/new_trip.dart';
 | 
					import 'package:fast_network_navigation/pages/new_trip.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/pages/tutorial.dart';
 | 
					import 'package:fast_network_navigation/pages/tutorial.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/structs/trip.dart';
 | 
					import 'package:fast_network_navigation/structs/trip.dart';
 | 
				
			||||||
 | 
					import 'package:fast_network_navigation/utils/load_trips.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:fast_network_navigation/pages/overview.dart';
 | 
					import 'package:fast_network_navigation/pages/overview.dart';
 | 
				
			||||||
@@ -11,10 +12,13 @@ import 'package:fast_network_navigation/pages/profile.dart';
 | 
				
			|||||||
// A side drawer is used to switch between pages
 | 
					// A side drawer is used to switch between pages
 | 
				
			||||||
class BasePage extends StatefulWidget {
 | 
					class BasePage extends StatefulWidget {
 | 
				
			||||||
  final String mainScreen;
 | 
					  final String mainScreen;
 | 
				
			||||||
  final String currentMap;
 | 
					  final Trip? trip;
 | 
				
			||||||
  final List<Trip> trips;
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  const BasePage({super.key, required this.mainScreen, this.currentMap = "map", this.trips = const []});
 | 
					  const BasePage({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.mainScreen,
 | 
				
			||||||
 | 
					    this.trip
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<BasePage> createState() => _BasePageState();
 | 
					  State<BasePage> createState() => _BasePageState();
 | 
				
			||||||
@@ -22,12 +26,15 @@ class BasePage extends StatefulWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class _BasePageState extends State<BasePage> {
 | 
					class _BasePageState extends State<BasePage> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    Widget currentView = const Text("loading...");
 | 
					    Widget currentView = const Text("loading...");
 | 
				
			||||||
 | 
					    Future<List<Trip>> trips = loadTrips();
 | 
				
			||||||
 | 
					    Future<Trip> firstTrip = getFirstTrip(trips);
 | 
				
			||||||
 | 
					    // Future<Trip> trip = Future(trips[0]);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    if (widget.mainScreen == "map") {
 | 
					    if (widget.mainScreen == "map") {
 | 
				
			||||||
      currentView = NavigationOverview();
 | 
					      currentView = NavigationOverview(trip: firstTrip);
 | 
				
			||||||
    } else if (widget.mainScreen == "tutorial") {
 | 
					    } else if (widget.mainScreen == "tutorial") {
 | 
				
			||||||
      currentView = TutorialPage();
 | 
					      currentView = TutorialPage();
 | 
				
			||||||
    } else if (widget.mainScreen == "profile") {
 | 
					    } else if (widget.mainScreen == "profile") {
 | 
				
			||||||
@@ -40,9 +47,6 @@ class _BasePageState extends State<BasePage> {
 | 
				
			|||||||
      appBar: AppBar(title: Text("City Nav")),
 | 
					      appBar: AppBar(title: Text("City Nav")),
 | 
				
			||||||
      body: Center(child: currentView),
 | 
					      body: Center(child: currentView),
 | 
				
			||||||
      drawer: Drawer(
 | 
					      drawer: Drawer(
 | 
				
			||||||
        // Add a ListView to the drawer. This ensures the user can scroll
 | 
					 | 
				
			||||||
        // through the options in the drawer if there isn't enough vertical
 | 
					 | 
				
			||||||
        // space to fit everything.
 | 
					 | 
				
			||||||
        child: Column(
 | 
					        child: Column(
 | 
				
			||||||
          children: [
 | 
					          children: [
 | 
				
			||||||
            DrawerHeader(
 | 
					            DrawerHeader(
 | 
				
			||||||
@@ -61,20 +65,10 @@ class _BasePageState extends State<BasePage> {
 | 
				
			|||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            ListTile(
 | 
					            ListTile(
 | 
				
			||||||
              title: const Text('Start'),
 | 
					              title: const Text('Your Trips'),
 | 
				
			||||||
              leading: const Icon(Icons.map),
 | 
					              leading: const Icon(Icons.map),
 | 
				
			||||||
              selected: widget.mainScreen == "map",
 | 
					              selected: widget.mainScreen == "map",
 | 
				
			||||||
              onTap: () {
 | 
					              onTap: () {},
 | 
				
			||||||
                Navigator.of(context).push(
 | 
					 | 
				
			||||||
                  MaterialPageRoute(
 | 
					 | 
				
			||||||
                    builder: (context) => BasePage(mainScreen: "map")
 | 
					 | 
				
			||||||
                  )
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            ListTile(
 | 
					 | 
				
			||||||
              title: const Text('Trip Overview'),
 | 
					 | 
				
			||||||
              leading: const Icon(Icons.list),
 | 
					 | 
				
			||||||
              trailing: ElevatedButton(
 | 
					              trailing: ElevatedButton(
 | 
				
			||||||
                onPressed: () {
 | 
					                onPressed: () {
 | 
				
			||||||
                  Navigator.of(context).push(
 | 
					                  Navigator.of(context).push(
 | 
				
			||||||
@@ -86,7 +80,23 @@ class _BasePageState extends State<BasePage> {
 | 
				
			|||||||
                child: const Text('New'),
 | 
					                child: const Text('New'),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            Expanded(child: TripsOverview()),
 | 
					
 | 
				
			||||||
 | 
					            // Adds a ListView to the drawer. This ensures the user can scroll
 | 
				
			||||||
 | 
					            // through the options in the drawer if there isn't enough vertical
 | 
				
			||||||
 | 
					            // space to fit everything.
 | 
				
			||||||
 | 
					            Expanded(
 | 
				
			||||||
 | 
					              child: TripsOverview(trips: trips),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            ElevatedButton(
 | 
				
			||||||
 | 
					              onPressed: () {
 | 
				
			||||||
 | 
					                Navigator.of(context).push(
 | 
				
			||||||
 | 
					                  MaterialPageRoute(
 | 
				
			||||||
 | 
					                    builder: (context) => const NewTripPage()
 | 
				
			||||||
 | 
					                  )
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              child: const Text('Clear trips'),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
            const Divider(),
 | 
					            const Divider(),
 | 
				
			||||||
            ListTile(
 | 
					            ListTile(
 | 
				
			||||||
              title: const Text('How to use'),
 | 
					              title: const Text('How to use'),
 | 
				
			||||||
@@ -101,6 +111,7 @@ class _BasePageState extends State<BasePage> {
 | 
				
			|||||||
              },
 | 
					              },
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // settings in the bottom of the drawer
 | 
				
			||||||
            ListTile(
 | 
					            ListTile(
 | 
				
			||||||
              title: const Text('Settings'),
 | 
					              title: const Text('Settings'),
 | 
				
			||||||
              leading: const Icon(Icons.settings),
 | 
					              leading: const Icon(Icons.settings),
 | 
				
			||||||
@@ -113,7 +124,6 @@ class _BasePageState extends State<BasePage> {
 | 
				
			|||||||
                );
 | 
					                );
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            // settings in the bottom of the drawer
 | 
					 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
@@ -121,3 +131,9 @@ class _BasePageState extends State<BasePage> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Future<Trip> getFirstTrip (Future<List<Trip>> trips) async {
 | 
				
			||||||
 | 
					  List<Trip> tripsf = await trips;
 | 
				
			||||||
 | 
					  return tripsf[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -17,4 +17,3 @@ class App extends StatelessWidget {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Widget Greeter (ThemeData theme, {bool full = false}) {
 | 
					Widget Greeter(ThemeData theme, {bool full = false}) {
 | 
				
			||||||
  String greeterText = "";
 | 
					  String greeterText = "";
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    String cityName = getCityName();
 | 
					    String cityName = getCityName();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,9 @@ class _LandmarkCardState extends State<LandmarkCard> {
 | 
				
			|||||||
              // force a fixed width
 | 
					              // force a fixed width
 | 
				
			||||||
              width: 160,
 | 
					              width: 160,
 | 
				
			||||||
              child: Image.network(
 | 
					              child: Image.network(
 | 
				
			||||||
                widget.landmark.imageURL,
 | 
					                widget.landmark.imageURL!,
 | 
				
			||||||
 | 
					                errorBuilder: (context, error, stackTrace) => Icon(Icons.question_mark_outlined),
 | 
				
			||||||
 | 
					                // TODO: make this a switch statement to load a placeholder if null
 | 
				
			||||||
                // cover the whole container meaning the image will be cropped
 | 
					                // cover the whole container meaning the image will be cropped
 | 
				
			||||||
                fit: BoxFit.cover,
 | 
					                fit: BoxFit.cover,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,29 +1,34 @@
 | 
				
			|||||||
 | 
					import 'dart:collection';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:fast_network_navigation/modules/landmark_card.dart';
 | 
					import 'package:fast_network_navigation/modules/landmark_card.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/structs/landmark.dart';
 | 
					import 'package:fast_network_navigation/structs/landmark.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/utils/get_landmarks.dart';
 | 
					
 | 
				
			||||||
 | 
					import 'package:fast_network_navigation/structs/trip.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class loadLandmarksOverview extends StatefulWidget {
 | 
					class LandmarksOverview extends StatefulWidget {
 | 
				
			||||||
  const loadLandmarksOverview({super.key});
 | 
					  final Future<Trip>? trip;
 | 
				
			||||||
 | 
					  const LandmarksOverview({super.key, this.trip});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<loadLandmarksOverview> createState() => _loadLandmarksOverviewState();
 | 
					  State<LandmarksOverview> createState() => _LandmarksOverviewState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _loadLandmarksOverviewState extends State<loadLandmarksOverview> {
 | 
					class _LandmarksOverviewState extends State<LandmarksOverview> {
 | 
				
			||||||
  final Future<List<Landmark>> _landmarks = fetchLandmarks();
 | 
					  // final Future<List<Landmark>> _landmarks = fetchLandmarks();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final Future<LinkedList<Landmark>> _landmarks = getLandmarks(widget.trip);
 | 
				
			||||||
    return DefaultTextStyle(
 | 
					    return DefaultTextStyle(
 | 
				
			||||||
      style: Theme.of(context).textTheme.displayMedium!,
 | 
					      style: Theme.of(context).textTheme.displayMedium!,
 | 
				
			||||||
      textAlign: TextAlign.center,
 | 
					      textAlign: TextAlign.center,
 | 
				
			||||||
      child: FutureBuilder<List<Landmark>>(
 | 
					      child: FutureBuilder<LinkedList<Landmark>>(
 | 
				
			||||||
        future: _landmarks,
 | 
					        future: _landmarks,
 | 
				
			||||||
        builder: (BuildContext context, AsyncSnapshot<List<Landmark>> snapshot) {
 | 
					        builder: (BuildContext context, AsyncSnapshot<LinkedList<Landmark>> snapshot) {
 | 
				
			||||||
          List<Widget> children;
 | 
					          List<Widget> children;
 | 
				
			||||||
          if (snapshot.hasData) {
 | 
					          if (snapshot.hasData) {
 | 
				
			||||||
            children = [landmarksWithSteps(snapshot.data!)];
 | 
					            children = [landmarksWithSteps(snapshot.data!)];
 | 
				
			||||||
@@ -42,13 +47,10 @@ class _loadLandmarksOverviewState extends State<loadLandmarksOverview> {
 | 
				
			|||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            children = [Center(child: CircularProgressIndicator())];
 | 
					            children = [Center(child: CircularProgressIndicator())];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          return Padding(
 | 
					          return Center(
 | 
				
			||||||
            padding: const EdgeInsets.all(10),
 | 
					            child: Column(
 | 
				
			||||||
            child: Center(
 | 
					              mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
              child: Column(
 | 
					              children: children,
 | 
				
			||||||
                mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
                children: children,
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@@ -57,12 +59,12 @@ class _loadLandmarksOverviewState extends State<loadLandmarksOverview> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Widget landmarksWithSteps(List<Landmark> landmarks) {
 | 
					Widget landmarksWithSteps(LinkedList<Landmark> landmarks) {
 | 
				
			||||||
  List<Widget> children = [];
 | 
					  List<Widget> children = [];
 | 
				
			||||||
  for (int i = 0; i < landmarks.length; i++) {
 | 
					  for (Landmark landmark in landmarks) {
 | 
				
			||||||
    children.add(LandmarkCard(landmarks[i]));
 | 
					    children.add(LandmarkCard(landmark));
 | 
				
			||||||
    if (i < landmarks.length - 1) {
 | 
					    if (landmark.next != null) {
 | 
				
			||||||
      Widget step = stepBetweenLandmarks(landmarks[i], landmarks[i + 1]);
 | 
					      Widget step = stepBetweenLandmarks(landmark, landmark.next!);
 | 
				
			||||||
      children.add(step);
 | 
					      children.add(step);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -109,4 +111,9 @@ Widget stepBetweenLandmarks(Landmark before, Landmark after) {
 | 
				
			|||||||
      ],
 | 
					      ],
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Future<LinkedList<Landmark>> getLandmarks (Future<Trip>? trip) async {
 | 
				
			||||||
 | 
					  Trip tripf = await trip!;
 | 
				
			||||||
 | 
					  return tripf.landmarks;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,18 @@
 | 
				
			|||||||
 | 
					import 'dart:collection';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:fast_network_navigation/structs/landmark.dart';
 | 
					import 'package:fast_network_navigation/structs/landmark.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/utils/get_landmarks.dart';
 | 
					import 'package:fast_network_navigation/structs/trip.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
 | 
					import 'package:google_maps_flutter/google_maps_flutter.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MapWidget extends StatefulWidget {
 | 
					class MapWidget extends StatefulWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Future<Trip>? trip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  MapWidget({
 | 
				
			||||||
 | 
					    this.trip
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<MapWidget> createState() => _MapWidgetState();
 | 
					  State<MapWidget> createState() => _MapWidgetState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -31,7 +40,8 @@ class _MapWidgetState extends State<MapWidget> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void drawLandmarks() async {
 | 
					  void drawLandmarks() async {
 | 
				
			||||||
    // (re)draws landmarks on the map
 | 
					    // (re)draws landmarks on the map
 | 
				
			||||||
    List<Landmark> landmarks = await fetchLandmarks();
 | 
					    Trip? trip = await widget.trip;
 | 
				
			||||||
 | 
					    LinkedList<Landmark> landmarks = trip!.landmarks;
 | 
				
			||||||
    setState(() {
 | 
					    setState(() {
 | 
				
			||||||
      for (Landmark landmark in landmarks) {
 | 
					      for (Landmark landmark in landmarks) {
 | 
				
			||||||
        markers.add(Marker(
 | 
					        markers.add(Marker(
 | 
				
			||||||
@@ -55,4 +65,3 @@ class _MapWidgetState extends State<MapWidget> {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,19 +2,21 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:fast_network_navigation/layout.dart';
 | 
					import 'package:fast_network_navigation/layout.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/structs/trip.dart';
 | 
					import 'package:fast_network_navigation/structs/trip.dart';
 | 
				
			||||||
import 'package:fast_network_navigation/utils/get_trips.dart';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TripsOverview extends StatefulWidget {
 | 
					class TripsOverview extends StatefulWidget {
 | 
				
			||||||
  
 | 
					  final Future<List<Trip>> trips;
 | 
				
			||||||
  const TripsOverview({super.key});
 | 
					  const TripsOverview({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.trips,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<TripsOverview> createState() => _TripsOverviewState();
 | 
					  State<TripsOverview> createState() => _TripsOverviewState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _TripsOverviewState extends State<TripsOverview> {
 | 
					class _TripsOverviewState extends State<TripsOverview> {
 | 
				
			||||||
  final Future<List<Trip>> _trips = loadTrips();
 | 
					  // final Future<List<Trip>> _trips = loadTrips();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Widget listBuild (BuildContext context, AsyncSnapshot<List<Trip>> snapshot) {
 | 
					  Widget listBuild (BuildContext context, AsyncSnapshot<List<Trip>> snapshot) {
 | 
				
			||||||
@@ -23,12 +25,12 @@ class _TripsOverviewState extends State<TripsOverview> {
 | 
				
			|||||||
      children = List<Widget>.generate(snapshot.data!.length, (index) {
 | 
					      children = List<Widget>.generate(snapshot.data!.length, (index) {
 | 
				
			||||||
        Trip trip = snapshot.data![index];
 | 
					        Trip trip = snapshot.data![index];
 | 
				
			||||||
        return ListTile(
 | 
					        return ListTile(
 | 
				
			||||||
          title: Text("Trip to ${trip.cityName} (${trip.landmarks.length} stops)"),
 | 
					          title: Text("Trip to ${trip.cityName}"),
 | 
				
			||||||
          leading: Icon(Icons.pin_drop),
 | 
					          leading: Icon(Icons.pin_drop),
 | 
				
			||||||
          onTap: () {
 | 
					          onTap: () {
 | 
				
			||||||
            Navigator.of(context).push(
 | 
					            Navigator.of(context).push(
 | 
				
			||||||
              MaterialPageRoute(
 | 
					              MaterialPageRoute(
 | 
				
			||||||
                builder: (context) => BasePage(mainScreen: "map") //, trip: trip)
 | 
					                builder: (context) => BasePage(mainScreen: "map", trip: trip)
 | 
				
			||||||
              )
 | 
					              )
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
@@ -58,7 +60,7 @@ class _TripsOverviewState extends State<TripsOverview> {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return FutureBuilder(
 | 
					    return FutureBuilder(
 | 
				
			||||||
      future: _trips,
 | 
					      future: widget.trips,
 | 
				
			||||||
      builder: listBuild,
 | 
					      builder: listBuild,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import 'package:fast_network_navigation/modules/greeter.dart';
 | 
					import 'package:fast_network_navigation/modules/greeter.dart';
 | 
				
			||||||
 | 
					import 'package:fast_network_navigation/structs/trip.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:sliding_up_panel/sliding_up_panel.dart';
 | 
					import 'package:sliding_up_panel/sliding_up_panel.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -8,6 +9,12 @@ import 'package:fast_network_navigation/modules/map.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NavigationOverview extends StatefulWidget {
 | 
					class NavigationOverview extends StatefulWidget {
 | 
				
			||||||
 | 
					  final Future<Trip> trip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  NavigationOverview({
 | 
				
			||||||
 | 
					    required this.trip
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<NavigationOverview> createState() => _NavigationOverviewState();
 | 
					  State<NavigationOverview> createState() => _NavigationOverviewState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -23,7 +30,7 @@ class _NavigationOverviewState extends State<NavigationOverview> {
 | 
				
			|||||||
        renderPanelSheet: false,
 | 
					        renderPanelSheet: false,
 | 
				
			||||||
        panel: _floatingPanel(theme),
 | 
					        panel: _floatingPanel(theme),
 | 
				
			||||||
        collapsed: _floatingCollapsed(theme),
 | 
					        collapsed: _floatingCollapsed(theme),
 | 
				
			||||||
        body: MapWidget()
 | 
					        body: MapWidget(trip: widget.trip)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,7 +65,7 @@ class _NavigationOverviewState extends State<NavigationOverview> {
 | 
				
			|||||||
          child: Column(
 | 
					          child: Column(
 | 
				
			||||||
            children: <Widget>[
 | 
					            children: <Widget>[
 | 
				
			||||||
              Greeter(theme, full: true),
 | 
					              Greeter(theme, full: true),
 | 
				
			||||||
              loadLandmarksOverview(),
 | 
					              LandmarksOverview(trip: widget.trip),
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,13 +51,7 @@ class ImportanceSliders extends StatefulWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class _ImportanceSlidersState extends State<ImportanceSliders> {
 | 
					class _ImportanceSlidersState extends State<ImportanceSliders> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final UserPreferences _prefs = UserPreferences();
 | 
					  UserPreferences _prefs = UserPreferences();
 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  void initState() {
 | 
					 | 
				
			||||||
    _prefs.load();
 | 
					 | 
				
			||||||
    super.initState();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  List<Card> _createSliders() {
 | 
					  List<Card> _createSliders() {
 | 
				
			||||||
    List<Card> sliders = [];
 | 
					    List<Card> sliders = [];
 | 
				
			||||||
@@ -89,6 +83,7 @@ class _ImportanceSlidersState extends State<ImportanceSliders> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Column(children: _createSliders());
 | 
					    return Column(children: _createSliders());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,56 +1,69 @@
 | 
				
			|||||||
class Landmark {
 | 
					import 'dart:collection';
 | 
				
			||||||
  final String name;
 | 
					import 'dart:convert';
 | 
				
			||||||
  final List location;
 | 
					 | 
				
			||||||
  final LandmarkType type;
 | 
					 | 
				
			||||||
  final String imageURL;
 | 
					 | 
				
			||||||
  // final String description;
 | 
					 | 
				
			||||||
  // final Duration duration;
 | 
					 | 
				
			||||||
  // final bool visited;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Landmark({
 | 
					import 'package:shared_preferences/shared_preferences.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final class Landmark extends LinkedListEntry<Landmark>{
 | 
				
			||||||
 | 
					  // A linked node of a list of Landmarks
 | 
				
			||||||
 | 
					  final String uuid;
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final List<double> location;
 | 
				
			||||||
 | 
					  final LandmarkType type;
 | 
				
			||||||
 | 
					  final bool? isSecondary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // description to be shown in the overview
 | 
				
			||||||
 | 
					  final String? imageURL;
 | 
				
			||||||
 | 
					  final String? description;
 | 
				
			||||||
 | 
					  final Duration? duration;
 | 
				
			||||||
 | 
					  final bool? visited;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Next node
 | 
				
			||||||
 | 
					  // final Landmark? next;
 | 
				
			||||||
 | 
					  final Duration? tripTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Landmark({
 | 
				
			||||||
 | 
					    required this.uuid,
 | 
				
			||||||
    required this.name,
 | 
					    required this.name,
 | 
				
			||||||
    required this.location,
 | 
					    required this.location,
 | 
				
			||||||
    required this.type,
 | 
					    required this.type,
 | 
				
			||||||
    this.imageURL = 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg',
 | 
					    this.isSecondary,
 | 
				
			||||||
    // required this.description,
 | 
					
 | 
				
			||||||
    // required this.duration,
 | 
					    this.imageURL,
 | 
				
			||||||
    // required this.visited,
 | 
					    this.description,
 | 
				
			||||||
 | 
					    this.duration,
 | 
				
			||||||
 | 
					    this.visited,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // this.next,
 | 
				
			||||||
 | 
					    this.tripTime,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  factory Landmark.fromJson(Map<String, dynamic> json) {
 | 
					  factory Landmark.fromJson(Map<String, dynamic> json) {
 | 
				
			||||||
    return switch (json) {
 | 
					    if (json
 | 
				
			||||||
      {
 | 
					      case { // automatically match all the non-optionals and cast them to the right type
 | 
				
			||||||
        'loc': List location,
 | 
					        'uuid': String uuid,
 | 
				
			||||||
        'name': String name,
 | 
					        'name': String name,
 | 
				
			||||||
        'type': String type,
 | 
					        'location': List<double> location,
 | 
				
			||||||
        // 'description': String description,
 | 
					        'type': LandmarkType type,
 | 
				
			||||||
        // 'duration': int duration,
 | 
					      }) {
 | 
				
			||||||
        // 'visited': bool visited
 | 
					        // parse the rest separately, they could be missing
 | 
				
			||||||
 | 
					        final isSecondary = json['is_secondary'] as bool?;
 | 
				
			||||||
      } =>
 | 
					        final imageURL = json['image_url'] as String?;
 | 
				
			||||||
        Landmark(
 | 
					        final description = json['description'] as String?;
 | 
				
			||||||
          name: name,
 | 
					        final duration = json['duration'] as Duration?;
 | 
				
			||||||
          location: location,
 | 
					        final visited = json['visited'] as bool?;
 | 
				
			||||||
          type: LandmarkType(name: type)
 | 
					        
 | 
				
			||||||
          // description: description,
 | 
					        return Landmark(
 | 
				
			||||||
          // duration: Duration(minutes: duration),
 | 
					          uuid: uuid, name: name, location: location, type: type, isSecondary: isSecondary, imageURL: imageURL, description: description, duration: duration, visited: visited);
 | 
				
			||||||
          // visited: visited
 | 
					    } else {
 | 
				
			||||||
        ),
 | 
					      throw FormatException('Invalid JSON: $json');
 | 
				
			||||||
      _ => throw const FormatException('Failed to load destination.'),
 | 
					    }
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Map<String, dynamic> toJson() {
 | 
					  @override
 | 
				
			||||||
      return {
 | 
					  bool operator ==(Object other) {
 | 
				
			||||||
        'name': name,
 | 
					    return other is Landmark && uuid == other.uuid;
 | 
				
			||||||
        'location': location,
 | 
					  }
 | 
				
			||||||
        'type': type.name,
 | 
					 | 
				
			||||||
        // 'description': description,
 | 
					 | 
				
			||||||
        // 'duration': duration.inMinutes,
 | 
					 | 
				
			||||||
        // 'visited': visited
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -67,3 +80,12 @@ class LandmarkType {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Helper
 | 
				
			||||||
 | 
					(Landmark, String?) getLandmarkFromPrefs(SharedPreferences prefs, String uuid) {
 | 
				
			||||||
 | 
					  String? content = prefs.getString('landmark_$uuid');
 | 
				
			||||||
 | 
					  Map<String, dynamic> json = jsonDecode(content!);
 | 
				
			||||||
 | 
					  String? nextUUID = json['next_uuid'];
 | 
				
			||||||
 | 
					  return (Landmark.fromJson(json), nextUUID);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										46
									
								
								frontend/lib/structs/linked_landmarks.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								frontend/lib/structs/linked_landmarks.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					// import "package:fast_network_navigation/structs/landmark.dart";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// class Linked<Landmark> {
 | 
				
			||||||
 | 
					//   Landmark? head;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					//   Linked();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   // class methods
 | 
				
			||||||
 | 
					//   bool get isEmpty => head == null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   // Add a new node to the end of the list
 | 
				
			||||||
 | 
					//   void add(Landmark value) {
 | 
				
			||||||
 | 
					//     if (isEmpty) {
 | 
				
			||||||
 | 
					//       // If the list is empty, set the new node as the head
 | 
				
			||||||
 | 
					//       head = value;
 | 
				
			||||||
 | 
					//     } else {
 | 
				
			||||||
 | 
					//       Landmark? current = head;
 | 
				
			||||||
 | 
					//       while (current!.next != null) {
 | 
				
			||||||
 | 
					//         // Traverse the list to find the last node
 | 
				
			||||||
 | 
					//         current = current.next;
 | 
				
			||||||
 | 
					//       }
 | 
				
			||||||
 | 
					//       current.next = value; // Set the new node as the next node of the last node
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   // Remove the first node with the given value
 | 
				
			||||||
 | 
					//   void remove(Landmark value) {
 | 
				
			||||||
 | 
					//     if (isEmpty) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     // If the value is in the head node, update the head to the next node
 | 
				
			||||||
 | 
					//     if (head! == value) {
 | 
				
			||||||
 | 
					//       head = head.next;
 | 
				
			||||||
 | 
					//       return;
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     var current = head;
 | 
				
			||||||
 | 
					//     while (current!.next != null) {
 | 
				
			||||||
 | 
					//       if (current.next! == value) {
 | 
				
			||||||
 | 
					//         // If the value is found in the next node, skip the next node
 | 
				
			||||||
 | 
					//         current.next = current.next.next;
 | 
				
			||||||
 | 
					//         return;
 | 
				
			||||||
 | 
					//       }
 | 
				
			||||||
 | 
					//       current = current.next;
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//   }
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
@@ -67,16 +67,16 @@ class UserPreferences {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void save() async {
 | 
					  void save() async {
 | 
				
			||||||
    SharedPreferences prefs = await SharedPreferences.getInstance();
 | 
					    SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
 | 
				
			||||||
    for (SinglePreference pref in preferences) {
 | 
					    for (SinglePreference pref in preferences) {
 | 
				
			||||||
      prefs.setInt(pref.key, pref.value);
 | 
					      sharedPrefs.setInt(pref.key, pref.value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void load() async {
 | 
					  void load() async {
 | 
				
			||||||
    SharedPreferences prefs = await SharedPreferences.getInstance();
 | 
					    SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
 | 
				
			||||||
    for (SinglePreference pref in preferences) {
 | 
					    for (SinglePreference pref in preferences) {
 | 
				
			||||||
      pref.value = prefs.getInt(pref.key) ?? 0;
 | 
					      pref.value = sharedPrefs.getInt(pref.key) ?? 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -5,7 +5,7 @@ class Route {
 | 
				
			|||||||
  final String name;
 | 
					  final String name;
 | 
				
			||||||
  final Duration duration;
 | 
					  final Duration duration;
 | 
				
			||||||
  final List<Landmark> landmarks;
 | 
					  final List<Landmark> landmarks;
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
  Route({
 | 
					  Route({
 | 
				
			||||||
    required this.name,
 | 
					    required this.name,
 | 
				
			||||||
    required this.duration,
 | 
					    required this.duration,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,25 +1,49 @@
 | 
				
			|||||||
// Represents a collection of landmarks that represent a journey
 | 
					// Represents a collection of landmarks that represent a journey
 | 
				
			||||||
// Different instances of a Trip can be saved and loaded by the user
 | 
					// Different instances of a Trip can be saved and loaded by the user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'dart:collection';
 | 
				
			||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:fast_network_navigation/structs/landmark.dart';
 | 
					import 'package:fast_network_navigation/structs/landmark.dart';
 | 
				
			||||||
 | 
					import 'package:shared_preferences/shared_preferences.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Trip {
 | 
					class Trip {
 | 
				
			||||||
  final String uuid;
 | 
					  final String uuid;
 | 
				
			||||||
  final String cityName;
 | 
					  final String cityName;
 | 
				
			||||||
  final List<Landmark> landmarks;
 | 
					  // TODO: cityName should be inferred from coordinates of the Landmarks
 | 
				
			||||||
 | 
					  final LinkedList<Landmark> landmarks;
 | 
				
			||||||
 | 
					  // could be empty as well
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Trip({
 | 
				
			||||||
  Trip({required this.uuid, required this.cityName, required this.landmarks});
 | 
					    required this.uuid,
 | 
				
			||||||
 | 
					    required this.cityName,
 | 
				
			||||||
 | 
					    required this.landmarks,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  factory Trip.fromJson(Map<String, dynamic> json) {
 | 
					  factory Trip.fromJson(Map<String, dynamic> json) {
 | 
				
			||||||
    List<Landmark> landmarks = [];
 | 
					 | 
				
			||||||
    for (var landmark in json['landmarks']) {
 | 
					 | 
				
			||||||
      landmarks.add(Landmark.fromJson(landmark));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Trip(
 | 
					    return Trip(
 | 
				
			||||||
      uuid: json['uuid'],
 | 
					      uuid: json['uuid'],
 | 
				
			||||||
      cityName: json['cityName'],
 | 
					      cityName: json['cityName'],
 | 
				
			||||||
      landmarks: landmarks,
 | 
					      landmarks: LinkedList()
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					
 | 
				
			||||||
 | 
					  factory Trip.fromPrefs(SharedPreferences prefs, String uuid) {
 | 
				
			||||||
 | 
					    String? content = prefs.getString('trip_$uuid');
 | 
				
			||||||
 | 
					    Map<String, dynamic> json = jsonDecode(content!);
 | 
				
			||||||
 | 
					    Trip trip = Trip.fromJson(json);
 | 
				
			||||||
 | 
					    String? firstUUID = json['entry_uuid'];
 | 
				
			||||||
 | 
					    appendLandmarks(trip.landmarks, prefs, firstUUID);
 | 
				
			||||||
 | 
					    return trip;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Helper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					appendLandmarks(LinkedList<Landmark> landmarks, SharedPreferences prefs, String? firstUUID) {
 | 
				
			||||||
 | 
					  while (firstUUID != null) {
 | 
				
			||||||
 | 
					    var (head, nextUUID) = getLandmarkFromPrefs(prefs, firstUUID);
 | 
				
			||||||
 | 
					    landmarks.add(head);
 | 
				
			||||||
 | 
					    firstUUID = nextUUID;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										52
									
								
								frontend/lib/utils/fetch_landmarks.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								frontend/lib/utils/fetch_landmarks.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					// import "package:fast_network_navigation/structs/landmark.dart";
 | 
				
			||||||
 | 
					// import 'package:http/http.dart' as http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Future<List<Landmark>> fetchLandmarks() async {
 | 
				
			||||||
 | 
					//   // final response = await http
 | 
				
			||||||
 | 
					//   //     .get(Uri.parse('https://nav.kluster.moll.re/v1/destination/1'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//   // if (response.statusCode == 200) {
 | 
				
			||||||
 | 
					//     // If the server did return a 200 OK response,
 | 
				
			||||||
 | 
					//     // then parse the JSON.
 | 
				
			||||||
 | 
					//     List<Landmark> landmarks = [
 | 
				
			||||||
 | 
					//       // 48°51′29.6″N 2°17′40.2″E
 | 
				
			||||||
 | 
					//       Landmark(
 | 
				
			||||||
 | 
					//         name: "Eiffel Tower",
 | 
				
			||||||
 | 
					//         location: [48.51296, 2.17402],
 | 
				
			||||||
 | 
					//         type: LandmarkType(name: "Tower"),
 | 
				
			||||||
 | 
					//         imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg"
 | 
				
			||||||
 | 
					//         ),
 | 
				
			||||||
 | 
					//       Landmark(
 | 
				
			||||||
 | 
					//         name: "Notre Dame Cathedral",
 | 
				
			||||||
 | 
					//         location: [48.8530, 2.3498],
 | 
				
			||||||
 | 
					//         type: LandmarkType(name: "Monument"),
 | 
				
			||||||
 | 
					//         imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Notre-Dame_de_Paris%2C_4_October_2017.jpg/440px-Notre-Dame_de_Paris%2C_4_October_2017.jpg"
 | 
				
			||||||
 | 
					//         ),
 | 
				
			||||||
 | 
					//       Landmark(
 | 
				
			||||||
 | 
					//         name: "Louvre palace",
 | 
				
			||||||
 | 
					//         location: [48.8606, 2.3376],
 | 
				
			||||||
 | 
					//         type: LandmarkType(name: "Museum"),
 | 
				
			||||||
 | 
					//         imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Louvre_Museum_Wikimedia_Commons.jpg/540px-Louvre_Museum_Wikimedia_Commons.jpg"
 | 
				
			||||||
 | 
					//         ),
 | 
				
			||||||
 | 
					//       Landmark(
 | 
				
			||||||
 | 
					//         name: "Pont-des-arts",
 | 
				
			||||||
 | 
					//         location: [48.5130, 2.2015],
 | 
				
			||||||
 | 
					//         type: LandmarkType(name: "Bridge"),
 | 
				
			||||||
 | 
					//         imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Pont_des_Arts%2C_6e_Arrondissement%2C_Paris_%28HDR%29_20140320_1.jpg/560px-Pont_des_Arts%2C_6e_Arrondissement%2C_Paris_%28HDR%29_20140320_1.jpg"),
 | 
				
			||||||
 | 
					//       Landmark(
 | 
				
			||||||
 | 
					//         name: "Panthéon",
 | 
				
			||||||
 | 
					//         location: [48.5046, 2.2046],
 | 
				
			||||||
 | 
					//         type: LandmarkType(name: "Monument"),
 | 
				
			||||||
 | 
					//         imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Pantheon_of_Paris_007.JPG/1280px-Pantheon_of_Paris_007.JPG"
 | 
				
			||||||
 | 
					//         ),
 | 
				
			||||||
 | 
					//     ];
 | 
				
			||||||
 | 
					//     // sleep 10 seconds
 | 
				
			||||||
 | 
					//     await Future.delayed(Duration(seconds: 5));
 | 
				
			||||||
 | 
					//     return landmarks;
 | 
				
			||||||
 | 
					//   // } else {
 | 
				
			||||||
 | 
					//   //   // If the server did not return a 200 OK response,
 | 
				
			||||||
 | 
					//   //   // then throw an exception.
 | 
				
			||||||
 | 
					//   //   throw Exception('Failed to load destination');
 | 
				
			||||||
 | 
					//   // }
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
@@ -1,52 +0,0 @@
 | 
				
			|||||||
import "package:fast_network_navigation/structs/landmark.dart";
 | 
					 | 
				
			||||||
import 'package:http/http.dart' as http;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Future<List<Landmark>> fetchLandmarks() async {
 | 
					 | 
				
			||||||
  // final response = await http
 | 
					 | 
				
			||||||
  //     .get(Uri.parse('https://nav.kluster.moll.re/v1/destination/1'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // if (response.statusCode == 200) {
 | 
					 | 
				
			||||||
    // If the server did return a 200 OK response,
 | 
					 | 
				
			||||||
    // then parse the JSON.
 | 
					 | 
				
			||||||
    List<Landmark> landmarks = [
 | 
					 | 
				
			||||||
      // 48°51′29.6″N 2°17′40.2″E
 | 
					 | 
				
			||||||
      Landmark(
 | 
					 | 
				
			||||||
        name: "Eiffel Tower",
 | 
					 | 
				
			||||||
        location: [48.51296, 2.17402],
 | 
					 | 
				
			||||||
        type: LandmarkType(name: "Tower"),
 | 
					 | 
				
			||||||
        imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg"
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      Landmark(
 | 
					 | 
				
			||||||
        name: "Notre Dame Cathedral",
 | 
					 | 
				
			||||||
        location: [48.8530, 2.3498],
 | 
					 | 
				
			||||||
        type: LandmarkType(name: "Monument"),
 | 
					 | 
				
			||||||
        imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Notre-Dame_de_Paris%2C_4_October_2017.jpg/440px-Notre-Dame_de_Paris%2C_4_October_2017.jpg"
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      Landmark(
 | 
					 | 
				
			||||||
        name: "Louvre palace",
 | 
					 | 
				
			||||||
        location: [48.8606, 2.3376],
 | 
					 | 
				
			||||||
        type: LandmarkType(name: "Museum"),
 | 
					 | 
				
			||||||
        imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Louvre_Museum_Wikimedia_Commons.jpg/540px-Louvre_Museum_Wikimedia_Commons.jpg"
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      Landmark(
 | 
					 | 
				
			||||||
        name: "Pont-des-arts",
 | 
					 | 
				
			||||||
        location: [48.5130, 2.2015],
 | 
					 | 
				
			||||||
        type: LandmarkType(name: "Bridge"),
 | 
					 | 
				
			||||||
        imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Pont_des_Arts%2C_6e_Arrondissement%2C_Paris_%28HDR%29_20140320_1.jpg/560px-Pont_des_Arts%2C_6e_Arrondissement%2C_Paris_%28HDR%29_20140320_1.jpg"),
 | 
					 | 
				
			||||||
      Landmark(
 | 
					 | 
				
			||||||
        name: "Panthéon",
 | 
					 | 
				
			||||||
        location: [48.5046, 2.2046],
 | 
					 | 
				
			||||||
        type: LandmarkType(name: "Monument"),
 | 
					 | 
				
			||||||
        imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Pantheon_of_Paris_007.JPG/1280px-Pantheon_of_Paris_007.JPG"
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    ];
 | 
					 | 
				
			||||||
    // sleep 10 seconds
 | 
					 | 
				
			||||||
    await Future.delayed(Duration(seconds: 5));
 | 
					 | 
				
			||||||
    return landmarks;
 | 
					 | 
				
			||||||
  // } else {
 | 
					 | 
				
			||||||
  //   // If the server did not return a 200 OK response,
 | 
					 | 
				
			||||||
  //   // then throw an exception.
 | 
					 | 
				
			||||||
  //   throw Exception('Failed to load destination');
 | 
					 | 
				
			||||||
  // }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,37 +0,0 @@
 | 
				
			|||||||
import 'dart:convert';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import 'package:fast_network_navigation/structs/trip.dart';
 | 
					 | 
				
			||||||
import 'package:fast_network_navigation/structs/landmark.dart';
 | 
					 | 
				
			||||||
import 'package:shared_preferences/shared_preferences.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Future<List<Trip>> loadTrips() async {
 | 
					 | 
				
			||||||
  SharedPreferences prefs = await SharedPreferences.getInstance();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Set<String> keys = prefs.getKeys();
 | 
					 | 
				
			||||||
  List<Trip> itineraries = [];
 | 
					 | 
				
			||||||
  for (String key in keys) {
 | 
					 | 
				
			||||||
    if (key.startsWith("itinerary_")) {
 | 
					 | 
				
			||||||
      String json = prefs.getString(key)!;
 | 
					 | 
				
			||||||
      itineraries.add(Trip.fromJson(jsonDecode(json)));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "1", cityName: "Paris", landmarks: [
 | 
					 | 
				
			||||||
      Landmark(name: "Landmark 1", location: [48.85, 2.35], type: LandmarkType(name: "Type 1")),
 | 
					 | 
				
			||||||
      Landmark(name: "Landmark 2", location: [48.86, 2.36], type: LandmarkType(name: "Type 2")),
 | 
					 | 
				
			||||||
      Landmark(name: "Landmark 3", location: [48.75, 2.3], type: LandmarkType(name: "Type 3")),
 | 
					 | 
				
			||||||
      Landmark(name: "Landmark 4", location: [48.9, 2.4], type: LandmarkType(name: "Type 4")),
 | 
					 | 
				
			||||||
      Landmark(name: "Landmark 5", location: [48.91, 2.45], type: LandmarkType(name: "Type 5")),
 | 
					 | 
				
			||||||
    ]));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "2", cityName: "Vienna", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "3", cityName: "London", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "4", cityName: "Madrid", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "5", cityName: "Tokyo", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "6", cityName: "New York", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "7", cityName: "Los Angeles", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "8", cityName: "Zurich", landmarks: []));
 | 
					 | 
				
			||||||
  itineraries.add(Trip(uuid: "9", cityName: "Orschwiller", landmarks: []));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  await Future.delayed(Duration(seconds: 3));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return itineraries;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										44
									
								
								frontend/lib/utils/load_trips.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								frontend/lib/utils/load_trips.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					import 'dart:collection';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:fast_network_navigation/structs/linked_landmarks.dart';
 | 
				
			||||||
 | 
					import 'package:fast_network_navigation/structs/trip.dart';
 | 
				
			||||||
 | 
					import 'package:fast_network_navigation/structs/landmark.dart';
 | 
				
			||||||
 | 
					import 'package:shared_preferences/shared_preferences.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Future<List<Trip>> loadTrips() async {
 | 
				
			||||||
 | 
					  SharedPreferences prefs = await SharedPreferences.getInstance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  List<Trip> trips = [];
 | 
				
			||||||
 | 
					  Set<String> keys = prefs.getKeys();
 | 
				
			||||||
 | 
					  for (String key in keys) {
 | 
				
			||||||
 | 
					    if (key.startsWith('trip_')) {
 | 
				
			||||||
 | 
					      String uuid = key.replaceFirst('trip_', '');
 | 
				
			||||||
 | 
					      trips.add(Trip.fromPrefs(prefs, uuid));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (trips.isEmpty) {
 | 
				
			||||||
 | 
					    String now = DateTime.now().toString();
 | 
				
			||||||
 | 
					    trips.add(
 | 
				
			||||||
 | 
					      Trip(uuid: '1', cityName: 'Paris (generated $now)', landmarks: LinkedList<Landmark>())
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    //   Trip(uuid: "1", cityName: "Paris", landmarks: [
 | 
				
			||||||
 | 
					    //     Landmark(name: "Landmark 1", location: [48.85, 2.35], type: LandmarkType(name: "Type 1")),
 | 
				
			||||||
 | 
					    //     Landmark(name: "Landmark 2", location: [48.86, 2.36], type: LandmarkType(name: "Type 2")),
 | 
				
			||||||
 | 
					    //     Landmark(name: "Landmark 3", location: [48.75, 2.3], type: LandmarkType(name: "Type 3")),
 | 
				
			||||||
 | 
					    //     Landmark(name: "Landmark 4", location: [48.9, 2.4], type: LandmarkType(name: "Type 4")),
 | 
				
			||||||
 | 
					    //     Landmark(name: "Landmark 5", location: [48.91, 2.45], type: LandmarkType(name: "Type 5")),
 | 
				
			||||||
 | 
					    //   ]));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "2", cityName: "Vienna", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "3", cityName: "London", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "4", cityName: "Madrid", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "5", cityName: "Tokyo", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "6", cityName: "New York", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "7", cityName: "Los Angeles", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "8", cityName: "Zurich", landmarks: []));
 | 
				
			||||||
 | 
					    // trips.add(Trip(uuid: "9", cityName: "Orschwiller", landmarks: []));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return trips;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user