mirror of
https://github.com/flutter/samples.git
synced 2025-11-14 11:28:36 +00:00
Compass app (#2446)
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import '../../../domain/models/booking/booking.dart';
|
||||
import '../../../domain/models/booking/booking_summary.dart';
|
||||
import '../../../utils/result.dart';
|
||||
|
||||
abstract class BookingRepository {
|
||||
/// Returns the list of [BookingSummary] for the current user.
|
||||
Future<Result<List<BookingSummary>>> getBookingsList();
|
||||
|
||||
/// Returns a full [Booking] given the id.
|
||||
Future<Result<Booking>> getBooking(int id);
|
||||
|
||||
/// Creates a new [Booking].
|
||||
Future<Result<void>> createBooking(Booking booking);
|
||||
|
||||
/// Delete booking
|
||||
Future<Result<void>> delete(int id);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import '../../../domain/models/booking/booking.dart';
|
||||
import '../../../domain/models/booking/booking_summary.dart';
|
||||
import '../../../utils/result.dart';
|
||||
|
||||
import '../../services/local/local_data_service.dart';
|
||||
import 'booking_repository.dart';
|
||||
|
||||
class BookingRepositoryLocal implements BookingRepository {
|
||||
BookingRepositoryLocal({
|
||||
required LocalDataService localDataService,
|
||||
}) : _localDataService = localDataService;
|
||||
|
||||
// Only create default booking once
|
||||
bool _isInitialized = false;
|
||||
// Used to generate IDs for bookings
|
||||
int _sequentialId = 0;
|
||||
|
||||
final _bookings = List<Booking>.empty(growable: true);
|
||||
final LocalDataService _localDataService;
|
||||
|
||||
@override
|
||||
Future<Result<void>> createBooking(Booking booking) async {
|
||||
// Bookings created come without id, we need to assign one
|
||||
final bookingWithId = booking.copyWith(id: _sequentialId++);
|
||||
_bookings.add(bookingWithId);
|
||||
return Result.ok(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Booking>> getBooking(int id) async {
|
||||
final booking = _bookings.firstWhereOrNull((booking) => booking.id == id);
|
||||
if (booking == null) {
|
||||
return Result.error(Exception('Booking not found'));
|
||||
}
|
||||
return Result.ok(booking);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<BookingSummary>>> getBookingsList() async {
|
||||
// Initialize the repository with a default booking
|
||||
if (!_isInitialized) {
|
||||
await _createDefaultBooking();
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
return Result.ok(_createSummaries());
|
||||
}
|
||||
|
||||
List<BookingSummary> _createSummaries() {
|
||||
return _bookings
|
||||
.map(
|
||||
(booking) => BookingSummary(
|
||||
id: booking.id!,
|
||||
name:
|
||||
'${booking.destination.name}, ${booking.destination.continent}',
|
||||
startDate: booking.startDate,
|
||||
endDate: booking.endDate,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<void> _createDefaultBooking() async {
|
||||
// create a default booking the first time
|
||||
if (_bookings.isEmpty) {
|
||||
final destination = (await _localDataService.getDestinations()).first;
|
||||
final activities = (await _localDataService.getActivities())
|
||||
.where((activity) => activity.destinationRef == destination.ref)
|
||||
.take(4)
|
||||
.toList();
|
||||
|
||||
_bookings.add(
|
||||
Booking(
|
||||
id: _sequentialId++,
|
||||
startDate: DateTime(2024, 1, 1),
|
||||
endDate: DateTime(2024, 2, 1),
|
||||
destination: destination,
|
||||
activity: activities,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> delete(int id) async {
|
||||
_bookings.removeWhere((booking) => booking.id == id);
|
||||
return Result.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import '../../../domain/models/activity/activity.dart';
|
||||
import '../../../domain/models/booking/booking.dart';
|
||||
import '../../../domain/models/booking/booking_summary.dart';
|
||||
import '../../../domain/models/destination/destination.dart';
|
||||
import '../../../utils/result.dart';
|
||||
import '../../services/api/api_client.dart';
|
||||
import '../../services/api/model/booking/booking_api_model.dart';
|
||||
import 'booking_repository.dart';
|
||||
|
||||
class BookingRepositoryRemote implements BookingRepository {
|
||||
BookingRepositoryRemote({
|
||||
required ApiClient apiClient,
|
||||
}) : _apiClient = apiClient;
|
||||
|
||||
final ApiClient _apiClient;
|
||||
|
||||
List<Destination>? _cachedDestinations;
|
||||
|
||||
@override
|
||||
Future<Result<void>> createBooking(Booking booking) async {
|
||||
try {
|
||||
final BookingApiModel bookingApiModel = BookingApiModel(
|
||||
startDate: booking.startDate,
|
||||
endDate: booking.endDate,
|
||||
name: '${booking.destination.name}, ${booking.destination.continent}',
|
||||
destinationRef: booking.destination.ref,
|
||||
activitiesRef:
|
||||
booking.activity.map((activity) => activity.ref).toList(),
|
||||
);
|
||||
return _apiClient.postBooking(bookingApiModel);
|
||||
} on Exception catch (e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Booking>> getBooking(int id) async {
|
||||
try {
|
||||
// Get booking by ID from server
|
||||
final resultBooking = await _apiClient.getBooking(id);
|
||||
if (resultBooking is Error<BookingApiModel>) {
|
||||
return Result.error(resultBooking.error);
|
||||
}
|
||||
final booking = resultBooking.asOk.value;
|
||||
|
||||
// Load destinations if not loaded yet
|
||||
if (_cachedDestinations == null) {
|
||||
final resultDestination = await _apiClient.getDestinations();
|
||||
if (resultDestination is Error<List<Destination>>) {
|
||||
return Result.error(resultDestination.error);
|
||||
}
|
||||
_cachedDestinations = resultDestination.asOk.value;
|
||||
}
|
||||
|
||||
// Get destination for booking
|
||||
final destination = _cachedDestinations!.firstWhere(
|
||||
(destination) => destination.ref == booking.destinationRef);
|
||||
|
||||
final resultActivities =
|
||||
await _apiClient.getActivityByDestination(destination.ref);
|
||||
|
||||
if (resultActivities is Error<List<Activity>>) {
|
||||
return Result.error(resultActivities.error);
|
||||
}
|
||||
final activities = resultActivities.asOk.value
|
||||
.where((activity) => booking.activitiesRef.contains(activity.ref))
|
||||
.toList();
|
||||
|
||||
return Result.ok(
|
||||
Booking(
|
||||
id: booking.id,
|
||||
startDate: booking.startDate,
|
||||
endDate: booking.endDate,
|
||||
destination: destination,
|
||||
activity: activities,
|
||||
),
|
||||
);
|
||||
} on Exception catch (e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<BookingSummary>>> getBookingsList() async {
|
||||
try {
|
||||
final result = await _apiClient.getBookings();
|
||||
if (result is Error<List<BookingApiModel>>) {
|
||||
return Result.error(result.error);
|
||||
}
|
||||
final bookingsApi = result.asOk.value;
|
||||
return Result.ok(bookingsApi
|
||||
.map(
|
||||
(bookingApi) => BookingSummary(
|
||||
id: bookingApi.id!,
|
||||
name: bookingApi.name,
|
||||
startDate: bookingApi.startDate,
|
||||
endDate: bookingApi.endDate,
|
||||
),
|
||||
)
|
||||
.toList());
|
||||
} on Exception catch (e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> delete(int id) async {
|
||||
try {
|
||||
return _apiClient.deleteBooking(id);
|
||||
} on Exception catch (e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user