Skip to content

Commit

Permalink
Merge pull request #7 from demola234/ui_implementation
Browse files Browse the repository at this point in the history
unit tests
  • Loading branch information
demola234 committed Aug 27, 2023
2 parents cec114b + ef5a701 commit fd4ff8b
Show file tree
Hide file tree
Showing 40 changed files with 4,103 additions and 232 deletions.
5 changes: 5 additions & 0 deletions lib/core/global/constants/app_texts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,9 @@ class AppTexts {
static String editProfile = "Edit Profile";
static String continueTo = "continue";
static String changePassword = "Change Password";
static String oldPassword = "Old Password";
static String newPassword = "New Password";
static String security = "Security";
static String securityDesc = "Enter Password to Access Private Key";
static String getPrivateKey = "Get Private Key";
}
4 changes: 4 additions & 0 deletions lib/core/network/endpoint_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ class EndpointManager {
static String getCampaignsByCategory(String id) =>
'$_defifundr/campaigns/categories/$id';
static const String createDonation = '$_defifundr/campaigns';
static const String setBiometrics = '$_defifundr/user/biometrics';
static const String changeUsername = '$_defifundr/user/update';
static const String changePassword = '$_defifundr/user/password/change';
static const String getPrivateKey = '$_defifundr/user/privatekey';
}
2 changes: 2 additions & 0 deletions lib/core/routers/_routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import 'package:defiraiser_mobile/features/home/presentation/_home.dart';
import 'package:defiraiser_mobile/features/home/presentation/view/category_campaign_screen.dart';
import 'package:defiraiser_mobile/features/profile/presentation/view/change_password_screen.dart';
import 'package:defiraiser_mobile/features/profile/presentation/view/edit_profile_screen.dart';
import 'package:defiraiser_mobile/features/profile/presentation/view/security_screen.dart';
import 'package:defiraiser_mobile/features/profile/presentation/view/select_avatar_screen.dart';
import 'package:defiraiser_mobile/features/profile/presentation/view/view_private_key_screen.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

Expand Down
46 changes: 46 additions & 0 deletions lib/core/routers/routers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,52 @@ class AppRouter {
);
},
),
GoRoute(
path: 'security',
name: RouteConstants.security,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: SecurityScreen(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
// Change the opacity of the screen using a Curve based on the the animation's
// value
return FadeTransition(
opacity: CurveTween(curve: Curves.easeInOutCirc)
.animate(animation),
child: child,
);
},
);
},
routes: [
GoRoute(
path: 'privateKey',
name: RouteConstants.privateKey,
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: ViewPrivateScreen(
address:
state.queryParameters['address'] ?? '',
privateKey:
state.queryParameters['privateKey'] ?? '',
),
transitionsBuilder: (context, animation,
secondaryAnimation, child) {
// Change the opacity of the screen using a Curve based on the the animation's
// value
return FadeTransition(
opacity:
CurveTween(curve: Curves.easeInOutCirc)
.animate(animation),
child: child,
);
},
);
})
]),
GoRoute(
path: 'selectAvatar2',
name: RouteConstants.selectAvatar2,
Expand Down
2 changes: 2 additions & 0 deletions lib/core/routers/routes_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ class RouteConstants {
static String viewDonors = 'viewDonors';
static String editProfile = 'editProfile';
static String changePassword = 'changePassword';
static String security = 'security';
static String privateKey = 'privateKey';
}
4 changes: 3 additions & 1 deletion lib/core/shared/appbar/appbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ class DeFiRaiseAppBar extends StatelessWidget {
final String? title;
final List<Widget>? actions;
final bool? isBack;
final Widget? leading;

const DeFiRaiseAppBar({
this.title,
this.actions,
this.isBack = false,
this.leading,
super.key,
});

Expand All @@ -39,7 +41,7 @@ class DeFiRaiseAppBar extends StatelessWidget {
context.pop();
},
)
: null,
: leading,
);
}
}
13 changes: 11 additions & 2 deletions lib/core/utils/input_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ mixin InputValidationMixin {
return null;
}

ValidateFailResult? isValidUsername(String? value) {
if (value == null || value.isEmpty) {
return ValidateFailResult.empty;
}
if (value.length < 4) {
return ValidateFailResult.invalidLength;
}
return null;
}

ValidateFailResult? isInvalidEmail(String? value) {
if (value == null || !isEmailRegEx.hasMatch(value)) {
return ValidateFailResult.invalidEmail;
Expand Down Expand Up @@ -102,11 +112,10 @@ mixin InputValidationMixin {
};
}


String? isValidTermsAndConditions(bool? value, String message) {
if (value == false || value == null) {
return message;
}
return null;
}
}
}
107 changes: 103 additions & 4 deletions lib/features/profile/data/data_source/profile_remote_date_source.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,116 @@
import 'package:defiraiser_mobile/core/di/injector.dart';
import 'package:defiraiser_mobile/core/global/error/exceptions.dart';
import 'package:defiraiser_mobile/core/network/endpoint_manager.dart';
import 'package:defiraiser_mobile/core/network/network_provider.dart';
import 'package:defiraiser_mobile/core/secure/secure.dart';
import 'package:defiraiser_mobile/core/secure/secure_key.dart';
import 'package:defiraiser_mobile/features/authentication/domain/entities/base_entity/base_entity.dart';
import 'package:defiraiser_mobile/features/profile/domain/entities/address_entity/address_entity.dart';
import 'package:dio/dio.dart';

abstract class ProfileRemoteDataSource {
Future<BaseEntity> setBiometrics();
Future<BaseEntity> setBiometrics({required bool biometrics});
Future<BaseEntity> changeUsername({required String username});
Future<BaseEntity> changePassword(
{required String oldPassword, required String newPassword});
Future<AddressEntity> getPrivateKey({required String password});
}

class ProfileRemoteDataSoImpl implements ProfileRemoteDataSource {
final NetworkProvider client;
ProfileRemoteDataSoImpl(this.client);

@override
Future<BaseEntity> setBiometrics() {
// TODO: implement setBiometrics
throw UnimplementedError();
Future<BaseEntity> setBiometrics({required bool biometrics}) async {
final token =
await sl<SecureStorage>().getAccessToken(SecureStorageKey().token);

final response = await client.call(
path: EndpointManager.setBiometrics,
method: RequestMethod.post,
body: {
'biometrics': biometrics,
},
options: Options(headers: {
'Authorization': 'Bearer $token',
}),
);
final res = response!.data;
if (response.statusCode == 200) {
return BaseEntity.fromJson(res);
} else {
throw ServerException(message: 'Server Error');
}
}

@override
Future<BaseEntity> changeUsername({required String username}) async {
final token =
await sl<SecureStorage>().getAccessToken(SecureStorageKey().token);

final response = await client.call(
path: EndpointManager.changeUsername,
method: RequestMethod.post,
body: {
'username': username,
},
options: Options(headers: {
'Authorization': 'Bearer $token',
}),
);
final res = response!.data;
if (response.statusCode == 200) {
return BaseEntity.fromJson(res);
} else {
throw ServerException(message: 'Server Error');
}
}

@override
Future<BaseEntity> changePassword(
{required String oldPassword, required String newPassword}) async {
final token =
await sl<SecureStorage>().getAccessToken(SecureStorageKey().token);

final response = await client.call(
path: EndpointManager.changePassword,
method: RequestMethod.post,
body: {
'old_password': oldPassword,
'new_password': newPassword,
},
options: Options(headers: {
'Authorization': 'Bearer $token',
}),
);
final res = response!.data;
if (response.statusCode == 200) {
return BaseEntity.fromJson(res);
} else {
throw ServerException(message: 'Server Error');
}
}

@override
Future<AddressEntity> getPrivateKey({required String password}) async {
final token =
await sl<SecureStorage>().getAccessToken(SecureStorageKey().token);

final response = await client.call(
path: EndpointManager.getPrivateKey,
method: RequestMethod.post,
body: {
'password': password,
},
options: Options(headers: {
'Authorization': 'Bearer $token',
}),
);
final res = response!.data;
if (response.statusCode == 200) {
return AddressEntity.fromJson(res);
} else {
throw ServerException(message: 'Server Error');
}
}
}
46 changes: 43 additions & 3 deletions lib/features/profile/data/repositories/profile_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:dartz/dartz.dart';
import 'package:defiraiser_mobile/core/network/api_error.dart';
import 'package:defiraiser_mobile/features/authentication/domain/entities/base_entity/base_entity.dart';
import 'package:defiraiser_mobile/features/profile/data/data_source/profile_remote_date_source.dart';
import 'package:defiraiser_mobile/features/profile/domain/entities/address_entity/address_entity.dart';
import 'package:defiraiser_mobile/features/profile/domain/repositories/profile_repository.dart';

class IProfileRepository implements ProfileRepository {
Expand All @@ -12,8 +13,47 @@ class IProfileRepository implements ProfileRepository {
});

@override
Future<Either<ApiError, BaseEntity>> setBiometrics({required bool isBiometrics}) {
// TODO: implement setBiometrics
throw UnimplementedError();
Future<Either<ApiError, BaseEntity>> setBiometrics(
{required bool isBiometrics}) async {
try {
final remoteCampaign =
await remoteDataSource.setBiometrics(biometrics: isBiometrics);
return Right(remoteCampaign);
} on ApiError catch (error) {
return Left(error);
}
}

@override
Future<Either<ApiError, BaseEntity>> changeUsername({required String username}) async {
try {
final remoteCampaign =
await remoteDataSource.changeUsername(username: username);
return Right(remoteCampaign);
} on ApiError catch (error) {
return Left(error);
}
}

@override
Future<Either<ApiError, BaseEntity>> changePassword({required String oldPassword, required String newPassword}) async {
try {
final remoteCampaign =
await remoteDataSource.changePassword(oldPassword: oldPassword, newPassword: newPassword);
return Right(remoteCampaign);
} on ApiError catch (error) {
return Left(error);
}
}

@override
Future<Either<ApiError, AddressEntity>> getPrivateKey({required String password}) async {
try {
final remoteCampaign =
await remoteDataSource.getPrivateKey(password: password);
return Right(remoteCampaign);
} on ApiError catch (error) {
return Left(error);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:meta/meta.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:convert';

part 'address_entity.freezed.dart';
part 'address_entity.g.dart';

AddressEntity addressEntityFromJson(String str) => AddressEntity.fromJson(json.decode(str));

String addressEntityToJson(AddressEntity data) => json.encode(data.toJson());

@freezed
class AddressEntity with _$AddressEntity {
const factory AddressEntity({
required Data data,
@Default('') message,
required int status,
}) = _AddressEntity;

factory AddressEntity.fromJson(Map<String, dynamic> json) => _$AddressEntityFromJson(json);
}

@freezed
class Data with _$Data {
@JsonSerializable(explicitToJson: true, fieldRename: FieldRename.snake)
const factory Data({
@Default('') address,
@Default('') privateKey,
}) = _Data;

factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json);
}
Loading

0 comments on commit fd4ff8b

Please sign in to comment.