From 016622c7af7e338d98af1dabf05236a536d8133d Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Thu, 1 Aug 2024 19:35:25 +0200 Subject: [PATCH] frontend compliant with backend --- frontend/lib/pages/profile.dart | 103 ++++++++++++-------- frontend/lib/structs/preferences.dart | 134 +++++++++++++++----------- frontend/lib/utils/fetch_trip.dart | 4 +- 3 files changed, 141 insertions(+), 100 deletions(-) diff --git a/frontend/lib/pages/profile.dart b/frontend/lib/pages/profile.dart index 4101895..9371e87 100644 --- a/frontend/lib/pages/profile.dart +++ b/frontend/lib/pages/profile.dart @@ -9,6 +9,9 @@ class ProfilePage extends StatefulWidget { } class _ProfilePageState extends State { + Future _prefs = loadUserPreferences(); + + @override Widget build(BuildContext context) { return ListView( @@ -24,66 +27,82 @@ class _ProfilePageState extends State { child: Text('Curious traveler', style: TextStyle(fontSize: 24)) ), - Padding(padding: EdgeInsets.all(10)), - Divider(indent: 25, endIndent: 25), - Padding(padding: EdgeInsets.all(10)), + Divider(indent: 25, endIndent: 25, height: 50), - Padding( - padding: EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 10), - child: Text('Please rate your personal preferences so that we can taylor your experience.', style: TextStyle(fontSize: 18)) + Center( + child: Padding( + padding: EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 10), + child: Text('For a tailored experience, please rate your discovery preferences.', style: TextStyle(fontSize: 18)) + ), ), - // Now the sliders - ImportanceSliders() + FutureBuilder(future: _prefs, builder: futureSliders) ] ); } + + Widget futureSliders(BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + UserPreferences prefs = snapshot.data!; + + return Column( + children: [ + PreferenceSliders(prefs: [prefs.maxTime, prefs.maxDetour]), + Divider(indent: 25, endIndent: 25, height: 50), + PreferenceSliders(prefs: [prefs.sightseeing, prefs.shopping, prefs.nature]) + ] + ); + } else { + return CircularProgressIndicator(); + } + } } -class ImportanceSliders extends StatefulWidget { +class PreferenceSliders extends StatefulWidget { + final List prefs; + + PreferenceSliders({required this.prefs}); @override - State createState() => _ImportanceSlidersState(); + State createState() => _PreferenceSlidersState(); } -class _ImportanceSlidersState extends State { - - UserPreferences _prefs = UserPreferences(); - - List _createSliders() { - List sliders = []; - for (SinglePreference pref in _prefs.preferences) { - sliders.add(Card( - child: ListTile( - leading: pref.icon, - title: Text(pref.name), - subtitle: Slider( - value: pref.value.toDouble(), - min: 0, - max: 10, - divisions: 10, - label: pref.value.toString(), - onChanged: (double newValue) { - setState(() { - pref.value = newValue.toInt(); - _prefs.save(); - }); - }, - ) - ), - margin: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 0), - shadowColor: Colors.grey, - )); - } - return sliders; - } +class _PreferenceSlidersState extends State { @override Widget build(BuildContext context) { + List sliders = []; + for (SinglePreference pref in widget.prefs) { + sliders.add( + Card( + child: ListTile( + leading: pref.icon, + title: Text(pref.name), + subtitle: Slider( + value: pref.value.toDouble(), + min: pref.minVal.toDouble(), + max: pref.maxVal.toDouble(), + divisions: pref.maxVal - pref.minVal, + label: pref.value.toString(), + onChanged: (double newValue) { + setState(() { + pref.value = newValue.toInt(); + pref.save(); + }); + }, + ) + ), + margin: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 0), + shadowColor: Colors.grey, + ) + ); + } - return Column(children: _createSliders()); + return Column( + children: sliders); } } + diff --git a/frontend/lib/structs/preferences.dart b/frontend/lib/structs/preferences.dart index 9a31fc7..d86b361 100644 --- a/frontend/lib/structs/preferences.dart +++ b/frontend/lib/structs/preferences.dart @@ -3,80 +3,102 @@ import 'package:shared_preferences/shared_preferences.dart'; class SinglePreference { + String slug; String name; String description; int value; + int minVal; + int maxVal; Icon icon; - String key; SinglePreference({ + required this.slug, required this.name, required this.description, required this.value, required this.icon, - required this.key, + this.minVal = 0, + this.maxVal = 5, }); -} - - -class UserPreferences { - List preferences = [ - SinglePreference( - name: "Sightseeing", - description: "How much do you like sightseeing?", - value: 0, - icon: Icon(Icons.church), - key: "sightseeing", - ), - SinglePreference( - name: "Shopping", - description: "How much do you like shopping?", - value: 0, - icon: Icon(Icons.shopping_bag), - key: "shopping", - ), - SinglePreference( - name: "Foods & Drinks", - description: "How much do you like eating?", - value: 0, - icon: Icon(Icons.restaurant), - key: "eating", - ), - SinglePreference( - name: "Nightlife", - description: "How much do you like nightlife?", - value: 0, - icon: Icon(Icons.wine_bar), - key: "nightlife", - ), - SinglePreference( - name: "Nature", - description: "How much do you like nature?", - value: 0, - icon: Icon(Icons.landscape), - key: "nature", - ), - SinglePreference( - name: "Culture", - description: "How much do you like culture?", - value: 0, - icon: Icon(Icons.palette), - key: "culture", - ), - ]; - void save() async { SharedPreferences sharedPrefs = await SharedPreferences.getInstance(); - for (SinglePreference pref in preferences) { - sharedPrefs.setInt(pref.key, pref.value); - } + sharedPrefs.setInt('pref_$slug', value); } void load() async { SharedPreferences sharedPrefs = await SharedPreferences.getInstance(); - for (SinglePreference pref in preferences) { - pref.value = sharedPrefs.getInt(pref.key) ?? 0; + value = sharedPrefs.getInt('pref_$slug') ?? minVal; + } +} + + +class UserPreferences { + SinglePreference sightseeing = SinglePreference( + name: "Sightseeing", + slug: "sightseeing", + description: "How much do you like sightseeing?", + value: 0, + icon: Icon(Icons.church), + ); + SinglePreference shopping = SinglePreference( + name: "Shopping", + slug: "shopping", + description: "How much do you like shopping?", + value: 0, + icon: Icon(Icons.shopping_bag), + ); + SinglePreference nature = SinglePreference( + name: "Nature", + slug: "nature", + description: "How much do you like nature?", + value: 0, + icon: Icon(Icons.landscape), + ); + + SinglePreference maxTime = SinglePreference( + name: "Trip duration", + slug: "duration", + description: "How long do you want your trip to be?", + value: 30, + minVal: 30, + maxVal: 720, + icon: Icon(Icons.timer), + ); + SinglePreference maxDetour = SinglePreference( + name: "Trip detours", + slug: "detours", + description: "Are you okay with roaming even if makes the trip longer?", + value: 0, + maxVal: 30, + icon: Icon(Icons.loupe_sharp), + ); + + + + Future load() async { + for (SinglePreference pref in [sightseeing, shopping, nature, maxTime, maxDetour]) { + pref.load(); } } + + String toJson() { + // This is "opinionated" JSON, corresponding to the backend's expectations + return ''' + { + "sightseeing": {"type": "sightseeing", "score": ${sightseeing.value}}, + "shopping": {"type": "shopping", "score": ${shopping.value}}, + "nature": {"type": "nature", "score": ${nature.value}}, + "max_time_minutes": ${maxTime.value}, + "detour_tolerance_minute": ${maxDetour.value} + } + '''; + } +} + + +Future loadUserPreferences() async { + UserPreferences prefs = UserPreferences(); + await prefs.load(); + return prefs; } \ No newline at end of file diff --git a/frontend/lib/utils/fetch_trip.dart b/frontend/lib/utils/fetch_trip.dart index fd55751..c1d17e7 100644 --- a/frontend/lib/utils/fetch_trip.dart +++ b/frontend/lib/utils/fetch_trip.dart @@ -28,8 +28,8 @@ Future fetchTrip( final response = await dio.post( "/trip/new", data: { - // 'preferences': preferences.toJson(), - 'start': [48,2.3] + 'preferences': preferences.toJson(), + 'start': startPoint } );