mirror of https://github.com/flutter/samples.git
Compass App: Add "Activities", "Itinerary Config" and MVVM Commands (#2366)
Part of the WIP for the Compass App example. Merge to `compass-app`. This PR introduces: - A new feature for Activities (UI unfinished). - A repository for the current Itinerary Configuration. - A `Command` utils class to be used in View Models. **Activities** - PR adds the `compass_app/app/assets/activities.json` (large file!) - Created `ActivityRepository` with local and remote implementation. - Added `getActivitiesByDestination` to `ApiClient` - Added `Activity` data model - Created `ActivitiesScreen` and `ActivitiesViewModel`. - WIP: Decided to finish the UI later due to the size the PR was taking. - WIP: Server implementation for Activities will be completed in another PR. **Itinerary Configuration** - Created the `ItineraryConfigRepository` with an "in-memory" implementation. (local database or shared preferences could potentially be implemented too) - Refactored the way screens share data, instead of passing data using the navigator query parameters, the screens store the state (the itinerary configuration) in this repository, and load it when the screen is opened. - This allows to navigate between screens, back and forth, and keep the selection of data the user made. **Commands** - To handle button taps and other running actions. - Encapsulates an action, exposes the running state (to show progress indicators), and ensures that the action cannot execute if it is already running (to avoid multiple taps on buttons). - Two implementations included, one without arguments `Command0`, and one that supports a single argument `Command1`. - Commands also provide an `onComplete` callback, in case the UI needs to do something when the action finished running (e.g. navigate). - Tests are included. **TODO in further PRs** - Finish the Activities UI and continue implementing the app flow. - Introduce an error handling solution. - Move the data jsons into a common folder (maybe a package?) so they can be shared between app and server and don't duplicate files. **Screencast** As it can be observed, the state of the screen is recovered from the stored "itinerary config". Note: Activites screen appears empty, the list is just printed on terminal at the moment. [Screencast from 2024-07-23 10-58-40.webm](https://github.com/user-attachments/assets/54805c66-2938-48dd-8f63-a26b1e88eab6) ## Pre-launch Checklist - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I read the [Contributors Guide]. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-devrel channel on [Discord]. <!-- Links --> [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md [Contributors Guide]: https://github.com/flutter/samples/blob/main/CONTRIBUTING.mdpull/2389/head
parent
be0b3dc0d1
commit
175195eae6
File diff suppressed because it is too large
Load Diff
@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '12.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,9 @@
|
|||||||
|
import 'package:compass_model/model.dart';
|
||||||
|
|
||||||
|
import '../../../utils/result.dart';
|
||||||
|
|
||||||
|
/// Data source for activities.
|
||||||
|
abstract class ActivityRepository {
|
||||||
|
/// Get activities by [Destination] ref.
|
||||||
|
Future<Result<List<Activity>>> getByDestination(String ref);
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:compass_model/model.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import '../../../utils/result.dart';
|
||||||
|
import 'activity_repository.dart';
|
||||||
|
|
||||||
|
/// Local implementation of ActivityRepository
|
||||||
|
/// Uses data from assets folder
|
||||||
|
class ActivityRepositoryLocal implements ActivityRepository {
|
||||||
|
@override
|
||||||
|
Future<Result<List<Activity>>> getByDestination(String ref) async {
|
||||||
|
try {
|
||||||
|
final localData = await _loadAsset();
|
||||||
|
final list = _parse(localData);
|
||||||
|
|
||||||
|
final activities =
|
||||||
|
list.where((activity) => activity.destinationRef == ref).toList();
|
||||||
|
|
||||||
|
return Result.ok(activities);
|
||||||
|
} on Exception catch (error) {
|
||||||
|
return Result.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> _loadAsset() async {
|
||||||
|
return await rootBundle.loadString('assets/activities.json');
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Activity> _parse(String localData) {
|
||||||
|
final parsed = (jsonDecode(localData) as List).cast<Map<String, dynamic>>();
|
||||||
|
|
||||||
|
return parsed.map<Activity>((json) => Activity.fromJson(json)).toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:compass_model/model.dart';
|
||||||
|
|
||||||
|
import '../../../utils/result.dart';
|
||||||
|
import '../../services/api_client.dart';
|
||||||
|
import 'activity_repository.dart';
|
||||||
|
|
||||||
|
/// Remote data source for [Activity].
|
||||||
|
/// Implements basic local caching.
|
||||||
|
/// See: https://docs.flutter.dev/get-started/fwe/local-caching
|
||||||
|
class ActivityRepositoryRemote implements ActivityRepository {
|
||||||
|
ActivityRepositoryRemote({
|
||||||
|
required ApiClient apiClient,
|
||||||
|
}) : _apiClient = apiClient;
|
||||||
|
|
||||||
|
final ApiClient _apiClient;
|
||||||
|
|
||||||
|
final Map<String, List<Activity>> _cachedData = {};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<List<Activity>>> getByDestination(String ref) async {
|
||||||
|
if (!_cachedData.containsKey(ref)) {
|
||||||
|
// No cached data, request activities
|
||||||
|
final result = await _apiClient.getActivityByDestination(ref);
|
||||||
|
if (result is Ok) {
|
||||||
|
_cachedData[ref] = result.asOk.value;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// Return cached data if available
|
||||||
|
return Result.ok(_cachedData[ref]!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import 'package:compass_model/model.dart';
|
||||||
|
|
||||||
|
import '../../../utils/result.dart';
|
||||||
|
|
||||||
|
/// Data source for the current [ItineraryConfig]
|
||||||
|
abstract class ItineraryConfigRepository {
|
||||||
|
/// Get current [ItineraryConfig], may be empty if no configuration started.
|
||||||
|
/// Method is async to support writing to database, file, etc.
|
||||||
|
Future<Result<ItineraryConfig>> getItineraryConfig();
|
||||||
|
|
||||||
|
/// Sets [ItineraryConfig], overrides the previous one stored.
|
||||||
|
/// Returns Result.Ok if set is successful.
|
||||||
|
Future<Result<void>> setItineraryConfig(ItineraryConfig itineraryConfig);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:compass_model/model.dart';
|
||||||
|
|
||||||
|
import '../../../utils/result.dart';
|
||||||
|
import 'itinerary_config_repository.dart';
|
||||||
|
|
||||||
|
/// In-memory implementation of [ItineraryConfigRepository].
|
||||||
|
class ItineraryConfigRepositoryMemory implements ItineraryConfigRepository {
|
||||||
|
ItineraryConfig? _itineraryConfig;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<ItineraryConfig>> getItineraryConfig() async {
|
||||||
|
return Result.ok(_itineraryConfig ?? const ItineraryConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<bool>> setItineraryConfig(
|
||||||
|
ItineraryConfig itineraryConfig,
|
||||||
|
) async {
|
||||||
|
_itineraryConfig = itineraryConfig;
|
||||||
|
return Result.ok(true);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
import 'package:compass_model/model.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
import '../../../data/repositories/activity/activity_repository.dart';
|
||||||
|
import '../../../data/repositories/itinerary_config/itinerary_config_repository.dart';
|
||||||
|
import '../../../utils/command.dart';
|
||||||
|
import '../../../utils/result.dart';
|
||||||
|
|
||||||
|
class ActivitiesViewModel extends ChangeNotifier {
|
||||||
|
ActivitiesViewModel({
|
||||||
|
required ActivityRepository activityRepository,
|
||||||
|
required ItineraryConfigRepository itineraryConfigRepository,
|
||||||
|
}) : _activityRepository = activityRepository,
|
||||||
|
_itineraryConfigRepository = itineraryConfigRepository {
|
||||||
|
loadActivities = Command0(_loadActivities)..execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ActivityRepository _activityRepository;
|
||||||
|
final ItineraryConfigRepository _itineraryConfigRepository;
|
||||||
|
List<Activity> _activities = <Activity>[];
|
||||||
|
final Set<String> _selectedActivities = <String>{};
|
||||||
|
|
||||||
|
/// List of [Activity] per destination.
|
||||||
|
List<Activity> get activities => _activities;
|
||||||
|
|
||||||
|
/// Selected [Activity] by ref.
|
||||||
|
Set<String> get selectedActivities => _selectedActivities;
|
||||||
|
|
||||||
|
/// Load list of [Activity] for a [Destination] by ref.
|
||||||
|
late final Command0 loadActivities;
|
||||||
|
|
||||||
|
Future<void> _loadActivities() async {
|
||||||
|
final result = await _itineraryConfigRepository.getItineraryConfig();
|
||||||
|
if (result is Error) {
|
||||||
|
// TODO: Handle error
|
||||||
|
print(result.asError.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final destinationRef = result.asOk.value.destination;
|
||||||
|
if (destinationRef == null) {
|
||||||
|
// TODO: Error here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final resultActivities =
|
||||||
|
await _activityRepository.getByDestination(destinationRef);
|
||||||
|
switch (resultActivities) {
|
||||||
|
case Ok():
|
||||||
|
{
|
||||||
|
_activities = resultActivities.value;
|
||||||
|
print(_activities);
|
||||||
|
}
|
||||||
|
case Error():
|
||||||
|
{
|
||||||
|
// TODO: Handle error
|
||||||
|
print(resultActivities.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add [Activity] to selected list.
|
||||||
|
void addActivity(String activityRef) {
|
||||||
|
assert(
|
||||||
|
activities.any((activity) => activity.ref == activityRef),
|
||||||
|
"Activity $activityRef not found",
|
||||||
|
);
|
||||||
|
_selectedActivities.add(activityRef);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove [Activity] from selected list.
|
||||||
|
void removeActivity(String activityRef) {
|
||||||
|
assert(
|
||||||
|
activities.any((activity) => activity.ref == activityRef),
|
||||||
|
"Activity $activityRef not found",
|
||||||
|
);
|
||||||
|
_selectedActivities.remove(activityRef);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
import '../../core/ui/back_button.dart';
|
||||||
|
import '../../core/ui/home_button.dart';
|
||||||
|
import '../view_models/activities_viewmodel.dart';
|
||||||
|
|
||||||
|
class ActivitiesScreen extends StatelessWidget {
|
||||||
|
const ActivitiesScreen({
|
||||||
|
super.key,
|
||||||
|
required this.viewModel,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ActivitiesViewModel viewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: ListenableBuilder(
|
||||||
|
listenable: viewModel.loadActivities,
|
||||||
|
builder: (context, child) {
|
||||||
|
if (viewModel.loadActivities.running) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
return child!;
|
||||||
|
},
|
||||||
|
child: ListenableBuilder(
|
||||||
|
listenable: viewModel,
|
||||||
|
builder: (context, child) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 24, bottom: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
CustomBackButton(
|
||||||
|
onTap: () {
|
||||||
|
// Navigate to ResultsScreen and edit search
|
||||||
|
context.go('/results');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const HomeButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// TODO: Display "activities" here
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
import '../themes/colors.dart';
|
||||||
|
|
||||||
|
/// Custom back button to pop navigation.
|
||||||
|
class CustomBackButton extends StatelessWidget {
|
||||||
|
const CustomBackButton({
|
||||||
|
super.key,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
final GestureTapCallback? onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 40.0,
|
||||||
|
width: 40.0,
|
||||||
|
child: DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: AppColors.grey1),
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
onTap: () {
|
||||||
|
if (onTap != null) {
|
||||||
|
onTap!();
|
||||||
|
} else {
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
size: 24.0,
|
||||||
|
Icons.arrow_back,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
final _dateFormatDay = DateFormat('d');
|
||||||
|
final _dateFormatDayMonth = DateFormat('d MMM');
|
||||||
|
|
||||||
|
String dateFormatStartEnd(DateTimeRange dateTimeRange) {
|
||||||
|
final start = dateTimeRange.start;
|
||||||
|
final end = dateTimeRange.end;
|
||||||
|
|
||||||
|
final dayMonthEnd = _dateFormatDayMonth.format(end);
|
||||||
|
|
||||||
|
if (start.month == end.month) {
|
||||||
|
final dayStart = _dateFormatDay.format(start);
|
||||||
|
return '$dayStart - $dayMonthEnd';
|
||||||
|
}
|
||||||
|
|
||||||
|
final dayMonthStart = _dateFormatDayMonth.format(start);
|
||||||
|
return '$dayMonthStart - $dayMonthEnd';
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
typedef CommandAction0<T> = Future<T> Function();
|
||||||
|
typedef CommandAction1<T, A> = Future<T> Function(A);
|
||||||
|
typedef OnComplete<T> = Function(T);
|
||||||
|
|
||||||
|
/// Facilitates interaction with a ViewModel.
|
||||||
|
///
|
||||||
|
/// Encapsulates an action,
|
||||||
|
/// exposes its running state,
|
||||||
|
/// and ensures that it can't be launched again until it finishes.
|
||||||
|
///
|
||||||
|
/// Use [Command0] for actions without arguments.
|
||||||
|
/// Use [Command1] for actions with one argument.
|
||||||
|
abstract class Command<T> extends ChangeNotifier {
|
||||||
|
Command();
|
||||||
|
|
||||||
|
bool _running = false;
|
||||||
|
|
||||||
|
/// True when the action is running.
|
||||||
|
bool get running => _running;
|
||||||
|
|
||||||
|
/// Internal execute implementation
|
||||||
|
Future<void> _execute(
|
||||||
|
CommandAction0<T> action,
|
||||||
|
OnComplete<T>? onComplete,
|
||||||
|
) async {
|
||||||
|
// Ensure the action can't launch multiple times.
|
||||||
|
// e.g. avoid multiple taps on button
|
||||||
|
if (_running) return;
|
||||||
|
|
||||||
|
// Notify listeners.
|
||||||
|
// e.g. button shows loading state
|
||||||
|
_running = true;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = await action();
|
||||||
|
onComplete?.call(result);
|
||||||
|
} finally {
|
||||||
|
_running = false;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [Command] without arguments.
|
||||||
|
/// Takes a [CommandAction0] as action.
|
||||||
|
class Command0<T> extends Command<T> {
|
||||||
|
Command0(this._action);
|
||||||
|
|
||||||
|
final CommandAction0<T> _action;
|
||||||
|
|
||||||
|
/// Executes the action.
|
||||||
|
/// onComplete is called when the action completes.
|
||||||
|
Future<void> execute({OnComplete<T>? onComplete}) async {
|
||||||
|
await _execute(() => _action(), onComplete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [Command] with one argument.
|
||||||
|
/// Takes a [CommandAction1] as action.
|
||||||
|
class Command1<T, A> extends Command<T> {
|
||||||
|
Command1(this._action);
|
||||||
|
|
||||||
|
final CommandAction1<T, A> _action;
|
||||||
|
|
||||||
|
/// Executes the action with the argument.
|
||||||
|
/// onComplete is called when the action completes.
|
||||||
|
Future<void> execute({required A argument, OnComplete<T>? onComplete}) async {
|
||||||
|
await _execute(() => _action(argument), onComplete);
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
platform :osx, '10.14'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_macos_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_macos_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:compass_app/data/repositories/activity/activity_repository_local.dart';
|
||||||
|
import 'package:compass_app/utils/result.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('ActivityRepositoryLocal tests', () {
|
||||||
|
// To load assets
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
final repository = ActivityRepositoryLocal();
|
||||||
|
|
||||||
|
test('should get by destination ref', () async {
|
||||||
|
final result = await repository.getByDestination('alaska');
|
||||||
|
expect(result, isA<Ok>());
|
||||||
|
|
||||||
|
final list = result.asOk.value;
|
||||||
|
expect(list.length, 20);
|
||||||
|
|
||||||
|
final activity = list.first;
|
||||||
|
expect(activity.name, 'Glacier Trekking and Ice Climbing');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
import 'package:compass_app/data/repositories/activity/activity_repository.dart';
|
||||||
|
import 'package:compass_app/data/repositories/activity/activity_repository_remote.dart';
|
||||||
|
import 'package:compass_app/utils/result.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../../../util/fakes/services/fake_api_client.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('ActivityRepositoryRemote tests', () {
|
||||||
|
late FakeApiClient apiClient;
|
||||||
|
late ActivityRepository repository;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
apiClient = FakeApiClient();
|
||||||
|
repository = ActivityRepositoryRemote(apiClient: apiClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get activities for destination', () async {
|
||||||
|
final result = await repository.getByDestination('alaska');
|
||||||
|
expect(result, isA<Ok>());
|
||||||
|
|
||||||
|
final list = result.asOk.value;
|
||||||
|
expect(list.length, 1);
|
||||||
|
|
||||||
|
final destination = list.first;
|
||||||
|
expect(destination.name, 'Glacier Trekking and Ice Climbing');
|
||||||
|
|
||||||
|
// Only one request happened
|
||||||
|
expect(apiClient.requestCount, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get destinations from cache', () async {
|
||||||
|
// Request destination once
|
||||||
|
var result = await repository.getByDestination('alaska');
|
||||||
|
expect(result, isA<Ok>());
|
||||||
|
|
||||||
|
// Request destination another time
|
||||||
|
result = await repository.getByDestination('alaska');
|
||||||
|
expect(result, isA<Ok>());
|
||||||
|
|
||||||
|
// Only one request happened
|
||||||
|
expect(apiClient.requestCount, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:compass_app/data/repositories/itinerary_config/itinerary_config_repository.dart';
|
||||||
|
import 'package:compass_app/utils/result.dart';
|
||||||
|
import 'package:compass_model/src/model/itinerary_config/itinerary_config.dart';
|
||||||
|
|
||||||
|
import 'fake_destination_repository.dart';
|
||||||
|
|
||||||
|
class FakeItineraryConfigRepository implements ItineraryConfigRepository {
|
||||||
|
FakeItineraryConfigRepository({this.itineraryConfig});
|
||||||
|
|
||||||
|
ItineraryConfig? itineraryConfig;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<ItineraryConfig>> getItineraryConfig() async {
|
||||||
|
return Result.ok(itineraryConfig ?? const ItineraryConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<void>> setItineraryConfig(
|
||||||
|
ItineraryConfig itineraryConfig) async {
|
||||||
|
this.itineraryConfig = itineraryConfig;
|
||||||
|
return Result.ok(null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:compass_app/utils/command.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('Command0 tests', () {
|
||||||
|
test('should complete void command', () async {
|
||||||
|
// Void action
|
||||||
|
final command = Command0<void>(() => Future.value());
|
||||||
|
bool completed = false;
|
||||||
|
|
||||||
|
// Run void action
|
||||||
|
await command.execute(onComplete: (_) {
|
||||||
|
completed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Action completed
|
||||||
|
expect(completed, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should complete bool command', () async {
|
||||||
|
// Action that returns bool
|
||||||
|
final command = Command0<bool>(() => Future.value(true));
|
||||||
|
bool completed = false;
|
||||||
|
|
||||||
|
// Run action with result
|
||||||
|
await command.execute(onComplete: (value) {
|
||||||
|
completed = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Action completed with result
|
||||||
|
expect(completed, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('running should be true', () async {
|
||||||
|
final command = Command0<void>(() => Future.value());
|
||||||
|
final future = command.execute();
|
||||||
|
|
||||||
|
// Action is running
|
||||||
|
expect(command.running, true);
|
||||||
|
|
||||||
|
// Await execution
|
||||||
|
await future;
|
||||||
|
|
||||||
|
// Action finished running
|
||||||
|
expect(command.running, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should only run once', () async {
|
||||||
|
int count = 0;
|
||||||
|
final command = Command0<int>(() => Future.value(count++));
|
||||||
|
final future = command.execute();
|
||||||
|
|
||||||
|
// Run multiple times
|
||||||
|
command.execute();
|
||||||
|
command.execute();
|
||||||
|
command.execute();
|
||||||
|
command.execute();
|
||||||
|
|
||||||
|
// Await execution
|
||||||
|
await future;
|
||||||
|
|
||||||
|
// Action is called once
|
||||||
|
expect(count, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Command1 tests', () {
|
||||||
|
test('should complete void command, bool argument', () async {
|
||||||
|
// Void action with bool argument
|
||||||
|
final command = Command1<void, bool>((a) {
|
||||||
|
expect(a, true);
|
||||||
|
return Future.value();
|
||||||
|
});
|
||||||
|
|
||||||
|
bool completed = false;
|
||||||
|
|
||||||
|
// Run void action, ignore void return
|
||||||
|
await command.execute(
|
||||||
|
argument: true,
|
||||||
|
onComplete: (_) {
|
||||||
|
completed = true;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(completed, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should complete bool command, bool argument', () async {
|
||||||
|
// Action that returns bool argument
|
||||||
|
final command = Command1<bool, bool>((a) => Future.value(a));
|
||||||
|
bool completed = false;
|
||||||
|
|
||||||
|
// Run action with result and argument
|
||||||
|
await command.execute(
|
||||||
|
argument: true,
|
||||||
|
onComplete: (value) {
|
||||||
|
completed = value;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Argument was passed to onComplete
|
||||||
|
expect(completed, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
library;
|
library;
|
||||||
|
|
||||||
|
export 'src/model/activity/activity.dart';
|
||||||
export 'src/model/continent/continent.dart';
|
export 'src/model/continent/continent.dart';
|
||||||
export 'src/model/destination/destination.dart';
|
export 'src/model/destination/destination.dart';
|
||||||
|
export 'src/model/itinerary_config/itinerary_config.dart';
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'activity.freezed.dart';
|
||||||
|
|
||||||
|
part 'activity.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class Activity with _$Activity {
|
||||||
|
const factory Activity({
|
||||||
|
/// e.g. 'Glacier Trekking and Ice Climbing'
|
||||||
|
required String name,
|
||||||
|
|
||||||
|
/// e.g. 'Embark on a thrilling adventure exploring the awe-inspiring glaciers of Alaska. Hike across the icy terrain, marvel at the deep blue crevasses, and even try your hand at ice climbing for an unforgettable experience.'
|
||||||
|
required String description,
|
||||||
|
|
||||||
|
/// e.g. 'Matanuska Glacier or Mendenhall Glacier'
|
||||||
|
required String locationName,
|
||||||
|
|
||||||
|
/// Duration in days.
|
||||||
|
/// e.g. 8
|
||||||
|
required int duration,
|
||||||
|
|
||||||
|
/// e.g. 'morning'
|
||||||
|
required String timeOfDay,
|
||||||
|
|
||||||
|
/// e.g. false
|
||||||
|
required bool familyFriendly,
|
||||||
|
|
||||||
|
/// e.g. 4
|
||||||
|
required int price,
|
||||||
|
|
||||||
|
/// e.g. 'alaska'
|
||||||
|
required String destinationRef,
|
||||||
|
|
||||||
|
/// e.g. 'glacier-trekking-and-ice-climbing'
|
||||||
|
required String ref,
|
||||||
|
|
||||||
|
/// e.g. 'https://storage.googleapis.com/tripedia-images/activities/alaska_glacier-trekking-and-ice-climbing.jpg'
|
||||||
|
required String imageUrl,
|
||||||
|
}) = _Activity;
|
||||||
|
|
||||||
|
factory Activity.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$ActivityFromJson(json);
|
||||||
|
}
|
@ -0,0 +1,425 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'activity.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
Activity _$ActivityFromJson(Map<String, dynamic> json) {
|
||||||
|
return _Activity.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$Activity {
|
||||||
|
/// e.g. 'Glacier Trekking and Ice Climbing'
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 'Embark on a thrilling adventure exploring the awe-inspiring glaciers of Alaska. Hike across the icy terrain, marvel at the deep blue crevasses, and even try your hand at ice climbing for an unforgettable experience.'
|
||||||
|
String get description => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 'Matanuska Glacier or Mendenhall Glacier'
|
||||||
|
String get locationName => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Duration in days.
|
||||||
|
/// e.g. 8
|
||||||
|
int get duration => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 'morning'
|
||||||
|
String get timeOfDay => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. false
|
||||||
|
bool get familyFriendly => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 4
|
||||||
|
int get price => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 'alaska'
|
||||||
|
String get destinationRef => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 'glacier-trekking-and-ice-climbing'
|
||||||
|
String get ref => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// e.g. 'https://storage.googleapis.com/tripedia-images/activities/alaska_glacier-trekking-and-ice-climbing.jpg'
|
||||||
|
String get imageUrl => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this Activity to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of Activity
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$ActivityCopyWith<Activity> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ActivityCopyWith<$Res> {
|
||||||
|
factory $ActivityCopyWith(Activity value, $Res Function(Activity) then) =
|
||||||
|
_$ActivityCopyWithImpl<$Res, Activity>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String name,
|
||||||
|
String description,
|
||||||
|
String locationName,
|
||||||
|
int duration,
|
||||||
|
String timeOfDay,
|
||||||
|
bool familyFriendly,
|
||||||
|
int price,
|
||||||
|
String destinationRef,
|
||||||
|
String ref,
|
||||||
|
String imageUrl});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ActivityCopyWithImpl<$Res, $Val extends Activity>
|
||||||
|
implements $ActivityCopyWith<$Res> {
|
||||||
|
_$ActivityCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of Activity
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? locationName = null,
|
||||||
|
Object? duration = null,
|
||||||
|
Object? timeOfDay = null,
|
||||||
|
Object? familyFriendly = null,
|
||||||
|
Object? price = null,
|
||||||
|
Object? destinationRef = null,
|
||||||
|
Object? ref = null,
|
||||||
|
Object? imageUrl = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
locationName: null == locationName
|
||||||
|
? _value.locationName
|
||||||
|
: locationName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
duration: null == duration
|
||||||
|
? _value.duration
|
||||||
|
: duration // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
timeOfDay: null == timeOfDay
|
||||||
|
? _value.timeOfDay
|
||||||
|
: timeOfDay // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
familyFriendly: null == familyFriendly
|
||||||
|
? _value.familyFriendly
|
||||||
|
: familyFriendly // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
price: null == price
|
||||||
|
? _value.price
|
||||||
|
: price // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
destinationRef: null == destinationRef
|
||||||
|
? _value.destinationRef
|
||||||
|
: destinationRef // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
ref: null == ref
|
||||||
|
? _value.ref
|
||||||
|
: ref // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
imageUrl: null == imageUrl
|
||||||
|
? _value.imageUrl
|
||||||
|
: imageUrl // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$ActivityImplCopyWith<$Res>
|
||||||
|
implements $ActivityCopyWith<$Res> {
|
||||||
|
factory _$$ActivityImplCopyWith(
|
||||||
|
_$ActivityImpl value, $Res Function(_$ActivityImpl) then) =
|
||||||
|
__$$ActivityImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String name,
|
||||||
|
String description,
|
||||||
|
String locationName,
|
||||||
|
int duration,
|
||||||
|
String timeOfDay,
|
||||||
|
bool familyFriendly,
|
||||||
|
int price,
|
||||||
|
String destinationRef,
|
||||||
|
String ref,
|
||||||
|
String imageUrl});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$ActivityImplCopyWithImpl<$Res>
|
||||||
|
extends _$ActivityCopyWithImpl<$Res, _$ActivityImpl>
|
||||||
|
implements _$$ActivityImplCopyWith<$Res> {
|
||||||
|
__$$ActivityImplCopyWithImpl(
|
||||||
|
_$ActivityImpl _value, $Res Function(_$ActivityImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of Activity
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? locationName = null,
|
||||||
|
Object? duration = null,
|
||||||
|
Object? timeOfDay = null,
|
||||||
|
Object? familyFriendly = null,
|
||||||
|
Object? price = null,
|
||||||
|
Object? destinationRef = null,
|
||||||
|
Object? ref = null,
|
||||||
|
Object? imageUrl = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$ActivityImpl(
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
locationName: null == locationName
|
||||||
|
? _value.locationName
|
||||||
|
: locationName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
duration: null == duration
|
||||||
|
? _value.duration
|
||||||
|
: duration // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
timeOfDay: null == timeOfDay
|
||||||
|
? _value.timeOfDay
|
||||||
|
: timeOfDay // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
familyFriendly: null == familyFriendly
|
||||||
|
? _value.familyFriendly
|
||||||
|
: familyFriendly // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
price: null == price
|
||||||
|
? _value.price
|
||||||
|
: price // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
|
destinationRef: null == destinationRef
|
||||||
|
? _value.destinationRef
|
||||||
|
: destinationRef // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
ref: null == ref
|
||||||
|
? _value.ref
|
||||||
|
: ref // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
imageUrl: null == imageUrl
|
||||||
|
? _value.imageUrl
|
||||||
|
: imageUrl // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$ActivityImpl implements _Activity {
|
||||||
|
const _$ActivityImpl(
|
||||||
|
{required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.locationName,
|
||||||
|
required this.duration,
|
||||||
|
required this.timeOfDay,
|
||||||
|
required this.familyFriendly,
|
||||||
|
required this.price,
|
||||||
|
required this.destinationRef,
|
||||||
|
required this.ref,
|
||||||
|
required this.imageUrl});
|
||||||
|
|
||||||
|
factory _$ActivityImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$ActivityImplFromJson(json);
|
||||||
|
|
||||||
|
/// e.g. 'Glacier Trekking and Ice Climbing'
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
/// e.g. 'Embark on a thrilling adventure exploring the awe-inspiring glaciers of Alaska. Hike across the icy terrain, marvel at the deep blue crevasses, and even try your hand at ice climbing for an unforgettable experience.'
|
||||||
|
@override
|
||||||
|
final String description;
|
||||||
|
|
||||||
|
/// e.g. 'Matanuska Glacier or Mendenhall Glacier'
|
||||||
|
@override
|
||||||
|
final String locationName;
|
||||||
|
|
||||||
|
/// Duration in days.
|
||||||
|
/// e.g. 8
|
||||||
|
@override
|
||||||
|
final int duration;
|
||||||
|
|
||||||
|
/// e.g. 'morning'
|
||||||
|
@override
|
||||||
|
final String timeOfDay;
|
||||||
|
|
||||||
|
/// e.g. false
|
||||||
|
@override
|
||||||
|
final bool familyFriendly;
|
||||||
|
|
||||||
|
/// e.g. 4
|
||||||
|
@override
|
||||||
|
final int price;
|
||||||
|
|
||||||
|
/// e.g. 'alaska'
|
||||||
|
@override
|
||||||
|
final String destinationRef;
|
||||||
|
|
||||||
|
/// e.g. 'glacier-trekking-and-ice-climbing'
|
||||||
|
@override
|
||||||
|
final String ref;
|
||||||
|
|
||||||
|
/// e.g. 'https://storage.googleapis.com/tripedia-images/activities/alaska_glacier-trekking-and-ice-climbing.jpg'
|
||||||
|
@override
|
||||||
|
final String imageUrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Activity(name: $name, description: $description, locationName: $locationName, duration: $duration, timeOfDay: $timeOfDay, familyFriendly: $familyFriendly, price: $price, destinationRef: $destinationRef, ref: $ref, imageUrl: $imageUrl)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$ActivityImpl &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.description, description) ||
|
||||||
|
other.description == description) &&
|
||||||
|
(identical(other.locationName, locationName) ||
|
||||||
|
other.locationName == locationName) &&
|
||||||
|
(identical(other.duration, duration) ||
|
||||||
|
other.duration == duration) &&
|
||||||
|
(identical(other.timeOfDay, timeOfDay) ||
|
||||||
|
other.timeOfDay == timeOfDay) &&
|
||||||
|
(identical(other.familyFriendly, familyFriendly) ||
|
||||||
|
other.familyFriendly == familyFriendly) &&
|
||||||
|
(identical(other.price, price) || other.price == price) &&
|
||||||
|
(identical(other.destinationRef, destinationRef) ||
|
||||||
|
other.destinationRef == destinationRef) &&
|
||||||
|
(identical(other.ref, ref) || other.ref == ref) &&
|
||||||
|
(identical(other.imageUrl, imageUrl) ||
|
||||||
|
other.imageUrl == imageUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
locationName,
|
||||||
|
duration,
|
||||||
|
timeOfDay,
|
||||||
|
familyFriendly,
|
||||||
|
price,
|
||||||
|
destinationRef,
|
||||||
|
ref,
|
||||||
|
imageUrl);
|
||||||
|
|
||||||
|
/// Create a copy of Activity
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$ActivityImplCopyWith<_$ActivityImpl> get copyWith =>
|
||||||
|
__$$ActivityImplCopyWithImpl<_$ActivityImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$ActivityImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _Activity implements Activity {
|
||||||
|
const factory _Activity(
|
||||||
|
{required final String name,
|
||||||
|
required final String description,
|
||||||
|
required final String locationName,
|
||||||
|
required final int duration,
|
||||||
|
required final String timeOfDay,
|
||||||
|
required final bool familyFriendly,
|
||||||
|
required final int price,
|
||||||
|
required final String destinationRef,
|
||||||
|
required final String ref,
|
||||||
|
required final String imageUrl}) = _$ActivityImpl;
|
||||||
|
|
||||||
|
factory _Activity.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$ActivityImpl.fromJson;
|
||||||
|
|
||||||
|
/// e.g. 'Glacier Trekking and Ice Climbing'
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
|
||||||
|
/// e.g. 'Embark on a thrilling adventure exploring the awe-inspiring glaciers of Alaska. Hike across the icy terrain, marvel at the deep blue crevasses, and even try your hand at ice climbing for an unforgettable experience.'
|
||||||
|
@override
|
||||||
|
String get description;
|
||||||
|
|
||||||
|
/// e.g. 'Matanuska Glacier or Mendenhall Glacier'
|
||||||
|
@override
|
||||||
|
String get locationName;
|
||||||
|
|
||||||
|
/// Duration in days.
|
||||||
|
/// e.g. 8
|
||||||
|
@override
|
||||||
|
int get duration;
|
||||||
|
|
||||||
|
/// e.g. 'morning'
|
||||||
|
@override
|
||||||
|
String get timeOfDay;
|
||||||
|
|
||||||
|
/// e.g. false
|
||||||
|
@override
|
||||||
|
bool get familyFriendly;
|
||||||
|
|
||||||
|
/// e.g. 4
|
||||||
|
@override
|
||||||
|
int get price;
|
||||||
|
|
||||||
|
/// e.g. 'alaska'
|
||||||
|
@override
|
||||||
|
String get destinationRef;
|
||||||
|
|
||||||
|
/// e.g. 'glacier-trekking-and-ice-climbing'
|
||||||
|
@override
|
||||||
|
String get ref;
|
||||||
|
|
||||||
|
/// e.g. 'https://storage.googleapis.com/tripedia-images/activities/alaska_glacier-trekking-and-ice-climbing.jpg'
|
||||||
|
@override
|
||||||
|
String get imageUrl;
|
||||||
|
|
||||||
|
/// Create a copy of Activity
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$ActivityImplCopyWith<_$ActivityImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'activity.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$ActivityImpl _$$ActivityImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ActivityImpl(
|
||||||
|
name: json['name'] as String,
|
||||||
|
description: json['description'] as String,
|
||||||
|
locationName: json['locationName'] as String,
|
||||||
|
duration: (json['duration'] as num).toInt(),
|
||||||
|
timeOfDay: json['timeOfDay'] as String,
|
||||||
|
familyFriendly: json['familyFriendly'] as bool,
|
||||||
|
price: (json['price'] as num).toInt(),
|
||||||
|
destinationRef: json['destinationRef'] as String,
|
||||||
|
ref: json['ref'] as String,
|
||||||
|
imageUrl: json['imageUrl'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ActivityImplToJson(_$ActivityImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'name': instance.name,
|
||||||
|
'description': instance.description,
|
||||||
|
'locationName': instance.locationName,
|
||||||
|
'duration': instance.duration,
|
||||||
|
'timeOfDay': instance.timeOfDay,
|
||||||
|
'familyFriendly': instance.familyFriendly,
|
||||||
|
'price': instance.price,
|
||||||
|
'destinationRef': instance.destinationRef,
|
||||||
|
'ref': instance.ref,
|
||||||
|
'imageUrl': instance.imageUrl,
|
||||||
|
};
|
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'itinerary_config.freezed.dart';
|
||||||
|
|
||||||
|
part 'itinerary_config.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ItineraryConfig with _$ItineraryConfig {
|
||||||
|
const factory ItineraryConfig({
|
||||||
|
/// [Continent] name
|
||||||
|
String? continent,
|
||||||
|
|
||||||
|
/// Start date (check in) of itinerary
|
||||||
|
DateTime? startDate,
|
||||||
|
|
||||||
|
/// End date (check out) of itinerary
|
||||||
|
DateTime? endDate,
|
||||||
|
|
||||||
|
/// Number of guests
|
||||||
|
int? guests,
|
||||||
|
|
||||||
|
/// Selected [Destination] reference
|
||||||
|
String? destination,
|
||||||
|
}) = _ItineraryConfig;
|
||||||
|
|
||||||
|
factory ItineraryConfig.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$ItineraryConfigFromJson(json);
|
||||||
|
}
|
@ -0,0 +1,280 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'itinerary_config.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
ItineraryConfig _$ItineraryConfigFromJson(Map<String, dynamic> json) {
|
||||||
|
return _ItineraryConfig.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ItineraryConfig {
|
||||||
|
/// [Continent] name
|
||||||
|
String? get continent => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Start date (check in) of itinerary
|
||||||
|
DateTime? get startDate => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// End date (check out) of itinerary
|
||||||
|
DateTime? get endDate => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Number of guests
|
||||||
|
int? get guests => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Selected [Destination] reference
|
||||||
|
String? get destination => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this ItineraryConfig to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of ItineraryConfig
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$ItineraryConfigCopyWith<ItineraryConfig> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ItineraryConfigCopyWith<$Res> {
|
||||||
|
factory $ItineraryConfigCopyWith(
|
||||||
|
ItineraryConfig value, $Res Function(ItineraryConfig) then) =
|
||||||
|
_$ItineraryConfigCopyWithImpl<$Res, ItineraryConfig>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String? continent,
|
||||||
|
DateTime? startDate,
|
||||||
|
DateTime? endDate,
|
||||||
|
int? guests,
|
||||||
|
String? destination});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ItineraryConfigCopyWithImpl<$Res, $Val extends ItineraryConfig>
|
||||||
|
implements $ItineraryConfigCopyWith<$Res> {
|
||||||
|
_$ItineraryConfigCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ItineraryConfig
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? continent = freezed,
|
||||||
|
Object? startDate = freezed,
|
||||||
|
Object? endDate = freezed,
|
||||||
|
Object? guests = freezed,
|
||||||
|
Object? destination = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
continent: freezed == continent
|
||||||
|
? _value.continent
|
||||||
|
: continent // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
startDate: freezed == startDate
|
||||||
|
? _value.startDate
|
||||||
|
: startDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
endDate: freezed == endDate
|
||||||
|
? _value.endDate
|
||||||
|
: endDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
guests: freezed == guests
|
||||||
|
? _value.guests
|
||||||
|
: guests // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
destination: freezed == destination
|
||||||
|
? _value.destination
|
||||||
|
: destination // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$ItineraryConfigImplCopyWith<$Res>
|
||||||
|
implements $ItineraryConfigCopyWith<$Res> {
|
||||||
|
factory _$$ItineraryConfigImplCopyWith(_$ItineraryConfigImpl value,
|
||||||
|
$Res Function(_$ItineraryConfigImpl) then) =
|
||||||
|
__$$ItineraryConfigImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String? continent,
|
||||||
|
DateTime? startDate,
|
||||||
|
DateTime? endDate,
|
||||||
|
int? guests,
|
||||||
|
String? destination});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$ItineraryConfigImplCopyWithImpl<$Res>
|
||||||
|
extends _$ItineraryConfigCopyWithImpl<$Res, _$ItineraryConfigImpl>
|
||||||
|
implements _$$ItineraryConfigImplCopyWith<$Res> {
|
||||||
|
__$$ItineraryConfigImplCopyWithImpl(
|
||||||
|
_$ItineraryConfigImpl _value, $Res Function(_$ItineraryConfigImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ItineraryConfig
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? continent = freezed,
|
||||||
|
Object? startDate = freezed,
|
||||||
|
Object? endDate = freezed,
|
||||||
|
Object? guests = freezed,
|
||||||
|
Object? destination = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_$ItineraryConfigImpl(
|
||||||
|
continent: freezed == continent
|
||||||
|
? _value.continent
|
||||||
|
: continent // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
startDate: freezed == startDate
|
||||||
|
? _value.startDate
|
||||||
|
: startDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
endDate: freezed == endDate
|
||||||
|
? _value.endDate
|
||||||
|
: endDate // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
guests: freezed == guests
|
||||||
|
? _value.guests
|
||||||
|
: guests // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
|
destination: freezed == destination
|
||||||
|
? _value.destination
|
||||||
|
: destination // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$ItineraryConfigImpl implements _ItineraryConfig {
|
||||||
|
const _$ItineraryConfigImpl(
|
||||||
|
{this.continent,
|
||||||
|
this.startDate,
|
||||||
|
this.endDate,
|
||||||
|
this.guests,
|
||||||
|
this.destination});
|
||||||
|
|
||||||
|
factory _$ItineraryConfigImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$ItineraryConfigImplFromJson(json);
|
||||||
|
|
||||||
|
/// [Continent] name
|
||||||
|
@override
|
||||||
|
final String? continent;
|
||||||
|
|
||||||
|
/// Start date (check in) of itinerary
|
||||||
|
@override
|
||||||
|
final DateTime? startDate;
|
||||||
|
|
||||||
|
/// End date (check out) of itinerary
|
||||||
|
@override
|
||||||
|
final DateTime? endDate;
|
||||||
|
|
||||||
|
/// Number of guests
|
||||||
|
@override
|
||||||
|
final int? guests;
|
||||||
|
|
||||||
|
/// Selected [Destination] reference
|
||||||
|
@override
|
||||||
|
final String? destination;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ItineraryConfig(continent: $continent, startDate: $startDate, endDate: $endDate, guests: $guests, destination: $destination)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$ItineraryConfigImpl &&
|
||||||
|
(identical(other.continent, continent) ||
|
||||||
|
other.continent == continent) &&
|
||||||
|
(identical(other.startDate, startDate) ||
|
||||||
|
other.startDate == startDate) &&
|
||||||
|
(identical(other.endDate, endDate) || other.endDate == endDate) &&
|
||||||
|
(identical(other.guests, guests) || other.guests == guests) &&
|
||||||
|
(identical(other.destination, destination) ||
|
||||||
|
other.destination == destination));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType, continent, startDate, endDate, guests, destination);
|
||||||
|
|
||||||
|
/// Create a copy of ItineraryConfig
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$ItineraryConfigImplCopyWith<_$ItineraryConfigImpl> get copyWith =>
|
||||||
|
__$$ItineraryConfigImplCopyWithImpl<_$ItineraryConfigImpl>(
|
||||||
|
this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$ItineraryConfigImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _ItineraryConfig implements ItineraryConfig {
|
||||||
|
const factory _ItineraryConfig(
|
||||||
|
{final String? continent,
|
||||||
|
final DateTime? startDate,
|
||||||
|
final DateTime? endDate,
|
||||||
|
final int? guests,
|
||||||
|
final String? destination}) = _$ItineraryConfigImpl;
|
||||||
|
|
||||||
|
factory _ItineraryConfig.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$ItineraryConfigImpl.fromJson;
|
||||||
|
|
||||||
|
/// [Continent] name
|
||||||
|
@override
|
||||||
|
String? get continent;
|
||||||
|
|
||||||
|
/// Start date (check in) of itinerary
|
||||||
|
@override
|
||||||
|
DateTime? get startDate;
|
||||||
|
|
||||||
|
/// End date (check out) of itinerary
|
||||||
|
@override
|
||||||
|
DateTime? get endDate;
|
||||||
|
|
||||||
|
/// Number of guests
|
||||||
|
@override
|
||||||
|
int? get guests;
|
||||||
|
|
||||||
|
/// Selected [Destination] reference
|
||||||
|
@override
|
||||||
|
String? get destination;
|
||||||
|
|
||||||
|
/// Create a copy of ItineraryConfig
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$ItineraryConfigImplCopyWith<_$ItineraryConfigImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'itinerary_config.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$ItineraryConfigImpl _$$ItineraryConfigImplFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$ItineraryConfigImpl(
|
||||||
|
continent: json['continent'] as String?,
|
||||||
|
startDate: json['startDate'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['startDate'] as String),
|
||||||
|
endDate: json['endDate'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['endDate'] as String),
|
||||||
|
guests: (json['guests'] as num?)?.toInt(),
|
||||||
|
destination: json['destination'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ItineraryConfigImplToJson(
|
||||||
|
_$ItineraryConfigImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'continent': instance.continent,
|
||||||
|
'startDate': instance.startDate?.toIso8601String(),
|
||||||
|
'endDate': instance.endDate?.toIso8601String(),
|
||||||
|
'guests': instance.guests,
|
||||||
|
'destination': instance.destination,
|
||||||
|
};
|
Loading…
Reference in new issue