Skip to content

Commit

Permalink
feat: [#17] 회원가입 보일러플레이트 생성
Browse files Browse the repository at this point in the history
  • Loading branch information
Younggun-Kim committed Nov 9, 2024
1 parent 693f5ec commit 111f0ef
Show file tree
Hide file tree
Showing 28 changed files with 308 additions and 2 deletions.
4 changes: 3 additions & 1 deletion assets/translations/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,7 @@
"findIdPw": "아이디/비밀번호 찾기",
"signUp": "회원가입",
"pleaseEnterValidEmail": "! 올바른 이메일을 입력해주세요.",
"pleaseEnterValidPassword": "! 8자리 이상의 비밀번호를 입력하세요."
"pleaseEnterValidPassword": "! 8자리 이상의 비밀번호를 입력하세요.",
"man": "남자",
"woman": "여자"
}
22 changes: 22 additions & 0 deletions lib/core/types/gender_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:withu_app/core/core.dart';

/// 계약 타입
@JsonEnum(valueField: 'serverKey')
enum GenderType with L10nKeyProvider {
man(l10nKey: 'man', serverKey: 'MAN'),

woman(l10nKey: 'woman', serverKey: 'WOMAN');

@override
final String l10nKey;

final String serverKey;

const GenderType({
required this.l10nKey,
required this.serverKey,
});

bool get isMan => this == GenderType.man;
}
1 change: 1 addition & 0 deletions lib/core/types/login_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';

