From ab51cc724d401dd702f02d89a75a9dfea543b8d0 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Wed, 24 Dec 2025 15:38:39 +0900 Subject: [PATCH 1/4] refactor(preparation-form): simplify preparation form list by removing dismissible option and consolidating list handling --- .../preparation_form_create_list.dart | 48 ++++++------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart index 280ac666..b2405d49 100644 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart @@ -3,7 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:on_time_front/presentation/onboarding/preparation_name_select/components/create_icon_button.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/bloc/preparation_form_bloc.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_list_field.dart'; -import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list_dissmissible.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_step_form_cubit.dart'; @@ -12,49 +11,32 @@ class PreparationFormCreateList extends StatelessWidget { {super.key, required this.preparationNameState, required this.onNameChanged, - required this.onCreationRequested, - this.enableDismissible = false}); + required this.onCreationRequested}); final PreparationFormState preparationNameState; final void Function({required int index, required String value}) onNameChanged; final VoidCallback onCreationRequested; - final bool enableDismissible; @override Widget build(BuildContext context) { return SingleChildScrollView( child: Column( children: [ - enableDismissible - ? PreparationFormReorderableListDismissible( - preparationStepList: preparationNameState.preparationStepList, - onNameChanged: (index, value) { - onNameChanged(index: index, value: value); - }, - onTimeChanged: (index, value) => context - .read() - .add(PreparationFormPreparationStepTimeChanged( - index: index, preparationStepTime: value)), - onReorder: (oldIndex, newIndex) => context - .read() - .add(PreparationFormPreparationStepOrderChanged( - oldIndex: oldIndex, newIndex: newIndex)), - ) - : PreparationFormReorderableList( - preparationStepList: preparationNameState.preparationStepList, - onNameChanged: (index, value) { - onNameChanged(index: index, value: value); - }, - onTimeChanged: (index, value) => context - .read() - .add(PreparationFormPreparationStepTimeChanged( - index: index, preparationStepTime: value)), - onReorder: (oldIndex, newIndex) => context - .read() - .add(PreparationFormPreparationStepOrderChanged( - oldIndex: oldIndex, newIndex: newIndex)), - ), + PreparationFormReorderableListDismissible( + preparationStepList: preparationNameState.preparationStepList, + onNameChanged: (index, value) { + onNameChanged(index: index, value: value); + }, + onTimeChanged: (index, value) => context + .read() + .add(PreparationFormPreparationStepTimeChanged( + index: index, preparationStepTime: value)), + onReorder: (oldIndex, newIndex) => context + .read() + .add(PreparationFormPreparationStepOrderChanged( + oldIndex: oldIndex, newIndex: newIndex)), + ), preparationNameState.status == PreparationFormStatus.adding ? BlocProvider( create: (context) => PreparationStepFormCubit( From ec26d8aa2b7923629eb40388fd8d78b633d3c7f2 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Wed, 24 Dec 2025 16:23:50 +0900 Subject: [PATCH 2/4] refactor(preparation-form): replace dismissible list with swipe actions for improved user interaction --- .../preparation_spare_time_edit_screen.dart | 1 - .../preparation_form_create_list.dart | 4 +- .../preparation_form_reorderable_list.dart | 73 ++++++++++++-- ...on_form_reorderable_list_dissmissible.dart | 94 ------------------- ...chedule_spare_and_preparing_time_form.dart | 4 +- lib/presentation/shared/router/go_router.dart | 3 +- 6 files changed, 69 insertions(+), 110 deletions(-) delete mode 100644 lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list_dissmissible.dart diff --git a/lib/presentation/my_page/preparation_spare_time_edit/preparation_spare_time_edit_screen.dart b/lib/presentation/my_page/preparation_spare_time_edit/preparation_spare_time_edit_screen.dart index ba9a7960..2fbf6118 100644 --- a/lib/presentation/my_page/preparation_spare_time_edit/preparation_spare_time_edit_screen.dart +++ b/lib/presentation/my_page/preparation_spare_time_edit/preparation_spare_time_edit_screen.dart @@ -201,7 +201,6 @@ class _PreparationSection extends StatelessWidget { Expanded( child: PreparationFormCreateList( preparationNameState: preparationNameState, - enableDismissible: true, onNameChanged: ({required int index, required String value}) { context.read().add( PreparationFormPreparationStepNameChanged( diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart index b2405d49..6a7ca06a 100644 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:on_time_front/presentation/onboarding/preparation_name_select/components/create_icon_button.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/bloc/preparation_form_bloc.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_list_field.dart'; -import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list_dissmissible.dart'; +import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_step_form_cubit.dart'; class PreparationFormCreateList extends StatelessWidget { @@ -23,7 +23,7 @@ class PreparationFormCreateList extends StatelessWidget { return SingleChildScrollView( child: Column( children: [ - PreparationFormReorderableListDismissible( + PreparationFormReorderableList( preparationStepList: preparationNameState.preparationStepList, onNameChanged: (index, value) { onNameChanged(index: index, value: value); diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list.dart index cd3ac0a4..625b6f26 100644 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list.dart +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list.dart @@ -1,7 +1,32 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_swipe_action_cell/core/cell.dart'; +import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/bloc/preparation_form_bloc.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_list_field.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_step_form_cubit.dart'; +class _SwipeActionContent extends StatelessWidget { + const _SwipeActionContent({ + required this.icon, + required this.color, + }); + + final Widget icon; + final Color color; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: color, + ), + padding: const EdgeInsets.all(18.0), + child: icon, + ); + } +} + class PreparationFormReorderableList extends StatelessWidget { const PreparationFormReorderableList({ super.key, @@ -40,16 +65,44 @@ class PreparationFormReorderableList extends StatelessWidget { physics: NeverScrollableScrollPhysics(), itemCount: preparationStepList.length, itemBuilder: (context, index) { - return PreparationFormListField( - key: ValueKey(preparationStepList[index].id), - index: index, - preparationStep: preparationStepList[index], - onNameChanged: (value) { - onNameChanged(index, value); - }, - onPreparationTimeChanged: (value) { - onTimeChanged(index, value); - }, + final step = preparationStepList[index]; + final theme = Theme.of(context); + + return SwipeActionCell( + key: ValueKey(step.id), + backgroundColor: Colors.transparent, + trailingActions: [ + SwipeAction( + onTap: (controller) { + if (preparationStepList.length <= 1) return; + context.read().add( + PreparationFormPreparationStepRemoved( + preparationStepId: step.id, + ), + ); + }, + color: Colors.transparent, + content: _SwipeActionContent( + icon: const Icon( + Icons.delete, + color: Colors.white, + size: 24, + ), + color: theme.colorScheme.error, + ), + ), + ], + child: PreparationFormListField( + key: ValueKey('field_${step.id}'), + index: index, + preparationStep: step, + onNameChanged: (value) { + onNameChanged(index, value); + }, + onPreparationTimeChanged: (value) { + onTimeChanged(index, value); + }, + ), ); }, onReorder: (int oldIndex, int newIndex) { diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list_dissmissible.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list_dissmissible.dart deleted file mode 100644 index 376df148..00000000 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_reorderable_list_dissmissible.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/bloc/preparation_form_bloc.dart'; -import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_list_field.dart'; -import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_step_form_cubit.dart'; - -class PreparationFormReorderableListDismissible extends StatelessWidget { - const PreparationFormReorderableListDismissible({ - super.key, - required this.preparationStepList, - required this.onNameChanged, - required this.onTimeChanged, - required this.onReorder, - }); - - final List preparationStepList; - final Function(int index, String value) onNameChanged; - final Function(int index, Duration value) onTimeChanged; - final Function(int oldIndex, int newIndex) onReorder; - - @override - Widget build(BuildContext context) { - Widget proxyDecorator( - Widget child, int index, Animation animation) { - return AnimatedBuilder( - animation: animation, - builder: (BuildContext context, Widget? child) { - return SizedBox( - child: child, - ); - }, - child: child, - ); - } - - return SingleChildScrollView( - child: ReorderableListView.builder( - buildDefaultDragHandles: false, - proxyDecorator: proxyDecorator, - shrinkWrap: true, - padding: EdgeInsets.zero, - physics: NeverScrollableScrollPhysics(), - itemCount: preparationStepList.length, - itemBuilder: (context, index) { - return Dismissible( - key: ValueKey( - 'dismissible_${preparationStepList[index].id}'), - direction: DismissDirection.endToStart, - background: Container( - height: double.infinity, - alignment: Alignment.centerRight, - padding: const EdgeInsets.only(right: 20.0), - color: Colors.red, - child: const Icon( - Icons.delete, - color: Colors.white, - size: 24, - ), - ), - confirmDismiss: (direction) async { - if (preparationStepList.length <= 1) { - return false; - } - return direction == DismissDirection.endToStart; - }, - onDismissed: (direction) { - if (direction == DismissDirection.endToStart) { - context.read().add( - PreparationFormPreparationStepRemoved( - preparationStepId: preparationStepList[index].id, - ), - ); - } - }, - child: PreparationFormListField( - key: ValueKey(preparationStepList[index].id), - index: index, - preparationStep: preparationStepList[index], - onNameChanged: (value) { - onNameChanged(index, value); - }, - onPreparationTimeChanged: (value) { - onTimeChanged(index, value); - }, - ), - ); - }, - onReorder: (int oldIndex, int newIndex) { - onReorder(oldIndex, newIndex); - }, - ), - ); - } -} diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart index 22bc4ddc..4b2f5e15 100644 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart @@ -96,11 +96,11 @@ class _ScheduleSpareAndPreparingTimeFormState Padding( padding: const EdgeInsets.only(top: 8.0, left: 16.0), child: MessageBubble( - message: state.getOverlapMessage(context)!, + message: state.getOverlapMessage(context)!, type: state.isOverlapError ? MessageBubbleType.error : MessageBubbleType.warning, - ), + ), ), ], ); diff --git a/lib/presentation/shared/router/go_router.dart b/lib/presentation/shared/router/go_router.dart index 72604b43..485b8432 100644 --- a/lib/presentation/shared/router/go_router.dart +++ b/lib/presentation/shared/router/go_router.dart @@ -113,7 +113,8 @@ GoRouter goRouterConfig(AuthBloc authBloc, ScheduleBloc scheduleBloc) { GoRoute( path: '/preparationEdit', builder: (context, state) => PreparationEditForm( - preparationEntity: state.extra as PreparationEntity)), + preparationEntity: (state.extra as PreparationEntity?) ?? + const PreparationEntity(preparationStepList: []))), GoRoute( path: '/scheduleStart', name: 'scheduleStart', From 7c11a3f110d9de5819c6a6af8f8f9c3e2e7ace86 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Thu, 25 Dec 2025 17:55:12 +0900 Subject: [PATCH 3/4] fix(preparation-remote-data-source): change HTTP method from POST to PUT for updating preparation schedules --- lib/data/data_sources/preparation_remote_data_source.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/data/data_sources/preparation_remote_data_source.dart b/lib/data/data_sources/preparation_remote_data_source.dart index 33108cfc..0cb762fc 100644 --- a/lib/data/data_sources/preparation_remote_data_source.dart +++ b/lib/data/data_sources/preparation_remote_data_source.dart @@ -145,7 +145,7 @@ class PreparationRemoteDataSourceImpl implements PreparationRemoteDataSource { PreparationScheduleModifyRequestModelListExtension.fromEntityList( preparationEntity.preparationStepList); - final result = await dio.post( + final result = await dio.put( Endpoint.updatePreparationByScheduleId(scheduleId), data: updateModel.map((model) => model.toJson()).toList(), ); From 1a98325c9f6abd8e7c1bae2e1ba77a9da89723c8 Mon Sep 17 00:00:00 2001 From: jjoonleo Date: Thu, 25 Dec 2025 17:56:25 +0900 Subject: [PATCH 4/4] feat(preparation-edit): implement PreparationEditDraftCubit for managing draft state in preparation editing flow --- .../cubit/preparation_edit_draft_cubit.dart | 18 +++++++++++ .../screens/preparation_edit_form.dart | 16 ++++++---- ...chedule_spare_and_preparing_time_form.dart | 30 +++++++++++++------ lib/presentation/shared/router/go_router.dart | 6 +--- 4 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_edit_draft_cubit.dart diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_edit_draft_cubit.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_edit_draft_cubit.dart new file mode 100644 index 00000000..5f0cc0c3 --- /dev/null +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_edit_draft_cubit.dart @@ -0,0 +1,18 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:injectable/injectable.dart'; +import 'package:on_time_front/domain/entities/preparation_entity.dart'; + +/// Shared draft state for the `/preparationEdit` flow. +/// +/// The caller sets a draft before navigating. The editor overwrites it on Save. +/// The caller reads it after pop and then clears it. +@LazySingleton() +class PreparationEditDraftCubit extends Cubit { + PreparationEditDraftCubit() : super(null); + + void setDraft(PreparationEntity draft) => emit(draft); + + void clear() => emit(null); +} + + diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/screens/preparation_edit_form.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/screens/preparation_edit_form.dart index d5141faa..250ae13e 100644 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/screens/preparation_edit_form.dart +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/screens/preparation_edit_form.dart @@ -4,13 +4,12 @@ import 'package:go_router/go_router.dart'; import 'package:on_time_front/core/di/di_setup.dart'; import 'package:on_time_front/domain/entities/preparation_entity.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/bloc/preparation_form_bloc.dart'; +import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_edit_draft_cubit.dart'; import 'package:on_time_front/presentation/schedule_create/components/top_bar.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/components/preparation_form_create_list.dart'; class PreparationEditForm extends StatefulWidget { - const PreparationEditForm({super.key, required this.preparationEntity}); - - final PreparationEntity preparationEntity; + const PreparationEditForm({super.key}); @override State createState() => _PreparationEditFormState(); @@ -24,12 +23,14 @@ class _PreparationEditFormState extends State { @override Widget build(BuildContext context) { + final draft = getIt.get().state ?? + const PreparationEntity(preparationStepList: []); + return Scaffold( body: SafeArea( child: BlocProvider( create: (context) => getIt.get() - ..add(PreparationFormEditRequested( - preparationEntity: widget.preparationEntity)), + ..add(PreparationFormEditRequested(preparationEntity: draft)), child: BlocBuilder( builder: (context, state) { return Column( @@ -37,7 +38,10 @@ class _PreparationEditFormState extends State { TopBar( onNextPageButtonClicked: state.isValid ? () { - context.pop(state.toPreparationEntity()); + getIt + .get() + .setDraft(state.toPreparationEntity()); + context.pop(); } : null, onPreviousPageButtonClicked: context.pop, diff --git a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart index 4b2f5e15..312e6cd1 100644 --- a/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart +++ b/lib/presentation/schedule_create/schedule_spare_and_preparing_time/screens/schedule_spare_and_preparing_time_form.dart @@ -2,8 +2,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:on_time_front/domain/entities/preparation_entity.dart'; +import 'package:on_time_front/core/di/di_setup.dart'; import 'package:on_time_front/presentation/app/bloc/auth/auth_bloc.dart'; import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/cubit/schedule_form_spare_time_cubit.dart'; +import 'package:on_time_front/presentation/schedule_create/schedule_spare_and_preparing_time/preparation_form/cubit/preparation_edit_draft_cubit.dart'; import 'package:on_time_front/presentation/shared/components/cupertino_picker_modal.dart'; import 'package:on_time_front/l10n/app_localizations.dart'; import 'package:on_time_front/presentation/shared/utils/duration_format.dart'; @@ -46,15 +48,25 @@ class _ScheduleSpareAndPreparingTimeFormState controller: TextEditingController( text: formatDuration( context, state.totalPreparationTime)), - onTap: () async { - final PreparationEntity? updatedPreparation = - await context.push('/preparationEdit', - extra: state.preparation); - if (updatedPreparation != null) { - context - .read() - .preparationChanged(updatedPreparation); - } + onTap: () { + final draftCubit = getIt.get(); + final scheduleSpareTimeCubit = + context.read(); + final before = state.preparation ?? + const PreparationEntity(preparationStepList: []); + + draftCubit.setDraft(before); + context.push('/preparationEdit').then((_) { + if (!mounted) return; + + final after = draftCubit.state; + if (after != null && after != before) { + scheduleSpareTimeCubit.preparationChanged(after); + } + + // Avoid stale drafts leaking into the next edit session. + draftCubit.clear(); + }); }, ), onSaved: (value) {}, diff --git a/lib/presentation/shared/router/go_router.dart b/lib/presentation/shared/router/go_router.dart index 485b8432..e671ca6f 100644 --- a/lib/presentation/shared/router/go_router.dart +++ b/lib/presentation/shared/router/go_router.dart @@ -5,8 +5,6 @@ import 'package:go_router/go_router.dart'; import 'package:on_time_front/core/di/di_setup.dart'; import 'package:on_time_front/core/services/navigation_service.dart'; import 'package:on_time_front/core/services/notification_service.dart'; -import 'package:on_time_front/domain/entities/preparation_entity.dart'; -import 'package:on_time_front/domain/entities/schedule_entity.dart'; import 'package:on_time_front/presentation/alarm/screens/alarm_screen.dart'; import 'package:on_time_front/presentation/alarm/screens/schedule_start_screen.dart'; import 'package:on_time_front/presentation/app/bloc/auth/auth_bloc.dart'; @@ -112,9 +110,7 @@ GoRouter goRouterConfig(AuthBloc authBloc, ScheduleBloc scheduleBloc) { scheduleId: state.pathParameters['scheduleId']!)), GoRoute( path: '/preparationEdit', - builder: (context, state) => PreparationEditForm( - preparationEntity: (state.extra as PreparationEntity?) ?? - const PreparationEntity(preparationStepList: []))), + builder: (context, state) => const PreparationEditForm()), GoRoute( path: '/scheduleStart', name: 'scheduleStart',