From ce3c0e317b7ad8014d7059493e50005c687e2138 Mon Sep 17 00:00:00 2001 From: Conner Date: Thu, 24 Oct 2024 11:02:10 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20#7/=EA=B3=B5=EA=B3=A0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=99=94=EB=A9=B4=20=EC=83=81=EC=84=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. JobPostingFormIdSet 이벤트 추가 2. JobPostingFormDetailFetched 이벤트 추가 3. 수정 화면 진입시 id 주입 --- lib/core/router/router.gr.dart | 36 ++++++++++-- .../blocs/form/job_posting_form_bloc.dart | 39 +++++++++++++ .../form/job_posting_form_bloc.freezed.dart | 57 ++++++++++++++++--- .../blocs/form/job_posting_form_event.dart | 16 ++++++ .../blocs/form/job_posting_form_state.dart | 4 +- .../form/job_posting_form_state_ext.dart | 32 +++++++++++ .../pages/job_posting_detail_page.dart | 4 +- .../pages/job_posting_form_page.dart | 13 ++++- .../presentation/pages/job_postings_page.dart | 2 +- 9 files changed, 187 insertions(+), 16 deletions(-) diff --git a/lib/core/router/router.gr.dart b/lib/core/router/router.gr.dart index 2a9107c..a32d9a7 100644 --- a/lib/core/router/router.gr.dart +++ b/lib/core/router/router.gr.dart @@ -68,10 +68,17 @@ class JobPostingDetailRouteArgs { /// generated route for /// [_i2.JobPostingFormPage] -class JobPostingFormRoute extends _i5.PageRouteInfo { - const JobPostingFormRoute({List<_i5.PageRouteInfo>? children}) - : super( +class JobPostingFormRoute extends _i5.PageRouteInfo { + JobPostingFormRoute({ + _i6.Key? key, + String? jobPostingId, + List<_i5.PageRouteInfo>? children, + }) : super( JobPostingFormRoute.name, + args: JobPostingFormRouteArgs( + key: key, + jobPostingId: jobPostingId, + ), initialChildren: children, ); @@ -80,11 +87,32 @@ class JobPostingFormRoute extends _i5.PageRouteInfo { static _i5.PageInfo page = _i5.PageInfo( name, builder: (data) { - return const _i2.JobPostingFormPage(); + final args = data.argsAs( + orElse: () => const JobPostingFormRouteArgs()); + return _i2.JobPostingFormPage( + key: args.key, + jobPostingId: args.jobPostingId, + ); }, ); } +class JobPostingFormRouteArgs { + const JobPostingFormRouteArgs({ + this.key, + this.jobPostingId, + }); + + final _i6.Key? key; + + final String? jobPostingId; + + @override + String toString() { + return 'JobPostingFormRouteArgs{key: $key, jobPostingId: $jobPostingId}'; + } +} + /// generated route for /// [_i3.JobPostingsPage] class JobPostingsRoute extends _i5.PageRouteInfo { diff --git a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.dart b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.dart index 4d195e6..a082488 100644 --- a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.dart +++ b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:withu_app/core/core.dart'; import 'package:withu_app/feature/job_posting/domain/domain.dart'; +import 'package:withu_app/feature/job_posting/domain/entities/job_posting_detail_entity.dart'; part 'job_posting_form_state.dart'; @@ -55,6 +56,8 @@ class JobPostingFormBloc on(_onSelectBreakTimePaid); on(_onToggleHasMealPaid); on(_onPressedSubmit); + on(_onIdSet); + on(_onDetailFetched); } /// 공고 제목 변경 이벤트. @@ -247,4 +250,40 @@ class JobPostingFormBloc emit(state.copyWith(status: JobPostingFormStatus.initial)); } } + + /// 공고 ID 설정 + void _onIdSet( + JobPostingFormIdSet event, + Emitter emit, + ) { + emit(state.copyWith(jobPostingId: event.id)); + } + + /// 공고 상세 조회 + void _onDetailFetched( + JobPostingFormDetailFetched event, + Emitter emit, + ) async { + final id = state.jobPostingId; + if (id == null) { + return; + } + emit(state.copyWith(status: JobPostingFormStatus.loading)); + + final Either result = await useCase.getJobPosting( + jobPostingId: id, + ); + + result.when(success: (JobPostingDetailEntity data) { + emit(state.copyWithEntity( + status: JobPostingFormStatus.loaded, + entity: data, + )); + }, fail: (String message) { + emit(state.copyWith( + status: JobPostingFormStatus.fail, + message: message, + )); + }); + } } diff --git a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.freezed.dart b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.freezed.dart index 83a9271..6fc3843 100644 --- a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.freezed.dart +++ b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_bloc.freezed.dart @@ -29,6 +29,7 @@ mixin _$JobPostingFormState { bool get hasTravelTime => throw _privateConstructorUsedError; bool get hasBreakTime => throw _privateConstructorUsedError; bool get isMealProvided => throw _privateConstructorUsedError; + String? get jobPostingId => throw _privateConstructorUsedError; JobCategoryType? get category => throw _privateConstructorUsedError; ContractType? get contractType => throw _privateConstructorUsedError; DateTime? get contractStartDate => throw _privateConstructorUsedError; @@ -38,6 +39,7 @@ mixin _$JobPostingFormState { PayType? get payType => throw _privateConstructorUsedError; bool? get isTravelTimePaid => throw _privateConstructorUsedError; bool? get isBreakTimePaid => throw _privateConstructorUsedError; + String? get message => throw _privateConstructorUsedError; /// Create a copy of JobPostingFormState /// with the given fields replaced by the non-null parameter values. @@ -66,6 +68,7 @@ abstract class $JobPostingFormStateCopyWith<$Res> { bool hasTravelTime, bool hasBreakTime, bool isMealProvided, + String? jobPostingId, JobCategoryType? category, ContractType? contractType, DateTime? contractStartDate, @@ -74,7 +77,8 @@ abstract class $JobPostingFormStateCopyWith<$Res> { DateTime? workEndTime, PayType? payType, bool? isTravelTimePaid, - bool? isBreakTimePaid}); + bool? isBreakTimePaid, + String? message}); } /// @nodoc @@ -105,6 +109,7 @@ class _$JobPostingFormStateCopyWithImpl<$Res, $Val extends JobPostingFormState> Object? hasTravelTime = null, Object? hasBreakTime = null, Object? isMealProvided = null, + Object? jobPostingId = freezed, Object? category = freezed, Object? contractType = freezed, Object? contractStartDate = freezed, @@ -114,6 +119,7 @@ class _$JobPostingFormStateCopyWithImpl<$Res, $Val extends JobPostingFormState> Object? payType = freezed, Object? isTravelTimePaid = freezed, Object? isBreakTimePaid = freezed, + Object? message = freezed, }) { return _then(_value.copyWith( status: null == status @@ -168,6 +174,10 @@ class _$JobPostingFormStateCopyWithImpl<$Res, $Val extends JobPostingFormState> ? _value.isMealProvided : isMealProvided // ignore: cast_nullable_to_non_nullable as bool, + jobPostingId: freezed == jobPostingId + ? _value.jobPostingId + : jobPostingId // ignore: cast_nullable_to_non_nullable + as String?, category: freezed == category ? _value.category : category // ignore: cast_nullable_to_non_nullable @@ -204,6 +214,10 @@ class _$JobPostingFormStateCopyWithImpl<$Res, $Val extends JobPostingFormState> ? _value.isBreakTimePaid : isBreakTimePaid // ignore: cast_nullable_to_non_nullable as bool?, + message: freezed == message + ? _value.message + : message // ignore: cast_nullable_to_non_nullable + as String?, ) as $Val); } } @@ -230,6 +244,7 @@ abstract class _$$JobPostingFormStateImplCopyWith<$Res> bool hasTravelTime, bool hasBreakTime, bool isMealProvided, + String? jobPostingId, JobCategoryType? category, ContractType? contractType, DateTime? contractStartDate, @@ -238,7 +253,8 @@ abstract class _$$JobPostingFormStateImplCopyWith<$Res> DateTime? workEndTime, PayType? payType, bool? isTravelTimePaid, - bool? isBreakTimePaid}); + bool? isBreakTimePaid, + String? message}); } /// @nodoc @@ -267,6 +283,7 @@ class __$$JobPostingFormStateImplCopyWithImpl<$Res> Object? hasTravelTime = null, Object? hasBreakTime = null, Object? isMealProvided = null, + Object? jobPostingId = freezed, Object? category = freezed, Object? contractType = freezed, Object? contractStartDate = freezed, @@ -276,6 +293,7 @@ class __$$JobPostingFormStateImplCopyWithImpl<$Res> Object? payType = freezed, Object? isTravelTimePaid = freezed, Object? isBreakTimePaid = freezed, + Object? message = freezed, }) { return _then(_$JobPostingFormStateImpl( status: null == status @@ -330,6 +348,10 @@ class __$$JobPostingFormStateImplCopyWithImpl<$Res> ? _value.isMealProvided : isMealProvided // ignore: cast_nullable_to_non_nullable as bool, + jobPostingId: freezed == jobPostingId + ? _value.jobPostingId + : jobPostingId // ignore: cast_nullable_to_non_nullable + as String?, category: freezed == category ? _value.category : category // ignore: cast_nullable_to_non_nullable @@ -366,6 +388,10 @@ class __$$JobPostingFormStateImplCopyWithImpl<$Res> ? _value.isBreakTimePaid : isBreakTimePaid // ignore: cast_nullable_to_non_nullable as bool?, + message: freezed == message + ? _value.message + : message // ignore: cast_nullable_to_non_nullable + as String?, )); } } @@ -387,6 +413,7 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { required this.hasTravelTime, required this.hasBreakTime, required this.isMealProvided, + this.jobPostingId, this.category, this.contractType, this.contractStartDate, @@ -395,7 +422,8 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { this.workEndTime, this.payType, this.isTravelTimePaid, - this.isBreakTimePaid}); + this.isBreakTimePaid, + this.message}); @override final JobPostingFormStatus status; @@ -424,6 +452,8 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { @override final bool isMealProvided; @override + final String? jobPostingId; + @override final JobCategoryType? category; @override final ContractType? contractType; @@ -441,10 +471,12 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { final bool? isTravelTimePaid; @override final bool? isBreakTimePaid; + @override + final String? message; @override String toString() { - return 'JobPostingFormState(status: $status, title: $title, content: $content, isVisibleStartCalendar: $isVisibleStartCalendar, isVisibleEndCalendar: $isVisibleEndCalendar, isTBC: $isTBC, participants: $participants, pay: $pay, address: $address, preferredQualifications: $preferredQualifications, hasTravelTime: $hasTravelTime, hasBreakTime: $hasBreakTime, isMealProvided: $isMealProvided, category: $category, contractType: $contractType, contractStartDate: $contractStartDate, contractEndDate: $contractEndDate, workStartTime: $workStartTime, workEndTime: $workEndTime, payType: $payType, isTravelTimePaid: $isTravelTimePaid, isBreakTimePaid: $isBreakTimePaid)'; + return 'JobPostingFormState(status: $status, title: $title, content: $content, isVisibleStartCalendar: $isVisibleStartCalendar, isVisibleEndCalendar: $isVisibleEndCalendar, isTBC: $isTBC, participants: $participants, pay: $pay, address: $address, preferredQualifications: $preferredQualifications, hasTravelTime: $hasTravelTime, hasBreakTime: $hasBreakTime, isMealProvided: $isMealProvided, jobPostingId: $jobPostingId, category: $category, contractType: $contractType, contractStartDate: $contractStartDate, contractEndDate: $contractEndDate, workStartTime: $workStartTime, workEndTime: $workEndTime, payType: $payType, isTravelTimePaid: $isTravelTimePaid, isBreakTimePaid: $isBreakTimePaid, message: $message)'; } @override @@ -473,6 +505,8 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { other.hasBreakTime == hasBreakTime) && (identical(other.isMealProvided, isMealProvided) || other.isMealProvided == isMealProvided) && + (identical(other.jobPostingId, jobPostingId) || + other.jobPostingId == jobPostingId) && (identical(other.category, category) || other.category == category) && (identical(other.contractType, contractType) || @@ -489,7 +523,8 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { (identical(other.isTravelTimePaid, isTravelTimePaid) || other.isTravelTimePaid == isTravelTimePaid) && (identical(other.isBreakTimePaid, isBreakTimePaid) || - other.isBreakTimePaid == isBreakTimePaid)); + other.isBreakTimePaid == isBreakTimePaid) && + (identical(other.message, message) || other.message == message)); } @override @@ -508,6 +543,7 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { hasTravelTime, hasBreakTime, isMealProvided, + jobPostingId, category, contractType, contractStartDate, @@ -516,7 +552,8 @@ class _$JobPostingFormStateImpl implements _JobPostingFormState { workEndTime, payType, isTravelTimePaid, - isBreakTimePaid + isBreakTimePaid, + message ]); /// Create a copy of JobPostingFormState @@ -544,6 +581,7 @@ abstract class _JobPostingFormState implements JobPostingFormState { required final bool hasTravelTime, required final bool hasBreakTime, required final bool isMealProvided, + final String? jobPostingId, final JobCategoryType? category, final ContractType? contractType, final DateTime? contractStartDate, @@ -552,7 +590,8 @@ abstract class _JobPostingFormState implements JobPostingFormState { final DateTime? workEndTime, final PayType? payType, final bool? isTravelTimePaid, - final bool? isBreakTimePaid}) = _$JobPostingFormStateImpl; + final bool? isBreakTimePaid, + final String? message}) = _$JobPostingFormStateImpl; @override JobPostingFormStatus get status; @@ -581,6 +620,8 @@ abstract class _JobPostingFormState implements JobPostingFormState { @override bool get isMealProvided; @override + String? get jobPostingId; + @override JobCategoryType? get category; @override ContractType? get contractType; @@ -598,6 +639,8 @@ abstract class _JobPostingFormState implements JobPostingFormState { bool? get isTravelTimePaid; @override bool? get isBreakTimePaid; + @override + String? get message; /// Create a copy of JobPostingFormState /// with the given fields replaced by the non-null parameter values. diff --git a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_event.dart b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_event.dart index c00f2f5..2c39884 100644 --- a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_event.dart +++ b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_event.dart @@ -205,3 +205,19 @@ class OnPressedSubmit extends JobPostingFormEvent { @override List get props => []; } + +/// 공고 Id 저장 +class JobPostingFormIdSet extends JobPostingFormEvent { + final String? id; + + JobPostingFormIdSet({required this.id}); + + @override + List get props => [id]; +} + +/// 상세 조회 이벤트 +class JobPostingFormDetailFetched extends JobPostingFormEvent { + @override + List get props => []; +} diff --git a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state.dart b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state.dart index ce3f269..931630c 100644 --- a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state.dart +++ b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state.dart @@ -1,6 +1,6 @@ part of 'job_posting_form_bloc.dart'; -enum JobPostingFormStatus { initial, loading, success } +enum JobPostingFormStatus { initial, loading, loaded, success, fail } extension JobPostingFormStatusExt on JobPostingFormStatus { bool get isSuccess => this == JobPostingFormStatus.success; @@ -24,6 +24,7 @@ class JobPostingFormState with _$JobPostingFormState { required bool hasTravelTime, required bool hasBreakTime, required bool isMealProvided, + String? jobPostingId, JobCategoryType? category, ContractType? contractType, DateTime? contractStartDate, @@ -33,6 +34,7 @@ class JobPostingFormState with _$JobPostingFormState { PayType? payType, bool? isTravelTimePaid, bool? isBreakTimePaid, + String? message, }) = _JobPostingFormState; } diff --git a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state_ext.dart b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state_ext.dart index fcc6928..5e24eed 100644 --- a/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state_ext.dart +++ b/lib/feature/job_posting/presentation/blocs/form/job_posting_form_state_ext.dart @@ -1,9 +1,11 @@ part of 'job_posting_form_bloc.dart'; extension JobPostingFormStateExt on JobPostingFormState { + /// 시작 날짜 문자열 String get contractStartDateStr => contractStartDate?.format('yyyy-MM-dd') ?? ''; + /// 종료 날짜 문자열 String get contractEndDateStr => contractEndDate?.format('yyyy-MM-dd') ?? ''; /// 등록/수정 요청 Entity로 변경 @@ -31,4 +33,34 @@ extension JobPostingFormStateExt on JobPostingFormState { workEndTime: workEndTime, ); } + + /// Entity -> State + JobPostingFormState copyWithEntity({ + required JobPostingFormStatus status, + required JobPostingDetailEntity entity, + }) { + return copyWith( + status: status, + title: entity.title, + content: entity.content, + isTBC: entity.isTBC, + participants: entity.participants, + pay: entity.payAmount, + address: entity.workAddress, + preferredQualifications: entity.preferredQualifications, + hasTravelTime: entity.hasTravelTime, + hasBreakTime: entity.hasBreakTime, + isMealProvided: entity.isMealProvided, + category: entity.categoryType, + contractType: entity.contractType, + contractStartDate: entity.contractStartDate, + contractEndDate: entity.contractEndDate, + workStartTime: entity.workStartTime, + workEndTime: entity.workEndTime, + payType: entity.payType, + isTravelTimePaid: entity.isTravelTimePaid, + isBreakTimePaid: entity.isBreakTimePaid, + message: '', + ); + } } diff --git a/lib/feature/job_posting/presentation/pages/job_posting_detail_page.dart b/lib/feature/job_posting/presentation/pages/job_posting_detail_page.dart index 9588a7c..1355c8b 100644 --- a/lib/feature/job_posting/presentation/pages/job_posting_detail_page.dart +++ b/lib/feature/job_posting/presentation/pages/job_posting_detail_page.dart @@ -55,7 +55,9 @@ class _JobPostingDetailPage extends StatelessWidget { if (state.status.isPushUpdate) { final bloc = context.read(); - await context.router.push(const JobPostingFormRoute()); + await context.router.push(JobPostingFormRoute( + jobPostingId: state.entity?.id, + )); bloc.add(OnPopForm()); } }, diff --git a/lib/feature/job_posting/presentation/pages/job_posting_form_page.dart b/lib/feature/job_posting/presentation/pages/job_posting_form_page.dart index 5ed91bd..295ce8f 100644 --- a/lib/feature/job_posting/presentation/pages/job_posting_form_page.dart +++ b/lib/feature/job_posting/presentation/pages/job_posting_form_page.dart @@ -11,13 +11,22 @@ import 'package:withu_app/shared/shared.dart'; /// 공고 등록/수정 화면 @RoutePage() class JobPostingFormPage extends StatelessWidget { - const JobPostingFormPage({super.key}); + final String? jobPostingId; + + const JobPostingFormPage({ + super.key, + this.jobPostingId, + }); @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider(create: (context) => getIt()), + BlocProvider( + create: (context) => getIt() + ..add(JobPostingFormIdSet(id: jobPostingId)) + ..add(JobPostingFormDetailFetched()), + ), ], child: BlocListener( listener: (context, state) { diff --git a/lib/feature/job_posting/presentation/pages/job_postings_page.dart b/lib/feature/job_posting/presentation/pages/job_postings_page.dart index 2389aab..327ae98 100644 --- a/lib/feature/job_posting/presentation/pages/job_postings_page.dart +++ b/lib/feature/job_posting/presentation/pages/job_postings_page.dart @@ -39,7 +39,7 @@ class _JobPostingsPage extends StatelessWidget { borderRadius: BorderRadius.circular(50), ), onPressed: () { - context.pushRoute(const JobPostingFormRoute()); + context.pushRoute(JobPostingFormRoute()); }, child: const Icon( Icons.add,