Skip to content
This repository was archived by the owner on Mar 22, 2025. It is now read-only.

Commit 5748e63

Browse files
authored
Merge pull request #105 from chornerman/release/0.2.0
Release - 0.2.0
2 parents 23c11b1 + 15ae42d commit 5748e63

File tree

67 files changed

+2124
-205
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2124
-205
lines changed

analysis_options.yaml

+6-29
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
1-
# This file configures the analyzer, which statically analyzes Dart code to
2-
# check for errors, warnings, and lints.
3-
#
4-
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5-
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6-
# invoked from the command line by running `flutter analyze`.
7-
8-
# The following line activates a set of recommended lints for Flutter apps,
9-
# packages, and plugins designed to encourage good coding practices.
10-
include: package:flutter_lints/flutter.yaml
11-
12-
linter:
13-
# The lint rules applied to this project can be customized in the
14-
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
15-
# included above or to enable additional rules. A list of all available lints
16-
# and their documentation is published at
17-
# https://dart-lang.github.io/linter/lints/index.html.
18-
#
19-
# Instead of disabling a lint rule for the entire project in the
20-
# section below, it can also be suppressed for a single line of code
21-
# or a specific dart file by using the `// ignore: name_of_lint` and
22-
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
23-
# producing the lint.
24-
rules:
25-
# avoid_print: false # Uncomment to disable the `avoid_print` rule
26-
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27-
28-
# Additional information about this file can be found at
29-
# https://dart.dev/guides/language/analysis-options
1+
analyzer:
2+
exclude: [
3+
lib/**.g.dart,
4+
lib/**.freezed.dart,
5+
test/**.mocks.dart
6+
]

assets/color/colors.xml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
<color name="chinese_black">#15151A</color>
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<color name="chinese_black">#15151A</color>
4+
</resources>

assets/images/ic_arrow_right.svg

+5
Loading

ios/Podfile.lock

+6
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,31 @@ PODS:
22
- Flutter (1.0.0)
33
- flutter_config (0.0.1):
44
- Flutter
5+
- path_provider_ios (0.0.1):
6+
- Flutter
57
- shared_preferences_ios (0.0.1):
68
- Flutter
79

810
DEPENDENCIES:
911
- Flutter (from `Flutter`)
1012
- flutter_config (from `.symlinks/plugins/flutter_config/ios`)
13+
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
1114
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
1215

1316
EXTERNAL SOURCES:
1417
Flutter:
1518
:path: Flutter
1619
flutter_config:
1720
:path: ".symlinks/plugins/flutter_config/ios"
21+
path_provider_ios:
22+
:path: ".symlinks/plugins/path_provider_ios/ios"
1823
shared_preferences_ios:
1924
:path: ".symlinks/plugins/shared_preferences_ios/ios"
2025

2126
SPEC CHECKSUMS:
2227
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
2328
flutter_config: 2226c1df19c78fe34a05eb7f1363445f18e76fc1
29+
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
2430
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
2531

2632
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import 'dart:io';
2+
3+
import 'package:dio/dio.dart';
4+
import 'package:freezed_annotation/freezed_annotation.dart';
5+
6+
part 'network_exceptions.freezed.dart';
7+
8+
@freezed
9+
class NetworkExceptions with _$NetworkExceptions {
10+
const factory NetworkExceptions.requestCancelled() = RequestCancelled;
11+
12+
const factory NetworkExceptions.unauthorisedRequest() = UnauthorisedRequest;
13+
14+
const factory NetworkExceptions.badRequest() = BadRequest;
15+
16+
const factory NetworkExceptions.notFound(String reason) = NotFound;
17+
18+
const factory NetworkExceptions.methodNotAllowed() = MethodNotAllowed;
19+
20+
const factory NetworkExceptions.notAcceptable() = NotAcceptable;
21+
22+
const factory NetworkExceptions.requestTimeout() = RequestTimeout;
23+
24+
const factory NetworkExceptions.receiveTimeout() = ReceiveTimeout;
25+
26+
const factory NetworkExceptions.sendTimeout() = SendTimeout;
27+
28+
const factory NetworkExceptions.conflict() = Conflict;
29+
30+
const factory NetworkExceptions.internalServerError() = InternalServerError;
31+
32+
const factory NetworkExceptions.notImplemented() = NotImplemented;
33+
34+
const factory NetworkExceptions.serviceUnavailable() = ServiceUnavailable;
35+
36+
const factory NetworkExceptions.noInternetConnection() = NoInternetConnection;
37+
38+
const factory NetworkExceptions.formatException() = FormatException;
39+
40+
const factory NetworkExceptions.unableToProcess() = UnableToProcess;
41+
42+
const factory NetworkExceptions.defaultError(String error) = DefaultError;
43+
44+
const factory NetworkExceptions.unexpectedError() = UnexpectedError;
45+
46+
static NetworkExceptions fromDioException(error) {
47+
if (error is Exception) {
48+
try {
49+
NetworkExceptions networkExceptions;
50+
if (error is DioError) {
51+
switch (error.type) {
52+
case DioErrorType.cancel:
53+
networkExceptions = const NetworkExceptions.requestCancelled();
54+
break;
55+
case DioErrorType.connectTimeout:
56+
networkExceptions = const NetworkExceptions.requestTimeout();
57+
break;
58+
case DioErrorType.other:
59+
networkExceptions =
60+
const NetworkExceptions.noInternetConnection();
61+
break;
62+
case DioErrorType.receiveTimeout:
63+
networkExceptions = const NetworkExceptions.receiveTimeout();
64+
break;
65+
case DioErrorType.sendTimeout:
66+
networkExceptions = const NetworkExceptions.sendTimeout();
67+
break;
68+
case DioErrorType.response:
69+
switch (error.response?.statusCode) {
70+
case 400:
71+
networkExceptions = const NetworkExceptions.badRequest();
72+
break;
73+
case 401:
74+
networkExceptions =
75+
const NetworkExceptions.unauthorisedRequest();
76+
break;
77+
case 403:
78+
networkExceptions =
79+
const NetworkExceptions.unauthorisedRequest();
80+
break;
81+
case 404:
82+
networkExceptions =
83+
const NetworkExceptions.notFound("Not found");
84+
break;
85+
case 409:
86+
networkExceptions = const NetworkExceptions.conflict();
87+
break;
88+
case 408:
89+
networkExceptions = const NetworkExceptions.requestTimeout();
90+
break;
91+
case 500:
92+
networkExceptions =
93+
const NetworkExceptions.internalServerError();
94+
break;
95+
case 503:
96+
networkExceptions =
97+
const NetworkExceptions.serviceUnavailable();
98+
break;
99+
default:
100+
var responseCode = error.response?.statusCode;
101+
networkExceptions = NetworkExceptions.defaultError(
102+
"Received invalid status code: $responseCode",
103+
);
104+
}
105+
break;
106+
}
107+
} else if (error is SocketException) {
108+
networkExceptions = const NetworkExceptions.noInternetConnection();
109+
} else {
110+
networkExceptions = const NetworkExceptions.unexpectedError();
111+
}
112+
return networkExceptions;
113+
} on FormatException catch (_) {
114+
return const NetworkExceptions.formatException();
115+
} catch (_) {
116+
return const NetworkExceptions.unexpectedError();
117+
}
118+
} else {
119+
if (error.toString().contains("is not a subtype of")) {
120+
return const NetworkExceptions.unableToProcess();
121+
} else {
122+
return const NetworkExceptions.unexpectedError();
123+
}
124+
}
125+
}
126+
127+
static String getErrorMessage(NetworkExceptions networkExceptions) {
128+
String? errorMessage;
129+
networkExceptions.when(notImplemented: () {
130+
errorMessage = "Not Implemented";
131+
}, requestCancelled: () {
132+
errorMessage = "Request Cancelled";
133+
}, internalServerError: () {
134+
errorMessage = "Internal Server Error";
135+
}, notFound: (String reason) {
136+
errorMessage = reason;
137+
}, serviceUnavailable: () {
138+
errorMessage = "Service unavailable";
139+
}, methodNotAllowed: () {
140+
errorMessage = "Method not allowed";
141+
}, badRequest: () {
142+
errorMessage = "Bad request";
143+
}, unauthorisedRequest: () {
144+
errorMessage = "Unauthorised request";
145+
}, unexpectedError: () {
146+
errorMessage = "Unexpected error occurred";
147+
}, requestTimeout: () {
148+
errorMessage = "Connection request timeout";
149+
}, noInternetConnection: () {
150+
errorMessage = "No internet connection";
151+
}, conflict: () {
152+
errorMessage = "Error due to a conflict";
153+
}, sendTimeout: () {
154+
errorMessage = "Send timeout in connection with API server";
155+
}, receiveTimeout: () {
156+
errorMessage = "Receive timeout in connection with API server";
157+
}, unableToProcess: () {
158+
errorMessage = "Unable to process the data";
159+
}, defaultError: (String error) {
160+
errorMessage = error;
161+
}, formatException: () {
162+
errorMessage = "Unexpected error occurred";
163+
}, notAcceptable: () {
164+
errorMessage = "Not acceptable";
165+
});
166+
return errorMessage ?? "Unknown error occurred";
167+
}
168+
}

lib/api/repository/auth_repository.dart

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:injectable/injectable.dart';
2+
import 'package:survey/api/exception/network_exceptions.dart';
23
import 'package:survey/api/grant_type.dart';
34
import 'package:survey/api/request/login_request.dart';
45
import 'package:survey/api/service/auth_service.dart';
@@ -23,19 +24,19 @@ class AuthRepositoryImpl extends AuthRepository {
2324
required String email,
2425
required String password,
2526
}) async {
26-
final response = await _authService.login(
27-
LoginRequest(
28-
grantType: GrantType.password.value,
29-
email: email,
30-
password: password,
31-
clientId: EnvVariables.clientId,
32-
clientSecret: EnvVariables.clientSecret,
33-
),
34-
);
35-
return LoginModel(
36-
accessToken: response.accessToken,
37-
tokenType: response.tokenType,
38-
refreshToken: response.refreshToken,
39-
);
27+
try {
28+
final response = await _authService.login(
29+
LoginRequest(
30+
grantType: GrantType.password.value,
31+
email: email,
32+
password: password,
33+
clientId: EnvVariables.clientId,
34+
clientSecret: EnvVariables.clientSecret,
35+
),
36+
);
37+
return LoginModel.fromResponse(response);
38+
} catch (exception) {
39+
throw NetworkExceptions.fromDioException(exception);
40+
}
4041
}
4142
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import 'package:injectable/injectable.dart';
2+
import 'package:survey/api/exception/network_exceptions.dart';
3+
import 'package:survey/api/service/survey_service.dart';
4+
import 'package:survey/constants.dart';
5+
import 'package:survey/database/hive_utils.dart';
6+
import 'package:survey/model/survey_model.dart';
7+
8+
abstract class SurveyRepository {
9+
Future<List<SurveyModel>> getSurveys({
10+
required int pageNumber,
11+
required int pageSize,
12+
});
13+
}
14+
15+
@Singleton(as: SurveyRepository)
16+
class SurveyRepositoryImpl extends SurveyRepository {
17+
final SurveyService _surveyService;
18+
final HiveUtils _hiveUtils;
19+
20+
SurveyRepositoryImpl(this._surveyService, this._hiveUtils);
21+
22+
@override
23+
Future<List<SurveyModel>> getSurveys({
24+
required int pageNumber,
25+
required int pageSize,
26+
}) async {
27+
try {
28+
final response = await _surveyService.getSurveys(pageNumber, pageSize);
29+
final surveyModels = response.surveys
30+
.map((item) => SurveyModel.fromResponse(item))
31+
.toList();
32+
33+
final shouldClearCache = pageNumber == Constants.firstSurveysPageNumber;
34+
_saveSurveysCache(shouldClearCache, surveyModels);
35+
36+
return surveyModels;
37+
} catch (exception) {
38+
throw NetworkExceptions.fromDioException(exception);
39+
}
40+
}
41+
42+
void _saveSurveysCache(
43+
bool shouldClearCache,
44+
List<SurveyModel> surveyModels,
45+
) {
46+
if (shouldClearCache) _hiveUtils.clearSurveys();
47+
_hiveUtils.saveSurveys(surveyModels);
48+
}
49+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'package:injectable/injectable.dart';
2+
import 'package:survey/api/exception/network_exceptions.dart';
3+
import 'package:survey/api/service/user_service.dart';
4+
import 'package:survey/model/user_model.dart';
5+
6+
abstract class UserRepository {
7+
Future<UserModel> getUser();
8+
}
9+
10+
@Singleton(as: UserRepository)
11+
class UserRepositoryImpl extends UserRepository {
12+
final UserService _userService;
13+
14+
UserRepositoryImpl(this._userService);
15+
16+
@override
17+
Future<UserModel> getUser() async {
18+
try {
19+
final response = await _userService.getUser();
20+
return UserModel.fromResponse(response);
21+
} catch (exception) {
22+
throw NetworkExceptions.fromDioException(exception);
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import 'package:japx/japx.dart';
22

3-
Map<String, dynamic> fromJsonApi(Map<String, dynamic> json) =>
3+
Map<String, dynamic> fromDataJsonApi(Map<String, dynamic> json) =>
44
json.containsKey('data') ? Japx.decode(json)['data'] : json;
5+
6+
Map<String, dynamic> fromRootJsonApi(Map<String, dynamic> json) {
7+
return Japx.decode(json);
8+
}

lib/api/response/login_response.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,5 @@ class LoginResponse {
2020
});
2121

2222
factory LoginResponse.fromJson(Map<String, dynamic> json) =>
23-
_$LoginResponseFromJson(fromJsonApi(json));
24-
25-
Map<String, dynamic> toJson() => _$LoginResponseToJson(this);
23+
_$LoginResponseFromJson(fromDataJsonApi(json));
2624
}

0 commit comments

Comments
 (0)