1
0
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:
Eric Windmill
2024-09-27 18:49:27 -04:00
committed by GitHub
parent fcf2552cda
commit 46b5a26b26
326 changed files with 53272 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}