@JsonEnum(valueField: 'serverKey')
enum LoginType {
none(serverKey: ''),
email(serverKey: 'EMAIL'),
kakao(serverKey: 'KAKAO'),
naver(serverKey: 'NAVER'),
Expand Down
2 changes: 2 additions & 0 deletions lib/core/utils/resource/string_res.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ enum StringRes {
signUp,
pleaseEnterValidEmail,
pleaseEnterValidPassword,
man,
woman,
}

extension StringResEx on StringRes {
Expand Down
1 change: 1 addition & 0 deletions lib/feature/account/data/data_sources/dto/dto.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'login/login.dart';
export 'sign_up/sign_up.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:withu_app/core/core.dart';
import 'package:withu_app/core/types/gender_type.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'sign_up_request_dto.freezed.dart';

part 'sign_up_request_dto.g.dart';

part 'sign_up_request_dto.mock.dart';

@freezed
class SignUpRequestDto with _$SignUpRequestDto {
factory SignUpRequestDto({
required String name,
required String birth,
required String cellPhoneNo,
required String loginId, // 이메일
required String password,
required LoginType type,
required GenderType gender,
}) = _SignUpRequestDto;

factory SignUpRequestDto.fromJson(Map<String, dynamic> json) =>
_$SignUpRequestDtoFromJson(json);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
part of 'sign_up_request_dto.dart';

extension SignUpRequestDtoMock on SignUpRequestDto {
static SignUpRequestDto mock() {
return SignUpRequestDto(
name: '홍길동',
birth: '1993-06-04',
cellPhoneNo: '01049212480',
loginId: '[email protected]',
password: '123qwe!@',
type: LoginType.email,
gender: GenderType.man,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'sign_up_response_dto.freezed.dart';

part 'sign_up_response_dto.g.dart';

part 'sign_up_response_dto.mock.dart';

@freezed
class SignUpResponseDto with _$SignUpResponseDto {
factory SignUpResponseDto({
required bool status,
required String message,
String? userId,
String? loginId,
String? birthDate,
String? sessionId,
}) = _SignUpResponseDto;

factory SignUpResponseDto.fromJson(Map<String, dynamic> json) =>
_$SignUpResponseDtoFromJson(json);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
part of 'sign_up_response_dto.dart';

extension SignUpResponseDtoMock on SignUpResponseDto {
static SignUpResponseDto successEmail() {
return SignUpResponseDto(
status: true,
message: "가입이 완료되었습니다",
userId: "1",
loginId: "[email protected]",
birthDate: "1993-06-04",
sessionId: "test-session-id",
);
}

static SignUpResponseDto fail() {
return SignUpResponseDto(
status: false,
message: "회원가입에 실패하셨습니다.",
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'request/sign_up_request_dto.dart';
export 'response/sign_up_response_dto.dart';
19 changes: 19 additions & 0 deletions lib/feature/account/data/data_sources/mock/mock_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,23 @@ class AccountMockApi extends AccountApiImpl {

return await super.login(requestData: requestData);
}

/// 회원가입 API
@override
FutureOr<ApiResponse<SignUpResponseDto>> signUp({
required SignUpRequestDto requestData,
}) async {
/// Mock 응답 등록
dioAdapter.onPost(
signUpPath,
(server) => server.reply(
200,
SignUpResponseDtoMock.successEmail().toJson(),
delay: const Duration(seconds: 1),
),
data: requestData.toJson(),
);

return await super.signUp(requestData: requestData);
}
}
8 changes: 8 additions & 0 deletions lib/feature/account/data/data_sources/remote/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ abstract class AccountApi {
/// 로그인 주소
late final loginPath = '$path/login';

/// 회원가입 주소
late final signUpPath = '$path/signUp';

/// 로그인 API
FutureOr<ApiResponse<LoginResponseDto>> login({
required LoginRequestDto requestData,
});

/// 회원가입 API
FutureOr<ApiResponse<SignUpResponseDto>> signUp({
required SignUpRequestDto requestData,
});
}
18 changes: 18 additions & 0 deletions lib/feature/account/data/data_sources/remote/api_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,22 @@ class AccountApiImpl extends AccountApi {
(_) => ApiResponse<LoginResponseDto>.fail(FailResponse.error()),
);
}

/// 회원가입 API
@override
FutureOr<ApiResponse<SignUpResponseDto>> signUp({
required SignUpRequestDto requestData,
}) async {
return network.dio
.post(
signUpPath,
data: requestData.toJson(),
)
.then((response) => ApiResponse.success(
SignUpResponseDto.fromJson(response.data),
))
.catchError(
(_) => ApiResponse<SignUpResponseDto>.fail(FailResponse.error()),
);
}
}
9 changes: 8 additions & 1 deletion lib/feature/account/data/repository/repository_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,17 @@ class AccountRepositoryImpl implements AccountRepository {
accountStorage.setSessionId(id: id);
}


/// Session Id Storage 에 조회
@override
Future<String> getSessionId() async {
return await accountStorage.getSessionId();
}

/// 회원 가입
@override
FutureOr<ApiResponse<SignUpResponseDto>> signUp({
required SignUpRequestDto requestData,
}) async {
return await accountApi.signUp(requestData: requestData);
}
}
1 change: 1 addition & 0 deletions lib/feature/account/domain/entity/entity.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'login/login.dart';
export 'sign_up/sign_up.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:withu_app/core/core.dart';

part 'sign_up_result_entity.freezed.dart';

part 'sign_up_result_entity.mock.dart';

@freezed
class SignUpResultEntity with _$SignUpResultEntity {
factory SignUpResultEntity({
required bool status,
required String message,
@Default('') String name,
@Default(LoginType.none) LoginType type,
}) = _SignUpResultEntity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
part of 'sign_up_result_entity.dart';

extension SignUpResultEntityMock on SignUpResultEntity {
static SignUpResultEntity successEmail() {
return SignUpResultEntity(
status: true,
message: '',
name: '홍길동',
type: LoginType.email,
);
}

static SignUpResultEntity failure() {
return SignUpResultEntity(
status: false,
message: '회원가입에 실패하셨습니다.',
name: '',
type: LoginType.none,
);
}
}
1 change: 1 addition & 0 deletions lib/feature/account/domain/entity/sign_up/sign_up.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'result/sign_up_result_entity.dart';
5 changes: 5 additions & 0 deletions lib/feature/account/domain/repository/repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ abstract class AccountRepository {

/// Session Id Storage 에 조회
Future<String> getSessionId() ;

/// 회원 가입
FutureOr<ApiResponse<SignUpResponseDto>> signUp({
required SignUpRequestDto requestData,
});
}
12 changes: 12 additions & 0 deletions lib/feature/account/domain/usecase/sign_up/sign_up_usecase.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:withu_app/feature/account/account.dart';

part 'sign_up_usecase_imple.dart';

abstract class SignUpUseCase {
final AccountRepository accountRepo;

SignUpUseCase({required this.accountRepo});

/// 로그인
Future<SignUpResultEntity> exec({required LoginRequestEntity entity});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
part of 'sign_up_usecase.dart';

class SignUpUseCaseImpl implements SignUpUseCase {
@override
final AccountRepository accountRepo;

SignUpUseCaseImpl({required this.accountRepo});

@override
Future<SignUpResultEntity> exec({required LoginRequestEntity entity}) async {
return SignUpResultEntityMock.failure();
}
}
11 changes: 11 additions & 0 deletions lib/feature/account/init_injections.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:withu_app/core/core.dart';
import 'package:withu_app/feature/account/account.dart';
import 'package:withu_app/feature/account/domain/usecase/sign_up/sign_up_usecase.dart';

void initAccountInjections() {
getIt.registerSingleton<AccountApi>(
Expand All @@ -16,10 +17,20 @@ void initAccountInjections() {
accountStorage: getIt(),
),
);

/// 로그인
getIt.registerSingleton<AccountUseCase>(
AccountUseCaseImpl(accountRepo: getIt()),
);
getIt.registerFactory<LoginBloc>(
() => LoginBloc(accountUseCase: getIt()),
);

/// 회원가입
getIt.registerSingleton<SignUpUseCase>(
SignUpUseCaseImpl(accountRepo: getIt()),
);
getIt.registerFactory<SignUpBloc>(
() => SignUpBloc(signUpUseCase: getIt()),
);
}
1 change: 1 addition & 0 deletions lib/feature/account/presentation/bloc/bloc.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'login/login_bloc.dart';
export 'sign_up/sign_up_bloc.dart';
18 changes: 18 additions & 0 deletions lib/feature/account/presentation/bloc/sign_up/sign_up_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:withu_app/core/utils/bloc/base_bloc.dart';
import 'package:withu_app/feature/account/domain/usecase/sign_up/sign_up_usecase.dart';

part 'sign_up_event.dart';

part 'sign_up_state.dart';

part 'sign_up_bloc.freezed.dart';

class SignUpBloc extends BaseBloc<SignUpEvent, SignUpState> {
final SignUpUseCase signUpUseCase;

SignUpBloc({required this.signUpUseCase})
: super(
SignUpState(status: BaseBlocStatus.initial()),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
part of 'sign_up_bloc.dart';
sealed class SignUpEvent extends BaseBlocEvent {}
13 changes: 13 additions & 0 deletions lib/feature/account/presentation/bloc/sign_up/sign_up_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
part of 'sign_up_bloc.dart';


@freezed
class SignUpState extends BaseBlocState with _$SignUpState {
factory SignUpState({
/// 상태.
required BaseBlocStatus status,

/// 다이얼로그 메시지
@Default('') String message,
}) = _SignUpState;
}
25 changes: 25 additions & 0 deletions lib/feature/account/presentation/page/sign_up/sign_up_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:withu_app/core/core.dart';
import 'package:withu_app/feature/account/account.dart';

class SignUpPage extends StatelessWidget {
const SignUpPage({super.key});

@override
Widget build(BuildContext context) {
return BlocProvider<SignUpBloc>(
create: (context) => getIt(),
child: const SignUpPageContent(),
);
}
}

class SignUpPageContent extends StatelessWidget {
const SignUpPageContent({super.key});

@override
Widget build(BuildContext context) {
return const SizedBox();
}
}
Loading

0 comments on commit 111f0ef

Please sign in to comment.