Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added compass_app/app/assets/user.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions compass_app/app/integration_test/app_local_data_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ void main() {
expect(find.byType(HomeScreen), findsOneWidget);
await tester.pumpAndSettle();

// Should show user name
expect(find.text('Sofie\'s Trips'), findsOneWidget);

// Tap on booking (Alaska is created by default)
await tester.tap(find.text('Alaska, North America'));
await tester.pumpAndSettle();
Expand Down
3 changes: 3 additions & 0 deletions compass_app/app/integration_test/app_server_data_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ void main() {
expect(find.byType(HomeScreen), findsOneWidget);
await tester.pumpAndSettle();

// Should show user name
expect(find.text('Sofie\'s Trips'), findsOneWidget);

// Tap on booking (Alaska is created by default)
await tester.tap(find.text('Alaska, North America'));
await tester.pumpAndSettle();
Expand Down
13 changes: 13 additions & 0 deletions compass_app/app/lib/config/dependencies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import '../data/repositories/auth/auth_repository_remote.dart';
import '../data/repositories/booking/booking_repository.dart';
import '../data/repositories/booking/booking_repository_local.dart';
import '../data/repositories/booking/booking_repository_remote.dart';
import '../data/repositories/user/user_repository.dart';
import '../data/repositories/user/user_repository_local.dart';
import '../data/repositories/user/user_repository_remote.dart';
import '../data/services/api/auth_api_client.dart';
import '../data/services/local/local_data_service.dart';
import '../data/services/shared_preferences_service.dart';
Expand Down Expand Up @@ -84,6 +87,11 @@ List<SingleChildWidget> get providersRemote {
apiClient: context.read(),
) as BookingRepository,
),
Provider(
create: (context) => UserRepositoryRemote(
apiClient: context.read(),
) as UserRepository,
),
..._sharedProviders,
];
}
Expand Down Expand Up @@ -122,6 +130,11 @@ List<SingleChildWidget> get providersLocal {
Provider.value(
value: ItineraryConfigRepositoryMemory() as ItineraryConfigRepository,
),
Provider(
create: (context) => UserRepositoryLocal(
localDataService: context.read(),
) as UserRepository,
),
..._sharedProviders,
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import '../../../domain/models/user/user.dart';
import '../../../utils/result.dart';

/// Data source for user related data
abstract class UserRepository {
/// Get current user
Future<Result<User>> getUser();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import '../../../domain/models/user/user.dart';
import '../../../utils/result.dart';
import '../../services/local/local_data_service.dart';
import 'user_repository.dart';

class UserRepositoryLocal implements UserRepository {
UserRepositoryLocal({
required LocalDataService localDataService,
}) : _localDataService = localDataService;

final LocalDataService _localDataService;

@override
Future<Result<User>> getUser() async {
return Result.ok(_localDataService.getUser());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import '../../../domain/models/user/user.dart';
import '../../../utils/result.dart';
import '../../services/api/api_client.dart';
import '../../services/api/model/user/user_api_model.dart';
import 'user_repository.dart';

class UserRepositoryRemote implements UserRepository {
UserRepositoryRemote({
required ApiClient apiClient,
}) : _apiClient = apiClient;

final ApiClient _apiClient;

User? _cachedData;

@override
Future<Result<User>> getUser() async {
if (_cachedData != null) {
return Future.value(Result.ok(_cachedData!));
}

final result = await _apiClient.getUser();
switch (result) {
case Ok<UserApiModel>():
final user = User(
name: result.value.name,
picture: result.value.picture,
);
_cachedData = user;
return Result.ok(user);
case Error<UserApiModel>():
return Result.error(result.error);
}
}
}
21 changes: 21 additions & 0 deletions compass_app/app/lib/data/services/api/api_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../../../domain/models/continent/continent.dart';
import '../../../domain/models/destination/destination.dart';
import '../../../utils/result.dart';
import 'model/booking/booking_api_model.dart';
import 'model/user/user_api_model.dart';

/// Adds the `Authentication` header to a header configuration.
typedef AuthHeaderProvider = String? Function();
Expand Down Expand Up @@ -154,4 +155,24 @@ class ApiClient {
client.close();
}
}

Future<Result<UserApiModel>> getUser() async {
final client = HttpClient();
try {
final request = await client.get('localhost', 8080, '/user');
await _authHeader(request.headers);
final response = await request.close();
if (response.statusCode == 200) {
final stringData = await response.transform(utf8.decoder).join();
final user = UserApiModel.fromJson(jsonDecode(stringData));
return Result.ok(user);
} else {
return Result.error(const HttpException("Invalid response"));
}
} on Exception catch (error) {
return Result.error(error);
} finally {
client.close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'user_api_model.freezed.dart';
part 'user_api_model.g.dart';

@freezed
abstract class UserApiModel with _$UserApiModel {
const factory UserApiModel({
/// The user's ID.
required String id,

/// The user's name.
required String name,

/// The user's email.
required String email,

/// The user's picture URL.
required String picture,
}) = _UserApiModel;

factory UserApiModel.fromJson(Map<String, Object?> json) =>
_$UserApiModelFromJson(json);
}
Loading