diff --git a/default.nix b/default.nix index a2f69a4..0210184 100644 --- a/default.nix +++ b/default.nix @@ -10,7 +10,8 @@ pkgs.mkShell { # androidenv.androidPkgs.ndk-bundle ]; - # Set up Android SDK paths if needed + # Setting up android build environments on nix is a bit of a pain - immutable paths, etc. + # I used a hacky workaround by manually downloading the SDK and NDK from the website and simply telling the shell where to find them ANDROID_HOME = "/scratch/remy/android"; shellHook = '' diff --git a/frontend/README.md b/frontend/README.md index dc91aeb..6bc4677 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -26,7 +26,7 @@ To truly deploy a new version of the application, i.e. to the official app store git tag -a v -m "Release " git push origin v ``` -We adhere to the [Semantic Versioning](https://semver.org/) standard, so the tag should be of the form `v0.1.8` for example. +We adhere to the [Semantic Versioning](https://semver.org/) standard, so the tag should be of the form `v0.1.8` for example. ### Icons and logos The application uses a custom launcher icon and splash screen. These are managed platform-independently using the `flutter_launcher_icons` package. @@ -66,3 +66,10 @@ These are used by the CI/CD pipeline to deploy the application. - `IOS_ASC_KEY_ID` as well - `IOS_MATCH_PASSWORD` is used by fastlane match to download the certificates - `IOS_MATCH_REPO_SSH_KEY_BASE64` is used to authenticate with the git repository where the certificates are stored + + + + + + +## Android SDK&NDK setup diff --git a/frontend/android/app/build.gradle b/frontend/android/app/build.gradle index 1602d04..36b7045 100644 --- a/frontend/android/app/build.gradle +++ b/frontend/android/app/build.gradle @@ -49,7 +49,8 @@ if (secretPropertiesFile.exists()) { android { namespace "com.anydev.anyway" compileSdk flutter.compileSdkVersion - ndkVersion flutter.ndkVersion + ndkVersion = "27.0.12077973" + // TODO - set back to ndkVersion flutter.ndkVersion once https://github.com/flutter/flutter/issues/139427 is resolved compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -65,7 +66,7 @@ android { } defaultConfig { - + applicationId "com.anydev.anyway" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. diff --git a/frontend/lib/core/constants.dart b/frontend/lib/core/constants.dart new file mode 100644 index 0000000..ae72339 --- /dev/null +++ b/frontend/lib/core/constants.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; + +const String APP_NAME = 'AnyWay'; + +String API_URL_BASE = 'https://anyway.anydev.info'; +String API_URL_DEBUG = 'https://anyway-stg.anydev.info'; +String PRIVACY_URL = 'https://anydev.info/privacy'; + +const String MAP_ID = '41c21ac9b81dbfd8'; + + +const Color GRADIENT_START = Color(0xFFF9B208); +const Color GRADIENT_END = Color(0xFFE72E77); + +const Color PRIMARY_COLOR = Color(0xFFF38F1A); + + + +const double TRIP_PANEL_MAX_HEIGHT = 0.8; +const double TRIP_PANEL_MIN_HEIGHT = 0.12; + +ThemeData APP_THEME = ThemeData( + primaryColor: PRIMARY_COLOR, + + scaffoldBackgroundColor: Colors.white, + cardColor: Colors.white, + useMaterial3: true, + + colorScheme: const ColorScheme.light( + primary: PRIMARY_COLOR, + secondary: GRADIENT_END, + surface: Colors.white, + error: Colors.red, + onPrimary: Colors.white, + onSecondary: Color.fromARGB(255, 30, 22, 22), + onSurface: Colors.black, + onError: Colors.white, + brightness: Brightness.light, + ), + + + textButtonTheme: const TextButtonThemeData( + style: ButtonStyle( + foregroundColor: WidgetStatePropertyAll(PRIMARY_COLOR), + side: WidgetStatePropertyAll( + BorderSide( + color: PRIMARY_COLOR, + width: 1, + ), + ), + ) + ), + + elevatedButtonTheme: const ElevatedButtonThemeData( + style: ButtonStyle( + foregroundColor: WidgetStatePropertyAll(PRIMARY_COLOR), + ) + ), + + outlinedButtonTheme: const OutlinedButtonThemeData( + style: ButtonStyle( + foregroundColor: WidgetStatePropertyAll(PRIMARY_COLOR), + ) + ), + + + sliderTheme: const SliderThemeData( + trackHeight: 15, + inactiveTrackColor: Colors.grey, + thumbColor: PRIMARY_COLOR, + activeTrackColor: GRADIENT_END + ) +); + + +const Gradient APP_GRADIENT = LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [GRADIENT_START, GRADIENT_END], +); + + +final GlobalKey rootScaffoldMessengerKey = GlobalKey(); diff --git a/frontend/lib/core/dio_client.dart b/frontend/lib/core/dio_client.dart new file mode 100644 index 0000000..cdf0541 --- /dev/null +++ b/frontend/lib/core/dio_client.dart @@ -0,0 +1,16 @@ +import 'package:dio/dio.dart'; + +class DioClient { + final Dio dio; + + DioClient({required String baseUrl}): dio = Dio(BaseOptions( + baseUrl: baseUrl, + connectTimeout: const Duration(seconds: 5), + receiveTimeout: const Duration(seconds: 120), + // also accept 500 errors, since we cannot rule out that the server is at fault. We still want to gracefully handle these errors + validateStatus: (status) => status! <= 500, + receiveDataWhenStatusError: true, + contentType: Headers.jsonContentType, + responseType: ResponseType.json, + )); +} diff --git a/frontend/lib/data/README.md b/frontend/lib/data/README.md new file mode 100644 index 0000000..e69de29 diff --git a/frontend/lib/data/datasources/backend_trip_datasource.dart b/frontend/lib/data/datasources/backend_trip_datasource.dart new file mode 100644 index 0000000..bbac5e7 --- /dev/null +++ b/frontend/lib/data/datasources/backend_trip_datasource.dart @@ -0,0 +1,5 @@ +import 'package:anyway/domain/entities/landmark.dart'; + +abstract class TripRemoteDataSource { + Future> fetchLandmarks(); +} diff --git a/frontend/lib/data/datasources/local_trip_datasource.dart b/frontend/lib/data/datasources/local_trip_datasource.dart new file mode 100644 index 0000000..e69de29 diff --git a/frontend/lib/data/models/landmark_model.dart b/frontend/lib/data/models/landmark_model.dart new file mode 100644 index 0000000..3077ba7 --- /dev/null +++ b/frontend/lib/data/models/landmark_model.dart @@ -0,0 +1,30 @@ +import 'package:anyway/domain/entities/landmark.dart'; +import 'package:anyway/domain/entities/landmark_description.dart'; +import 'package:anyway/domain/entities/landmark_type.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'landmark_model.freezed.dart'; +part 'landmark_model.g.dart'; + +@freezed +abstract class LandmarkModel with _$LandmarkModel { + const factory LandmarkModel({ + required String uuid, + required String name, + required List location, + required String type, + required bool isSecondary, + required String description, + }) = _LandmarkModel; + + factory LandmarkModel.fromJson(Map json) => _$LandmarkModelFromJson(json); + + Landmark toEntity() => Landmark( + uuid: uuid, + name: name, + location: location, + type: LandmarkType(type: LandmarkTypeEnum.values.firstWhere((e) => e.value == type)), + isSecondary: isSecondary, + // TODO - try to set tags + description: LandmarkDescription(description: description, tags: []) + ); +} diff --git a/frontend/lib/data/models/landmark_model.freezed.dart b/frontend/lib/data/models/landmark_model.freezed.dart new file mode 100644 index 0000000..2f4c21e --- /dev/null +++ b/frontend/lib/data/models/landmark_model.freezed.dart @@ -0,0 +1,443 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'landmark_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$LandmarkModel { + String get uuid; + String get name; + List get location; + String get type; + bool get isSecondary; + String get description; + + /// Create a copy of LandmarkModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $LandmarkModelCopyWith get copyWith => + _$LandmarkModelCopyWithImpl( + this as LandmarkModel, _$identity); + + /// Serializes this LandmarkModel to a JSON map. + Map toJson(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is LandmarkModel && + (identical(other.uuid, uuid) || other.uuid == uuid) && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other.location, location) && + (identical(other.type, type) || other.type == type) && + (identical(other.isSecondary, isSecondary) || + other.isSecondary == isSecondary) && + (identical(other.description, description) || + other.description == description)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + uuid, + name, + const DeepCollectionEquality().hash(location), + type, + isSecondary, + description); + + @override + String toString() { + return 'LandmarkModel(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description)'; + } +} + +/// @nodoc +abstract mixin class $LandmarkModelCopyWith<$Res> { + factory $LandmarkModelCopyWith( + LandmarkModel value, $Res Function(LandmarkModel) _then) = + _$LandmarkModelCopyWithImpl; + @useResult + $Res call( + {String uuid, + String name, + List location, + String type, + bool isSecondary, + String description}); +} + +/// @nodoc +class _$LandmarkModelCopyWithImpl<$Res> + implements $LandmarkModelCopyWith<$Res> { + _$LandmarkModelCopyWithImpl(this._self, this._then); + + final LandmarkModel _self; + final $Res Function(LandmarkModel) _then; + + /// Create a copy of LandmarkModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uuid = null, + Object? name = null, + Object? location = null, + Object? type = null, + Object? isSecondary = null, + Object? description = null, + }) { + return _then(_self.copyWith( + uuid: null == uuid + ? _self.uuid + : uuid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _self.name + : name // ignore: cast_nullable_to_non_nullable + as String, + location: null == location + ? _self.location + : location // ignore: cast_nullable_to_non_nullable + as List, + type: null == type + ? _self.type + : type // ignore: cast_nullable_to_non_nullable + as String, + isSecondary: null == isSecondary + ? _self.isSecondary + : isSecondary // ignore: cast_nullable_to_non_nullable + as bool, + description: null == description + ? _self.description + : description // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [LandmarkModel]. +extension LandmarkModelPatterns on LandmarkModel { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_LandmarkModel value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _LandmarkModel() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_LandmarkModel value) $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkModel(): + return $default(_that); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_LandmarkModel value)? $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkModel() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String uuid, String name, List location, + String type, bool isSecondary, String description)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _LandmarkModel() when $default != null: + return $default(_that.uuid, _that.name, _that.location, _that.type, + _that.isSecondary, _that.description); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String uuid, String name, List location, + String type, bool isSecondary, String description) + $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkModel(): + return $default(_that.uuid, _that.name, _that.location, _that.type, + _that.isSecondary, _that.description); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String uuid, String name, List location, + String type, bool isSecondary, String description)? + $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkModel() when $default != null: + return $default(_that.uuid, _that.name, _that.location, _that.type, + _that.isSecondary, _that.description); + case _: + return null; + } + } +} + +/// @nodoc +@JsonSerializable() +class _LandmarkModel implements LandmarkModel { + const _LandmarkModel( + {required this.uuid, + required this.name, + required final List location, + required this.type, + required this.isSecondary, + required this.description}) + : _location = location; + factory _LandmarkModel.fromJson(Map json) => + _$LandmarkModelFromJson(json); + + @override + final String uuid; + @override + final String name; + final List _location; + @override + List get location { + if (_location is EqualUnmodifiableListView) return _location; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_location); + } + + @override + final String type; + @override + final bool isSecondary; + @override + final String description; + + /// Create a copy of LandmarkModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$LandmarkModelCopyWith<_LandmarkModel> get copyWith => + __$LandmarkModelCopyWithImpl<_LandmarkModel>(this, _$identity); + + @override + Map toJson() { + return _$LandmarkModelToJson( + this, + ); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _LandmarkModel && + (identical(other.uuid, uuid) || other.uuid == uuid) && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other._location, _location) && + (identical(other.type, type) || other.type == type) && + (identical(other.isSecondary, isSecondary) || + other.isSecondary == isSecondary) && + (identical(other.description, description) || + other.description == description)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + uuid, + name, + const DeepCollectionEquality().hash(_location), + type, + isSecondary, + description); + + @override + String toString() { + return 'LandmarkModel(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description)'; + } +} + +/// @nodoc +abstract mixin class _$LandmarkModelCopyWith<$Res> + implements $LandmarkModelCopyWith<$Res> { + factory _$LandmarkModelCopyWith( + _LandmarkModel value, $Res Function(_LandmarkModel) _then) = + __$LandmarkModelCopyWithImpl; + @override + @useResult + $Res call( + {String uuid, + String name, + List location, + String type, + bool isSecondary, + String description}); +} + +/// @nodoc +class __$LandmarkModelCopyWithImpl<$Res> + implements _$LandmarkModelCopyWith<$Res> { + __$LandmarkModelCopyWithImpl(this._self, this._then); + + final _LandmarkModel _self; + final $Res Function(_LandmarkModel) _then; + + /// Create a copy of LandmarkModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? uuid = null, + Object? name = null, + Object? location = null, + Object? type = null, + Object? isSecondary = null, + Object? description = null, + }) { + return _then(_LandmarkModel( + uuid: null == uuid + ? _self.uuid + : uuid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _self.name + : name // ignore: cast_nullable_to_non_nullable + as String, + location: null == location + ? _self._location + : location // ignore: cast_nullable_to_non_nullable + as List, + type: null == type + ? _self.type + : type // ignore: cast_nullable_to_non_nullable + as String, + isSecondary: null == isSecondary + ? _self.isSecondary + : isSecondary // ignore: cast_nullable_to_non_nullable + as bool, + description: null == description + ? _self.description + : description // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +// dart format on diff --git a/frontend/lib/data/models/landmark_model.g.dart b/frontend/lib/data/models/landmark_model.g.dart new file mode 100644 index 0000000..bd76e39 --- /dev/null +++ b/frontend/lib/data/models/landmark_model.g.dart @@ -0,0 +1,29 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'landmark_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LandmarkModel _$LandmarkModelFromJson(Map json) => + _LandmarkModel( + uuid: json['uuid'] as String, + name: json['name'] as String, + location: (json['location'] as List) + .map((e) => (e as num).toDouble()) + .toList(), + type: json['type'] as String, + isSecondary: json['isSecondary'] as bool, + description: json['description'] as String, + ); + +Map _$LandmarkModelToJson(_LandmarkModel instance) => + { + 'uuid': instance.uuid, + 'name': instance.name, + 'location': instance.location, + 'type': instance.type, + 'isSecondary': instance.isSecondary, + 'description': instance.description, + }; diff --git a/frontend/lib/data/repositories/backend_trip_repository.dart b/frontend/lib/data/repositories/backend_trip_repository.dart new file mode 100644 index 0000000..db1bf34 --- /dev/null +++ b/frontend/lib/data/repositories/backend_trip_repository.dart @@ -0,0 +1,119 @@ +import 'dart:developer'; + +import 'package:anyway/domain/entities/preferences.dart'; +import 'package:anyway/domain/entities/trip.dart'; +import 'package:anyway/domain/repositories/trip_repository.dart'; +import 'package:dio/dio.dart'; + +// We can request a new trip from our backend API by passing it user preferences (which contain all the necessary data) +class BackendTripRepository implements TripRepository { + final Dio dio; + + BackendTripRepository({required this.dio}); + + + @override + Future getTrip({Preferences? preferences, String? tripUUID}) async { + Map data = { + "preferences": preferences!.toJson(), + // "start": preferences!.startPoint.location, + }; + + + late Response response; + try { + response = await dio.post( + "/trip/new", + data: data + ); + } catch (e) { + trip.updateUUID("error"); + + // Format the error message to be more user friendly + String errorDescription; + if (e is DioException) { + errorDescription = e.message ?? "Unknown error"; + } else if (e is SocketException) { + errorDescription = "No internet connection"; + } else if (e is TimeoutException) { + errorDescription = "Request timed out"; + } else { + errorDescription = "Unknown error"; + } + + String errorMessage = """ + We're sorry, the following error was generated: + + ${errorDescription.trim()} + """.trim(); + + trip.updateError(errorMessage); + log(e.toString()); + log(errorMessage); + return; + } + + // handle more specific errors + if (response.statusCode != 200) { + trip.updateUUID("error"); + String errorDescription; + if (response.data.runtimeType == String) { + errorDescription = response.data; + } else if (response.data.runtimeType == Map) { + errorDescription = response.data["detail"] ?? "Unknown error"; + } else { + errorDescription = "Unknown error"; + } + + String errorMessage = """ + We're sorry, our servers generated the following error: + + ${errorDescription.trim()} + Please try again. + """.trim(); + trip.updateError(errorMessage); + log(errorMessage); + // Actualy no need to throw an exception, we can just log the error and let the user retry + // throw Exception(errorDetail); + } else { + + // if the response data is not json, throw an error + if (response.data is! Map) { + log("${response.data.runtimeType}"); + trip.updateUUID("error"); + String errorMessage = """ + We're sorry, our servers generated the following error: + + ${response.data.trim()} + Please try again. + """.trim(); + trip.updateError(errorMessage); + log(errorMessage); + return; + } + + Map json = response.data; + + // only fill in the trip "meta" data for now + trip.loadFromJson(json); + + // now fill the trip with landmarks + // we are going to recreate ALL the landmarks from the information given by the api + trip.landmarks.remove(trip.landmarks.first); + String? nextUUID = json["first_landmark_uuid"]; + while (nextUUID != null) { + var (landmark, newUUID) = await fetchLandmark(nextUUID); + trip.addLandmark(landmark); + nextUUID = newUUID; + } + + log(response.data.toString()); + // // Also save the trip for the user's convenience + // savedTrips.addTrip(trip); + } + + + + + } +} diff --git a/frontend/lib/domain/README.md b/frontend/lib/domain/README.md new file mode 100644 index 0000000..1746555 --- /dev/null +++ b/frontend/lib/domain/README.md @@ -0,0 +1,24 @@ +# Domain layer + +## `entities` - Model definition + +Since we follow the repository structure convention, in this folder we purely define data models, without providing any logic. To reduce boilerplate, we use the `freezed` package. This requires some code generation, which means that all model definitions have the following structure: +```dart +import 'package:freezed_annotation/freezed_annotation.dart'; + +// required: associates our `main.dart` with the code generated by Freezed +part 'main.freezed.dart'; +// optional: Since our Person class is serializable, we must add this line. +// But if Person was not serializable, we could skip it. +part 'main.g.dart'; +``` + +This is required boilerplate for all models. Then, we define the model itself using the `@freezed` annotation: +```dart +@freezed +... +``` + +The `*.frozen.dart` and `*.g.dart` are pure boilerplate and should not be touched. + +Note that the description of the data will losely follow the capabilities of the backend but does not need to reflect it exactly. That is where the `data` part is for: translating api calls into flutter objects. diff --git a/frontend/lib/domain/entities/landmark.dart b/frontend/lib/domain/entities/landmark.dart new file mode 100644 index 0000000..08b8aa0 --- /dev/null +++ b/frontend/lib/domain/entities/landmark.dart @@ -0,0 +1,21 @@ +import 'package:anyway/domain/entities/landmark_type.dart'; +import 'package:anyway/domain/entities/landmark_description.dart'; + +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'landmark.freezed.dart'; +part 'landmark.g.dart'; + +@unfreezed +abstract class Landmark with _$Landmark { + factory Landmark({ + required String uuid, + required String name, + required List location, + required LandmarkType type, + required bool isSecondary, + + required LandmarkDescription description, + }) = _Landmark; + + factory Landmark.fromJson(Map json) => _$LandmarkFromJson(json); +} diff --git a/frontend/lib/domain/entities/landmark.freezed.dart b/frontend/lib/domain/entities/landmark.freezed.dart new file mode 100644 index 0000000..14e862b --- /dev/null +++ b/frontend/lib/domain/entities/landmark.freezed.dart @@ -0,0 +1,448 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'landmark.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$Landmark { + String get uuid; + set uuid(String value); + String get name; + set name(String value); + List get location; + set location(List value); + LandmarkType get type; + set type(LandmarkType value); + bool get isSecondary; + set isSecondary(bool value); + LandmarkDescription get description; + set description(LandmarkDescription value); + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $LandmarkCopyWith get copyWith => + _$LandmarkCopyWithImpl(this as Landmark, _$identity); + + /// Serializes this Landmark to a JSON map. + Map toJson(); + + @override + String toString() { + return 'Landmark(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description)'; + } +} + +/// @nodoc +abstract mixin class $LandmarkCopyWith<$Res> { + factory $LandmarkCopyWith(Landmark value, $Res Function(Landmark) _then) = + _$LandmarkCopyWithImpl; + @useResult + $Res call( + {String uuid, + String name, + List location, + LandmarkType type, + bool isSecondary, + LandmarkDescription description}); + + $LandmarkTypeCopyWith<$Res> get type; + $LandmarkDescriptionCopyWith<$Res> get description; +} + +/// @nodoc +class _$LandmarkCopyWithImpl<$Res> implements $LandmarkCopyWith<$Res> { + _$LandmarkCopyWithImpl(this._self, this._then); + + final Landmark _self; + final $Res Function(Landmark) _then; + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uuid = null, + Object? name = null, + Object? location = null, + Object? type = null, + Object? isSecondary = null, + Object? description = null, + }) { + return _then(_self.copyWith( + uuid: null == uuid + ? _self.uuid + : uuid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _self.name + : name // ignore: cast_nullable_to_non_nullable + as String, + location: null == location + ? _self.location + : location // ignore: cast_nullable_to_non_nullable + as List, + type: null == type + ? _self.type + : type // ignore: cast_nullable_to_non_nullable + as LandmarkType, + isSecondary: null == isSecondary + ? _self.isSecondary + : isSecondary // ignore: cast_nullable_to_non_nullable + as bool, + description: null == description + ? _self.description + : description // ignore: cast_nullable_to_non_nullable + as LandmarkDescription, + )); + } + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LandmarkTypeCopyWith<$Res> get type { + return $LandmarkTypeCopyWith<$Res>(_self.type, (value) { + return _then(_self.copyWith(type: value)); + }); + } + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LandmarkDescriptionCopyWith<$Res> get description { + return $LandmarkDescriptionCopyWith<$Res>(_self.description, (value) { + return _then(_self.copyWith(description: value)); + }); + } +} + +/// Adds pattern-matching-related methods to [Landmark]. +extension LandmarkPatterns on Landmark { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_Landmark value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _Landmark() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_Landmark value) $default, + ) { + final _that = this; + switch (_that) { + case _Landmark(): + return $default(_that); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_Landmark value)? $default, + ) { + final _that = this; + switch (_that) { + case _Landmark() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function( + String uuid, + String name, + List location, + LandmarkType type, + bool isSecondary, + LandmarkDescription description)? + $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _Landmark() when $default != null: + return $default(_that.uuid, _that.name, _that.location, _that.type, + _that.isSecondary, _that.description); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function( + String uuid, + String name, + List location, + LandmarkType type, + bool isSecondary, + LandmarkDescription description) + $default, + ) { + final _that = this; + switch (_that) { + case _Landmark(): + return $default(_that.uuid, _that.name, _that.location, _that.type, + _that.isSecondary, _that.description); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function( + String uuid, + String name, + List location, + LandmarkType type, + bool isSecondary, + LandmarkDescription description)? + $default, + ) { + final _that = this; + switch (_that) { + case _Landmark() when $default != null: + return $default(_that.uuid, _that.name, _that.location, _that.type, + _that.isSecondary, _that.description); + case _: + return null; + } + } +} + +/// @nodoc +@JsonSerializable() +class _Landmark implements Landmark { + _Landmark( + {required this.uuid, + required this.name, + required this.location, + required this.type, + required this.isSecondary, + required this.description}); + factory _Landmark.fromJson(Map json) => + _$LandmarkFromJson(json); + + @override + String uuid; + @override + String name; + @override + List location; + @override + LandmarkType type; + @override + bool isSecondary; + @override + LandmarkDescription description; + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$LandmarkCopyWith<_Landmark> get copyWith => + __$LandmarkCopyWithImpl<_Landmark>(this, _$identity); + + @override + Map toJson() { + return _$LandmarkToJson( + this, + ); + } + + @override + String toString() { + return 'Landmark(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description)'; + } +} + +/// @nodoc +abstract mixin class _$LandmarkCopyWith<$Res> + implements $LandmarkCopyWith<$Res> { + factory _$LandmarkCopyWith(_Landmark value, $Res Function(_Landmark) _then) = + __$LandmarkCopyWithImpl; + @override + @useResult + $Res call( + {String uuid, + String name, + List location, + LandmarkType type, + bool isSecondary, + LandmarkDescription description}); + + @override + $LandmarkTypeCopyWith<$Res> get type; + @override + $LandmarkDescriptionCopyWith<$Res> get description; +} + +/// @nodoc +class __$LandmarkCopyWithImpl<$Res> implements _$LandmarkCopyWith<$Res> { + __$LandmarkCopyWithImpl(this._self, this._then); + + final _Landmark _self; + final $Res Function(_Landmark) _then; + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? uuid = null, + Object? name = null, + Object? location = null, + Object? type = null, + Object? isSecondary = null, + Object? description = null, + }) { + return _then(_Landmark( + uuid: null == uuid + ? _self.uuid + : uuid // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _self.name + : name // ignore: cast_nullable_to_non_nullable + as String, + location: null == location + ? _self.location + : location // ignore: cast_nullable_to_non_nullable + as List, + type: null == type + ? _self.type + : type // ignore: cast_nullable_to_non_nullable + as LandmarkType, + isSecondary: null == isSecondary + ? _self.isSecondary + : isSecondary // ignore: cast_nullable_to_non_nullable + as bool, + description: null == description + ? _self.description + : description // ignore: cast_nullable_to_non_nullable + as LandmarkDescription, + )); + } + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LandmarkTypeCopyWith<$Res> get type { + return $LandmarkTypeCopyWith<$Res>(_self.type, (value) { + return _then(_self.copyWith(type: value)); + }); + } + + /// Create a copy of Landmark + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LandmarkDescriptionCopyWith<$Res> get description { + return $LandmarkDescriptionCopyWith<$Res>(_self.description, (value) { + return _then(_self.copyWith(description: value)); + }); + } +} + +// dart format on diff --git a/frontend/lib/domain/entities/landmark.g.dart b/frontend/lib/domain/entities/landmark.g.dart new file mode 100644 index 0000000..81fdc35 --- /dev/null +++ b/frontend/lib/domain/entities/landmark.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'landmark.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_Landmark _$LandmarkFromJson(Map json) => _Landmark( + uuid: json['uuid'] as String, + name: json['name'] as String, + location: (json['location'] as List) + .map((e) => (e as num).toDouble()) + .toList(), + type: LandmarkType.fromJson(json['type'] as Map), + isSecondary: json['isSecondary'] as bool, + description: LandmarkDescription.fromJson( + json['description'] as Map), + ); + +Map _$LandmarkToJson(_Landmark instance) => { + 'uuid': instance.uuid, + 'name': instance.name, + 'location': instance.location, + 'type': instance.type, + 'isSecondary': instance.isSecondary, + 'description': instance.description, + }; diff --git a/frontend/lib/domain/entities/landmark_description.dart b/frontend/lib/domain/entities/landmark_description.dart new file mode 100644 index 0000000..4853447 --- /dev/null +++ b/frontend/lib/domain/entities/landmark_description.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'landmark_description.freezed.dart'; +part 'landmark_description.g.dart'; + + +@Freezed(makeCollectionsUnmodifiable: false) +abstract class LandmarkDescription with _$LandmarkDescription { + const factory LandmarkDescription({ + required String description, + required List tags, + }) = _LandmarkDescription; + + factory LandmarkDescription.fromJson(Map json) => _$LandmarkDescriptionFromJson(json); +} + diff --git a/frontend/lib/domain/entities/landmark_description.freezed.dart b/frontend/lib/domain/entities/landmark_description.freezed.dart new file mode 100644 index 0000000..842b41a --- /dev/null +++ b/frontend/lib/domain/entities/landmark_description.freezed.dart @@ -0,0 +1,336 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'landmark_description.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$LandmarkDescription { + String get description; + List get tags; + + /// Create a copy of LandmarkDescription + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $LandmarkDescriptionCopyWith get copyWith => + _$LandmarkDescriptionCopyWithImpl( + this as LandmarkDescription, _$identity); + + /// Serializes this LandmarkDescription to a JSON map. + Map toJson(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is LandmarkDescription && + (identical(other.description, description) || + other.description == description) && + const DeepCollectionEquality().equals(other.tags, tags)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, description, const DeepCollectionEquality().hash(tags)); + + @override + String toString() { + return 'LandmarkDescription(description: $description, tags: $tags)'; + } +} + +/// @nodoc +abstract mixin class $LandmarkDescriptionCopyWith<$Res> { + factory $LandmarkDescriptionCopyWith( + LandmarkDescription value, $Res Function(LandmarkDescription) _then) = + _$LandmarkDescriptionCopyWithImpl; + @useResult + $Res call({String description, List tags}); +} + +/// @nodoc +class _$LandmarkDescriptionCopyWithImpl<$Res> + implements $LandmarkDescriptionCopyWith<$Res> { + _$LandmarkDescriptionCopyWithImpl(this._self, this._then); + + final LandmarkDescription _self; + final $Res Function(LandmarkDescription) _then; + + /// Create a copy of LandmarkDescription + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? description = null, + Object? tags = null, + }) { + return _then(_self.copyWith( + description: null == description + ? _self.description + : description // ignore: cast_nullable_to_non_nullable + as String, + tags: null == tags + ? _self.tags + : tags // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// Adds pattern-matching-related methods to [LandmarkDescription]. +extension LandmarkDescriptionPatterns on LandmarkDescription { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_LandmarkDescription value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _LandmarkDescription() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_LandmarkDescription value) $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkDescription(): + return $default(_that); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_LandmarkDescription value)? $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkDescription() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String description, List tags)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _LandmarkDescription() when $default != null: + return $default(_that.description, _that.tags); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String description, List tags) $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkDescription(): + return $default(_that.description, _that.tags); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String description, List tags)? $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkDescription() when $default != null: + return $default(_that.description, _that.tags); + case _: + return null; + } + } +} + +/// @nodoc +@JsonSerializable() +class _LandmarkDescription implements LandmarkDescription { + const _LandmarkDescription({required this.description, required this.tags}); + factory _LandmarkDescription.fromJson(Map json) => + _$LandmarkDescriptionFromJson(json); + + @override + final String description; + @override + final List tags; + + /// Create a copy of LandmarkDescription + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$LandmarkDescriptionCopyWith<_LandmarkDescription> get copyWith => + __$LandmarkDescriptionCopyWithImpl<_LandmarkDescription>( + this, _$identity); + + @override + Map toJson() { + return _$LandmarkDescriptionToJson( + this, + ); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _LandmarkDescription && + (identical(other.description, description) || + other.description == description) && + const DeepCollectionEquality().equals(other.tags, tags)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, description, const DeepCollectionEquality().hash(tags)); + + @override + String toString() { + return 'LandmarkDescription(description: $description, tags: $tags)'; + } +} + +/// @nodoc +abstract mixin class _$LandmarkDescriptionCopyWith<$Res> + implements $LandmarkDescriptionCopyWith<$Res> { + factory _$LandmarkDescriptionCopyWith(_LandmarkDescription value, + $Res Function(_LandmarkDescription) _then) = + __$LandmarkDescriptionCopyWithImpl; + @override + @useResult + $Res call({String description, List tags}); +} + +/// @nodoc +class __$LandmarkDescriptionCopyWithImpl<$Res> + implements _$LandmarkDescriptionCopyWith<$Res> { + __$LandmarkDescriptionCopyWithImpl(this._self, this._then); + + final _LandmarkDescription _self; + final $Res Function(_LandmarkDescription) _then; + + /// Create a copy of LandmarkDescription + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? description = null, + Object? tags = null, + }) { + return _then(_LandmarkDescription( + description: null == description + ? _self.description + : description // ignore: cast_nullable_to_non_nullable + as String, + tags: null == tags + ? _self.tags + : tags // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +// dart format on diff --git a/frontend/lib/domain/entities/landmark_description.g.dart b/frontend/lib/domain/entities/landmark_description.g.dart new file mode 100644 index 0000000..ffc5c5e --- /dev/null +++ b/frontend/lib/domain/entities/landmark_description.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'landmark_description.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LandmarkDescription _$LandmarkDescriptionFromJson(Map json) => + _LandmarkDescription( + description: json['description'] as String, + tags: (json['tags'] as List).map((e) => e as String).toList(), + ); + +Map _$LandmarkDescriptionToJson( + _LandmarkDescription instance) => + { + 'description': instance.description, + 'tags': instance.tags, + }; diff --git a/frontend/lib/domain/entities/landmark_type.dart b/frontend/lib/domain/entities/landmark_type.dart new file mode 100644 index 0000000..858cf84 --- /dev/null +++ b/frontend/lib/domain/entities/landmark_type.dart @@ -0,0 +1,27 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'landmark_type.freezed.dart'; +part 'landmark_type.g.dart'; + +@freezed +abstract class LandmarkType with _$LandmarkType { + const factory LandmarkType({ + required LandmarkTypeEnum type, + }) = _LandmarkType; + + factory LandmarkType.fromJson(Map json) => _$LandmarkTypeFromJson(json); +} + +@JsonEnum(alwaysCreate: true) +enum LandmarkTypeEnum { + @JsonValue('culture') + culture, + @JsonValue('nature') + nature, + @JsonValue('shopping') + shopping, +} + +extension LandmarkTypeEnumExtension on LandmarkTypeEnum { + String get value => _$LandmarkTypeEnumEnumMap[this]!; +} diff --git a/frontend/lib/domain/entities/landmark_type.freezed.dart b/frontend/lib/domain/entities/landmark_type.freezed.dart new file mode 100644 index 0000000..5df1c7b --- /dev/null +++ b/frontend/lib/domain/entities/landmark_type.freezed.dart @@ -0,0 +1,315 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'landmark_type.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$LandmarkType { + LandmarkTypeEnum get type; + + /// Create a copy of LandmarkType + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $LandmarkTypeCopyWith get copyWith => + _$LandmarkTypeCopyWithImpl( + this as LandmarkType, _$identity); + + /// Serializes this LandmarkType to a JSON map. + Map toJson(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is LandmarkType && + (identical(other.type, type) || other.type == type)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, type); + + @override + String toString() { + return 'LandmarkType(type: $type)'; + } +} + +/// @nodoc +abstract mixin class $LandmarkTypeCopyWith<$Res> { + factory $LandmarkTypeCopyWith( + LandmarkType value, $Res Function(LandmarkType) _then) = + _$LandmarkTypeCopyWithImpl; + @useResult + $Res call({LandmarkTypeEnum type}); +} + +/// @nodoc +class _$LandmarkTypeCopyWithImpl<$Res> implements $LandmarkTypeCopyWith<$Res> { + _$LandmarkTypeCopyWithImpl(this._self, this._then); + + final LandmarkType _self; + final $Res Function(LandmarkType) _then; + + /// Create a copy of LandmarkType + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? type = null, + }) { + return _then(_self.copyWith( + type: null == type + ? _self.type + : type // ignore: cast_nullable_to_non_nullable + as LandmarkTypeEnum, + )); + } +} + +/// Adds pattern-matching-related methods to [LandmarkType]. +extension LandmarkTypePatterns on LandmarkType { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_LandmarkType value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _LandmarkType() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_LandmarkType value) $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkType(): + return $default(_that); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_LandmarkType value)? $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkType() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(LandmarkTypeEnum type)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _LandmarkType() when $default != null: + return $default(_that.type); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(LandmarkTypeEnum type) $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkType(): + return $default(_that.type); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(LandmarkTypeEnum type)? $default, + ) { + final _that = this; + switch (_that) { + case _LandmarkType() when $default != null: + return $default(_that.type); + case _: + return null; + } + } +} + +/// @nodoc +@JsonSerializable() +class _LandmarkType implements LandmarkType { + const _LandmarkType({required this.type}); + factory _LandmarkType.fromJson(Map json) => + _$LandmarkTypeFromJson(json); + + @override + final LandmarkTypeEnum type; + + /// Create a copy of LandmarkType + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$LandmarkTypeCopyWith<_LandmarkType> get copyWith => + __$LandmarkTypeCopyWithImpl<_LandmarkType>(this, _$identity); + + @override + Map toJson() { + return _$LandmarkTypeToJson( + this, + ); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _LandmarkType && + (identical(other.type, type) || other.type == type)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, type); + + @override + String toString() { + return 'LandmarkType(type: $type)'; + } +} + +/// @nodoc +abstract mixin class _$LandmarkTypeCopyWith<$Res> + implements $LandmarkTypeCopyWith<$Res> { + factory _$LandmarkTypeCopyWith( + _LandmarkType value, $Res Function(_LandmarkType) _then) = + __$LandmarkTypeCopyWithImpl; + @override + @useResult + $Res call({LandmarkTypeEnum type}); +} + +/// @nodoc +class __$LandmarkTypeCopyWithImpl<$Res> + implements _$LandmarkTypeCopyWith<$Res> { + __$LandmarkTypeCopyWithImpl(this._self, this._then); + + final _LandmarkType _self; + final $Res Function(_LandmarkType) _then; + + /// Create a copy of LandmarkType + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? type = null, + }) { + return _then(_LandmarkType( + type: null == type + ? _self.type + : type // ignore: cast_nullable_to_non_nullable + as LandmarkTypeEnum, + )); + } +} + +// dart format on diff --git a/frontend/lib/domain/entities/landmark_type.g.dart b/frontend/lib/domain/entities/landmark_type.g.dart new file mode 100644 index 0000000..4188d3d --- /dev/null +++ b/frontend/lib/domain/entities/landmark_type.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'landmark_type.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LandmarkType _$LandmarkTypeFromJson(Map json) => + _LandmarkType( + type: $enumDecode(_$LandmarkTypeEnumEnumMap, json['type']), + ); + +Map _$LandmarkTypeToJson(_LandmarkType instance) => + { + 'type': _$LandmarkTypeEnumEnumMap[instance.type]!, + }; + +const _$LandmarkTypeEnumEnumMap = { + LandmarkTypeEnum.culture: 'culture', + LandmarkTypeEnum.nature: 'nature', + LandmarkTypeEnum.shopping: 'shopping', +}; diff --git a/frontend/lib/domain/entities/preferences.dart b/frontend/lib/domain/entities/preferences.dart new file mode 100644 index 0000000..d1046af --- /dev/null +++ b/frontend/lib/domain/entities/preferences.dart @@ -0,0 +1,12 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'preferences.freezed.dart'; +part 'preferences.g.dart'; + +@freezed +abstract class Preferences with _$Preferences { + const factory Preferences({ + required String test, + }) = _Preferences; + + factory Preferences.fromJson(Map json) => _$PreferencesFromJson(json); +} diff --git a/frontend/lib/domain/entities/preferences.freezed.dart b/frontend/lib/domain/entities/preferences.freezed.dart new file mode 100644 index 0000000..56612f2 --- /dev/null +++ b/frontend/lib/domain/entities/preferences.freezed.dart @@ -0,0 +1,313 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'preferences.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$Preferences { + String get test; + + /// Create a copy of Preferences + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $PreferencesCopyWith get copyWith => + _$PreferencesCopyWithImpl(this as Preferences, _$identity); + + /// Serializes this Preferences to a JSON map. + Map toJson(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is Preferences && + (identical(other.test, test) || other.test == test)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, test); + + @override + String toString() { + return 'Preferences(test: $test)'; + } +} + +/// @nodoc +abstract mixin class $PreferencesCopyWith<$Res> { + factory $PreferencesCopyWith( + Preferences value, $Res Function(Preferences) _then) = + _$PreferencesCopyWithImpl; + @useResult + $Res call({String test}); +} + +/// @nodoc +class _$PreferencesCopyWithImpl<$Res> implements $PreferencesCopyWith<$Res> { + _$PreferencesCopyWithImpl(this._self, this._then); + + final Preferences _self; + final $Res Function(Preferences) _then; + + /// Create a copy of Preferences + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? test = null, + }) { + return _then(_self.copyWith( + test: null == test + ? _self.test + : test // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// Adds pattern-matching-related methods to [Preferences]. +extension PreferencesPatterns on Preferences { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_Preferences value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _Preferences() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_Preferences value) $default, + ) { + final _that = this; + switch (_that) { + case _Preferences(): + return $default(_that); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_Preferences value)? $default, + ) { + final _that = this; + switch (_that) { + case _Preferences() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String test)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _Preferences() when $default != null: + return $default(_that.test); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String test) $default, + ) { + final _that = this; + switch (_that) { + case _Preferences(): + return $default(_that.test); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String test)? $default, + ) { + final _that = this; + switch (_that) { + case _Preferences() when $default != null: + return $default(_that.test); + case _: + return null; + } + } +} + +/// @nodoc +@JsonSerializable() +class _Preferences implements Preferences { + const _Preferences({required this.test}); + factory _Preferences.fromJson(Map json) => + _$PreferencesFromJson(json); + + @override + final String test; + + /// Create a copy of Preferences + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$PreferencesCopyWith<_Preferences> get copyWith => + __$PreferencesCopyWithImpl<_Preferences>(this, _$identity); + + @override + Map toJson() { + return _$PreferencesToJson( + this, + ); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _Preferences && + (identical(other.test, test) || other.test == test)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, test); + + @override + String toString() { + return 'Preferences(test: $test)'; + } +} + +/// @nodoc +abstract mixin class _$PreferencesCopyWith<$Res> + implements $PreferencesCopyWith<$Res> { + factory _$PreferencesCopyWith( + _Preferences value, $Res Function(_Preferences) _then) = + __$PreferencesCopyWithImpl; + @override + @useResult + $Res call({String test}); +} + +/// @nodoc +class __$PreferencesCopyWithImpl<$Res> implements _$PreferencesCopyWith<$Res> { + __$PreferencesCopyWithImpl(this._self, this._then); + + final _Preferences _self; + final $Res Function(_Preferences) _then; + + /// Create a copy of Preferences + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? test = null, + }) { + return _then(_Preferences( + test: null == test + ? _self.test + : test // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +// dart format on diff --git a/frontend/lib/domain/entities/preferences.g.dart b/frontend/lib/domain/entities/preferences.g.dart new file mode 100644 index 0000000..0398396 --- /dev/null +++ b/frontend/lib/domain/entities/preferences.g.dart @@ -0,0 +1,16 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'preferences.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_Preferences _$PreferencesFromJson(Map json) => _Preferences( + test: json['test'] as String, + ); + +Map _$PreferencesToJson(_Preferences instance) => + { + 'test': instance.test, + }; diff --git a/frontend/lib/domain/entities/trip.dart b/frontend/lib/domain/entities/trip.dart new file mode 100644 index 0000000..ab07ea3 --- /dev/null +++ b/frontend/lib/domain/entities/trip.dart @@ -0,0 +1,19 @@ +import 'package:anyway/domain/entities/landmark.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'trip.freezed.dart'; +part 'trip.g.dart'; + + +@Freezed(makeCollectionsUnmodifiable: false) +abstract class Trip with _$Trip { + + const factory Trip({ + required String uuid, + // Duration totalTime, + required List landmarks, + }) = _Trip; + + factory Trip.fromJson(Map json) => _$TripFromJson(json); + +} diff --git a/frontend/lib/domain/entities/trip.freezed.dart b/frontend/lib/domain/entities/trip.freezed.dart new file mode 100644 index 0000000..32a98c0 --- /dev/null +++ b/frontend/lib/domain/entities/trip.freezed.dart @@ -0,0 +1,327 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'trip.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$Trip { + String get uuid; // Duration totalTime, + List get landmarks; + + /// Create a copy of Trip + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + $TripCopyWith get copyWith => + _$TripCopyWithImpl(this as Trip, _$identity); + + /// Serializes this Trip to a JSON map. + Map toJson(); + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is Trip && + (identical(other.uuid, uuid) || other.uuid == uuid) && + const DeepCollectionEquality().equals(other.landmarks, landmarks)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, uuid, const DeepCollectionEquality().hash(landmarks)); + + @override + String toString() { + return 'Trip(uuid: $uuid, landmarks: $landmarks)'; + } +} + +/// @nodoc +abstract mixin class $TripCopyWith<$Res> { + factory $TripCopyWith(Trip value, $Res Function(Trip) _then) = + _$TripCopyWithImpl; + @useResult + $Res call({String uuid, List landmarks}); +} + +/// @nodoc +class _$TripCopyWithImpl<$Res> implements $TripCopyWith<$Res> { + _$TripCopyWithImpl(this._self, this._then); + + final Trip _self; + final $Res Function(Trip) _then; + + /// Create a copy of Trip + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? uuid = null, + Object? landmarks = null, + }) { + return _then(_self.copyWith( + uuid: null == uuid + ? _self.uuid + : uuid // ignore: cast_nullable_to_non_nullable + as String, + landmarks: null == landmarks + ? _self.landmarks + : landmarks // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// Adds pattern-matching-related methods to [Trip]. +extension TripPatterns on Trip { + /// A variant of `map` that fallback to returning `orElse`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeMap( + TResult Function(_Trip value)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _Trip() when $default != null: + return $default(_that); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// Callbacks receives the raw object, upcasted. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case final Subclass2 value: + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult map( + TResult Function(_Trip value) $default, + ) { + final _that = this; + switch (_that) { + case _Trip(): + return $default(_that); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `map` that fallback to returning `null`. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case final Subclass value: + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? mapOrNull( + TResult? Function(_Trip value)? $default, + ) { + final _that = this; + switch (_that) { + case _Trip() when $default != null: + return $default(_that); + case _: + return null; + } + } + + /// A variant of `when` that fallback to an `orElse` callback. + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return orElse(); + /// } + /// ``` + + @optionalTypeArgs + TResult maybeWhen( + TResult Function(String uuid, List landmarks)? $default, { + required TResult orElse(), + }) { + final _that = this; + switch (_that) { + case _Trip() when $default != null: + return $default(_that.uuid, _that.landmarks); + case _: + return orElse(); + } + } + + /// A `switch`-like method, using callbacks. + /// + /// As opposed to `map`, this offers destructuring. + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case Subclass2(:final field2): + /// return ...; + /// } + /// ``` + + @optionalTypeArgs + TResult when( + TResult Function(String uuid, List landmarks) $default, + ) { + final _that = this; + switch (_that) { + case _Trip(): + return $default(_that.uuid, _that.landmarks); + case _: + throw StateError('Unexpected subclass'); + } + } + + /// A variant of `when` that fallback to returning `null` + /// + /// It is equivalent to doing: + /// ```dart + /// switch (sealedClass) { + /// case Subclass(:final field): + /// return ...; + /// case _: + /// return null; + /// } + /// ``` + + @optionalTypeArgs + TResult? whenOrNull( + TResult? Function(String uuid, List landmarks)? $default, + ) { + final _that = this; + switch (_that) { + case _Trip() when $default != null: + return $default(_that.uuid, _that.landmarks); + case _: + return null; + } + } +} + +/// @nodoc +@JsonSerializable() +class _Trip implements Trip { + const _Trip({required this.uuid, required this.landmarks}); + factory _Trip.fromJson(Map json) => _$TripFromJson(json); + + @override + final String uuid; +// Duration totalTime, + @override + final List landmarks; + + /// Create a copy of Trip + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + @pragma('vm:prefer-inline') + _$TripCopyWith<_Trip> get copyWith => + __$TripCopyWithImpl<_Trip>(this, _$identity); + + @override + Map toJson() { + return _$TripToJson( + this, + ); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _Trip && + (identical(other.uuid, uuid) || other.uuid == uuid) && + const DeepCollectionEquality().equals(other.landmarks, landmarks)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, uuid, const DeepCollectionEquality().hash(landmarks)); + + @override + String toString() { + return 'Trip(uuid: $uuid, landmarks: $landmarks)'; + } +} + +/// @nodoc +abstract mixin class _$TripCopyWith<$Res> implements $TripCopyWith<$Res> { + factory _$TripCopyWith(_Trip value, $Res Function(_Trip) _then) = + __$TripCopyWithImpl; + @override + @useResult + $Res call({String uuid, List landmarks}); +} + +/// @nodoc +class __$TripCopyWithImpl<$Res> implements _$TripCopyWith<$Res> { + __$TripCopyWithImpl(this._self, this._then); + + final _Trip _self; + final $Res Function(_Trip) _then; + + /// Create a copy of Trip + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $Res call({ + Object? uuid = null, + Object? landmarks = null, + }) { + return _then(_Trip( + uuid: null == uuid + ? _self.uuid + : uuid // ignore: cast_nullable_to_non_nullable + as String, + landmarks: null == landmarks + ? _self.landmarks + : landmarks // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +// dart format on diff --git a/frontend/lib/domain/entities/trip.g.dart b/frontend/lib/domain/entities/trip.g.dart new file mode 100644 index 0000000..148cec2 --- /dev/null +++ b/frontend/lib/domain/entities/trip.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'trip.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_Trip _$TripFromJson(Map json) => _Trip( + uuid: json['uuid'] as String, + landmarks: (json['landmarks'] as List) + .map((e) => Landmark.fromJson(e as Map)) + .toList(), + ); + +Map _$TripToJson(_Trip instance) => { + 'uuid': instance.uuid, + 'landmarks': instance.landmarks, + }; diff --git a/frontend/lib/domain/repositories/preferences_repository.dart b/frontend/lib/domain/repositories/preferences_repository.dart new file mode 100644 index 0000000..5bce78a --- /dev/null +++ b/frontend/lib/domain/repositories/preferences_repository.dart @@ -0,0 +1,5 @@ +import 'package:anyway/domain/entities/preferences.dart'; + +abstract class PreferencesRepository { + Future getPreferences(); +} diff --git a/frontend/lib/domain/repositories/trip_repository.dart b/frontend/lib/domain/repositories/trip_repository.dart new file mode 100644 index 0000000..82f222e --- /dev/null +++ b/frontend/lib/domain/repositories/trip_repository.dart @@ -0,0 +1,6 @@ +import 'package:anyway/domain/entities/preferences.dart'; +import 'package:anyway/domain/entities/trip.dart'; + +abstract class TripRepository { + Future getTrip({Preferences? preferences, String? tripUUID}); +} diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 2fe5991..a670a10 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -1,26 +1,39 @@ +import 'package:anyway/presentation/pages/start.dart'; import 'package:flutter/material.dart'; - -import 'package:anyway/constants.dart'; -import 'package:anyway/utils/get_first_page.dart'; -import 'package:anyway/utils/load_trips.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:anyway/core/constants.dart'; +import 'package:shared_preferences/shared_preferences.dart'; -void main() => runApp(const App()); +/// The app entry point. +/// Initializes persistence, sets up dependency injection via ProviderScope, +/// and determines which screen (login or main app) to show based on auth state. +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); -// Some global variables -final GlobalKey rootScaffoldMessengerKey = GlobalKey(); -final SavedTrips savedTrips = SavedTrips(); -// the list of saved trips is then populated implicitly by getFirstPage() + // initialize local persistence (shared preferences) + SharedPreferences prefs = await SharedPreferences.getInstance(); + // the app wrapped in ProviderScope + runApp(const ProviderScope(child: MyApp())); +} + +class MyApp extends ConsumerWidget { + const MyApp({super.key}); -class App extends StatelessWidget { - const App({super.key}); @override - Widget build(BuildContext context) => MaterialApp( - title: APP_NAME, - home: getFirstPage(), - theme: APP_THEME, - scaffoldMessengerKey: rootScaffoldMessengerKey - ); + Widget build(BuildContext context, WidgetRef ref) { + + return MaterialApp( + debugShowCheckedModeBanner: false, + title: APP_NAME, + theme: APP_THEME, + scaffoldMessengerKey: rootScaffoldMessengerKey, + home: const StartPage() + + // TODO - set up routing + // onGenerateRoute: AppRouter.onGenerateRoute, + ); + } } diff --git a/frontend/lib/constants.dart b/frontend/lib/old/constants.dart similarity index 100% rename from frontend/lib/constants.dart rename to frontend/lib/old/constants.dart diff --git a/frontend/lib/layouts/scaffold.dart b/frontend/lib/old/layouts/scaffold.dart similarity index 100% rename from frontend/lib/layouts/scaffold.dart rename to frontend/lib/old/layouts/scaffold.dart diff --git a/frontend/lib/modules/current_trip_error_message.dart b/frontend/lib/old/modules/current_trip_error_message.dart similarity index 100% rename from frontend/lib/modules/current_trip_error_message.dart rename to frontend/lib/old/modules/current_trip_error_message.dart diff --git a/frontend/lib/modules/current_trip_greeter.dart b/frontend/lib/old/modules/current_trip_greeter.dart similarity index 100% rename from frontend/lib/modules/current_trip_greeter.dart rename to frontend/lib/old/modules/current_trip_greeter.dart diff --git a/frontend/lib/modules/current_trip_landmarks_list.dart b/frontend/lib/old/modules/current_trip_landmarks_list.dart similarity index 100% rename from frontend/lib/modules/current_trip_landmarks_list.dart rename to frontend/lib/old/modules/current_trip_landmarks_list.dart diff --git a/frontend/lib/modules/current_trip_loading_indicator.dart b/frontend/lib/old/modules/current_trip_loading_indicator.dart similarity index 100% rename from frontend/lib/modules/current_trip_loading_indicator.dart rename to frontend/lib/old/modules/current_trip_loading_indicator.dart diff --git a/frontend/lib/modules/current_trip_locations.dart b/frontend/lib/old/modules/current_trip_locations.dart similarity index 100% rename from frontend/lib/modules/current_trip_locations.dart rename to frontend/lib/old/modules/current_trip_locations.dart diff --git a/frontend/lib/modules/current_trip_map.dart b/frontend/lib/old/modules/current_trip_map.dart similarity index 100% rename from frontend/lib/modules/current_trip_map.dart rename to frontend/lib/old/modules/current_trip_map.dart diff --git a/frontend/lib/modules/current_trip_overview.dart b/frontend/lib/old/modules/current_trip_overview.dart similarity index 100% rename from frontend/lib/modules/current_trip_overview.dart rename to frontend/lib/old/modules/current_trip_overview.dart diff --git a/frontend/lib/modules/current_trip_panel.dart b/frontend/lib/old/modules/current_trip_panel.dart similarity index 100% rename from frontend/lib/modules/current_trip_panel.dart rename to frontend/lib/old/modules/current_trip_panel.dart diff --git a/frontend/lib/modules/current_trip_save_button.dart b/frontend/lib/old/modules/current_trip_save_button.dart similarity index 100% rename from frontend/lib/modules/current_trip_save_button.dart rename to frontend/lib/old/modules/current_trip_save_button.dart diff --git a/frontend/lib/modules/current_trip_summary.dart b/frontend/lib/old/modules/current_trip_summary.dart similarity index 100% rename from frontend/lib/modules/current_trip_summary.dart rename to frontend/lib/old/modules/current_trip_summary.dart diff --git a/frontend/lib/modules/help_dialog.dart b/frontend/lib/old/modules/help_dialog.dart similarity index 100% rename from frontend/lib/modules/help_dialog.dart rename to frontend/lib/old/modules/help_dialog.dart diff --git a/frontend/lib/modules/landmark_card.dart b/frontend/lib/old/modules/landmark_card.dart similarity index 100% rename from frontend/lib/modules/landmark_card.dart rename to frontend/lib/old/modules/landmark_card.dart diff --git a/frontend/lib/modules/landmark_map_marker.dart b/frontend/lib/old/modules/landmark_map_marker.dart similarity index 100% rename from frontend/lib/modules/landmark_map_marker.dart rename to frontend/lib/old/modules/landmark_map_marker.dart diff --git a/frontend/lib/modules/map_chooser.dart b/frontend/lib/old/modules/map_chooser.dart similarity index 100% rename from frontend/lib/modules/map_chooser.dart rename to frontend/lib/old/modules/map_chooser.dart diff --git a/frontend/lib/modules/new_trip_button.dart b/frontend/lib/old/modules/new_trip_button.dart similarity index 100% rename from frontend/lib/modules/new_trip_button.dart rename to frontend/lib/old/modules/new_trip_button.dart diff --git a/frontend/lib/modules/new_trip_location_search.dart b/frontend/lib/old/modules/new_trip_location_search.dart similarity index 100% rename from frontend/lib/modules/new_trip_location_search.dart rename to frontend/lib/old/modules/new_trip_location_search.dart diff --git a/frontend/lib/modules/new_trip_map.dart b/frontend/lib/old/modules/new_trip_map.dart similarity index 100% rename from frontend/lib/modules/new_trip_map.dart rename to frontend/lib/old/modules/new_trip_map.dart diff --git a/frontend/lib/modules/new_trip_options_button.dart b/frontend/lib/old/modules/new_trip_options_button.dart similarity index 100% rename from frontend/lib/modules/new_trip_options_button.dart rename to frontend/lib/old/modules/new_trip_options_button.dart diff --git a/frontend/lib/modules/onbarding_agreement_card.dart b/frontend/lib/old/modules/onbarding_agreement_card.dart similarity index 100% rename from frontend/lib/modules/onbarding_agreement_card.dart rename to frontend/lib/old/modules/onbarding_agreement_card.dart diff --git a/frontend/lib/modules/onboarding_card.dart b/frontend/lib/old/modules/onboarding_card.dart similarity index 100% rename from frontend/lib/modules/onboarding_card.dart rename to frontend/lib/old/modules/onboarding_card.dart diff --git a/frontend/lib/modules/step_between_landmarks.dart b/frontend/lib/old/modules/step_between_landmarks.dart similarity index 100% rename from frontend/lib/modules/step_between_landmarks.dart rename to frontend/lib/old/modules/step_between_landmarks.dart diff --git a/frontend/lib/modules/trips_saved_list.dart b/frontend/lib/old/modules/trips_saved_list.dart similarity index 100% rename from frontend/lib/modules/trips_saved_list.dart rename to frontend/lib/old/modules/trips_saved_list.dart diff --git a/frontend/lib/pages/current_trip.dart b/frontend/lib/old/pages/current_trip.dart similarity index 100% rename from frontend/lib/pages/current_trip.dart rename to frontend/lib/old/pages/current_trip.dart diff --git a/frontend/lib/pages/new_trip_location.dart b/frontend/lib/old/pages/new_trip_location.dart similarity index 100% rename from frontend/lib/pages/new_trip_location.dart rename to frontend/lib/old/pages/new_trip_location.dart diff --git a/frontend/lib/pages/new_trip_preferences.dart b/frontend/lib/old/pages/new_trip_preferences.dart similarity index 100% rename from frontend/lib/pages/new_trip_preferences.dart rename to frontend/lib/old/pages/new_trip_preferences.dart diff --git a/frontend/lib/pages/no_trips_page.dart b/frontend/lib/old/pages/no_trips_page.dart similarity index 100% rename from frontend/lib/pages/no_trips_page.dart rename to frontend/lib/old/pages/no_trips_page.dart diff --git a/frontend/lib/pages/settings.dart b/frontend/lib/old/pages/settings.dart similarity index 100% rename from frontend/lib/pages/settings.dart rename to frontend/lib/old/pages/settings.dart diff --git a/frontend/lib/structs/agreement.dart b/frontend/lib/old/structs/agreement.dart similarity index 100% rename from frontend/lib/structs/agreement.dart rename to frontend/lib/old/structs/agreement.dart diff --git a/frontend/lib/structs/landmark.dart b/frontend/lib/old/structs/landmark.dart similarity index 100% rename from frontend/lib/structs/landmark.dart rename to frontend/lib/old/structs/landmark.dart diff --git a/frontend/lib/structs/preferences.dart b/frontend/lib/old/structs/preferences.dart similarity index 100% rename from frontend/lib/structs/preferences.dart rename to frontend/lib/old/structs/preferences.dart diff --git a/frontend/lib/structs/trip.dart b/frontend/lib/old/structs/trip.dart similarity index 100% rename from frontend/lib/structs/trip.dart rename to frontend/lib/old/structs/trip.dart diff --git a/frontend/lib/utils/fetch_trip.dart b/frontend/lib/old/utils/fetch_trip.dart similarity index 100% rename from frontend/lib/utils/fetch_trip.dart rename to frontend/lib/old/utils/fetch_trip.dart diff --git a/frontend/lib/utils/get_first_page.dart b/frontend/lib/old/utils/get_first_page.dart similarity index 100% rename from frontend/lib/utils/get_first_page.dart rename to frontend/lib/old/utils/get_first_page.dart diff --git a/frontend/lib/utils/load_landmark_image.dart b/frontend/lib/old/utils/load_landmark_image.dart similarity index 100% rename from frontend/lib/utils/load_landmark_image.dart rename to frontend/lib/old/utils/load_landmark_image.dart diff --git a/frontend/lib/utils/load_trips.dart b/frontend/lib/old/utils/load_trips.dart similarity index 100% rename from frontend/lib/utils/load_trips.dart rename to frontend/lib/old/utils/load_trips.dart diff --git a/frontend/lib/presentation/pages/create_trip.dart b/frontend/lib/presentation/pages/create_trip.dart new file mode 100644 index 0000000..078fa06 --- /dev/null +++ b/frontend/lib/presentation/pages/create_trip.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +class NewTripPage extends StatefulWidget { + const NewTripPage({super.key}); + + @override + _NewTripPageState createState() => _NewTripPageState(); +} + + +class _NewTripPageState extends State { + int _currentStep = 0; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Create New Trip'), + ), + body: Stepper( + currentStep: _currentStep, + onStepContinue: () { + if (_currentStep < 1) { + setState(() { + _currentStep += 1; + }); + } + }, + onStepCancel: () { + if (_currentStep > 0) { + setState(() { + _currentStep -= 1; + }); + } + }, + steps: [ + Step( + title: const Text('Select Location'), + content: const MapWithSearchField(), // Replace with your map module + isActive: _currentStep >= 0, + ), + Step( + title: const Text('Choose Options'), + content: const OptionsList(), // Replace with your options module + isActive: _currentStep >= 1, + ), + ], + ), + ); + } diff --git a/frontend/lib/presentation/pages/login.dart b/frontend/lib/presentation/pages/login.dart new file mode 100644 index 0000000..283171a --- /dev/null +++ b/frontend/lib/presentation/pages/login.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class LoginPage extends StatelessWidget { + const LoginPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center(child: Text('Login Page')), + ); + } +} diff --git a/frontend/lib/pages/onboarding.dart b/frontend/lib/presentation/pages/onboarding.dart similarity index 67% rename from frontend/lib/pages/onboarding.dart rename to frontend/lib/presentation/pages/onboarding.dart index c5d3446..f53e0c7 100644 --- a/frontend/lib/pages/onboarding.dart +++ b/frontend/lib/presentation/pages/onboarding.dart @@ -1,12 +1,11 @@ import 'dart:ui'; -import 'package:anyway/constants.dart'; -import 'package:anyway/modules/onbarding_agreement_card.dart'; -import 'package:anyway/modules/onboarding_card.dart'; -import 'package:anyway/pages/new_trip_location.dart'; -import 'package:anyway/structs/agreement.dart'; +import 'package:anyway/core/constants.dart'; +import 'package:anyway/presentation/providers/onboarding_state_provider.dart'; +import 'package:anyway/presentation/widgets/onbarding_agreement_card.dart'; +import 'package:anyway/presentation/widgets/onboarding_card.dart'; import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; List onboardingCards = [ @@ -33,14 +32,14 @@ List onboardingCards = [ ]; -class OnboardingPage extends StatefulWidget { +class OnboardingPage extends ConsumerStatefulWidget { const OnboardingPage({super.key}); @override - State createState() => _OnboardingPageState(); + ConsumerState createState() => _OnboardingPageState(); } -class _OnboardingPageState extends State { +class _OnboardingPageState extends ConsumerState { final PageController _controller = PageController(); late List fullCards; @@ -121,41 +120,53 @@ class _OnboardingPageState extends State { label: const Icon(Icons.arrow_forward) ); } else { - // only allow the user to proceed if they have agreed to the terms and conditions - Future hasAgreed = getAgreement().then((agreement) => agreement.agreed); + // only allow the user to proceed if they have agreed to the terms and conditions + // the information is accessible through ref.watch(onboardingStateProvider) - return FutureBuilder( - future: hasAgreed, - builder: (context, snapshot){ - if (snapshot.hasData && snapshot.data!) { - return FloatingActionButton.extended( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const NewTripPage() - ) - ); - }, - label: const Row( - children: [ - Text("Start planning!"), - Padding(padding: EdgeInsets.only(right: 8.0)), - Icon(Icons.map_outlined) - ], - ) - ); - } else { - return Container(); - } - } - ); + Widget disabledWidget = FloatingActionButton.extended( + onPressed: null, + label: const Row( + children: [ + Text("Start planning!"), + Padding(padding: EdgeInsets.only(right: 8.0)), + Icon(Icons.map_outlined) + ], + ) + ); + + return ref.watch(onboardingStateProvider).when( + data: (isOnboarded) { + if (isOnboarded) { + return FloatingActionButton.extended( + onPressed: () { + // proceed to the next page - pop the onboarding page so the StartPage can decide what to show next + Navigator.of(context).pop(); + }, + label: const Row( + children: [ + Text("Start planning!"), + Padding(padding: EdgeInsets.only(right: 8.0)), + Icon(Icons.map_outlined) + ], + ) + ); + } else { + return disabledWidget; + } + }, + loading: () => disabledWidget, + error: (error, stack) => disabledWidget, + ); } } ); void onAgreementChanged(bool value) async { - saveAgreement(value); - // Update the state of the OnboardingPage - setState(() {}); + await ref.read(onboardingControllerProvider).setOnboarded(value); + + setState(() { + // rebuild to show the next button + + }); } } diff --git a/frontend/lib/presentation/pages/start.dart b/frontend/lib/presentation/pages/start.dart new file mode 100644 index 0000000..d81fcc4 --- /dev/null +++ b/frontend/lib/presentation/pages/start.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:anyway/presentation/providers/onboarding_state_provider.dart'; +import 'package:anyway/presentation/pages/login.dart'; +import 'package:anyway/presentation/pages/onboarding.dart'; + +// Example providers (replace these with your actual providers) +// final onboardingStateProvider = Provider((ref) => true); // Replace with actual onboarding state logic +final authStateProvider = FutureProvider((ref) async => true); // Replace with actual auth state logic +final tripsAvailableProvider = FutureProvider((ref) async => false); // Replace with actual trips availability logic + +class StartPage extends ConsumerWidget { + const StartPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + // the home page is dependent on the state of the providers: + // - if the user is not onboarded, show the onboarding flow + // - if the user is not logged in, show the login page + // - if there are no trips available, show the trip creation page + // - else: show the overview page that shows the last trip + + final onboardingState = ref.watch(onboardingStateProvider); + final authState = ref.watch(authStateProvider); + final tripsAvailable = ref.watch(tripsAvailableProvider); + + return onboardingState.when( + data: (isOnboarded) { + if (!isOnboarded) { + return const OnboardingPage(); + } + + return authState.when( + data: (isLoggedIn) { + if (!isLoggedIn) { + return const LoginPage(); + } + + return tripsAvailable.when( + data: (hasTrips) { + if (!hasTrips) { + return const TripCreationPage(); + } + return const OverviewPage(); + }, + loading: () => const Scaffold( + body: Center(child: CircularProgressIndicator()), + ), + error: (error, stack) => Scaffold( + body: Center(child: Text('Error: $error')), + ), + ); + }, + loading: () => const Scaffold( + body: Center(child: CircularProgressIndicator()), + ), + error: (error, stack) => Scaffold( + body: Center(child: Text('Error: $error')), + ), + ); + }, + loading: () => const Scaffold( + body: Center(child: CircularProgressIndicator()), + ), + error: (error, stack) => Scaffold( + body: Center(child: Text('Error: $error') + ), + ), + ); + } +} + + + + +class TripCreationPage extends StatelessWidget { + const TripCreationPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center(child: Text('Trip Creation Page')), + ); + } +} + +class OverviewPage extends StatelessWidget { + const OverviewPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center(child: Text('Overview Page')), + ); + } +} diff --git a/frontend/lib/presentation/providers/auth_state_provider.dart b/frontend/lib/presentation/providers/auth_state_provider.dart new file mode 100644 index 0000000..e69de29 diff --git a/frontend/lib/presentation/providers/onboarding_state_provider.dart b/frontend/lib/presentation/providers/onboarding_state_provider.dart new file mode 100644 index 0000000..f9ffbb0 --- /dev/null +++ b/frontend/lib/presentation/providers/onboarding_state_provider.dart @@ -0,0 +1,24 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +final onboardingStateProvider = FutureProvider((ref) async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getBool('onboardingCompleted') ?? false; +}); + + +final onboardingControllerProvider = Provider((ref) { + return OnboardingController(ref); +}); + +class OnboardingController { + final Ref ref; + OnboardingController(this.ref); + + Future setOnboarded(bool value) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool('onboardingCompleted', value); + // refresh the read provider so UI updates + ref.invalidate(onboardingStateProvider); + } +} diff --git a/frontend/lib/presentation/providers/trip_provider.dart b/frontend/lib/presentation/providers/trip_provider.dart new file mode 100644 index 0000000..b3b0110 --- /dev/null +++ b/frontend/lib/presentation/providers/trip_provider.dart @@ -0,0 +1,6 @@ +// import 'package:anyway/data/repositories/trip_repository.dart'; +// import 'package:flutter_riverpod/flutter_riverpod.dart'; + +// final weatherRepositoryProvider = Provider((ref) { +// return TripRepositoryImpl(???); +// }); diff --git a/frontend/lib/presentation/widgets/create_trip_location.dart b/frontend/lib/presentation/widgets/create_trip_location.dart new file mode 100644 index 0000000..cd8dbf4 --- /dev/null +++ b/frontend/lib/presentation/widgets/create_trip_location.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:your_project/models/trip_request.dart'; +import 'package:your_project/presentation/widgets/new_trip_map.dart'; +import 'package:your_project/presentation/widgets/new_trip_location_search.dart'; + +class CreateTripLocation extends StatelessWidget { + final TripRequest tripRequest; + + const CreateTripLocation(this.tripRequest, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + NewTripMap(tripRequest), + Padding( + padding: const EdgeInsets.all(15), + child: NewTripLocationSearch(tripRequest), + ), + ], + ); + } +} diff --git a/frontend/lib/presentation/widgets/create_trip_location_map.dart b/frontend/lib/presentation/widgets/create_trip_location_map.dart new file mode 100644 index 0000000..cd203be --- /dev/null +++ b/frontend/lib/presentation/widgets/create_trip_location_map.dart @@ -0,0 +1,105 @@ +// A map that allows the user to select a location for a new trip. +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:widget_to_marker/widget_to_marker.dart'; + +import 'package:anyway/constants.dart'; + +import 'package:anyway/structs/trip.dart'; +import 'package:anyway/structs/landmark.dart'; +import 'package:anyway/modules/landmark_map_marker.dart'; + + +class NewTripMap extends StatefulWidget { + + @override + State createState() => _NewTripMapState(); +} + +class _NewTripMapState extends State { + final CameraPosition _cameraPosition = const CameraPosition( + target: LatLng(48.8566, 2.3522), + zoom: 11.0, + ); + GoogleMapController? _mapController; + final Set _markers = {}; + + _onLongPress(LatLng location) { + // widget.trip.landmarks.clear(); + // widget.trip.addLandmark( + // Landmark( + // uuid: 'pending', + // name: 'start', + // location: [location.latitude, location.longitude], + // type: typeStart + // ) + // ); + } + + updateTripDetails() async { + _markers.clear(); + if (widget.trip.landmarks.isNotEmpty) { + Landmark landmark = widget.trip.landmarks.first; + _markers.add( + Marker( + markerId: MarkerId(landmark.uuid), + position: LatLng(landmark.location[0], landmark.location[1]), + icon: await ThemedMarker(landmark: landmark, position: 0).toBitmapDescriptor( + logicalSize: const Size(150, 150), + imageSize: const Size(150, 150) + ), + ) + ); + // check if the controller is ready + + if (_mapController != null) { + _mapController!.animateCamera( + CameraUpdate.newLatLng( + LatLng(landmark.location[0], landmark.location[1]) + ) + ); + } + setState(() {}); + } + } + + void _onMapCreated(GoogleMapController controller) async { + _mapController = controller; + } + + + @override + Widget build(BuildContext context) { + widget.trip.addListener(updateTripDetails); + Future preferences = SharedPreferences.getInstance(); + + + return FutureBuilder( + future: preferences, + builder: (context, snapshot) { + if (snapshot.hasData) { + SharedPreferences prefs = snapshot.data as SharedPreferences; + bool useLocation = prefs.getBool('useLocation') ?? true; + return _buildMap(useLocation); + } else { + return const CircularProgressIndicator(); + } + } + ); + } + + Widget _buildMap(bool useLocation) { + return GoogleMap( + onMapCreated: _onMapCreated, + initialCameraPosition: _cameraPosition, + onLongPress: _onLongPress, + markers: _markers, + cloudMapId: MAP_ID, + mapToolbarEnabled: false, + zoomControlsEnabled: false, + myLocationButtonEnabled: false, + myLocationEnabled: useLocation, + ); + } +} diff --git a/frontend/lib/presentation/widgets/create_trip_location_search.dart b/frontend/lib/presentation/widgets/create_trip_location_search.dart new file mode 100644 index 0000000..ef29194 --- /dev/null +++ b/frontend/lib/presentation/widgets/create_trip_location_search.dart @@ -0,0 +1,124 @@ + +// A search bar that allow the user to enter a city name +import 'dart:developer'; +import 'package:flutter/material.dart'; +import 'package:geocoding/geocoding.dart'; + +import 'package:geolocator/geolocator.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +const Map debugLocations = { + 'paris': [48.8575, 2.3514], + 'london': [51.5074, -0.1278], + 'new york': [40.7128, -74.0060], + 'tokyo': [35.6895, 139.6917], +}; + + + +class NewTripLocationSearch extends StatefulWidget { + Future prefs = SharedPreferences.getInstance(); + Trip trip; + + NewTripLocationSearch( + this.trip, + ); + + + @override + State createState() => _NewTripLocationSearchState(); +} + +class _NewTripLocationSearchState extends State { + final TextEditingController _controller = TextEditingController(); + + setTripLocation (String query) async { + List locations = []; + Location startLocation; + log('Searching for: $query'); + if (GeocodingPlatform.instance != null) { + locations.addAll(await locationFromAddress(query)); + } + + if (locations.isNotEmpty) { + startLocation = locations.first; + } else { + log('No results found for: $query. Is geocoding available?'); + log('Setting Fallback location'); + List coordinates = debugLocations[query.toLowerCase()] ?? [48.8575, 2.3514]; + startLocation = Location( + latitude: coordinates[0], + longitude: coordinates[1], + timestamp: DateTime.now(), + ); + } + + widget.trip.landmarks.clear(); + widget.trip.addLandmark( + Landmark( + uuid: 'pending', + name: query, + location: [startLocation.latitude, startLocation.longitude], + type: typeStart + ) + ); + + } + + late Widget locationSearchBar = SearchBar( + hintText: 'Enter a city name or long press on the map.', + onSubmitted: setTripLocation, + controller: _controller, + leading: const Icon(Icons.search), + trailing: [ + ElevatedButton( + onPressed: () { + setTripLocation(_controller.text); + }, + child: const Text('Search'), + ) + ] + ); + + + late Widget useCurrentLocationButton = ElevatedButton( + onPressed: () async { + // this widget is only shown if the user has already granted location permissions + Position position = await Geolocator.getCurrentPosition(); + widget.trip.landmarks.clear(); + widget.trip.addLandmark( + Landmark( + uuid: 'pending', + name: 'start', + location: [position.latitude, position.longitude], + type: typeStart + ) + ); + }, + child: const Text('Use current location'), + ); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: widget.prefs, + builder: (context, snapshot) { + if (snapshot.hasData) { + final useLocation = snapshot.data!.getBool('useLocation') ?? false; + if (useLocation) { + return Column( + children: [ + locationSearchBar, + useCurrentLocationButton, + ], + ); + } else { + return locationSearchBar; + } + } else { + return locationSearchBar; + } + }, + ); + } +} diff --git a/frontend/lib/presentation/widgets/onbarding_agreement_card.dart b/frontend/lib/presentation/widgets/onbarding_agreement_card.dart new file mode 100644 index 0000000..fbd49ba --- /dev/null +++ b/frontend/lib/presentation/widgets/onbarding_agreement_card.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_markdown_plus/flutter_markdown_plus.dart'; +import 'package:anyway/presentation/providers/onboarding_state_provider.dart'; +import 'package:anyway/presentation/widgets/onboarding_card.dart'; + + + +class OnboardingAgreementCard extends ConsumerStatefulWidget { + final String title; + final String description; + final String imagePath; + final String agreementTextPath; + final ValueChanged onAgreementChanged; + + + const OnboardingAgreementCard({ + super.key, + required this.title, + required this.description, + required this.imagePath, + required this.agreementTextPath, + required this.onAgreementChanged + }); + + @override + ConsumerState createState() => _OnboardingAgreementCardState(); + +} + +class _OnboardingAgreementCardState extends ConsumerState { + + // @override + // void initState() { + // super.initState(); + // // You can use ref here if needed in initState + // } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + OnboardingCard(title: widget.title, description: widget.description, imagePath: widget.imagePath), + const Padding(padding: EdgeInsets.only(top: 20)), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // The checkbox of the agreement + FutureBuilder( + future: ref.read(onboardingStateProvider.future), + builder: (context, snapshot) { + bool agreed = false; + if (snapshot.hasData) { + agreed = snapshot.data!; + } + return Checkbox( + value: agreed, + onChanged: (bool? value) { + if (value != null) { + widget.onAgreementChanged(value); + } + }, + activeColor: Colors.white, + checkColor: Colors.black, + ); + }, + ), + + // The text of the agreement + Text( + "I agree to the ", + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Colors.white, + ), + ), + + // The clickable text of the agreement that shows the agreement text + GestureDetector( + onTap: () { + // show a dialog with the agreement text + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + scrollable: true, + content: FutureBuilder( + future: DefaultAssetBundle.of(context).loadString(widget.agreementTextPath), + builder: (context, snapshot) { + if (snapshot.hasData) { + return MarkdownBody( + data: snapshot.data.toString(), + ); + } else { + return const CircularProgressIndicator(); + } + + }, + ) + ); + } + ); + + }, + child: Text( + "Terms of Service (click to view)", + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/frontend/lib/presentation/widgets/onboarding_card.dart b/frontend/lib/presentation/widgets/onboarding_card.dart new file mode 100644 index 0000000..1202b73 --- /dev/null +++ b/frontend/lib/presentation/widgets/onboarding_card.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class OnboardingCard extends StatelessWidget { + final String title; + final String description; + final String imagePath; + + const OnboardingCard({super.key, + required this.title, + required this.description, + required this.imagePath, + }); + + @override + Widget build(BuildContext context) { + + return Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + title, + style: Theme.of(context).textTheme.headlineLarge!.copyWith( + color: Colors.white, + ), + ), + const Padding(padding: EdgeInsets.only(top: 20)), + SvgPicture.asset( + imagePath, + height: 200, + ), + const Padding(padding: EdgeInsets.only(top: 20)), + Text( + description, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Colors.white, + ), + ), + ] + ), + ); + } +} diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index 62d371f..9839703 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -1,14 +1,46 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + url: "https://pub.dev" + source: hosted + version: "85.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c + url: "https://pub.dev" + source: hosted + version: "7.6.0" + analyzer_buffer: + dependency: transitive + description: + name: analyzer_buffer + sha256: f7833bee67c03c37241c67f8741b17cc501b69d9758df7a5a4a13ed6c947be43 + url: "https://pub.dev" + source: hosted + version: "0.1.10" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce + url: "https://pub.dev" + source: hosted + version: "0.13.4" archive: dependency: transitive description: name: archive - sha256: "7dcbd0f87fe5f61cb28da39a1a8b70dbc106e2fe0516f7836eb7bb2948481a12" + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" url: "https://pub.dev" source: hosted - version: "4.0.5" + version: "4.0.7" args: dependency: transitive description: @@ -41,6 +73,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: ce76b1d48875e3233fde17717c23d1f60a91cc631597e49a400c89b475395b1d + url: "https://pub.dev" + source: hosted + version: "3.1.0" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 + url: "https://pub.dev" + source: hosted + version: "4.1.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: d1d57f7807debd7349b4726a19fd32ec8bc177c71ad0febf91a20f84cd2d4b46 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: b24597fceb695969d47025c958f3837f9f0122e237c6a22cb082a5ac66c3ca30 + url: "https://pub.dev" + source: hosted + version: "2.7.1" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "066dda7f73d8eb48ba630a55acb50c4a84a2e6b453b1cb4567f581729e794f7b" + url: "https://pub.dev" + source: hosted + version: "9.3.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: a30f0a0e38671e89a492c44d005b5545b830a961575bbd8336d42869ff71066d + url: "https://pub.dev" + source: hosted + version: "8.12.0" cached_network_image: dependency: "direct main" description: @@ -77,10 +173,26 @@ packages: dependency: transitive description: name: checked_yaml - sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "2.0.4" + ci: + dependency: transitive + description: + name: ci + sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" cli_util: dependency: transitive description: @@ -97,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243" + url: "https://pub.dev" + source: hosted + version: "4.11.0" collection: dependency: transitive description: @@ -105,14 +225,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" crypto: dependency: transitive description: name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" csslib: dependency: transitive description: @@ -129,14 +265,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + custom_lint: + dependency: "direct dev" + description: + name: custom_lint + sha256: "78085fbe842de7c5bef92de811ca81536968dbcbbcdac5c316711add2d15e796" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + custom_lint_builder: + dependency: transitive + description: + name: custom_lint_builder + sha256: cc5532d5733d4eccfccaaec6070a1926e9f21e613d93ad0927fad020b95c9e52 + url: "https://pub.dev" + source: hosted + version: "0.8.0" + custom_lint_core: + dependency: transitive + description: + name: custom_lint_core + sha256: cc4684d22ca05bf0a4a51127e19a8aea576b42079ed2bc9e956f11aaebe35dd1 + url: "https://pub.dev" + source: hosted + version: "0.8.0" + custom_lint_visitor: + dependency: transitive + description: + name: custom_lint_visitor + sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2" + url: "https://pub.dev" + source: hosted + version: "1.0.0+7.7.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.dev" + source: hosted + version: "0.7.11" dio: dependency: "direct main" description: name: dio - sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9 url: "https://pub.dev" source: hosted - version: "5.8.0+1" + version: "5.9.0" dio_web_adapter: dependency: transitive description: @@ -194,42 +378,50 @@ packages: dependency: "direct main" description: name: flutter_launcher_icons - sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" url: "https://pub.dev" source: hosted - version: "0.13.1" + version: "0.14.4" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" url: "https://pub.dev" source: hosted - version: "4.0.0" - flutter_markdown: + version: "6.0.0" + flutter_markdown_plus: dependency: "direct main" description: - name: flutter_markdown - sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5 + name: flutter_markdown_plus + sha256: "7f349c075157816da399216a4127096108fd08e1ac931e34e72899281db4113c" url: "https://pub.dev" source: hosted - version: "0.7.6+2" + version: "1.0.5" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "5a1e6fb2c0561958d7e4c33574674bda7b77caaca7a33b758876956f2902eea3" + sha256: c2fe1001710127dfa7da89977a08d591398370d099aacdaa6d44da7eb14b8476 url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.0.31" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "9e2d6907f12cc7d23a846847615941bddee8709bf2bfd274acdf5e80bcf22fde" + url: "https://pub.dev" + source: hosted + version: "3.0.3" flutter_svg: dependency: "direct main" description: name: flutter_svg - sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b + sha256: "055de8921be7b8e8b98a233c7a5ef84b3a6fcc32f46f1ebf5b9bb3576d108355" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.2.2" flutter_test: dependency: "direct dev" description: flutter @@ -240,38 +432,62 @@ packages: description: flutter source: sdk version: "0.0.0" - fuzzywuzzy: - dependency: "direct main" + freezed: + dependency: "direct dev" description: - name: fuzzywuzzy - sha256: "3004379ffd6e7f476a0c2091f38f16588dc45f67de7adf7c41aa85dec06b432c" + name: freezed + sha256: "13065f10e135263a4f5a4391b79a8efc5fb8106f8dd555a9e49b750b45393d77" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "3.2.3" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + geoclue: + dependency: transitive + description: + name: geoclue + sha256: c2a998c77474fc57aa00c6baa2928e58f4b267649057a1c76738656e9dbd2a7f + url: "https://pub.dev" + source: hosted + version: "0.1.1" geocoding: dependency: "direct main" description: name: geocoding - sha256: d580c801cba9386b4fac5047c4c785a4e19554f46be42f4f5e5b7deacd088a66 + sha256: "606be036287842d779d7ec4e2f6c9435fc29bbbd3c6da6589710f981d8852895" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.0.0" geocoding_android: dependency: transitive description: name: geocoding_android - sha256: "1b13eca79b11c497c434678fed109c2be020b158cec7512c848c102bc7232603" + sha256: ba810da90d6633cbb82bbab630e5b4a3b7d23503263c00ae7f1ef0316dcae5b9 url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "4.0.1" geocoding_ios: dependency: transitive description: name: geocoding_ios - sha256: "94ddba60387501bd1c11e18dca7c5a9e8c645d6e3da9c38b9762434941870c24" + sha256: "18ab1c8369e2b0dcb3a8ccc907319334f35ee8cf4cfef4d9c8e23b13c65cb825" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.0" geocoding_platform_interface: dependency: transitive description: @@ -284,18 +500,18 @@ packages: dependency: "direct main" description: name: geolocator - sha256: afebc912cbe6496e8823e064ca519afb5610072bb9c4a9feea715f6feb4f7f28 + sha256: "79939537046c9025be47ec645f35c8090ecadb6fe98eba146a0d25e8c1357516" url: "https://pub.dev" source: hosted - version: "13.0.3" + version: "14.0.2" geolocator_android: dependency: transitive description: name: geolocator_android - sha256: fcb1760a50d7500deca37c9a666785c047139b5f9ee15aa5469fae7dbbe3170d + sha256: "179c3cb66dfa674fc9ccbf2be872a02658724d1c067634e2c427cf6df7df901a" url: "https://pub.dev" source: hosted - version: "4.6.2" + version: "5.0.2" geolocator_apple: dependency: transitive description: @@ -304,6 +520,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.13" + geolocator_linux: + dependency: transitive + description: + name: geolocator_linux + sha256: c4e966f0a7a87e70049eac7a2617f9e16fd4c585a26e4330bdfc3a71e6a721f3 + url: "https://pub.dev" + source: hosted + version: "0.2.3" geolocator_platform_interface: dependency: transitive description: @@ -316,82 +540,122 @@ packages: dependency: transitive description: name: geolocator_web - sha256: e54434b2ce9c677759a188d7e32e950802f79a9e9f45728239404bece0f1bd8d + sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172 url: "https://pub.dev" source: hosted - version: "4.1.2" + version: "4.1.3" geolocator_windows: dependency: transitive description: name: geolocator_windows - sha256: "4862e798b8a84ec300531888e7acd137b74637636069df230d79fabd110e2734" + sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6" url: "https://pub.dev" source: hosted - version: "0.2.4" + version: "0.2.5" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" google_maps: dependency: transitive description: name: google_maps - sha256: "4d6e199c561ca06792c964fa24b2bac7197bf4b401c2e1d23e345e5f9939f531" + sha256: "5d410c32112d7c6eb7858d359275b2aa04778eed3e36c745aeae905fb2fa6468" url: "https://pub.dev" source: hosted - version: "8.1.1" + version: "8.2.0" google_maps_flutter: dependency: "direct main" description: name: google_maps_flutter - sha256: "20b84284fb8de970e3734820a5b3dae35983fafca3a873c8ee346d7802072fb0" + sha256: "819985697596a42e1054b5feb2f407ba1ac92262e02844a40168e742b9f36dca" url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.14.0" google_maps_flutter_android: dependency: transitive description: name: google_maps_flutter_android - sha256: f199fdcb8a8e1b77f6aaed78aeed1e46b7526daf9007d5c71536a8266c4f0081 + sha256: "7c7ff5b883b27bfdd0d52d91d89faf00858a6c1b33aeca0dc80faca64f389983" url: "https://pub.dev" source: hosted - version: "2.15.0" + version: "2.18.3" google_maps_flutter_ios: dependency: transitive description: name: google_maps_flutter_ios - sha256: "7b5663bfcfbbe8ff96f394ba351b53fa00a8ba75cfc894b790426df4e2d888d6" + sha256: ca02463b19a9abc7d31fcaf22631d021d647107467f741b917a69fa26659fd75 url: "https://pub.dev" source: hosted - version: "2.14.0" + version: "2.15.5" google_maps_flutter_platform_interface: dependency: transitive description: name: google_maps_flutter_platform_interface - sha256: "970c8f766c02909c7be282dea923c971f83a88adaf07f8871d0aacebc3b07bb2" + sha256: f4b9b44f7b12a1f6707ffc79d082738e0b7e194bf728ee61d2b3cdf5fdf16081 url: "https://pub.dev" source: hosted - version: "2.11.1" + version: "2.14.0" google_maps_flutter_web: dependency: transitive description: name: google_maps_flutter_web - sha256: a45786ea6691cc7cdbe2cf3ce2c2daf4f82a885745666b4a36baada3a4e12897 + sha256: d416602944e1859f3cbbaa53e34785c223fa0a11eddb34a913c964c5cbb5d8cf url: "https://pub.dev" source: hosted - version: "0.5.12" + version: "0.5.14+3" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + gsettings: + dependency: transitive + description: + name: gsettings + sha256: "1b0ce661f5436d2db1e51f3c4295a49849f03d304003a7ba177d01e3a858249c" + url: "https://pub.dev" + source: hosted + version: "0.2.8" + hotreloader: + dependency: transitive + description: + name: hotreloader + sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b + url: "https://pub.dev" + source: hosted + version: "4.3.0" html: dependency: transitive description: name: html - sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" url: "https://pub.dev" source: hosted - version: "0.15.5" + version: "0.15.6" http: dependency: "direct main" description: name: http - sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.6.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" http_parser: dependency: transitive description: @@ -408,14 +672,38 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.4" - json_annotation: + io: dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + json_annotation: + dependency: "direct main" description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted version: "4.9.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: "33a040668b31b320aafa4822b7b1e177e163fc3c1e835c6750319d4ab23aa6fe" + url: "https://pub.dev" + source: hosted + version: "6.11.1" leak_tracker: dependency: transitive description: @@ -444,18 +732,18 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 url: "https://pub.dev" source: hosted - version: "4.0.0" - map_launcher: - dependency: "direct main" + version: "6.0.0" + logging: + dependency: transitive description: - name: map_launcher - sha256: "7436d6ef9ae57ff15beafcedafe0a8f0604006cbecd2d26024c4cfb0158c2b9a" + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "1.3.0" markdown: dependency: transitive description: @@ -488,14 +776,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" - nested: + mime: dependency: transitive description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "2.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" octo_image: dependency: transitive description: @@ -504,6 +800,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + package_info_plus: + dependency: transitive + description: + name: package_info_plus + sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" + url: "https://pub.dev" + source: hosted + version: "8.3.1" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + url: "https://pub.dev" + source: hosted + version: "3.2.1" path: dependency: transitive description: @@ -532,18 +852,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "0ca7359dad67fd7063cb2892ab0c0737b2daafd807cf1acecd62374c8fae6c12" + sha256: "3b4c1fc3aa55ddc9cd4aa6759984330d5c8e66aa7702a6223c61540dc6380c37" url: "https://pub.dev" source: hosted - version: "2.2.16" + version: "2.2.19" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -572,26 +892,26 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" + sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 url: "https://pub.dev" source: hosted - version: "11.4.0" + version: "12.0.1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc + sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6" url: "https://pub.dev" source: hosted - version: "12.1.0" + version: "13.0.1" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98 + sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 url: "https://pub.dev" source: hosted - version: "9.4.6" + version: "9.4.7" permission_handler_html: dependency: transitive description: @@ -620,10 +940,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "7.0.1" platform: dependency: transitive description: @@ -640,22 +960,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" posix: dependency: transitive description: name: posix - sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" url: "https://pub.dev" source: hosted - version: "6.0.1" - provider: - dependency: "direct main" + version: "6.0.3" + pub_semver: + dependency: transitive description: - name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: c406de02bff19d920b832bddfb8283548bfa05ce41c59afba57ce643e116aa59 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + riverpod_analyzer_utils: + dependency: transitive + description: + name: riverpod_analyzer_utils + sha256: a0f68adb078b790faa3c655110a017f9a7b7b079a57bbd40f540e80dce5fcd29 + url: "https://pub.dev" + source: hosted + version: "1.0.0-dev.7" + riverpod_lint: + dependency: "direct dev" + description: + name: riverpod_lint + sha256: "7ef9c43469e9b5ac4e4c3b24d7c30642e47ce1b12cd7dcdd643534db0a72ed13" + url: "https://pub.dev" + source: hosted + version: "3.0.3" rxdart: dependency: transitive description: @@ -676,18 +1036,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "3ec7210872c4ba945e3244982918e502fa2bfb5230dff6832459ca0e1879b7ad" + sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.13" shared_preferences_foundation: dependency: transitive description: @@ -728,6 +1088,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -741,6 +1133,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0+1" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "7b19d6ba131c6eb98bfcbf8d56c1a7002eba438af2e7ae6f8398b2b0f4f381e3" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" + url: "https://pub.dev" + source: hosted + version: "1.3.8" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" source_span: dependency: transitive description: @@ -749,14 +1173,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" sqflite: dependency: transitive description: @@ -777,10 +1193,10 @@ packages: dependency: transitive description: name: sqflite_common - sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b" + sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" url: "https://pub.dev" source: hosted - version: "2.5.5" + version: "2.5.6" sqflite_darwin: dependency: transitive description: @@ -805,6 +1221,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -833,10 +1257,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6" + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.4.0" term_glyph: dependency: transitive description: @@ -845,6 +1269,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" + url: "https://pub.dev" + source: hosted + version: "1.25.15" test_api: dependency: transitive description: @@ -853,6 +1285,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.4" + test_core: + dependency: transitive + description: + name: test_core + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" + url: "https://pub.dev" + source: hosted + version: "0.6.8" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" typed_data: dependency: transitive description: @@ -865,26 +1313,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "1d0eae19bd7606ef60fe69ef3b312a437a16549476c42321d5dc1506c9ca3bf4" + sha256: "81777b08c498a292d93ff2feead633174c386291e35612f8da438d6e92c4447e" url: "https://pub.dev" source: hosted - version: "6.3.15" + version: "6.3.20" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" + sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.4" url_launcher_linux: dependency: transitive description: @@ -897,10 +1345,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.3" url_launcher_platform_interface: dependency: transitive description: @@ -913,10 +1361,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" url_launcher_windows: dependency: transitive description: @@ -926,21 +1374,21 @@ packages: source: hosted version: "3.1.4" uuid: - dependency: transitive + dependency: "direct main" description: name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.5.2" vector_graphics: dependency: transitive description: name: vector_graphics - sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 url: "https://pub.dev" source: hosted - version: "1.1.18" + version: "1.1.19" vector_graphics_codec: dependency: transitive description: @@ -953,10 +1401,10 @@ packages: dependency: transitive description: name: vector_graphics_compiler - sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" + sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc url: "https://pub.dev" source: hosted - version: "1.1.16" + version: "1.1.19" vector_math: dependency: transitive description: @@ -973,6 +1421,14 @@ packages: url: "https://pub.dev" source: hosted version: "15.0.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" + url: "https://pub.dev" + source: hosted + version: "1.1.4" web: dependency: transitive description: @@ -981,6 +1437,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" widget_to_marker: dependency: "direct main" description: @@ -989,6 +1469,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" xdg_directories: dependency: transitive description: @@ -1001,10 +1489,10 @@ packages: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "6.6.1" yaml: dependency: transitive description: @@ -1014,5 +1502,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.7.0 <4.0.0" - flutter: ">=3.29.1" + dart: ">=3.8.0 <4.0.0" + flutter: ">=3.32.0" diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index 3210ac0..59bad47 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -19,8 +19,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=3.3.4 <4.0.0' - flutter: '3.29.1' + sdk: ^3.8.0 + flutter: '3.32.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -32,7 +32,6 @@ dependencies: flutter: sdk: flutter - # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 @@ -42,18 +41,20 @@ dependencies: dio: ^5.5.0+1 google_maps_flutter: ^2.7.0 cached_network_image: ^3.4.0 - geocoding: ^3.0.0 + geocoding: ^4.0.0 widget_to_marker: ^1.0.6 - provider: ^6.1.2 auto_size_text: ^3.0.0 - map_launcher: ^3.3.1 + # map_launcher: ^4.4.2 flutter_svg: ^2.0.10+1 url_launcher: ^6.3.0 - flutter_launcher_icons: ^0.13.1 - permission_handler: ^11.3.1 - geolocator: ^13.0.1 - fuzzywuzzy: ^1.2.0 - flutter_markdown: ^0.7.6+2 + flutter_launcher_icons: ^0.14.4 + permission_handler: ^12.0.1 + geolocator: ^14.0.2 + freezed_annotation: ^3.1.0 + json_annotation: ^4.9.0 + uuid: ^4.5.1 + flutter_riverpod: ^3.0.3 + flutter_markdown_plus: ^1.0.5 dev_dependencies: flutter_test: @@ -64,7 +65,12 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 + build_runner: + freezed: ^3.2.3 + json_serializable: ^6.11.1 + custom_lint: + riverpod_lint: ^3.0.3 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec