Skip to content

Commit

Permalink
[#18] Implement getting Survey Detail from API
Browse files Browse the repository at this point in the history
  • Loading branch information
Thieurom committed Sep 7, 2023
1 parent b058807 commit 09276ad
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lib/api/survey_api_service.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:dio/dio.dart';
import 'package:retrofit/http.dart';
import 'package:survey_flutter/model/response/survey_detail_data_response.dart';
import 'package:survey_flutter/model/response/surveys_container_response.dart';

part 'survey_api_service.g.dart';
Expand All @@ -13,4 +14,9 @@ abstract class SurveyApiService {
@Query('page[number]') int pageNumber,
@Query('page[size]') int pageSize,
);

@GET('/surveys/{surveyId}')
Future<SurveyDetailDataResponse> getSurveyDetail(
@Path('surveyId') String surveyId,
);
}
28 changes: 28 additions & 0 deletions lib/model/answer_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:survey_flutter/model/response/answer_response.dart';
import 'package:survey_flutter/utils/string_extension.dart';

class AnswerModel {
final String id;
final String type;
final String text;
final int displayOrder;
final String displayType;

const AnswerModel({

Check warning on line 11 in lib/model/answer_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/answer_model.dart#L11

Added line #L11 was not covered by tests
required this.id,
required this.type,
required this.text,
required this.displayOrder,
required this.displayType,
});
}

extension AnswerModelExtension on AnswerResponse {
AnswerModel toAnswerModel() => AnswerModel(
id: id.orEmpty(),
type: type.orEmpty(),
text: text.orEmpty(),
displayOrder: displayOrder ?? 0,
displayType: displayType.orEmpty(),

Check warning on line 26 in lib/model/answer_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/answer_model.dart#L21-L26

Added lines #L21 - L26 were not covered by tests
);
}
30 changes: 30 additions & 0 deletions lib/model/question_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:survey_flutter/model/answer_model.dart';
import 'package:survey_flutter/model/response/question_response.dart';
import 'package:survey_flutter/utils/string_extension.dart';

class QuestionModel {
final String id;
final String type;
final String text;
final String displayType;
final List<AnswerModel> answers;

QuestionModel({

Check warning on line 12 in lib/model/question_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/question_model.dart#L12

Added line #L12 was not covered by tests
required this.id,
required this.type,
required this.text,
required this.displayType,
required this.answers,
});
}

extension QuestionModelExtension on QuestionResponse {
QuestionModel toQuestionModel() => QuestionModel(
id: id.orEmpty(),
type: type.orEmpty(),
text: text.orEmpty(),
displayType: displayType.orEmpty(),

Check warning on line 26 in lib/model/question_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/question_model.dart#L22-L26

Added lines #L22 - L26 were not covered by tests
answers:
answers?.map((answer) => answer.toAnswerModel()).toList() ?? [],

Check warning on line 28 in lib/model/question_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/question_model.dart#L28

Added line #L28 was not covered by tests
);
}
28 changes: 28 additions & 0 deletions lib/model/response/answer_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'answer_response.g.dart';

@JsonSerializable()
class AnswerResponse {
@JsonKey(name: 'id')
final String? id;
@JsonKey(name: 'type')
final String? type;
@JsonKey(name: 'text')
final String? text;
@JsonKey(name: 'display_order')
final int? displayOrder;
@JsonKey(name: 'display_type')
final String? displayType;

AnswerResponse({

Check warning on line 18 in lib/model/response/answer_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/answer_response.dart#L18

Added line #L18 was not covered by tests
this.id,
this.type,
this.text,
this.displayOrder,
this.displayType,
});

factory AnswerResponse.fromJson(Map<String, dynamic> json) =>
_$AnswerResponseFromJson(json);

Check warning on line 27 in lib/model/response/answer_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/answer_response.dart#L26-L27

Added lines #L26 - L27 were not covered by tests
}
29 changes: 29 additions & 0 deletions lib/model/response/question_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:survey_flutter/model/response/answer_response.dart';

part 'question_response.g.dart';

@JsonSerializable()
class QuestionResponse {
@JsonKey(name: 'id')
final String? id;
@JsonKey(name: 'type')
final String? type;
@JsonKey(name: 'text')
final String? text;
@JsonKey(name: 'display_type')
final String? displayType;
@JsonKey(name: 'answers')
final List<AnswerResponse>? answers;

QuestionResponse({

Check warning on line 19 in lib/model/response/question_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/question_response.dart#L19

Added line #L19 was not covered by tests
this.id,
this.type,
this.text,
this.displayType,
this.answers,
});

factory QuestionResponse.fromJson(Map<String, dynamic> json) =>
_$QuestionResponseFromJson(json);

Check warning on line 28 in lib/model/response/question_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/question_response.dart#L27-L28

Added lines #L27 - L28 were not covered by tests
}
15 changes: 15 additions & 0 deletions lib/model/response/survey_detail_data_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:survey_flutter/model/response/survey_detail_response.dart';

part 'survey_detail_data_response.g.dart';

@JsonSerializable()
class SurveyDetailDataResponse {
@JsonKey(name: 'data')
final SurveyDetailResponse? surveyDetailResponse;

SurveyDetailDataResponse(this.surveyDetailResponse);

Check warning on line 11 in lib/model/response/survey_detail_data_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/survey_detail_data_response.dart#L11

Added line #L11 was not covered by tests

factory SurveyDetailDataResponse.fromJson(Map<String, dynamic> json) =>
_$SurveyDetailDataResponseFromJson(json);

Check warning on line 14 in lib/model/response/survey_detail_data_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/survey_detail_data_response.dart#L13-L14

Added lines #L13 - L14 were not covered by tests
}
35 changes: 35 additions & 0 deletions lib/model/response/survey_detail_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:survey_flutter/model/response/question_response.dart';

part 'survey_detail_response.g.dart';

@JsonSerializable()
class SurveyDetailResponse {
@JsonKey(name: 'id')
final String? id;
@JsonKey(name: 'type')
final String? type;
@JsonKey(name: 'title')
final String? title;
@JsonKey(name: 'description')
final String? description;
@JsonKey(name: 'cover_image_url')
final String? coverImageUrl;
@JsonKey(name: 'survey_type')
final String? surveyType;
@JsonKey(name: 'questions')
final List<QuestionResponse>? questions;

SurveyDetailResponse({

Check warning on line 23 in lib/model/response/survey_detail_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/survey_detail_response.dart#L23

Added line #L23 was not covered by tests
this.id,
this.type,
this.title,
this.description,
this.coverImageUrl,
this.surveyType,
this.questions,
});

factory SurveyDetailResponse.fromJson(Map<String, dynamic> json) =>
_$SurveyDetailResponseFromJson(json);

Check warning on line 34 in lib/model/response/survey_detail_response.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/response/survey_detail_response.dart#L33-L34

Added lines #L33 - L34 were not covered by tests
}
37 changes: 37 additions & 0 deletions lib/model/survey_detail_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:survey_flutter/model/question_model.dart';
import 'package:survey_flutter/model/response/survey_detail_response.dart';
import 'package:survey_flutter/utils/string_extension.dart';

class SurveyDetailModel {
final String id;
final String type;
final String title;
final String description;
final String coverImageUrl;
final String surveyType;
final List<QuestionModel> questions;

const SurveyDetailModel({

Check warning on line 14 in lib/model/survey_detail_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/survey_detail_model.dart#L14

Added line #L14 was not covered by tests
required this.id,
required this.type,
required this.title,
required this.description,
required this.coverImageUrl,
required this.surveyType,
required this.questions,
});
}

extension SurveyDetailModelExtension on SurveyDetailResponse {
SurveyDetailModel toSurveyDetailModel() => SurveyDetailModel(
id: id.orEmpty(),
type: type.orEmpty(),
title: type.orEmpty(),
description: description.orEmpty(),
coverImageUrl: coverImageUrl.orEmpty(),
surveyType: surveyType.orEmpty(),

Check warning on line 32 in lib/model/survey_detail_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/survey_detail_model.dart#L26-L32

Added lines #L26 - L32 were not covered by tests
questions:
questions?.map((question) => question.toQuestionModel()).toList() ??
[],

Check warning on line 35 in lib/model/survey_detail_model.dart

View check run for this annotation

Codecov / codecov/patch

lib/model/survey_detail_model.dart#L34-L35

Added lines #L34 - L35 were not covered by tests
);
}
18 changes: 18 additions & 0 deletions lib/repositories/survey_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:survey_flutter/api/data_sources/token_data_source.dart';
import 'package:survey_flutter/api/exception/network_exceptions.dart';
import 'package:survey_flutter/api/survey_api_service.dart';
import 'package:survey_flutter/di/provider/dio_provider.dart';
import 'package:survey_flutter/model/survey_detail_model.dart';
import 'package:survey_flutter/model/survey_model.dart';
import 'package:survey_flutter/storage/survey_storage.dart';

Expand All @@ -21,6 +22,8 @@ abstract class SurveyRepository {
required int pageNumber,
required int pageSize,
});

Future<SurveyDetailModel> getSurveyDetail(String surveyid);
}

class SurveyRepositoryImpl extends SurveyRepository {
Expand All @@ -45,4 +48,19 @@ class SurveyRepositoryImpl extends SurveyRepository {
throw NetworkExceptions.fromDioException(exception);
}
}

@override

Check warning on line 52 in lib/repositories/survey_repository.dart

View check run for this annotation

Codecov / codecov/patch

lib/repositories/survey_repository.dart#L52

Added line #L52 was not covered by tests
Future<SurveyDetailModel> getSurveyDetail(String surveyid) async {
try {
final response = await _apiService.getSurveyDetail(surveyid);
final surveyDetailResponse = response.surveyDetailResponse;

Check warning on line 56 in lib/repositories/survey_repository.dart

View check run for this annotation

Codecov / codecov/patch

lib/repositories/survey_repository.dart#L55-L56

Added lines #L55 - L56 were not covered by tests
if (surveyDetailResponse == null) {
// TODO: Update catching
throw const NetworkExceptions.unexpectedError();
}
return surveyDetailResponse.toSurveyDetailModel();

Check warning on line 61 in lib/repositories/survey_repository.dart

View check run for this annotation

Codecov / codecov/patch

lib/repositories/survey_repository.dart#L61

Added line #L61 was not covered by tests
} catch (exception) {
throw NetworkExceptions.fromDioException(exception);

Check warning on line 63 in lib/repositories/survey_repository.dart

View check run for this annotation

Codecov / codecov/patch

lib/repositories/survey_repository.dart#L63

Added line #L63 was not covered by tests
}
}
}
20 changes: 20 additions & 0 deletions lib/usecases/get_survey_detail_use_case.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:survey_flutter/model/survey_detail_model.dart';
import 'package:survey_flutter/repositories/survey_repository.dart';
import 'package:survey_flutter/usecases/base/base_use_case.dart';

class GetSurveyDetailUseCase extends UseCase<SurveyDetailModel, String> {
final SurveyRepository _surveyRepository;

GetSurveyDetailUseCase(this._surveyRepository);

@override
// ignore: avoid_renaming_method_parameters
Future<Result<SurveyDetailModel>> call(String surveyId) async {
try {
final result = await _surveyRepository.getSurveyDetail(surveyId);
return Success(result);
} catch (exception) {
return Failed(UseCaseException(exception));
}
}
}
4 changes: 4 additions & 0 deletions lib/utils/string_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extension StringExtension on String? {
String unWrappedOr(String fallback) => this ?? fallback;
String orEmpty() => unWrappedOr('');

Check warning on line 3 in lib/utils/string_extension.dart

View check run for this annotation

Codecov / codecov/patch

lib/utils/string_extension.dart#L2-L3

Added lines #L2 - L3 were not covered by tests
}

0 comments on commit 09276ad

Please sign in to comment.