This commit is contained in:
40
frontend/lib/modules/destination_card.dart
Normal file
40
frontend/lib/modules/destination_card.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
||||
class DestinationCard extends StatefulWidget {
|
||||
final String title;
|
||||
final String description;
|
||||
final String image;
|
||||
bool visited;
|
||||
|
||||
@override
|
||||
_DestinationCardState createState() => _DestinationCardState();
|
||||
|
||||
|
||||
DestinationCard(this.title, this.description, this.image, this.visited);
|
||||
|
||||
Widget build() {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.location_on),
|
||||
title: Text(title),
|
||||
subtitle: Text(description),
|
||||
onTap: () {
|
||||
// Navigator.pushNamed(context, '/destination');
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class _DestinationCardState extends State<DestinationCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card();
|
||||
}
|
||||
|
||||
}
|
63
frontend/lib/modules/navigation.dart
Normal file
63
frontend/lib/modules/navigation.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
import 'package:fast_network_navigation/modules/destination_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
List<Widget> loadDestinations() {
|
||||
List<Widget> cities = [
|
||||
singleDestination(
|
||||
"New York",
|
||||
"The Big Apple",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/View_of_New_York_City.jpg/800px-View_of_New_York_City.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"Los Angeles",
|
||||
"City of Angels",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Los_Angeles_City_Hall_2013.jpg/800px-Los_Angeles_City_Hall_2013.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"Chicago",
|
||||
"The Windy City",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Chicago_skyline%2C_viewed_from_John_Hancock_Center.jpg/800px-Chicago_skyline%2C_viewed_from_John_Hancock_Center.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"San Francisco",
|
||||
"The Golden City",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/San_Francisco_City_Hall_2013.jpg/800px-San_Francisco_City_Hall_2013.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"Miami",
|
||||
"The Magic City",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Miami_collage.jpg/800px-Miami_collage.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"Las Vegas",
|
||||
"Sin City",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Las_Vegas_Strip.jpg/800px-Las_Vegas_Strip.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"Seattle",
|
||||
"Emerald City",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Seattle_Kerry_Park_Skyline.jpg/800px-Seattle_Kerry_Park_Skyline.jpg"
|
||||
),
|
||||
singleDestination(
|
||||
"Boston",
|
||||
"Beantown",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Boston_skyline_from_Longfellow_Bridge_September_2017_panorama_2.jpg/800px-Boston"
|
||||
)
|
||||
];
|
||||
cities.shuffle();
|
||||
return cities;
|
||||
}
|
||||
|
||||
Widget singleDestination(String title, String description, String image) {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.location_on),
|
||||
title: Text(title),
|
||||
subtitle: Text(description),
|
||||
onTap: () {
|
||||
// Navigator.pushNamed(context, '/destination');
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
153
frontend/lib/modules/overview.dart
Normal file
153
frontend/lib/modules/overview.dart
Normal file
@@ -0,0 +1,153 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:sliding_up_panel/sliding_up_panel.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geocode/geocode.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fast_network_navigation/modules/navigation.dart';
|
||||
|
||||
class MapPage extends StatefulWidget {
|
||||
@override
|
||||
_MapPageState createState() => _MapPageState();
|
||||
}
|
||||
class Debounce {
|
||||
Duration delay;
|
||||
Timer? _timer;
|
||||
|
||||
Debounce(
|
||||
this.delay,
|
||||
);
|
||||
|
||||
call(void Function() callback) {
|
||||
_timer?.cancel();
|
||||
_timer = Timer(delay, callback);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
_timer?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class _MapPageState extends State<MapPage> {
|
||||
GeoCode geoCode = GeoCode();
|
||||
final mapController = MapController();
|
||||
String _currentCityName = "...";
|
||||
final Debounce _debounce = Debounce(Duration(seconds: 3));
|
||||
|
||||
void _setCurrentCityName() async {
|
||||
if (mapController.camera.zoom < 9) {
|
||||
return; // Don't bother if the view is too wide
|
||||
}
|
||||
var currentCoordinates = mapController.camera.center;
|
||||
String? city;
|
||||
|
||||
try{
|
||||
List<Placemark> placemarks = await placemarkFromCoordinates(currentCoordinates.latitude, currentCoordinates.longitude);
|
||||
city = placemarks[0].locality.toString();
|
||||
} catch (e) {
|
||||
debugPrint("Error: $e");
|
||||
try {
|
||||
Address address = await geoCode.reverseGeocoding(latitude: currentCoordinates.latitude, longitude: currentCoordinates.longitude);
|
||||
|
||||
if (address.city == null || address.city.toString().contains("Throttled!")){
|
||||
throw Exception("Probably rate limited");
|
||||
}
|
||||
city = address.city.toString();
|
||||
} catch (e) {
|
||||
debugPrint("Error: $e");
|
||||
|
||||
}
|
||||
}
|
||||
if (city != null) {
|
||||
setState(() {
|
||||
_currentCityName = city!;
|
||||
});
|
||||
} else {
|
||||
_debounce(() async {_setCurrentCityName();});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return SlidingUpPanel(
|
||||
renderPanelSheet: false,
|
||||
panel: _floatingPanel(theme),
|
||||
collapsed: _floatingCollapsed(theme),
|
||||
body: FlutterMap(
|
||||
mapController: mapController,
|
||||
options: MapOptions(
|
||||
initialZoom: 11,
|
||||
initialCenter: LatLng(51.509364, -0.128928),
|
||||
onMapReady: () {
|
||||
mapController.mapEventStream.listen((evt) {_debounce(() async {_setCurrentCityName();});});
|
||||
// And any other `MapController` dependent non-movement methods
|
||||
},
|
||||
|
||||
),
|
||||
children: [
|
||||
openStreetMapTileLayer,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _floatingCollapsed(ThemeData theme){
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.canvasColor,
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(24.0), topRight: Radius.circular(24.0)),
|
||||
),
|
||||
|
||||
child: Greeting(theme)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _floatingPanel(ThemeData theme){
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(24.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 20.0,
|
||||
color: theme.shadowColor,
|
||||
),
|
||||
]
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Greeting(theme),
|
||||
Text("Got a lot to do today! Here is a rundown:"),
|
||||
...loadDestinations(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget Greeting (ThemeData theme) {
|
||||
return Center(
|
||||
child: Text(
|
||||
"Explore ${_currentCityName}",
|
||||
style: TextStyle(color: theme.primaryColor, fontSize: 24.0, fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TileLayer get openStreetMapTileLayer => TileLayer(
|
||||
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
userAgentPackageName: 'flutter_map',
|
||||
);
|
||||
|
||||
// Add a pin to the map
|
55
frontend/lib/modules/profile.dart
Normal file
55
frontend/lib/modules/profile.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
|
||||
class ProfilePage extends StatefulWidget {
|
||||
@override
|
||||
_ProfilePageState createState() => _ProfilePageState();
|
||||
}
|
||||
|
||||
class _ProfilePageState extends State<ProfilePage> {
|
||||
|
||||
double value = 0.0;
|
||||
void onChanged(double newValue) {
|
||||
setState(() {
|
||||
value = newValue;
|
||||
});
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Profile'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.notifications_sharp),
|
||||
title: Text('Notification 1'),
|
||||
subtitle: Text('This is a first notification'),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.notifications_sharp),
|
||||
title: Text('Notification 2'),
|
||||
subtitle: Text('This is a notification'),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.outdoor_grill),
|
||||
title: Text("Eating preference"),
|
||||
subtitle: Slider.adaptive(value: value, onChanged: onChanged, min: 0, max: 5, divisions: 5, label: value.toInt().toString(),)
|
||||
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
89
frontend/lib/modules/scaffold.dart
Normal file
89
frontend/lib/modules/scaffold.dart
Normal file
@@ -0,0 +1,89 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fast_network_navigation/modules/overview.dart';
|
||||
import 'package:fast_network_navigation/modules/profile.dart';
|
||||
|
||||
|
||||
class BasePage extends StatefulWidget {
|
||||
const BasePage({super.key, required this.title});
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<BasePage> createState() => _BasePageState();
|
||||
}
|
||||
|
||||
class _BasePageState extends State<BasePage> {
|
||||
int _selectedIndex = 0;
|
||||
|
||||
void _onItemTapped(int index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
}
|
||||
|
||||
Widget currentView = MapPage();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(widget.title)),
|
||||
body: Center(child: currentView),
|
||||
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: ListView(
|
||||
// Important: Remove any padding from the ListView.
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
DrawerHeader(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(colors: [Colors.cyan, theme.primaryColor])
|
||||
),
|
||||
child: const Text('The fanciest navigation!'),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Home'),
|
||||
selected: _selectedIndex == 0,
|
||||
onTap: () {
|
||||
// Update the state of the app
|
||||
_onItemTapped(0);
|
||||
// Then close the drawer
|
||||
currentView = MapPage();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Business'),
|
||||
selected: _selectedIndex == 1,
|
||||
onTap: () {
|
||||
// Update the state of the app
|
||||
_onItemTapped(1);
|
||||
currentView = const Text("ghfhggfhgf");
|
||||
|
||||
// Then close the drawer
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
// add a whitespace so that the settings are at the bottom
|
||||
|
||||
const Divider(),
|
||||
ListTile(
|
||||
title: const Text('Settings'),
|
||||
leading: const Icon(Icons.settings),
|
||||
selected: _selectedIndex == 2,
|
||||
onTap: () {
|
||||
_onItemTapped(2);
|
||||
currentView = ProfilePage();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
// settings in the bottom of the drawer
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user