feat(wip): Update entities and adopt a proper repository workflow for trip "obtention"

This commit is contained in:
2025-12-29 00:23:10 +01:00
parent 239b63ca81
commit 81ed2fd8c3
34 changed files with 1929 additions and 1925 deletions

View File

@@ -24,5 +24,12 @@ linter:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Exclude legacy/experimental code that is not part of the current
# refactor work. This prevents the analyzer from failing on old files
# in `lib/old` while we iterate on the new architecture in `lib/`.
analyzer:
exclude:
- lib/old/**
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

View File

@@ -1,5 +0,0 @@
import 'package:anyway/domain/entities/landmark.dart';
abstract class TripRemoteDataSource {
Future<List<Landmark>> fetchLandmarks();
}

View File

@@ -0,0 +1,142 @@
import 'dart:convert';
import 'dart:developer';
import 'package:dio/dio.dart';
abstract class TripRemoteDataSource {
/// Fetch available landmarks for the provided preferences/start payload.
Future<List<Map<String, dynamic>>> fetchLandmarks(Map<String, dynamic> body);
/// Create a new trip using the optimizer payload (that includes landmarks).
Future<Map<String, dynamic>> createTrip(Map<String, dynamic> body);
/// Fetch an existing trip by UUID
Future<Map<String, dynamic>> fetchTrip(String uuid);
}
class TripRemoteDataSourceImpl implements TripRemoteDataSource {
final Dio dio;
TripRemoteDataSourceImpl({required this.dio});
@override
Future<List<Map<String, dynamic>>> fetchLandmarks(Map<String, dynamic> body) async {
final response = await dio.post('/get/landmarks', data: body);
if (response.statusCode != 200) {
throw Exception('Server error fetching landmarks: ${response.statusCode}');
}
if (response.data is! List) {
throw Exception('Unexpected landmarks response format');
}
return _normalizeLandmarks(List<dynamic>.from(response.data as List));
}
@override
Future<Map<String, dynamic>> createTrip(Map<String, dynamic> body) async {
log('Creating trip with body: $body');
// convert body to actual json
String bodyJson = jsonEncode(body);
log('Trip request JSON: $bodyJson');
final response = await dio.post('/optimize/trip', data: body);
if (response.statusCode != 200) {
throw Exception('Server error: ${response.statusCode}');
}
if (response.data is! Map<String, dynamic>) {
throw Exception('Unexpected response format');
}
final Map<String, dynamic> json = Map<String, dynamic>.from(response.data as Map);
_ensureLandmarks(json);
if (json.containsKey('landmarks') && json['landmarks'] is List) {
return json;
}
final String? firstUuid = json['first_landmark_uuid'] as String?;
if (firstUuid == null) {
return json;
}
final List<Map<String, dynamic>> landmarks = [];
String? next = firstUuid;
while (next != null) {
final lm = await _fetchLandmarkByUuid(next);
landmarks.add(lm);
final dynamic nxt = lm['next_uuid'];
next = (nxt is String) ? nxt : null;
}
json['landmarks'] = landmarks;
return json;
}
@override
Future<Map<String, dynamic>> fetchTrip(String uuid) async {
final response = await dio.get('/trip/$uuid');
if (response.statusCode != 200) {
throw Exception('Server error: ${response.statusCode}');
}
if (response.data is! Map<String, dynamic>) {
throw Exception('Unexpected response format');
}
final Map<String, dynamic> json = Map<String, dynamic>.from(response.data as Map);
// Normalize same as createTrip: if trip contains first_landmark_uuid, expand chain
if (json.containsKey('landmarks') && json['landmarks'] is List) {
_ensureLandmarks(json);
return json;
}
final String? firstUuid = json['first_landmark_uuid'] as String?;
if (firstUuid == null) return json;
final List<Map<String, dynamic>> landmarks = [];
String? next = firstUuid;
while (next != null) {
final lm = await _fetchLandmarkByUuid(next);
landmarks.add(lm);
final dynamic nxt = lm['next_uuid'];
next = (nxt is String) ? nxt : null;
}
json['landmarks'] = landmarks;
return json;
}
// Fetch a single landmark by uuid via the /landmark/{landmark_uuid} endpoint
Future<Map<String, dynamic>> _fetchLandmarkByUuid(String uuid) async {
final response = await dio.get('/landmark/$uuid');
if (response.statusCode != 200) {
throw Exception('Failed to fetch landmark $uuid: ${response.statusCode}');
}
if (response.data is! Map<String, dynamic>) {
throw Exception('Unexpected landmark response format');
}
return _normalizeLandmark(Map<String, dynamic>.from(response.data as Map));
}
static void _ensureLandmarks(Map<String, dynamic> json) {
final raw = json['landmarks'];
if (raw is List) {
json['landmarks'] = _normalizeLandmarks(raw);
}
}
static List<Map<String, dynamic>> _normalizeLandmarks(List<dynamic> rawList) {
return rawList
.map((item) => _normalizeLandmark(Map<String, dynamic>.from(item as Map)))
.toList();
}
static Map<String, dynamic> _normalizeLandmark(Map<String, dynamic> source) {
final normalized = Map<String, dynamic>.from(source);
final typeValue = normalized['type'];
if (typeValue is String) {
normalized['type'] = {'type': typeValue};
}
return normalized;
}
}

View File

@@ -1,3 +1,4 @@
// TODO - I have the feeling this file is outdated and not used anymore
import 'package:anyway/domain/entities/landmark.dart';
import 'package:anyway/domain/entities/landmark_description.dart';
import 'package:anyway/domain/entities/landmark_type.dart';
@@ -16,6 +17,8 @@ abstract class LandmarkModel with _$LandmarkModel {
required String description,
}) = _LandmarkModel;
const LandmarkModel._();
factory LandmarkModel.fromJson(Map<String, dynamic> json) => _$LandmarkModelFromJson(json);
Landmark toEntity() => Landmark(
@@ -24,7 +27,6 @@ abstract class LandmarkModel with _$LandmarkModel {
location: location,
type: LandmarkType(type: LandmarkTypeEnum.values.firstWhere((e) => e.value == type)),
isSecondary: isSecondary,
// TODO - try to set tags
description: LandmarkDescription(description: description, tags: [])
description: LandmarkDescription(description: description, tags: []),
);
}

View File

@@ -14,71 +14,47 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$LandmarkModel {
String get uuid;
String get name;
List<double> get location;
String get type;
bool get isSecondary;
String get description;
String get uuid; String get name; List<double> 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<LandmarkModel> get copyWith =>
_$LandmarkModelCopyWithImpl<LandmarkModel>(
this as LandmarkModel, _$identity);
$LandmarkModelCopyWith<LandmarkModel> get copyWith => _$LandmarkModelCopyWithImpl<LandmarkModel>(this as LandmarkModel, _$identity);
/// Serializes this LandmarkModel to a JSON map.
Map<String, dynamic> 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));
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);
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;
factory $LandmarkModelCopyWith(LandmarkModel value, $Res Function(LandmarkModel) _then) = _$LandmarkModelCopyWithImpl;
@useResult
$Res call(
{String uuid,
String name,
List<double> location,
String type,
bool isSecondary,
String description});
}
$Res call({
String uuid, String name, List<double> location, String type, bool isSecondary, String description
});
}
/// @nodoc
class _$LandmarkModelCopyWithImpl<$Res>
implements $LandmarkModelCopyWith<$Res> {
@@ -89,45 +65,21 @@ class _$LandmarkModelCopyWithImpl<$Res>
/// 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,
}) {
@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<double>,
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
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<double>,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`.
@@ -142,20 +94,15 @@ extension LandmarkModelPatterns on LandmarkModel {
/// }
/// ```
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_LandmarkModel value)? $default, {
required TResult orElse(),
}) {
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LandmarkModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _LandmarkModel() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
@@ -169,19 +116,15 @@ extension LandmarkModelPatterns on LandmarkModel {
/// }
/// ```
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_LandmarkModel value) $default,
) {
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LandmarkModel value) $default,){
final _that = this;
switch (_that) {
case _LandmarkModel():
return $default(_that);
case _:
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
@@ -194,19 +137,15 @@ extension LandmarkModelPatterns on LandmarkModel {
/// }
/// ```
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_LandmarkModel value)? $default,
) {
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LandmarkModel value)? $default,){
final _that = this;
switch (_that) {
case _LandmarkModel() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return null;
}
}
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
@@ -219,23 +158,14 @@ extension LandmarkModelPatterns on LandmarkModel {
/// }
/// ```
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function(String uuid, String name, List<double> location,
String type, bool isSecondary, String description)?
$default, {
required TResult orElse(),
}) {
final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String uuid, String name, List<double> 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 $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.
@@ -249,22 +179,14 @@ extension LandmarkModelPatterns on LandmarkModel {
/// }
/// ```
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function(String uuid, String name, List<double> location,
String type, bool isSecondary, String description)
$default,
) {
final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String uuid, String name, List<double> 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 _:
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:
@@ -277,120 +199,77 @@ extension LandmarkModelPatterns on LandmarkModel {
/// }
/// ```
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function(String uuid, String name, List<double> location,
String type, bool isSecondary, String description)?
$default,
) {
final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String uuid, String name, List<double> 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 $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<double> location,
required this.type,
required this.isSecondary,
required this.description})
: _location = location;
factory _LandmarkModel.fromJson(Map<String, dynamic> json) =>
_$LandmarkModelFromJson(json);
@override
final String uuid;
@override
final String name;
class _LandmarkModel extends LandmarkModel {
const _LandmarkModel({required this.uuid, required this.name, required final List<double> location, required this.type, required this.isSecondary, required this.description}): _location = location,super._();
factory _LandmarkModel.fromJson(Map<String, dynamic> json) => _$LandmarkModelFromJson(json);
@override final String uuid;
@override final String name;
final List<double> _location;
@override
List<double> get location {
@override List<double> 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;
@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)
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LandmarkModelCopyWith<_LandmarkModel> get copyWith =>
__$LandmarkModelCopyWithImpl<_LandmarkModel>(this, _$identity);
_$LandmarkModelCopyWith<_LandmarkModel> get copyWith => __$LandmarkModelCopyWithImpl<_LandmarkModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$LandmarkModelToJson(
this,
);
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));
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);
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<double> location,
String type,
bool isSecondary,
String description});
}
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<double> location, String type, bool isSecondary, String description
});
}
/// @nodoc
class __$LandmarkModelCopyWithImpl<$Res>
implements _$LandmarkModelCopyWith<$Res> {
@@ -401,43 +280,19 @@ class __$LandmarkModelCopyWithImpl<$Res>
/// 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,
}) {
@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<double>,
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
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<double>,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

View File

@@ -1,119 +1,89 @@
import 'dart:developer';
import 'package:anyway/domain/entities/landmark.dart';
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';
import 'package:anyway/data/datasources/trip_remote_datasource.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});
final TripRemoteDataSource remote;
BackendTripRepository({required this.remote});
@override
Future<Trip> getTrip({Preferences? preferences, String? tripUUID}) async {
Map<String, dynamic> data = {
"preferences": preferences!.toJson(),
// "start": preferences!.startPoint.location,
Future<Trip> getTrip({Preferences? preferences, String? tripUUID, List<Landmark>? landmarks}) async {
try {
Map<String, dynamic> json;
if (tripUUID != null) {
json = await remote.fetchTrip(tripUUID);
} else {
if (preferences == null) {
throw ArgumentError('Either preferences or tripUUID must be provided');
}
final Map<String, dynamic> prefsPayload = _buildPreferencesPayload(preferences);
List<Map<String, dynamic>> landmarkBodies = landmarks != null
? landmarks.map((lm) => lm.toJson()).toList()
: await _fetchLandmarkPayloads(prefsPayload, preferences.startLocation);
// TODO: remove
// restrict the landmark list to 30 to iterate quickly
landmarkBodies = landmarkBodies.take(30).toList();
// change the json key because of backend inconsistency
for (var lm in landmarkBodies) {
if (lm.containsKey('type')) {
lm['type'] = "sightseeing";
}
lm['osm_type'] = 'node';
lm['osm_id'] = 1;
}
final Map<String, dynamic> body = {
'preferences': prefsPayload,
'landmarks': landmarkBodies,
'start': preferences.startLocation,
};
if (preferences.endLocation != null) {
body['end'] = preferences.endLocation;
}
if (preferences.detourToleranceMinutes != null) {
body['detour_tolerance_minute'] = preferences.detourToleranceMinutes;
}
json = await remote.createTrip(body);
}
return Trip.fromJson(json);
} catch (e) {
throw Exception('Failed to fetch trip: ${e.toString()}');
}
}
// TODO - maybe shorten this
@override
Future<List<Landmark>> searchLandmarks(Preferences preferences) async {
final Map<String, dynamic> prefsPayload = _buildPreferencesPayload(preferences);
final List<Map<String, dynamic>> rawLandmarks = await _fetchLandmarkPayloads(prefsPayload, preferences.startLocation);
return rawLandmarks.map((lmJson) => Landmark.fromJson(lmJson)).toList();
}
Future<List<Map<String, dynamic>>> _fetchLandmarkPayloads(
Map<String, dynamic> prefsPayload, List<double> startLocation) async {
final Map<String, dynamic> landmarkRequest = {
'preferences': prefsPayload,
'start': startLocation,
};
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";
return await remote.fetchLandmarks(landmarkRequest);
}
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<String, dynamic>) {
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<String, dynamic>) {
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<String, dynamic> 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);
}
Map<String, dynamic> _buildPreferencesPayload(Preferences preferences) {
final Map<String, dynamic> prefsPayload = {};
preferences.scores.forEach((type, score) {
prefsPayload[type] = {'type': type, 'score': score};
});
prefsPayload['max_time_minute'] = preferences.maxTimeMinutes;
return prefsPayload;
}
}

View File

@@ -0,0 +1,18 @@
import 'package:shared_preferences/shared_preferences.dart';
import 'package:anyway/domain/repositories/onboarding_repository.dart';
class LocalOnboardingRepository implements OnboardingRepository {
static const _key = 'onboardingCompleted';
@override
Future<bool> isOnboarded() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(_key) ?? false;
}
@override
Future<void> setOnboarded(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_key, value);
}
}

View File

@@ -0,0 +1,50 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:anyway/domain/entities/preferences.dart';
import 'package:anyway/domain/repositories/preferences_repository.dart';
class PreferencesRepositoryImpl implements PreferencesRepository {
static const _key = 'userPreferences';
@override
Future<Preferences> getPreferences() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(_key);
if (raw == null) {
// TODO - rethink this
// return a sensible default
return Preferences(
scores: {
'sightseeing': 0,
'shopping': 0,
'nature': 0,
},
maxTimeMinutes: 120,
startLocation: const [48.8575, 2.3514],
);
}
try {
final map = json.decode(raw) as Map<String, dynamic>;
return Preferences.fromJson(map);
} catch (_) {
return Preferences(
scores: {
'sightseeing': 0,
'shopping': 0,
'nature': 0,
},
maxTimeMinutes: 120,
startLocation: const [48.8575, 2.3514],
);
}
}
@override
Future<void> savePreferences(Preferences preferences) async {
final prefs = await SharedPreferences.getInstance();
final raw = json.encode(preferences.toJson());
await prefs.setString(_key, raw);
}
}

View File

@@ -22,3 +22,14 @@ This is required boilerplate for all models. Then, we define the model itself us
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.
To ensure the creation of the boilerplate code, run the following command in your terminal:
```bash
flutter pub run build_runner build --delete-conflicting-outputs
```
or interactively:
```
dart run build_runner watch -d
```

View File

@@ -12,9 +12,38 @@ abstract class Landmark with _$Landmark {
required String name,
required List<double> location,
required LandmarkType type,
required bool isSecondary,
required LandmarkDescription description,
@JsonKey(name: 'is_secondary')
bool? isSecondary,
/// Optional rich description object (may be null if API returns plain string)
LandmarkDescription? description,
@JsonKey(name: 'name_en')
String? nameEn,
@JsonKey(name: 'website_url')
String? websiteUrl,
@JsonKey(name: 'image_url')
String? imageUrl,
@JsonKey(name: 'attractiveness')
int? attractiveness,
@JsonKey(name: 'n_tags')
int? tagCount,
/// Duration at landmark in minutes
@JsonKey(name: 'duration')
int? durationMinutes,
bool? visited,
@JsonKey(name: 'time_to_reach_next')
int? timeToReachNextMinutes,
}) = _Landmark;
factory Landmark.fromJson(Map<String, Object?> json) => _$LandmarkFromJson(json);

View File

@@ -14,54 +14,47 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$Landmark {
String get uuid;
set uuid(String value);
String get name;
set name(String value);
List<double> get location;
set location(List<double> value);
LandmarkType get type;
set type(LandmarkType value);
bool get isSecondary;
set isSecondary(bool value);
LandmarkDescription get description;
set description(LandmarkDescription value);
String get uuid; set uuid(String value); String get name; set name(String value); List<double> get location; set location(List<double> value); LandmarkType get type; set type(LandmarkType value);@JsonKey(name: 'is_secondary') bool? get isSecondary;@JsonKey(name: 'is_secondary') set isSecondary(bool? value);/// Optional rich description object (may be null if API returns plain string)
LandmarkDescription? get description;/// Optional rich description object (may be null if API returns plain string)
set description(LandmarkDescription? value);@JsonKey(name: 'name_en') String? get nameEn;@JsonKey(name: 'name_en') set nameEn(String? value);@JsonKey(name: 'website_url') String? get websiteUrl;@JsonKey(name: 'website_url') set websiteUrl(String? value);@JsonKey(name: 'image_url') String? get imageUrl;@JsonKey(name: 'image_url') set imageUrl(String? value);@JsonKey(name: 'attractiveness') int? get attractiveness;@JsonKey(name: 'attractiveness') set attractiveness(int? value);@JsonKey(name: 'n_tags') int? get tagCount;@JsonKey(name: 'n_tags') set tagCount(int? value);/// Duration at landmark in minutes
@JsonKey(name: 'duration') int? get durationMinutes;/// Duration at landmark in minutes
@JsonKey(name: 'duration') set durationMinutes(int? value); bool? get visited; set visited(bool? value);@JsonKey(name: 'time_to_reach_next') int? get timeToReachNextMinutes;@JsonKey(name: 'time_to_reach_next') set timeToReachNextMinutes(int? 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<Landmark> get copyWith =>
_$LandmarkCopyWithImpl<Landmark>(this as Landmark, _$identity);
$LandmarkCopyWith<Landmark> get copyWith => _$LandmarkCopyWithImpl<Landmark>(this as Landmark, _$identity);
/// Serializes this Landmark to a JSON map.
Map<String, dynamic> toJson();
@override
String toString() {
return 'Landmark(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description)';
return 'Landmark(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description, nameEn: $nameEn, websiteUrl: $websiteUrl, imageUrl: $imageUrl, attractiveness: $attractiveness, tagCount: $tagCount, durationMinutes: $durationMinutes, visited: $visited, timeToReachNextMinutes: $timeToReachNextMinutes)';
}
}
/// @nodoc
abstract mixin class $LandmarkCopyWith<$Res> {
factory $LandmarkCopyWith(Landmark value, $Res Function(Landmark) _then) =
_$LandmarkCopyWithImpl;
factory $LandmarkCopyWith(Landmark value, $Res Function(Landmark) _then) = _$LandmarkCopyWithImpl;
@useResult
$Res call(
{String uuid,
String name,
List<double> location,
LandmarkType type,
bool isSecondary,
LandmarkDescription description});
$Res call({
String uuid, String name, List<double> location, LandmarkType type,@JsonKey(name: 'is_secondary') bool? isSecondary, LandmarkDescription? description,@JsonKey(name: 'name_en') String? nameEn,@JsonKey(name: 'website_url') String? websiteUrl,@JsonKey(name: 'image_url') String? imageUrl,@JsonKey(name: 'attractiveness') int? attractiveness,@JsonKey(name: 'n_tags') int? tagCount,@JsonKey(name: 'duration') int? durationMinutes, bool? visited,@JsonKey(name: 'time_to_reach_next') int? timeToReachNextMinutes
});
$LandmarkTypeCopyWith<$Res> get type;$LandmarkDescriptionCopyWith<$Res>? get description;
$LandmarkTypeCopyWith<$Res> get type;
$LandmarkDescriptionCopyWith<$Res> get description;
}
/// @nodoc
class _$LandmarkCopyWithImpl<$Res> implements $LandmarkCopyWith<$Res> {
class _$LandmarkCopyWithImpl<$Res>
implements $LandmarkCopyWith<$Res> {
_$LandmarkCopyWithImpl(this._self, this._then);
final Landmark _self;
@@ -69,65 +62,50 @@ class _$LandmarkCopyWithImpl<$Res> implements $LandmarkCopyWith<$Res> {
/// 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,
}) {
@pragma('vm:prefer-inline') @override $Res call({Object? uuid = null,Object? name = null,Object? location = null,Object? type = null,Object? isSecondary = freezed,Object? description = freezed,Object? nameEn = freezed,Object? websiteUrl = freezed,Object? imageUrl = freezed,Object? attractiveness = freezed,Object? tagCount = freezed,Object? durationMinutes = freezed,Object? visited = freezed,Object? timeToReachNextMinutes = freezed,}) {
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<double>,
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,
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<double>,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
as LandmarkType,isSecondary: freezed == isSecondary ? _self.isSecondary : isSecondary // ignore: cast_nullable_to_non_nullable
as bool?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as LandmarkDescription?,nameEn: freezed == nameEn ? _self.nameEn : nameEn // ignore: cast_nullable_to_non_nullable
as String?,websiteUrl: freezed == websiteUrl ? _self.websiteUrl : websiteUrl // ignore: cast_nullable_to_non_nullable
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
as String?,attractiveness: freezed == attractiveness ? _self.attractiveness : attractiveness // ignore: cast_nullable_to_non_nullable
as int?,tagCount: freezed == tagCount ? _self.tagCount : tagCount // ignore: cast_nullable_to_non_nullable
as int?,durationMinutes: freezed == durationMinutes ? _self.durationMinutes : durationMinutes // ignore: cast_nullable_to_non_nullable
as int?,visited: freezed == visited ? _self.visited : visited // ignore: cast_nullable_to_non_nullable
as bool?,timeToReachNextMinutes: freezed == timeToReachNextMinutes ? _self.timeToReachNextMinutes : timeToReachNextMinutes // ignore: cast_nullable_to_non_nullable
as int?,
));
}
/// 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
}/// 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) {
$LandmarkDescriptionCopyWith<$Res>? get description {
if (_self.description == null) {
return null;
}
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`.
@@ -142,20 +120,15 @@ extension LandmarkPatterns on Landmark {
/// }
/// ```
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_Landmark value)? $default, {
required TResult orElse(),
}) {
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Landmark value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Landmark() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
@@ -169,19 +142,15 @@ extension LandmarkPatterns on Landmark {
/// }
/// ```
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_Landmark value) $default,
) {
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Landmark value) $default,){
final _that = this;
switch (_that) {
case _Landmark():
return $default(_that);
case _:
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
@@ -194,19 +163,15 @@ extension LandmarkPatterns on Landmark {
/// }
/// ```
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_Landmark value)? $default,
) {
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Landmark value)? $default,){
final _that = this;
switch (_that) {
case _Landmark() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return null;
}
}
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
@@ -219,28 +184,14 @@ extension LandmarkPatterns on Landmark {
/// }
/// ```
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function(
String uuid,
String name,
List<double> location,
LandmarkType type,
bool isSecondary,
LandmarkDescription description)?
$default, {
required TResult orElse(),
}) {
final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String uuid, String name, List<double> location, LandmarkType type, @JsonKey(name: 'is_secondary') bool? isSecondary, LandmarkDescription? description, @JsonKey(name: 'name_en') String? nameEn, @JsonKey(name: 'website_url') String? websiteUrl, @JsonKey(name: 'image_url') String? imageUrl, @JsonKey(name: 'attractiveness') int? attractiveness, @JsonKey(name: 'n_tags') int? tagCount, @JsonKey(name: 'duration') int? durationMinutes, bool? visited, @JsonKey(name: 'time_to_reach_next') int? timeToReachNextMinutes)? $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 $default(_that.uuid,_that.name,_that.location,_that.type,_that.isSecondary,_that.description,_that.nameEn,_that.websiteUrl,_that.imageUrl,_that.attractiveness,_that.tagCount,_that.durationMinutes,_that.visited,_that.timeToReachNextMinutes);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
@@ -254,27 +205,14 @@ extension LandmarkPatterns on Landmark {
/// }
/// ```
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function(
String uuid,
String name,
List<double> location,
LandmarkType type,
bool isSecondary,
LandmarkDescription description)
$default,
) {
final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String uuid, String name, List<double> location, LandmarkType type, @JsonKey(name: 'is_secondary') bool? isSecondary, LandmarkDescription? description, @JsonKey(name: 'name_en') String? nameEn, @JsonKey(name: 'website_url') String? websiteUrl, @JsonKey(name: 'image_url') String? imageUrl, @JsonKey(name: 'attractiveness') int? attractiveness, @JsonKey(name: 'n_tags') int? tagCount, @JsonKey(name: 'duration') int? durationMinutes, bool? visited, @JsonKey(name: 'time_to_reach_next') int? timeToReachNextMinutes) $default,) {final _that = this;
switch (_that) {
case _Landmark():
return $default(_that.uuid, _that.name, _that.location, _that.type,
_that.isSecondary, _that.description);
case _:
return $default(_that.uuid,_that.name,_that.location,_that.type,_that.isSecondary,_that.description,_that.nameEn,_that.websiteUrl,_that.imageUrl,_that.attractiveness,_that.tagCount,_that.durationMinutes,_that.visited,_that.timeToReachNextMinutes);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
@@ -287,98 +225,77 @@ extension LandmarkPatterns on Landmark {
/// }
/// ```
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function(
String uuid,
String name,
List<double> location,
LandmarkType type,
bool isSecondary,
LandmarkDescription description)?
$default,
) {
final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String uuid, String name, List<double> location, LandmarkType type, @JsonKey(name: 'is_secondary') bool? isSecondary, LandmarkDescription? description, @JsonKey(name: 'name_en') String? nameEn, @JsonKey(name: 'website_url') String? websiteUrl, @JsonKey(name: 'image_url') String? imageUrl, @JsonKey(name: 'attractiveness') int? attractiveness, @JsonKey(name: 'n_tags') int? tagCount, @JsonKey(name: 'duration') int? durationMinutes, bool? visited, @JsonKey(name: 'time_to_reach_next') int? timeToReachNextMinutes)? $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 $default(_that.uuid,_that.name,_that.location,_that.type,_that.isSecondary,_that.description,_that.nameEn,_that.websiteUrl,_that.imageUrl,_that.attractiveness,_that.tagCount,_that.durationMinutes,_that.visited,_that.timeToReachNextMinutes);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<String, dynamic> json) =>
_$LandmarkFromJson(json);
@override
String uuid;
@override
String name;
@override
List<double> location;
@override
LandmarkType type;
@override
bool isSecondary;
@override
LandmarkDescription description;
class _Landmark implements Landmark {
_Landmark({required this.uuid, required this.name, required this.location, required this.type, @JsonKey(name: 'is_secondary') this.isSecondary, this.description, @JsonKey(name: 'name_en') this.nameEn, @JsonKey(name: 'website_url') this.websiteUrl, @JsonKey(name: 'image_url') this.imageUrl, @JsonKey(name: 'attractiveness') this.attractiveness, @JsonKey(name: 'n_tags') this.tagCount, @JsonKey(name: 'duration') this.durationMinutes, this.visited, @JsonKey(name: 'time_to_reach_next') this.timeToReachNextMinutes});
factory _Landmark.fromJson(Map<String, dynamic> json) => _$LandmarkFromJson(json);
@override String uuid;
@override String name;
@override List<double> location;
@override LandmarkType type;
@override@JsonKey(name: 'is_secondary') bool? isSecondary;
/// Optional rich description object (may be null if API returns plain string)
@override LandmarkDescription? description;
@override@JsonKey(name: 'name_en') String? nameEn;
@override@JsonKey(name: 'website_url') String? websiteUrl;
@override@JsonKey(name: 'image_url') String? imageUrl;
@override@JsonKey(name: 'attractiveness') int? attractiveness;
@override@JsonKey(name: 'n_tags') int? tagCount;
/// Duration at landmark in minutes
@override@JsonKey(name: 'duration') int? durationMinutes;
@override bool? visited;
@override@JsonKey(name: 'time_to_reach_next') int? timeToReachNextMinutes;
/// Create a copy of Landmark
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LandmarkCopyWith<_Landmark> get copyWith =>
__$LandmarkCopyWithImpl<_Landmark>(this, _$identity);
_$LandmarkCopyWith<_Landmark> get copyWith => __$LandmarkCopyWithImpl<_Landmark>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$LandmarkToJson(
this,
);
return _$LandmarkToJson(this, );
}
@override
String toString() {
return 'Landmark(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description)';
return 'Landmark(uuid: $uuid, name: $name, location: $location, type: $type, isSecondary: $isSecondary, description: $description, nameEn: $nameEn, websiteUrl: $websiteUrl, imageUrl: $imageUrl, attractiveness: $attractiveness, tagCount: $tagCount, durationMinutes: $durationMinutes, visited: $visited, timeToReachNextMinutes: $timeToReachNextMinutes)';
}
}
/// @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<double> location,
LandmarkType type,
bool isSecondary,
LandmarkDescription description});
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<double> location, LandmarkType type,@JsonKey(name: 'is_secondary') bool? isSecondary, LandmarkDescription? description,@JsonKey(name: 'name_en') String? nameEn,@JsonKey(name: 'website_url') String? websiteUrl,@JsonKey(name: 'image_url') String? imageUrl,@JsonKey(name: 'attractiveness') int? attractiveness,@JsonKey(name: 'n_tags') int? tagCount,@JsonKey(name: 'duration') int? durationMinutes, bool? visited,@JsonKey(name: 'time_to_reach_next') int? timeToReachNextMinutes
});
@override $LandmarkTypeCopyWith<$Res> get type;@override $LandmarkDescriptionCopyWith<$Res>? get description;
@override
$LandmarkTypeCopyWith<$Res> get type;
@override
$LandmarkDescriptionCopyWith<$Res> get description;
}
/// @nodoc
class __$LandmarkCopyWithImpl<$Res> implements _$LandmarkCopyWith<$Res> {
class __$LandmarkCopyWithImpl<$Res>
implements _$LandmarkCopyWith<$Res> {
__$LandmarkCopyWithImpl(this._self, this._then);
final _Landmark _self;
@@ -386,41 +303,23 @@ class __$LandmarkCopyWithImpl<$Res> implements _$LandmarkCopyWith<$Res> {
/// 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,
}) {
@override @pragma('vm:prefer-inline') $Res call({Object? uuid = null,Object? name = null,Object? location = null,Object? type = null,Object? isSecondary = freezed,Object? description = freezed,Object? nameEn = freezed,Object? websiteUrl = freezed,Object? imageUrl = freezed,Object? attractiveness = freezed,Object? tagCount = freezed,Object? durationMinutes = freezed,Object? visited = freezed,Object? timeToReachNextMinutes = freezed,}) {
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<double>,
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,
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<double>,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
as LandmarkType,isSecondary: freezed == isSecondary ? _self.isSecondary : isSecondary // ignore: cast_nullable_to_non_nullable
as bool?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as LandmarkDescription?,nameEn: freezed == nameEn ? _self.nameEn : nameEn // ignore: cast_nullable_to_non_nullable
as String?,websiteUrl: freezed == websiteUrl ? _self.websiteUrl : websiteUrl // ignore: cast_nullable_to_non_nullable
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
as String?,attractiveness: freezed == attractiveness ? _self.attractiveness : attractiveness // ignore: cast_nullable_to_non_nullable
as int?,tagCount: freezed == tagCount ? _self.tagCount : tagCount // ignore: cast_nullable_to_non_nullable
as int?,durationMinutes: freezed == durationMinutes ? _self.durationMinutes : durationMinutes // ignore: cast_nullable_to_non_nullable
as int?,visited: freezed == visited ? _self.visited : visited // ignore: cast_nullable_to_non_nullable
as bool?,timeToReachNextMinutes: freezed == timeToReachNextMinutes ? _self.timeToReachNextMinutes : timeToReachNextMinutes // ignore: cast_nullable_to_non_nullable
as int?,
));
}
@@ -429,17 +328,20 @@ class __$LandmarkCopyWithImpl<$Res> implements _$LandmarkCopyWith<$Res> {
@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
}/// 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) {
$LandmarkDescriptionCopyWith<$Res>? get description {
if (_self.description == null) {
return null;
}
return $LandmarkDescriptionCopyWith<$Res>(_self.description!, (value) {
return _then(_self.copyWith(description: value));
});
}

View File

@@ -13,9 +13,20 @@ _Landmark _$LandmarkFromJson(Map<String, dynamic> json) => _Landmark(
.map((e) => (e as num).toDouble())
.toList(),
type: LandmarkType.fromJson(json['type'] as Map<String, dynamic>),
isSecondary: json['isSecondary'] as bool,
description: LandmarkDescription.fromJson(
json['description'] as Map<String, dynamic>),
isSecondary: json['is_secondary'] as bool?,
description: json['description'] == null
? null
: LandmarkDescription.fromJson(
json['description'] as Map<String, dynamic>,
),
nameEn: json['name_en'] as String?,
websiteUrl: json['website_url'] as String?,
imageUrl: json['image_url'] as String?,
attractiveness: (json['attractiveness'] as num?)?.toInt(),
tagCount: (json['n_tags'] as num?)?.toInt(),
durationMinutes: (json['duration'] as num?)?.toInt(),
visited: json['visited'] as bool?,
timeToReachNextMinutes: (json['time_to_reach_next'] as num?)?.toInt(),
);
Map<String, dynamic> _$LandmarkToJson(_Landmark instance) => <String, dynamic>{
@@ -23,6 +34,14 @@ Map<String, dynamic> _$LandmarkToJson(_Landmark instance) => <String, dynamic>{
'name': instance.name,
'location': instance.location,
'type': instance.type,
'isSecondary': instance.isSecondary,
'is_secondary': instance.isSecondary,
'description': instance.description,
'name_en': instance.nameEn,
'website_url': instance.websiteUrl,
'image_url': instance.imageUrl,
'attractiveness': instance.attractiveness,
'n_tags': instance.tagCount,
'duration': instance.durationMinutes,
'visited': instance.visited,
'time_to_reach_next': instance.timeToReachNextMinutes,
};

View File

@@ -3,7 +3,7 @@ part 'landmark_description.freezed.dart';
part 'landmark_description.g.dart';
@Freezed(makeCollectionsUnmodifiable: false)
@freezed
abstract class LandmarkDescription with _$LandmarkDescription {
const factory LandmarkDescription({
required String description,

View File

@@ -14,50 +14,47 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$LandmarkDescription {
String get description;
List<String> get tags;
String get description; List<String> 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<LandmarkDescription> get copyWith =>
_$LandmarkDescriptionCopyWithImpl<LandmarkDescription>(
this as LandmarkDescription, _$identity);
$LandmarkDescriptionCopyWith<LandmarkDescription> get copyWith => _$LandmarkDescriptionCopyWithImpl<LandmarkDescription>(this as LandmarkDescription, _$identity);
/// Serializes this LandmarkDescription to a JSON map.
Map<String, dynamic> 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));
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));
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;
factory $LandmarkDescriptionCopyWith(LandmarkDescription value, $Res Function(LandmarkDescription) _then) = _$LandmarkDescriptionCopyWithImpl;
@useResult
$Res call({String description, List<String> tags});
}
$Res call({
String description, List<String> tags
});
}
/// @nodoc
class _$LandmarkDescriptionCopyWithImpl<$Res>
implements $LandmarkDescriptionCopyWith<$Res> {
@@ -68,25 +65,17 @@ class _$LandmarkDescriptionCopyWithImpl<$Res>
/// 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,
}) {
@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
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<String>,
));
}
}
/// Adds pattern-matching-related methods to [LandmarkDescription].
extension LandmarkDescriptionPatterns on LandmarkDescription {
/// A variant of `map` that fallback to returning `orElse`.
@@ -101,20 +90,15 @@ extension LandmarkDescriptionPatterns on LandmarkDescription {
/// }
/// ```
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_LandmarkDescription value)? $default, {
required TResult orElse(),
}) {
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LandmarkDescription value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _LandmarkDescription() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
@@ -128,19 +112,15 @@ extension LandmarkDescriptionPatterns on LandmarkDescription {
/// }
/// ```
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_LandmarkDescription value) $default,
) {
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LandmarkDescription value) $default,){
final _that = this;
switch (_that) {
case _LandmarkDescription():
return $default(_that);
case _:
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
@@ -153,19 +133,15 @@ extension LandmarkDescriptionPatterns on LandmarkDescription {
/// }
/// ```
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_LandmarkDescription value)? $default,
) {
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LandmarkDescription value)? $default,){
final _that = this;
switch (_that) {
case _LandmarkDescription() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return null;
}
}
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
@@ -178,20 +154,14 @@ extension LandmarkDescriptionPatterns on LandmarkDescription {
/// }
/// ```
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function(String description, List<String> tags)? $default, {
required TResult orElse(),
}) {
final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String description, List<String> tags)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _LandmarkDescription() when $default != null:
return $default(_that.description, _that.tags);
case _:
return $default(_that.description,_that.tags);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
@@ -205,19 +175,14 @@ extension LandmarkDescriptionPatterns on LandmarkDescription {
/// }
/// ```
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function(String description, List<String> tags) $default,
) {
final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String description, List<String> tags) $default,) {final _that = this;
switch (_that) {
case _LandmarkDescription():
return $default(_that.description, _that.tags);
case _:
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:
@@ -230,80 +195,73 @@ extension LandmarkDescriptionPatterns on LandmarkDescription {
/// }
/// ```
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function(String description, List<String> tags)? $default,
) {
final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String description, List<String> tags)? $default,) {final _that = this;
switch (_that) {
case _LandmarkDescription() when $default != null:
return $default(_that.description, _that.tags);
case _:
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<String, dynamic> json) =>
_$LandmarkDescriptionFromJson(json);
@override
final String description;
@override
final List<String> tags;
class _LandmarkDescription implements LandmarkDescription {
const _LandmarkDescription({required this.description, required final List<String> tags}): _tags = tags;
factory _LandmarkDescription.fromJson(Map<String, dynamic> json) => _$LandmarkDescriptionFromJson(json);
@override final String description;
final List<String> _tags;
@override List<String> get tags {
if (_tags is EqualUnmodifiableListView) return _tags;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_tags);
}
/// Create a copy of LandmarkDescription
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LandmarkDescriptionCopyWith<_LandmarkDescription> get copyWith =>
__$LandmarkDescriptionCopyWithImpl<_LandmarkDescription>(
this, _$identity);
_$LandmarkDescriptionCopyWith<_LandmarkDescription> get copyWith => __$LandmarkDescriptionCopyWithImpl<_LandmarkDescription>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$LandmarkDescriptionToJson(
this,
);
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));
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));
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<String> tags});
}
abstract mixin class _$LandmarkDescriptionCopyWith<$Res> implements $LandmarkDescriptionCopyWith<$Res> {
factory _$LandmarkDescriptionCopyWith(_LandmarkDescription value, $Res Function(_LandmarkDescription) _then) = __$LandmarkDescriptionCopyWithImpl;
@override @useResult
$Res call({
String description, List<String> tags
});
}
/// @nodoc
class __$LandmarkDescriptionCopyWithImpl<$Res>
implements _$LandmarkDescriptionCopyWith<$Res> {
@@ -314,23 +272,15 @@ class __$LandmarkDescriptionCopyWithImpl<$Res>
/// 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,
}) {
@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
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<String>,
));
}
}
// dart format on

View File

@@ -13,8 +13,8 @@ _LandmarkDescription _$LandmarkDescriptionFromJson(Map<String, dynamic> json) =>
);
Map<String, dynamic> _$LandmarkDescriptionToJson(
_LandmarkDescription instance) =>
<String, dynamic>{
_LandmarkDescription instance,
) => <String, dynamic>{
'description': instance.description,
'tags': instance.tags,
};

View File

@@ -14,12 +14,16 @@ abstract class LandmarkType with _$LandmarkType {
@JsonEnum(alwaysCreate: true)
enum LandmarkTypeEnum {
@JsonValue('culture')
culture,
@JsonValue('sightseeing')
sightseeing,
@JsonValue('nature')
nature,
@JsonValue('shopping')
shopping,
@JsonValue('start')
start,
@JsonValue('finish')
finish,
}
extension LandmarkTypeEnumExtension on LandmarkTypeEnum {

View File

@@ -14,25 +14,21 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$LandmarkType {
LandmarkTypeEnum get type;
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<LandmarkType> get copyWith =>
_$LandmarkTypeCopyWithImpl<LandmarkType>(
this as LandmarkType, _$identity);
$LandmarkTypeCopyWith<LandmarkType> get copyWith => _$LandmarkTypeCopyWithImpl<LandmarkType>(this as LandmarkType, _$identity);
/// Serializes this LandmarkType to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is LandmarkType &&
(identical(other.type, type) || other.type == type));
return identical(this, other) || (other.runtimeType == runtimeType&&other is LandmarkType&&(identical(other.type, type) || other.type == type));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -43,19 +39,25 @@ mixin _$LandmarkType {
String toString() {
return 'LandmarkType(type: $type)';
}
}
/// @nodoc
abstract mixin class $LandmarkTypeCopyWith<$Res> {
factory $LandmarkTypeCopyWith(
LandmarkType value, $Res Function(LandmarkType) _then) =
_$LandmarkTypeCopyWithImpl;
factory $LandmarkTypeCopyWith(LandmarkType value, $Res Function(LandmarkType) _then) = _$LandmarkTypeCopyWithImpl;
@useResult
$Res call({LandmarkTypeEnum type});
}
$Res call({
LandmarkTypeEnum type
});
}
/// @nodoc
class _$LandmarkTypeCopyWithImpl<$Res> implements $LandmarkTypeCopyWith<$Res> {
class _$LandmarkTypeCopyWithImpl<$Res>
implements $LandmarkTypeCopyWith<$Res> {
_$LandmarkTypeCopyWithImpl(this._self, this._then);
final LandmarkType _self;
@@ -63,20 +65,16 @@ class _$LandmarkTypeCopyWithImpl<$Res> implements $LandmarkTypeCopyWith<$Res> {
/// 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,
}) {
@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
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`.
@@ -91,20 +89,15 @@ extension LandmarkTypePatterns on LandmarkType {
/// }
/// ```
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_LandmarkType value)? $default, {
required TResult orElse(),
}) {
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LandmarkType value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _LandmarkType() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
@@ -118,19 +111,15 @@ extension LandmarkTypePatterns on LandmarkType {
/// }
/// ```
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_LandmarkType value) $default,
) {
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LandmarkType value) $default,){
final _that = this;
switch (_that) {
case _LandmarkType():
return $default(_that);
case _:
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
@@ -143,19 +132,15 @@ extension LandmarkTypePatterns on LandmarkType {
/// }
/// ```
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_LandmarkType value)? $default,
) {
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LandmarkType value)? $default,){
final _that = this;
switch (_that) {
case _LandmarkType() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return null;
}
}
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
@@ -168,20 +153,14 @@ extension LandmarkTypePatterns on LandmarkType {
/// }
/// ```
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function(LandmarkTypeEnum type)? $default, {
required TResult orElse(),
}) {
final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( LandmarkTypeEnum type)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _LandmarkType() when $default != null:
return $default(_that.type);
case _:
return $default(_that.type);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
@@ -195,19 +174,14 @@ extension LandmarkTypePatterns on LandmarkType {
/// }
/// ```
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function(LandmarkTypeEnum type) $default,
) {
final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( LandmarkTypeEnum type) $default,) {final _that = this;
switch (_that) {
case _LandmarkType():
return $default(_that.type);
case _:
return $default(_that.type);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
@@ -220,51 +194,40 @@ extension LandmarkTypePatterns on LandmarkType {
/// }
/// ```
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function(LandmarkTypeEnum type)? $default,
) {
final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( LandmarkTypeEnum type)? $default,) {final _that = this;
switch (_that) {
case _LandmarkType() when $default != null:
return $default(_that.type);
case _:
return $default(_that.type);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _LandmarkType implements LandmarkType {
const _LandmarkType({required this.type});
factory _LandmarkType.fromJson(Map<String, dynamic> json) =>
_$LandmarkTypeFromJson(json);
factory _LandmarkType.fromJson(Map<String, dynamic> json) => _$LandmarkTypeFromJson(json);
@override
final LandmarkTypeEnum type;
@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)
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LandmarkTypeCopyWith<_LandmarkType> get copyWith =>
__$LandmarkTypeCopyWithImpl<_LandmarkType>(this, _$identity);
_$LandmarkTypeCopyWith<_LandmarkType> get copyWith => __$LandmarkTypeCopyWithImpl<_LandmarkType>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$LandmarkTypeToJson(
this,
);
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));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LandmarkType&&(identical(other.type, type) || other.type == type));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -275,19 +238,22 @@ class _LandmarkType implements LandmarkType {
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});
}
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> {
@@ -298,18 +264,14 @@ class __$LandmarkTypeCopyWithImpl<$Res>
/// 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,
}) {
@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
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
as LandmarkTypeEnum,
));
}
}
// dart format on

View File

@@ -7,17 +7,15 @@ part of 'landmark_type.dart';
// **************************************************************************
_LandmarkType _$LandmarkTypeFromJson(Map<String, dynamic> json) =>
_LandmarkType(
type: $enumDecode(_$LandmarkTypeEnumEnumMap, json['type']),
);
_LandmarkType(type: $enumDecode(_$LandmarkTypeEnumEnumMap, json['type']));
Map<String, dynamic> _$LandmarkTypeToJson(_LandmarkType instance) =>
<String, dynamic>{
'type': _$LandmarkTypeEnumEnumMap[instance.type]!,
};
<String, dynamic>{'type': _$LandmarkTypeEnumEnumMap[instance.type]!};
const _$LandmarkTypeEnumEnumMap = {
LandmarkTypeEnum.culture: 'culture',
LandmarkTypeEnum.sightseeing: 'sightseeing',
LandmarkTypeEnum.nature: 'nature',
LandmarkTypeEnum.shopping: 'shopping',
LandmarkTypeEnum.start: 'start',
LandmarkTypeEnum.finish: 'finish',
};

View File

@@ -5,7 +5,20 @@ part 'preferences.g.dart';
@freezed
abstract class Preferences with _$Preferences {
const factory Preferences({
required String test,
/// Scores keyed by preference type (e.g. 'sightseeing', 'shopping', 'nature')
required Map<String, int> scores,
/// Maximum trip duration in minutes
required int maxTimeMinutes,
/// Required start location [lat, lon]
required List<double> startLocation,
/// Optional end location
List<double>? endLocation,
/// Optional detour tolerance in minutes
int? detourToleranceMinutes,
}) = _Preferences;
factory Preferences.fromJson(Map<String, Object?> json) => _$PreferencesFromJson(json);

View File

@@ -14,47 +14,55 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$Preferences {
String get test;
/// Scores keyed by preference type (e.g. 'sightseeing', 'shopping', 'nature')
Map<String, int> get scores;/// Maximum trip duration in minutes
int get maxTimeMinutes;/// Required start location [lat, lon]
List<double> get startLocation;/// Optional end location
List<double>? get endLocation;/// Optional detour tolerance in minutes
int? get detourToleranceMinutes;
/// 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<Preferences> get copyWith =>
_$PreferencesCopyWithImpl<Preferences>(this as Preferences, _$identity);
$PreferencesCopyWith<Preferences> get copyWith => _$PreferencesCopyWithImpl<Preferences>(this as Preferences, _$identity);
/// Serializes this Preferences to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is Preferences &&
(identical(other.test, test) || other.test == test));
return identical(this, other) || (other.runtimeType == runtimeType&&other is Preferences&&const DeepCollectionEquality().equals(other.scores, scores)&&(identical(other.maxTimeMinutes, maxTimeMinutes) || other.maxTimeMinutes == maxTimeMinutes)&&const DeepCollectionEquality().equals(other.startLocation, startLocation)&&const DeepCollectionEquality().equals(other.endLocation, endLocation)&&(identical(other.detourToleranceMinutes, detourToleranceMinutes) || other.detourToleranceMinutes == detourToleranceMinutes));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, test);
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(scores),maxTimeMinutes,const DeepCollectionEquality().hash(startLocation),const DeepCollectionEquality().hash(endLocation),detourToleranceMinutes);
@override
String toString() {
return 'Preferences(test: $test)';
return 'Preferences(scores: $scores, maxTimeMinutes: $maxTimeMinutes, startLocation: $startLocation, endLocation: $endLocation, detourToleranceMinutes: $detourToleranceMinutes)';
}
}
/// @nodoc
abstract mixin class $PreferencesCopyWith<$Res> {
factory $PreferencesCopyWith(
Preferences value, $Res Function(Preferences) _then) =
_$PreferencesCopyWithImpl;
factory $PreferencesCopyWith(Preferences value, $Res Function(Preferences) _then) = _$PreferencesCopyWithImpl;
@useResult
$Res call({String test});
}
$Res call({
Map<String, int> scores, int maxTimeMinutes, List<double> startLocation, List<double>? endLocation, int? detourToleranceMinutes
});
}
/// @nodoc
class _$PreferencesCopyWithImpl<$Res> implements $PreferencesCopyWith<$Res> {
class _$PreferencesCopyWithImpl<$Res>
implements $PreferencesCopyWith<$Res> {
_$PreferencesCopyWithImpl(this._self, this._then);
final Preferences _self;
@@ -62,20 +70,20 @@ class _$PreferencesCopyWithImpl<$Res> implements $PreferencesCopyWith<$Res> {
/// 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,
}) {
@pragma('vm:prefer-inline') @override $Res call({Object? scores = null,Object? maxTimeMinutes = null,Object? startLocation = null,Object? endLocation = freezed,Object? detourToleranceMinutes = freezed,}) {
return _then(_self.copyWith(
test: null == test
? _self.test
: test // ignore: cast_nullable_to_non_nullable
as String,
scores: null == scores ? _self.scores : scores // ignore: cast_nullable_to_non_nullable
as Map<String, int>,maxTimeMinutes: null == maxTimeMinutes ? _self.maxTimeMinutes : maxTimeMinutes // ignore: cast_nullable_to_non_nullable
as int,startLocation: null == startLocation ? _self.startLocation : startLocation // ignore: cast_nullable_to_non_nullable
as List<double>,endLocation: freezed == endLocation ? _self.endLocation : endLocation // ignore: cast_nullable_to_non_nullable
as List<double>?,detourToleranceMinutes: freezed == detourToleranceMinutes ? _self.detourToleranceMinutes : detourToleranceMinutes // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
/// Adds pattern-matching-related methods to [Preferences].
extension PreferencesPatterns on Preferences {
/// A variant of `map` that fallback to returning `orElse`.
@@ -90,20 +98,15 @@ extension PreferencesPatterns on Preferences {
/// }
/// ```
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_Preferences value)? $default, {
required TResult orElse(),
}) {
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Preferences value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Preferences() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
@@ -117,19 +120,15 @@ extension PreferencesPatterns on Preferences {
/// }
/// ```
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_Preferences value) $default,
) {
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Preferences value) $default,){
final _that = this;
switch (_that) {
case _Preferences():
return $default(_that);
case _:
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
@@ -142,19 +141,15 @@ extension PreferencesPatterns on Preferences {
/// }
/// ```
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_Preferences value)? $default,
) {
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Preferences value)? $default,){
final _that = this;
switch (_that) {
case _Preferences() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return null;
}
}
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
@@ -167,20 +162,14 @@ extension PreferencesPatterns on Preferences {
/// }
/// ```
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function(String test)? $default, {
required TResult orElse(),
}) {
final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( Map<String, int> scores, int maxTimeMinutes, List<double> startLocation, List<double>? endLocation, int? detourToleranceMinutes)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Preferences() when $default != null:
return $default(_that.test);
case _:
return $default(_that.scores,_that.maxTimeMinutes,_that.startLocation,_that.endLocation,_that.detourToleranceMinutes);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
@@ -194,19 +183,14 @@ extension PreferencesPatterns on Preferences {
/// }
/// ```
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function(String test) $default,
) {
final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( Map<String, int> scores, int maxTimeMinutes, List<double> startLocation, List<double>? endLocation, int? detourToleranceMinutes) $default,) {final _that = this;
switch (_that) {
case _Preferences():
return $default(_that.test);
case _:
return $default(_that.scores,_that.maxTimeMinutes,_that.startLocation,_that.endLocation,_that.detourToleranceMinutes);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
@@ -219,76 +203,101 @@ extension PreferencesPatterns on Preferences {
/// }
/// ```
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function(String test)? $default,
) {
final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( Map<String, int> scores, int maxTimeMinutes, List<double> startLocation, List<double>? endLocation, int? detourToleranceMinutes)? $default,) {final _that = this;
switch (_that) {
case _Preferences() when $default != null:
return $default(_that.test);
case _:
return $default(_that.scores,_that.maxTimeMinutes,_that.startLocation,_that.endLocation,_that.detourToleranceMinutes);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _Preferences implements Preferences {
const _Preferences({required this.test});
factory _Preferences.fromJson(Map<String, dynamic> json) =>
_$PreferencesFromJson(json);
@override
final String test;
class _Preferences implements Preferences {
const _Preferences({required final Map<String, int> scores, required this.maxTimeMinutes, required final List<double> startLocation, final List<double>? endLocation, this.detourToleranceMinutes}): _scores = scores,_startLocation = startLocation,_endLocation = endLocation;
factory _Preferences.fromJson(Map<String, dynamic> json) => _$PreferencesFromJson(json);
/// Scores keyed by preference type (e.g. 'sightseeing', 'shopping', 'nature')
final Map<String, int> _scores;
/// Scores keyed by preference type (e.g. 'sightseeing', 'shopping', 'nature')
@override Map<String, int> get scores {
if (_scores is EqualUnmodifiableMapView) return _scores;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_scores);
}
/// Maximum trip duration in minutes
@override final int maxTimeMinutes;
/// Required start location [lat, lon]
final List<double> _startLocation;
/// Required start location [lat, lon]
@override List<double> get startLocation {
if (_startLocation is EqualUnmodifiableListView) return _startLocation;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_startLocation);
}
/// Optional end location
final List<double>? _endLocation;
/// Optional end location
@override List<double>? get endLocation {
final value = _endLocation;
if (value == null) return null;
if (_endLocation is EqualUnmodifiableListView) return _endLocation;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
}
/// Optional detour tolerance in minutes
@override final int? detourToleranceMinutes;
/// Create a copy of Preferences
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$PreferencesCopyWith<_Preferences> get copyWith =>
__$PreferencesCopyWithImpl<_Preferences>(this, _$identity);
_$PreferencesCopyWith<_Preferences> get copyWith => __$PreferencesCopyWithImpl<_Preferences>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$PreferencesToJson(
this,
);
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));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Preferences&&const DeepCollectionEquality().equals(other._scores, _scores)&&(identical(other.maxTimeMinutes, maxTimeMinutes) || other.maxTimeMinutes == maxTimeMinutes)&&const DeepCollectionEquality().equals(other._startLocation, _startLocation)&&const DeepCollectionEquality().equals(other._endLocation, _endLocation)&&(identical(other.detourToleranceMinutes, detourToleranceMinutes) || other.detourToleranceMinutes == detourToleranceMinutes));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, test);
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_scores),maxTimeMinutes,const DeepCollectionEquality().hash(_startLocation),const DeepCollectionEquality().hash(_endLocation),detourToleranceMinutes);
@override
String toString() {
return 'Preferences(test: $test)';
return 'Preferences(scores: $scores, maxTimeMinutes: $maxTimeMinutes, startLocation: $startLocation, endLocation: $endLocation, detourToleranceMinutes: $detourToleranceMinutes)';
}
}
/// @nodoc
abstract mixin class _$PreferencesCopyWith<$Res>
implements $PreferencesCopyWith<$Res> {
factory _$PreferencesCopyWith(
_Preferences value, $Res Function(_Preferences) _then) =
__$PreferencesCopyWithImpl;
@override
@useResult
$Res call({String test});
}
abstract mixin class _$PreferencesCopyWith<$Res> implements $PreferencesCopyWith<$Res> {
factory _$PreferencesCopyWith(_Preferences value, $Res Function(_Preferences) _then) = __$PreferencesCopyWithImpl;
@override @useResult
$Res call({
Map<String, int> scores, int maxTimeMinutes, List<double> startLocation, List<double>? endLocation, int? detourToleranceMinutes
});
}
/// @nodoc
class __$PreferencesCopyWithImpl<$Res> implements _$PreferencesCopyWith<$Res> {
class __$PreferencesCopyWithImpl<$Res>
implements _$PreferencesCopyWith<$Res> {
__$PreferencesCopyWithImpl(this._self, this._then);
final _Preferences _self;
@@ -296,18 +305,18 @@ class __$PreferencesCopyWithImpl<$Res> implements _$PreferencesCopyWith<$Res> {
/// 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,
}) {
@override @pragma('vm:prefer-inline') $Res call({Object? scores = null,Object? maxTimeMinutes = null,Object? startLocation = null,Object? endLocation = freezed,Object? detourToleranceMinutes = freezed,}) {
return _then(_Preferences(
test: null == test
? _self.test
: test // ignore: cast_nullable_to_non_nullable
as String,
scores: null == scores ? _self._scores : scores // ignore: cast_nullable_to_non_nullable
as Map<String, int>,maxTimeMinutes: null == maxTimeMinutes ? _self.maxTimeMinutes : maxTimeMinutes // ignore: cast_nullable_to_non_nullable
as int,startLocation: null == startLocation ? _self._startLocation : startLocation // ignore: cast_nullable_to_non_nullable
as List<double>,endLocation: freezed == endLocation ? _self._endLocation : endLocation // ignore: cast_nullable_to_non_nullable
as List<double>?,detourToleranceMinutes: freezed == detourToleranceMinutes ? _self.detourToleranceMinutes : detourToleranceMinutes // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
// dart format on

View File

@@ -7,10 +7,22 @@ part of 'preferences.dart';
// **************************************************************************
_Preferences _$PreferencesFromJson(Map<String, dynamic> json) => _Preferences(
test: json['test'] as String,
scores: Map<String, int>.from(json['scores'] as Map),
maxTimeMinutes: (json['maxTimeMinutes'] as num).toInt(),
startLocation: (json['startLocation'] as List<dynamic>)
.map((e) => (e as num).toDouble())
.toList(),
endLocation: (json['endLocation'] as List<dynamic>?)
?.map((e) => (e as num).toDouble())
.toList(),
detourToleranceMinutes: (json['detourToleranceMinutes'] as num?)?.toInt(),
);
Map<String, dynamic> _$PreferencesToJson(_Preferences instance) =>
<String, dynamic>{
'test': instance.test,
'scores': instance.scores,
'maxTimeMinutes': instance.maxTimeMinutes,
'startLocation': instance.startLocation,
'endLocation': instance.endLocation,
'detourToleranceMinutes': instance.detourToleranceMinutes,
};

View File

@@ -5,12 +5,17 @@ part 'trip.freezed.dart';
part 'trip.g.dart';
@Freezed(makeCollectionsUnmodifiable: false)
@unfreezed
abstract class Trip with _$Trip {
const factory Trip({
factory Trip({
required String uuid,
// Duration totalTime,
/// total time in minutes
int? totalTimeMinutes,
/// ordered list of landmarks in this trip
required List<Landmark> landmarks,
}) = _Trip;

View File

@@ -14,49 +14,49 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$Trip {
String get uuid; // Duration totalTime,
List<Landmark> get landmarks;
String get uuid; set uuid(String value);// Duration totalTime,
/// total time in minutes
int? get totalTimeMinutes;// Duration totalTime,
/// total time in minutes
set totalTimeMinutes(int? value);/// ordered list of landmarks in this trip
List<Landmark> get landmarks;/// ordered list of landmarks in this trip
set landmarks(List<Landmark> value);
/// 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<Trip> get copyWith =>
_$TripCopyWithImpl<Trip>(this as Trip, _$identity);
$TripCopyWith<Trip> get copyWith => _$TripCopyWithImpl<Trip>(this as Trip, _$identity);
/// Serializes this Trip to a JSON map.
Map<String, dynamic> 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)';
return 'Trip(uuid: $uuid, totalTimeMinutes: $totalTimeMinutes, landmarks: $landmarks)';
}
}
/// @nodoc
abstract mixin class $TripCopyWith<$Res> {
factory $TripCopyWith(Trip value, $Res Function(Trip) _then) =
_$TripCopyWithImpl;
factory $TripCopyWith(Trip value, $Res Function(Trip) _then) = _$TripCopyWithImpl;
@useResult
$Res call({String uuid, List<Landmark> landmarks});
}
$Res call({
String uuid, int? totalTimeMinutes, List<Landmark> landmarks
});
}
/// @nodoc
class _$TripCopyWithImpl<$Res> implements $TripCopyWith<$Res> {
class _$TripCopyWithImpl<$Res>
implements $TripCopyWith<$Res> {
_$TripCopyWithImpl(this._self, this._then);
final Trip _self;
@@ -64,25 +64,18 @@ class _$TripCopyWithImpl<$Res> implements $TripCopyWith<$Res> {
/// 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,
}) {
@pragma('vm:prefer-inline') @override $Res call({Object? uuid = null,Object? totalTimeMinutes = freezed,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
uuid: null == uuid ? _self.uuid : uuid // ignore: cast_nullable_to_non_nullable
as String,totalTimeMinutes: freezed == totalTimeMinutes ? _self.totalTimeMinutes : totalTimeMinutes // ignore: cast_nullable_to_non_nullable
as int?,landmarks: null == landmarks ? _self.landmarks : landmarks // ignore: cast_nullable_to_non_nullable
as List<Landmark>,
));
}
}
/// Adds pattern-matching-related methods to [Trip].
extension TripPatterns on Trip {
/// A variant of `map` that fallback to returning `orElse`.
@@ -97,20 +90,15 @@ extension TripPatterns on Trip {
/// }
/// ```
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_Trip value)? $default, {
required TResult orElse(),
}) {
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Trip value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Trip() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
@@ -124,19 +112,15 @@ extension TripPatterns on Trip {
/// }
/// ```
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_Trip value) $default,
) {
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Trip value) $default,){
final _that = this;
switch (_that) {
case _Trip():
return $default(_that);
case _:
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
@@ -149,19 +133,15 @@ extension TripPatterns on Trip {
/// }
/// ```
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_Trip value)? $default,
) {
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Trip value)? $default,){
final _that = this;
switch (_that) {
case _Trip() when $default != null:
return $default(_that);
case _:
return $default(_that);case _:
return null;
}
}
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
@@ -174,20 +154,14 @@ extension TripPatterns on Trip {
/// }
/// ```
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function(String uuid, List<Landmark> landmarks)? $default, {
required TResult orElse(),
}) {
final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String uuid, int? totalTimeMinutes, List<Landmark> landmarks)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Trip() when $default != null:
return $default(_that.uuid, _that.landmarks);
case _:
return $default(_that.uuid,_that.totalTimeMinutes,_that.landmarks);case _:
return orElse();
}
}
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
@@ -201,19 +175,14 @@ extension TripPatterns on Trip {
/// }
/// ```
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function(String uuid, List<Landmark> landmarks) $default,
) {
final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String uuid, int? totalTimeMinutes, List<Landmark> landmarks) $default,) {final _that = this;
switch (_that) {
case _Trip():
return $default(_that.uuid, _that.landmarks);
case _:
return $default(_that.uuid,_that.totalTimeMinutes,_that.landmarks);case _:
throw StateError('Unexpected subclass');
}
}
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
@@ -226,78 +195,67 @@ extension TripPatterns on Trip {
/// }
/// ```
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function(String uuid, List<Landmark> landmarks)? $default,
) {
final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String uuid, int? totalTimeMinutes, List<Landmark> landmarks)? $default,) {final _that = this;
switch (_that) {
case _Trip() when $default != null:
return $default(_that.uuid, _that.landmarks);
case _:
return $default(_that.uuid,_that.totalTimeMinutes,_that.landmarks);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _Trip implements Trip {
const _Trip({required this.uuid, required this.landmarks});
_Trip({required this.uuid, this.totalTimeMinutes, required this.landmarks});
factory _Trip.fromJson(Map<String, dynamic> json) => _$TripFromJson(json);
@override
final String uuid;
@override String uuid;
// Duration totalTime,
@override
final List<Landmark> landmarks;
/// total time in minutes
@override int? totalTimeMinutes;
/// ordered list of landmarks in this trip
@override List<Landmark> landmarks;
/// Create a copy of Trip
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$TripCopyWith<_Trip> get copyWith =>
__$TripCopyWithImpl<_Trip>(this, _$identity);
_$TripCopyWith<_Trip> get copyWith => __$TripCopyWithImpl<_Trip>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$TripToJson(
this,
);
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)';
return 'Trip(uuid: $uuid, totalTimeMinutes: $totalTimeMinutes, 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<Landmark> landmarks});
}
factory _$TripCopyWith(_Trip value, $Res Function(_Trip) _then) = __$TripCopyWithImpl;
@override @useResult
$Res call({
String uuid, int? totalTimeMinutes, List<Landmark> landmarks
});
}
/// @nodoc
class __$TripCopyWithImpl<$Res> implements _$TripCopyWith<$Res> {
class __$TripCopyWithImpl<$Res>
implements _$TripCopyWith<$Res> {
__$TripCopyWithImpl(this._self, this._then);
final _Trip _self;
@@ -305,23 +263,16 @@ class __$TripCopyWithImpl<$Res> implements _$TripCopyWith<$Res> {
/// 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,
}) {
@override @pragma('vm:prefer-inline') $Res call({Object? uuid = null,Object? totalTimeMinutes = freezed,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
uuid: null == uuid ? _self.uuid : uuid // ignore: cast_nullable_to_non_nullable
as String,totalTimeMinutes: freezed == totalTimeMinutes ? _self.totalTimeMinutes : totalTimeMinutes // ignore: cast_nullable_to_non_nullable
as int?,landmarks: null == landmarks ? _self.landmarks : landmarks // ignore: cast_nullable_to_non_nullable
as List<Landmark>,
));
}
}
// dart format on

View File

@@ -8,6 +8,7 @@ part of 'trip.dart';
_Trip _$TripFromJson(Map<String, dynamic> json) => _Trip(
uuid: json['uuid'] as String,
totalTimeMinutes: (json['totalTimeMinutes'] as num?)?.toInt(),
landmarks: (json['landmarks'] as List<dynamic>)
.map((e) => Landmark.fromJson(e as Map<String, dynamic>))
.toList(),
@@ -15,5 +16,6 @@ _Trip _$TripFromJson(Map<String, dynamic> json) => _Trip(
Map<String, dynamic> _$TripToJson(_Trip instance) => <String, dynamic>{
'uuid': instance.uuid,
'totalTimeMinutes': instance.totalTimeMinutes,
'landmarks': instance.landmarks,
};

View File

@@ -0,0 +1,7 @@
abstract class OnboardingRepository {
/// Returns true when the user accepted the onboarding agreement
Future<bool> isOnboarded();
/// Sets the onboarding completion flag
Future<void> setOnboarded(bool value);
}

View File

@@ -2,4 +2,5 @@ import 'package:anyway/domain/entities/preferences.dart';
abstract class PreferencesRepository {
Future<Preferences> getPreferences();
Future<void> savePreferences(Preferences preferences);
}

View File

@@ -1,6 +1,9 @@
import 'package:anyway/domain/entities/landmark.dart';
import 'package:anyway/domain/entities/preferences.dart';
import 'package:anyway/domain/entities/trip.dart';
abstract class TripRepository {
Future<Trip> getTrip({Preferences? preferences, String? tripUUID});
Future<Trip> getTrip({Preferences? preferences, String? tripUUID, List<Landmark>? landmarks});
Future<List<Landmark>> searchLandmarks(Preferences preferences);
}

View File

@@ -3,6 +3,7 @@ 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';
import 'package:anyway/presentation/pages/new_trip_preferences.dart';
// Example providers (replace these with your actual providers)
// final onboardingStateProvider = Provider<bool>((ref) => true); // Replace with actual onboarding state logic
@@ -80,7 +81,16 @@ class TripCreationPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text('Trip Creation Page')),
appBar: AppBar(title: const Text('Create a Trip')),
body: Center(
child: ElevatedButton.icon(
icon: const Icon(Icons.tune),
label: const Text('Set Preferences'),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => const NewTripPreferencesPage()));
},
),
),
);
}
}

View File

@@ -0,0 +1,49 @@
import 'package:anyway/core/dio_client.dart';
import 'package:anyway/data/repositories/local_onboarding_repository.dart';
import 'package:anyway/domain/repositories/onboarding_repository.dart';
import 'package:anyway/domain/repositories/trip_repository.dart';
import 'package:anyway/data/repositories/backend_trip_repository.dart';
import 'package:anyway/data/datasources/trip_remote_datasource.dart';
import 'package:anyway/data/repositories/preferences_repository_impl.dart';
import 'package:anyway/domain/repositories/preferences_repository.dart';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// Provide a configured Dio instance (used by data layer)
final dioProvider = Provider<Dio>((ref) {
// baseUrl can be configured via environment; use a sensible default
return Dio(BaseOptions(
baseUrl: 'https://anyway.anydev.info',
connectTimeout: const Duration(seconds: 5),
receiveTimeout: const Duration(seconds: 120),
headers: {
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.contentTypeHeader: 'application/json',
},
));
});
/// Provide a simple wrapper client if needed elsewhere
final dioClientProvider = Provider<DioClient>((ref) {
final dio = ref.read(dioProvider);
return DioClient(baseUrl: dio.options.baseUrl);
});
/// Onboarding repository backed by SharedPreferences
final onboardingRepositoryProvider = Provider<OnboardingRepository>((ref) {
return LocalOnboardingRepository();
});
/// Preferences repository (local persistence)
final preferencesRepositoryProvider = Provider<PreferencesRepository>((ref) {
return PreferencesRepositoryImpl();
});
/// Trip repository backed by the backend
final tripRepositoryProvider = Provider<TripRepository>((ref) {
final dio = ref.read(dioProvider);
final remote = TripRemoteDataSourceImpl(dio: dio);
return BackendTripRepository(remote: remote);
});

View File

@@ -0,0 +1,16 @@
import 'package:anyway/domain/entities/landmark.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class IntermediateLandmarksNotifier extends Notifier<List<Landmark>> {
@override
List<Landmark> build() => [];
void setLandmarks(List<Landmark> landmarks) {
state = List.unmodifiable(landmarks);
}
void clear() => state = [];
}
final intermediateLandmarksProvider =
NotifierProvider<IntermediateLandmarksNotifier, List<Landmark>>(IntermediateLandmarksNotifier.new);

View File

@@ -1,9 +1,10 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:anyway/domain/repositories/onboarding_repository.dart';
import 'package:anyway/presentation/providers/core_providers.dart';
final onboardingStateProvider = FutureProvider<bool>((ref) async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool('onboardingCompleted') ?? false;
final repo = ref.watch(onboardingRepositoryProvider);
return repo.isOnboarded();
});
@@ -16,9 +17,10 @@ class OnboardingController {
OnboardingController(this.ref);
Future<void> setOnboarded(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('onboardingCompleted', value);
final repo = ref.read(onboardingRepositoryProvider);
await repo.setOnboarded(value);
// refresh the read provider so UI updates
ref.invalidate(onboardingStateProvider);
}
}

View File

@@ -1,6 +1,16 @@
// import 'package:anyway/data/repositories/trip_repository.dart';
// import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:anyway/domain/entities/preferences.dart';
import 'package:anyway/domain/entities/trip.dart';
import 'package:anyway/presentation/providers/landmark_providers.dart';
// final weatherRepositoryProvider = Provider<TripRepository>((ref) {
// return TripRepositoryImpl(???);
// });
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:anyway/presentation/providers/core_providers.dart';
// Provides a function that creates a trip given preferences.
final createTripProvider = Provider<Future<Trip> Function(Preferences)>((ref) {
return (Preferences prefs) async {
final repo = ref.read(tripRepositoryProvider);
final landmarks = await repo.searchLandmarks(prefs);
ref.read(intermediateLandmarksProvider.notifier).setLandmarks(landmarks);
return repo.getTrip(preferences: prefs, landmarks: landmarks);
};
});

View File

@@ -708,26 +708,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
@@ -772,10 +772,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
version: "1.16.0"
version: "1.17.0"
mime:
dependency: transitive
description:
@@ -1273,26 +1273,26 @@ packages:
dependency: transitive
description:
name: test
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7"
url: "https://pub.dev"
source: hosted
version: "1.25.15"
version: "1.26.3"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.7"
test_core:
dependency: transitive
description:
name: test_core
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0"
url: "https://pub.dev"
source: hosted
version: "0.6.8"
version: "0.6.12"
timing:
dependency: transitive
description:
@@ -1409,10 +1409,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description: