From bd7feb3efdef026a7b43fefc667b8ff72d732c81 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 03:00:51 +0900 Subject: [PATCH 01/17] refactor: change variables in alarm screen --- lib/presentation/alarm/screens/alarm_screen.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/presentation/alarm/screens/alarm_screen.dart b/lib/presentation/alarm/screens/alarm_screen.dart index 97aef786..cfc23b22 100644 --- a/lib/presentation/alarm/screens/alarm_screen.dart +++ b/lib/presentation/alarm/screens/alarm_screen.dart @@ -62,7 +62,7 @@ class AlarmScreen extends StatelessWidget { } Widget _buildAlarmScreen( - AlarmScreenPreparationLoadSuccess infoState, + AlarmScreenPreparationLoadSuccess timerState, BuildContext context, ) { return BlocListener( @@ -73,8 +73,8 @@ class AlarmScreen extends StatelessWidget { context.go( '/earlyLate', extra: { - 'earlyLateTime': infoState.beforeOutTime, - 'isLate': infoState.isLate, + 'earlyLateTime': timerState.beforeOutTime, + 'isLate': timerState.isLate, }, ); } From 9068cd7e94060a407b1a5fff93cb72398f306f16 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:12:48 +0900 Subject: [PATCH 02/17] chore: add button in widgetbook --- .../alarm/screens/alarm_screen.dart | 2 +- pubspec.lock | 48 +++++++++++++++++++ pubspec.yaml | 2 + widgetbook/lib/button.dart | 25 ++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 widgetbook/lib/button.dart diff --git a/lib/presentation/alarm/screens/alarm_screen.dart b/lib/presentation/alarm/screens/alarm_screen.dart index cfc23b22..9806bfd2 100644 --- a/lib/presentation/alarm/screens/alarm_screen.dart +++ b/lib/presentation/alarm/screens/alarm_screen.dart @@ -62,7 +62,7 @@ class AlarmScreen extends StatelessWidget { } Widget _buildAlarmScreen( - AlarmScreenPreparationLoadSuccess timerState, + AlarmScreenPreparationLoadSuccess infoState, BuildContext context, ) { return BlocListener( diff --git a/pubspec.lock b/pubspec.lock index dbbc8df1..b401d978 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.53" + accessibility_tools: + dependency: transitive + description: + name: accessibility_tools + sha256: "1ee3612b9439ca315f92dcc31c6a4828e95b96c1aa64ac3a7776c149722deca8" + url: "https://pub.dev" + source: hosted + version: "2.4.0" analyzer: dependency: transitive description: @@ -304,6 +312,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.11" + device_frame: + dependency: transitive + description: + name: device_frame + sha256: d031a06f5d6f4750009672db98a5aa1536aa4a231713852469ce394779a23d75 + url: "https://pub.dev" + source: hosted + version: "1.2.0" dio: dependency: "direct main" description: @@ -767,6 +783,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.0" + inspector: + dependency: transitive + description: + name: inspector + sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" + url: "https://pub.dev" + source: hosted + version: "2.1.0" intl: dependency: transitive description: @@ -1111,6 +1135,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + resizable_widget: + dependency: transitive + description: + name: resizable_widget + sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a + url: "https://pub.dev" + source: hosted + version: "1.0.5" riverpod: dependency: transitive description: @@ -1572,6 +1604,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.18.4" + widgetbook: + dependency: "direct main" + description: + name: widgetbook + sha256: "43fb5d65e5617cae47aeb5b25d6c8c51ee44bb5296b9a72df7bd60dbc6c51877" + url: "https://pub.dev" + source: hosted + version: "3.11.0" + widgetbook_annotation: + dependency: "direct main" + description: + name: widgetbook_annotation + sha256: b6f1da292c20a6238d973a640d253ce3ebddbe1f9fa8f2afd72624797a38e7cc + url: "https://pub.dev" + source: hosted + version: "3.3.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 02f7257b..b2431c0f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -78,6 +78,8 @@ dependencies: flutter_local_notifications: ^18.0.1 google_sign_in_web: ^0.12.4+4 google_sign_in_platform_interface: ^2.5.0 + widgetbook: ^3.11.0 + widgetbook_annotation: ^3.3.0 diff --git a/widgetbook/lib/button.dart b/widgetbook/lib/button.dart new file mode 100644 index 00000000..06f48056 --- /dev/null +++ b/widgetbook/lib/button.dart @@ -0,0 +1,25 @@ +import 'package:flutter/widgets.dart'; +import 'package:on_time_front/presentation/shared/components/button.dart'; +import 'package:widgetbook/widgetbook.dart'; + +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: Button, +) +Widget buttonUseCase(BuildContext context) { + final label = context.knobs.string(label: 'Text', initialValue: 'Click Me'); + final size = context.knobs.list( + label: 'Size', + options: ButtonSize.values, + initialOption: ButtonSize.Giant); + + return Center( + child: Button( + text: label, + size: size, + onPressed: () {}, + ), + ); +} From 226d4762bf16eff4fe7d1ffc0f08af97d1da68b2 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:22 +0900 Subject: [PATCH 03/17] chore: add alarm graph animator in widgetbook --- widgetbook/lib/alarm_graph_animator.dart | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 widgetbook/lib/alarm_graph_animator.dart diff --git a/widgetbook/lib/alarm_graph_animator.dart b/widgetbook/lib/alarm_graph_animator.dart new file mode 100644 index 00000000..5527ef29 --- /dev/null +++ b/widgetbook/lib/alarm_graph_animator.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; +import 'package:on_time_front/presentation/alarm/components/alarm_graph_animator.dart'; + +@widgetbook.UseCase( + name: 'Graph Progress Animation', + type: AlarmGraphAnimator, +) +Widget alarmGraphAnimatorUseCase(BuildContext context) { + final progress = context.knobs.double.slider( + label: 'Progress', + initialValue: 0.5, + max: 1, + min: 0, + ); + + return Container( + color: const Color(0xff5C79FB), + alignment: Alignment.center, + child: AlarmGraphAnimator(progress: progress), + ); +} From ee131efcede2f3c27d806b2848ee6d8c60f79238 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:31:24 +0900 Subject: [PATCH 04/17] chore: add alarm graph component in widgetbook --- widgetbook/lib/alarm_graph_component.dart | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 widgetbook/lib/alarm_graph_component.dart diff --git a/widgetbook/lib/alarm_graph_component.dart b/widgetbook/lib/alarm_graph_component.dart new file mode 100644 index 00000000..e9ccb939 --- /dev/null +++ b/widgetbook/lib/alarm_graph_component.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; +import 'package:on_time_front/presentation/alarm/components/alarm_graph_component.dart'; + +@widgetbook.UseCase( + name: 'Static Graph Painter', + type: AlarmGraphComponent, +) +Widget alarmGraphComponentUseCase(BuildContext context) { + final progress = context.knobs.double.slider( + label: 'Progress', + initialValue: 0.5, + max: 1, + min: 0, + ); + + return CustomPaint( + size: const Size(230, 115), + painter: AlarmGraphComponent(progress: progress), + ); +} From 6c59afb677ec0230fcffc6220c700bf62af391bb Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:32:00 +0900 Subject: [PATCH 05/17] chore: add alarm screen top section component in widgetbook --- widgetbook/lib/alarm_screen_top_section.dart | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 widgetbook/lib/alarm_screen_top_section.dart diff --git a/widgetbook/lib/alarm_screen_top_section.dart b/widgetbook/lib/alarm_screen_top_section.dart new file mode 100644 index 00000000..507ed76c --- /dev/null +++ b/widgetbook/lib/alarm_screen_top_section.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; +import 'package:on_time_front/presentation/alarm/components/alarm_screen_top_section.dart'; + +@widgetbook.UseCase( + name: 'Default', + type: AlarmScreenTopSection, +) +Widget alarmScreenTopSectionUseCase(BuildContext context) { + final isLate = context.knobs.boolean(label: 'Is Late', initialValue: false); + final beforeOutTime = context.knobs.int + .input(label: 'Before Out Time (sec)', initialValue: 180); + final preparationName = + context.knobs.string(label: 'Preparation Name', initialValue: '세수하기'); + final remainingTime = + context.knobs.int.input(label: 'Remaining Time (sec)', initialValue: 120); + final progress = context.knobs.double.slider( + label: 'Progress', + initialValue: 0.5, + max: 1, + min: 0, + ); + + return Container( + color: const Color(0xff5C79FB), + child: AlarmScreenTopSection( + isLate: isLate, + beforeOutTime: beforeOutTime, + preparationName: preparationName, + preparationRemainingTime: remainingTime, + progress: progress, + ), + ); +} From b26781327bbf34f6e24e697eb6e366a2c9614ea3 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:22:01 +0900 Subject: [PATCH 06/17] chore: add alarm screen bottom section component in widgetbook --- .../lib/alarm_screen_bottom_section.dart | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 widgetbook/lib/alarm_screen_bottom_section.dart diff --git a/widgetbook/lib/alarm_screen_bottom_section.dart b/widgetbook/lib/alarm_screen_bottom_section.dart new file mode 100644 index 00000000..5c360933 --- /dev/null +++ b/widgetbook/lib/alarm_screen_bottom_section.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/domain/entities/preparation_step_entity.dart'; +import 'package:on_time_front/presentation/alarm/components/alarm_screen_bottom_section.dart'; +import 'package:on_time_front/presentation/shared/constants/constants.dart'; +import 'package:uuid/uuid.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: AlarmScreenBottomSection, +) +Widget alarmScreenBottomSectionUseCase(BuildContext context) { + final currentStepIndex = context.knobs.int.slider( + label: 'Current Step Index', + initialValue: 0, + min: 0, + max: 1, + ); + + return AlarmScreenBottomSection( + preparationSteps: [ + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '세수하기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '양치하기', + preparationTime: const Duration(seconds: 60), + ), + ], + currentStepIndex: currentStepIndex, + stepElapsedTimes: const [10, 0], + preparationStepStates: const [ + PreparationStateEnum.now, + PreparationStateEnum.yet, + ], + onSkip: () {}, + onEndPreparation: () {}, + ); +} From d156d0c1c6e37ebd8171c1f6e8181b8211267a00 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:23:35 +0900 Subject: [PATCH 07/17] chore: add preparation step list widget into widgetbook --- .../lib/preparatoin_step_list_widget.dart | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 widgetbook/lib/preparatoin_step_list_widget.dart diff --git a/widgetbook/lib/preparatoin_step_list_widget.dart b/widgetbook/lib/preparatoin_step_list_widget.dart new file mode 100644 index 00000000..8cc9df02 --- /dev/null +++ b/widgetbook/lib/preparatoin_step_list_widget.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/domain/entities/preparation_step_entity.dart'; +import 'package:on_time_front/presentation/alarm/components/preparation_step_list_widget.dart'; +import 'package:on_time_front/presentation/shared/constants/constants.dart'; +import 'package:uuid/uuid.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: PreparationStepListWidget, +) +Widget preparationStepListWidgetUseCase(BuildContext context) { + final currentStepIndex = context.knobs.int.slider( + label: 'Current Step Index', + initialValue: 0, + min: 0, + max: 1, + ); + + return SizedBox( + height: 400, + child: PreparationStepListWidget( + preparationSteps: [ + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '양치하기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '가방 챙기기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + ], + currentStepIndex: currentStepIndex, + stepElapsedTimes: const [15, 0], + preparationStepStates: const [ + PreparationStateEnum.now, + PreparationStateEnum.yet, + ], + onSkip: () {}, + ), + ); +} From 2cc5d3ad08b85f46f84dd7ebd637755ac6a0bfea Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:24:17 +0900 Subject: [PATCH 08/17] chore: add preparation step tile widget into widgetbook --- widgetbook/lib/preparation_step_tile.dart | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 widgetbook/lib/preparation_step_tile.dart diff --git a/widgetbook/lib/preparation_step_tile.dart b/widgetbook/lib/preparation_step_tile.dart new file mode 100644 index 00000000..9ae755ea --- /dev/null +++ b/widgetbook/lib/preparation_step_tile.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/presentation/alarm/components/preparation_step_tile.dart'; +import 'package:on_time_front/presentation/shared/constants/constants.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: PreparationStepTile, +) +Widget preparationStepTileUseCase(BuildContext context) { + final index = context.knobs.int.slider( + label: 'Step Index', + initialValue: 1, + min: 1, + max: 5, + ); + + final elapsed = context.knobs.int.slider( + label: 'Elapsed Seconds', + initialValue: 20, + min: 0, + max: 120, + ); + + final state = context.knobs.list( + label: 'Step State', + options: PreparationStateEnum.values, + initialOption: PreparationStateEnum.now, + ); + + return PreparationStepTile( + stepIndex: index, + preparationName: '가방 챙기기', + preparationTime: '01:20', + isLastItem: false, + onSkip: () {}, + stepElapsedTime: elapsed, + preparationStepState: state, + ); +} From b7729d9a616bef216dc5e12cdafa0517dab793d0 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:30:38 +0900 Subject: [PATCH 09/17] chore: slight change in alarm graph compoent usecases --- widgetbook/lib/alarm_graph_animator.dart | 3 ++- widgetbook/lib/alarm_graph_component.dart | 12 +++++++---- widgetbook/lib/alarm_screen_top_section.dart | 22 ++++++++++++++------ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/widgetbook/lib/alarm_graph_animator.dart b/widgetbook/lib/alarm_graph_animator.dart index 5527ef29..d883e59f 100644 --- a/widgetbook/lib/alarm_graph_animator.dart +++ b/widgetbook/lib/alarm_graph_animator.dart @@ -11,12 +11,13 @@ Widget alarmGraphAnimatorUseCase(BuildContext context) { final progress = context.knobs.double.slider( label: 'Progress', initialValue: 0.5, - max: 1, min: 0, + max: 1, ); return Container( color: const Color(0xff5C79FB), + height: 190, alignment: Alignment.center, child: AlarmGraphAnimator(progress: progress), ); diff --git a/widgetbook/lib/alarm_graph_component.dart b/widgetbook/lib/alarm_graph_component.dart index e9ccb939..ecec15b0 100644 --- a/widgetbook/lib/alarm_graph_component.dart +++ b/widgetbook/lib/alarm_graph_component.dart @@ -11,12 +11,16 @@ Widget alarmGraphComponentUseCase(BuildContext context) { final progress = context.knobs.double.slider( label: 'Progress', initialValue: 0.5, - max: 1, min: 0, + max: 1, ); - return CustomPaint( - size: const Size(230, 115), - painter: AlarmGraphComponent(progress: progress), + return Container( + color: const Color(0xff5C79FB), + alignment: Alignment.center, + child: CustomPaint( + size: const Size(230, 115), + painter: AlarmGraphComponent(progress: progress), + ), ); } diff --git a/widgetbook/lib/alarm_screen_top_section.dart b/widgetbook/lib/alarm_screen_top_section.dart index 507ed76c..8e9f14ea 100644 --- a/widgetbook/lib/alarm_screen_top_section.dart +++ b/widgetbook/lib/alarm_screen_top_section.dart @@ -9,12 +9,22 @@ import 'package:on_time_front/presentation/alarm/components/alarm_screen_top_sec ) Widget alarmScreenTopSectionUseCase(BuildContext context) { final isLate = context.knobs.boolean(label: 'Is Late', initialValue: false); - final beforeOutTime = context.knobs.int - .input(label: 'Before Out Time (sec)', initialValue: 180); - final preparationName = - context.knobs.string(label: 'Preparation Name', initialValue: '세수하기'); - final remainingTime = - context.knobs.int.input(label: 'Remaining Time (sec)', initialValue: 120); + final beforeOutTime = context.knobs.int.slider( + label: 'Before Out Time (sec)', + initialValue: 180, + min: 0, + max: 600, + ); + final preparationName = context.knobs.string( + label: 'Preparation Name', + initialValue: '세수하기', + ); + final remainingTime = context.knobs.int.slider( + label: 'Remaining Time (sec)', + initialValue: 120, + min: 0, + max: 600, + ); final progress = context.knobs.double.slider( label: 'Progress', initialValue: 0.5, From a25457f1ed813a8c8bda0f6d0b7488525be2ecf6 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:39:39 +0900 Subject: [PATCH 10/17] chore: add check list box widget in widgetbook --- .../components/check_list_box_widget.dart | 133 ++++++----- .../components/check_list_item_widget.dart | 93 ++++---- .../early_late_message_image_widget.dart | 57 ++--- .../early_late/screens/early_late_screen.dart | 215 ++++++++++++------ widgetbook/lib/check_list_box_widget.dart | 30 +++ 5 files changed, 323 insertions(+), 205 deletions(-) create mode 100644 widgetbook/lib/check_list_box_widget.dart diff --git a/lib/presentation/early_late/components/check_list_box_widget.dart b/lib/presentation/early_late/components/check_list_box_widget.dart index 30f518d4..1a5c4b97 100644 --- a/lib/presentation/early_late/components/check_list_box_widget.dart +++ b/lib/presentation/early_late/components/check_list_box_widget.dart @@ -1,70 +1,99 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:on_time_front/presentation/early_late/bloc/early_late_screen_bloc.dart'; import 'package:on_time_front/presentation/early_late/components/check_list_item_widget.dart'; -class ChecklistBox extends StatelessWidget { +class CheckListBoxWidget extends StatelessWidget { final double screenWidth; final double screenHeight; - final List items; // 체크리스트 항목들 + final List checkList; + final List checkedStates; + final void Function(int index) onItemToggled; - const ChecklistBox({ + const CheckListBoxWidget({ super.key, required this.screenWidth, required this.screenHeight, - required this.items, + required this.checkList, + required this.checkedStates, + required this.onItemToggled, }); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state is EarlyLateScreenLoadSuccess) { - return Center( - child: SizedBox( - width: screenWidth * 0.9, - height: screenHeight * 0.35, - child: Container( - decoration: BoxDecoration( - color: const Color(0xffF6F6F6), - borderRadius: const BorderRadius.all(Radius.circular(18)), + return Center( + child: SizedBox( + width: screenWidth * 0.9, + height: screenHeight * 0.35, + child: Container( + decoration: const BoxDecoration( + color: Color(0xffF6F6F6), + borderRadius: BorderRadius.all(Radius.circular(18)), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const _TextSection(), + const SizedBox(height: 20), + _ChecklistSection( + checkList: checkList, + checkedStates: checkedStates, + screenHeight: screenHeight, + onItemToggled: onItemToggled, ), - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '나가기 전에 확인하세요', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 20), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: List.generate( - items.length, - (index) => Padding( - padding: - EdgeInsets.only(bottom: screenHeight * 0.01), - child: ChecklistItemWidget( - index: index, - label: items[index], - ), - ), - ), - ), - ], - ), - ), - ), + ], ), - ); - } - return const SizedBox.shrink(); - }, + ), + ), + ), + ); + } +} + +class _TextSection extends StatelessWidget { + const _TextSection(); + + @override + Widget build(BuildContext context) { + return const Text( + '나가기 전에 확인하세요', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ); + } +} + +class _ChecklistSection extends StatelessWidget { + final List checkList; + final List checkedStates; + final double screenHeight; + final void Function(int index) onItemToggled; + + const _ChecklistSection({ + required this.checkList, + required this.checkedStates, + required this.screenHeight, + required this.onItemToggled, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: List.generate( + checkList.length, + (index) => Padding( + padding: EdgeInsets.only(bottom: screenHeight * 0.01), + child: ChecklistItemWidget( + index: index, + label: checkList[index], + isChecked: checkedStates[index], + onToggle: () => onItemToggled(index), + ), + ), + ), ); } } diff --git a/lib/presentation/early_late/components/check_list_item_widget.dart b/lib/presentation/early_late/components/check_list_item_widget.dart index 746c6254..7c564af5 100644 --- a/lib/presentation/early_late/components/check_list_item_widget.dart +++ b/lib/presentation/early_late/components/check_list_item_widget.dart @@ -1,65 +1,54 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:on_time_front/presentation/early_late/bloc/early_late_screen_bloc.dart'; class ChecklistItemWidget extends StatelessWidget { final int index; final String label; + final bool isChecked; + final VoidCallback onToggle; - const ChecklistItemWidget( - {super.key, required this.index, required this.label}); + const ChecklistItemWidget({ + super.key, + required this.index, + required this.label, + required this.isChecked, + required this.onToggle, + }); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state is EarlyLateScreenLoadSuccess) { - bool isChecked = state.checklist[index]; - - return GestureDetector( - onTap: () { - context - .read() - .add(ChecklistItemToggled(index)); - }, - child: Row( - children: [ - Container( - width: 24, - height: 24, - decoration: BoxDecoration( - shape: BoxShape.rectangle, - border: Border.all( - color: const Color(0xff5C79FB), - width: 2, - ), - borderRadius: const BorderRadius.all(Radius.circular(5)), - color: isChecked - ? const Color(0xff5C79FB) - : Colors.transparent, - ), - child: isChecked - ? const Icon(Icons.check, color: Colors.white, size: 20) - : null, - ), - const SizedBox(width: 15), - Text( - label, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: isChecked ? const Color(0xff5C79FB) : Colors.black, - decoration: isChecked - ? TextDecoration.lineThrough - : TextDecoration.none, - ), - ), - ], + return GestureDetector( + onTap: onToggle, + child: Row( + children: [ + Container( + width: 24, + height: 24, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + border: Border.all( + color: const Color(0xff5C79FB), + width: 2, + ), + borderRadius: const BorderRadius.all(Radius.circular(5)), + color: isChecked ? const Color(0xff5C79FB) : Colors.transparent, + ), + child: isChecked + ? const Icon(Icons.check, color: Colors.white, size: 20) + : null, + ), + const SizedBox(width: 15), + Text( + label, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: isChecked ? const Color(0xff5C79FB) : Colors.black, + decoration: + isChecked ? TextDecoration.lineThrough : TextDecoration.none, ), - ); - } - return const SizedBox.shrink(); - }, + ), + ], + ), ); } } diff --git a/lib/presentation/early_late/components/early_late_message_image_widget.dart b/lib/presentation/early_late/components/early_late_message_image_widget.dart index 887702fe..c92b170f 100644 --- a/lib/presentation/early_late/components/early_late_message_image_widget.dart +++ b/lib/presentation/early_late/components/early_late_message_image_widget.dart @@ -1,45 +1,34 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:on_time_front/presentation/early_late/bloc/early_late_screen_bloc.dart'; class EarlyLateMessageImageWidget extends StatelessWidget { final double screenHeight; + final String earlylateMessage; - const EarlyLateMessageImageWidget({super.key, required this.screenHeight}); + const EarlyLateMessageImageWidget({ + super.key, + required this.screenHeight, + required this.earlylateMessage, + }); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state is EarlyLateScreenLoadSuccess) { - return Column( - children: [ - SizedBox( - width: 292, - height: 60, - child: Text( - state.earlylateMessage, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - height: 1.8, - ), - textAlign: TextAlign.center, - ), - ), - Padding( - padding: EdgeInsets.only(top: screenHeight * 0.01), - child: Image.asset( - 'assets/character.png', - width: 150, - height: 150, - ), - ), - ], - ); - } - return const SizedBox.shrink(); - }, + return Column( + children: [ + Text( + earlylateMessage, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + Image.asset( + 'assets/character.png', + height: screenHeight * 0.25, + ), + ], ); } } diff --git a/lib/presentation/early_late/screens/early_late_screen.dart b/lib/presentation/early_late/screens/early_late_screen.dart index 1f301b34..18517492 100644 --- a/lib/presentation/early_late/screens/early_late_screen.dart +++ b/lib/presentation/early_late/screens/early_late_screen.dart @@ -26,79 +26,160 @@ class EarlyLateScreen extends StatelessWidget { backgroundColor: Colors.white, body: Stack( children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 70), - child: Center( - child: Column( - children: [ - BlocBuilder( - builder: (context, state) { - if (state is EarlyLateScreenLoadSuccess) { - final textColor = isLate - ? const Color(0xffFF6953) - : const Color(0xff5C79FB); - - return Text.rich( - TextSpan( - children: [ - TextSpan( - text: formatEalyLateTime(earlyLateTime), - style: TextStyle( - fontSize: 34, - fontWeight: FontWeight.bold, - color: textColor, - ), - ), - TextSpan( - text: isLate ? ' 지각했어요' : ' 일찍 준비했어요', - style: const TextStyle( - fontSize: 34, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - ], - ), - textAlign: TextAlign.center, - ); - } - return const SizedBox.shrink(); - }, - ), - const SizedBox(height: 20), - // 지각/일찍 준비 문구 + 이미지 표시 - EarlyLateMessageImageWidget( + BlocBuilder( + builder: (context, state) { + if (state is EarlyLateScreenLoadSuccess) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 70), + child: _EarlyLateSection( + earlyLateTime: earlyLateTime, + isLate: isLate, screenHeight: MediaQuery.of(context).size.height, + earlylateMessage: state.earlylateMessage, ), - ], - ), - ), - ), - const SizedBox(height: 20), - // 체크리스트 박스 - ChecklistBox( - screenWidth: MediaQuery.of(context).size.width, - screenHeight: MediaQuery.of(context).size.height, - items: ["우산 챙기기", "지갑 챙기기", "문 잠그기"], - ), - ], - ), - Positioned( - bottom: 20, - left: 0, - right: 0, - child: Center( - child: Button( - text: '까먹지 않고 출발', - onPressed: () {}, - ), - ), + ), + const SizedBox(height: 20), + _CheckListBoxSection( + screenWidth: MediaQuery.of(context).size.width, + screenHeight: MediaQuery.of(context).size.height, + checkList: ["우산 챙기기", "지갑 챙기기", "문 잠그기"], + checkedStates: state.checklist, + onItemToggled: (index) { + context + .read() + .add(ChecklistItemToggled(index)); + }, + ), + ], + ); + } + return const SizedBox.shrink(); + }, ), + const _ButtonSection(), ], ), ), ); } } + +class _EarlyLateSection extends StatelessWidget { + final int earlyLateTime; + final bool isLate; + final double screenHeight; + final String earlylateMessage; + + const _EarlyLateSection({ + required this.earlyLateTime, + required this.isLate, + required this.screenHeight, + required this.earlylateMessage, + }); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + children: [ + _EarlyLateText( + earlyLateTime: earlyLateTime, + isLate: isLate, + ), + const SizedBox(height: 20), + EarlyLateMessageImageWidget( + screenHeight: screenHeight, + earlylateMessage: earlylateMessage, + ), + ], + ), + ); + } +} + +class _EarlyLateText extends StatelessWidget { + final int earlyLateTime; + final bool isLate; + + const _EarlyLateText({ + required this.earlyLateTime, + required this.isLate, + }); + + @override + Widget build(BuildContext context) { + final textColor = + isLate ? const Color(0xffFF6953) : const Color(0xff5C79FB); + return Text.rich( + TextSpan( + children: [ + TextSpan( + text: formatEalyLateTime(earlyLateTime), + style: TextStyle( + fontSize: 34, + fontWeight: FontWeight.bold, + color: textColor, + ), + ), + TextSpan( + text: isLate ? ' 지각했어요' : ' 일찍 준비했어요', + style: const TextStyle( + fontSize: 34, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ], + ), + textAlign: TextAlign.center, + ); + } +} + +class _CheckListBoxSection extends StatelessWidget { + final double screenWidth; + final double screenHeight; + final List checkList; + final List checkedStates; + final Function(int) onItemToggled; + + const _CheckListBoxSection({ + required this.screenWidth, + required this.screenHeight, + required this.checkList, + required this.checkedStates, + required this.onItemToggled, + }); + + @override + Widget build(BuildContext context) { + return CheckListBoxWidget( + screenWidth: screenWidth, + screenHeight: screenHeight, + checkList: checkList, + checkedStates: checkedStates, + onItemToggled: onItemToggled, + ); + } +} + +class _ButtonSection extends StatelessWidget { + const _ButtonSection(); + + @override + Widget build(BuildContext context) { + return Positioned( + bottom: 20, + left: 0, + right: 0, + child: Center( + child: Button( + text: '까먹지 않고 출발', + onPressed: () {}, + ), + ), + ); + } +} diff --git a/widgetbook/lib/check_list_box_widget.dart b/widgetbook/lib/check_list_box_widget.dart new file mode 100644 index 00000000..2dfcc666 --- /dev/null +++ b/widgetbook/lib/check_list_box_widget.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/presentation/early_late/components/check_list_box_widget.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: CheckListBoxWidget, +) +Widget checkListBoxWidgetUseCase(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + final screenHeight = MediaQuery.of(context).size.height; + + final checkList = ['지갑 챙기기', '문 잠그기', '우산 챙기기']; + final checkStates = List.generate( + checkList.length, + (index) => context.knobs.boolean( + label: '${checkList[index]} 체크됨', + initialValue: false, + ), + ); + + return CheckListBoxWidget( + screenWidth: screenWidth, + screenHeight: screenHeight, + checkList: checkList, + checkedStates: checkStates, + onItemToggled: (_) {}, + ); +} From 28ecdcf1ce23d05723d02abf0fef43ccec7bb3ee Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:40:42 +0900 Subject: [PATCH 11/17] chore: add check list item widget in widgetbook --- widgetbook/lib/check_list_item_widget.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 widgetbook/lib/check_list_item_widget.dart diff --git a/widgetbook/lib/check_list_item_widget.dart b/widgetbook/lib/check_list_item_widget.dart new file mode 100644 index 00000000..f3f2adbf --- /dev/null +++ b/widgetbook/lib/check_list_item_widget.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/presentation/early_late/components/check_list_item_widget.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: ChecklistItemWidget, +) +Widget checklistItemWidgetUseCase(BuildContext context) { + final label = context.knobs.string(label: 'Label', initialValue: '우산 챙기기'); + final isChecked = + context.knobs.boolean(label: 'Checked', initialValue: false); + + return ChecklistItemWidget( + index: 0, + label: label, + isChecked: isChecked, + onToggle: () {}, + ); +} From d6c43d99bfa45a7d44d27496a7e726c2dde6672a Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Fri, 28 Mar 2025 05:44:42 +0900 Subject: [PATCH 12/17] chore: add early late message image widget in widget book --- .../lib/early_late_message_image_widget.dart | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 widgetbook/lib/early_late_message_image_widget.dart diff --git a/widgetbook/lib/early_late_message_image_widget.dart b/widgetbook/lib/early_late_message_image_widget.dart new file mode 100644 index 00000000..619b3306 --- /dev/null +++ b/widgetbook/lib/early_late_message_image_widget.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:on_time_front/presentation/early_late/components/early_late_message_image_widget.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Default', + type: EarlyLateMessageImageWidget, +) +Widget earlyLateMessageImageWidgetUseCase(BuildContext context) { + final message = context.knobs.string( + label: 'Message', + initialValue: '지금 출발하면 늦지 않아요!', + ); + + final screenHeight = MediaQuery.of(context).size.height; + + return EarlyLateMessageImageWidget( + screenHeight: screenHeight, + earlylateMessage: message, + ); +} From f085d72d52ab902fd3c8fe11cc1a8de922de7e58 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Mon, 31 Mar 2025 20:38:59 +0900 Subject: [PATCH 13/17] refactor: align preparation step tile component usecase in center --- widgetbook/lib/alarm_graph_animator.dart | 24 ---------- .../lib/alarm_screen_bottom_section.dart | 44 ------------------ widgetbook/lib/alarm_screen_top_section.dart | 45 ------------------- .../lib/early_late_message_image_widget.dart | 22 --------- widgetbook/lib/preparation_step_tile.dart | 25 +++++++---- widgetbook/pubspec.yaml | 5 +-- 6 files changed, 18 insertions(+), 147 deletions(-) delete mode 100644 widgetbook/lib/alarm_graph_animator.dart delete mode 100644 widgetbook/lib/alarm_screen_bottom_section.dart delete mode 100644 widgetbook/lib/alarm_screen_top_section.dart delete mode 100644 widgetbook/lib/early_late_message_image_widget.dart diff --git a/widgetbook/lib/alarm_graph_animator.dart b/widgetbook/lib/alarm_graph_animator.dart deleted file mode 100644 index d883e59f..00000000 --- a/widgetbook/lib/alarm_graph_animator.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; -import 'package:on_time_front/presentation/alarm/components/alarm_graph_animator.dart'; - -@widgetbook.UseCase( - name: 'Graph Progress Animation', - type: AlarmGraphAnimator, -) -Widget alarmGraphAnimatorUseCase(BuildContext context) { - final progress = context.knobs.double.slider( - label: 'Progress', - initialValue: 0.5, - min: 0, - max: 1, - ); - - return Container( - color: const Color(0xff5C79FB), - height: 190, - alignment: Alignment.center, - child: AlarmGraphAnimator(progress: progress), - ); -} diff --git a/widgetbook/lib/alarm_screen_bottom_section.dart b/widgetbook/lib/alarm_screen_bottom_section.dart deleted file mode 100644 index 5c360933..00000000 --- a/widgetbook/lib/alarm_screen_bottom_section.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:on_time_front/domain/entities/preparation_step_entity.dart'; -import 'package:on_time_front/presentation/alarm/components/alarm_screen_bottom_section.dart'; -import 'package:on_time_front/presentation/shared/constants/constants.dart'; -import 'package:uuid/uuid.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; - -@widgetbook.UseCase( - name: 'Default', - type: AlarmScreenBottomSection, -) -Widget alarmScreenBottomSectionUseCase(BuildContext context) { - final currentStepIndex = context.knobs.int.slider( - label: 'Current Step Index', - initialValue: 0, - min: 0, - max: 1, - ); - - return AlarmScreenBottomSection( - preparationSteps: [ - PreparationStepEntity( - id: const Uuid().v7(), - preparationName: '세수하기', - preparationTime: const Duration(seconds: 60), - nextPreparationId: const Uuid().v7(), - ), - PreparationStepEntity( - id: const Uuid().v7(), - preparationName: '양치하기', - preparationTime: const Duration(seconds: 60), - ), - ], - currentStepIndex: currentStepIndex, - stepElapsedTimes: const [10, 0], - preparationStepStates: const [ - PreparationStateEnum.now, - PreparationStateEnum.yet, - ], - onSkip: () {}, - onEndPreparation: () {}, - ); -} diff --git a/widgetbook/lib/alarm_screen_top_section.dart b/widgetbook/lib/alarm_screen_top_section.dart deleted file mode 100644 index 8e9f14ea..00000000 --- a/widgetbook/lib/alarm_screen_top_section.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; -import 'package:on_time_front/presentation/alarm/components/alarm_screen_top_section.dart'; - -@widgetbook.UseCase( - name: 'Default', - type: AlarmScreenTopSection, -) -Widget alarmScreenTopSectionUseCase(BuildContext context) { - final isLate = context.knobs.boolean(label: 'Is Late', initialValue: false); - final beforeOutTime = context.knobs.int.slider( - label: 'Before Out Time (sec)', - initialValue: 180, - min: 0, - max: 600, - ); - final preparationName = context.knobs.string( - label: 'Preparation Name', - initialValue: '세수하기', - ); - final remainingTime = context.knobs.int.slider( - label: 'Remaining Time (sec)', - initialValue: 120, - min: 0, - max: 600, - ); - final progress = context.knobs.double.slider( - label: 'Progress', - initialValue: 0.5, - max: 1, - min: 0, - ); - - return Container( - color: const Color(0xff5C79FB), - child: AlarmScreenTopSection( - isLate: isLate, - beforeOutTime: beforeOutTime, - preparationName: preparationName, - preparationRemainingTime: remainingTime, - progress: progress, - ), - ); -} diff --git a/widgetbook/lib/early_late_message_image_widget.dart b/widgetbook/lib/early_late_message_image_widget.dart deleted file mode 100644 index 619b3306..00000000 --- a/widgetbook/lib/early_late_message_image_widget.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:on_time_front/presentation/early_late/components/early_late_message_image_widget.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; - -@widgetbook.UseCase( - name: 'Default', - type: EarlyLateMessageImageWidget, -) -Widget earlyLateMessageImageWidgetUseCase(BuildContext context) { - final message = context.knobs.string( - label: 'Message', - initialValue: '지금 출발하면 늦지 않아요!', - ); - - final screenHeight = MediaQuery.of(context).size.height; - - return EarlyLateMessageImageWidget( - screenHeight: screenHeight, - earlylateMessage: message, - ); -} diff --git a/widgetbook/lib/preparation_step_tile.dart b/widgetbook/lib/preparation_step_tile.dart index 9ae755ea..d54869ac 100644 --- a/widgetbook/lib/preparation_step_tile.dart +++ b/widgetbook/lib/preparation_step_tile.dart @@ -29,13 +29,22 @@ Widget preparationStepTileUseCase(BuildContext context) { initialOption: PreparationStateEnum.now, ); - return PreparationStepTile( - stepIndex: index, - preparationName: '가방 챙기기', - preparationTime: '01:20', - isLastItem: false, - onSkip: () {}, - stepElapsedTime: elapsed, - preparationStepState: state, + return Scaffold( + backgroundColor: const Color.fromARGB(255, 243, 241, 241), + body: Center( + child: SizedBox( + width: 400, + height: 200, + child: PreparationStepTile( + stepIndex: index, + preparationName: '가방 챙기기', + preparationTime: '01:20', + isLastItem: false, + onSkip: () {}, + stepElapsedTime: elapsed, + preparationStepState: state, + ), + ), + ), ); } diff --git a/widgetbook/pubspec.yaml b/widgetbook/pubspec.yaml index f7e71f34..e320481d 100644 --- a/widgetbook/pubspec.yaml +++ b/widgetbook/pubspec.yaml @@ -26,7 +26,4 @@ dev_dependencies: build_runner: ^2.4.13 flutter: - uses-material-design: true - assets: - - assets/ - - assets/characters/ + uses-material-design: true \ No newline at end of file From 8346d338a34967201c6a6e17c620d8e6e33daaf9 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Mon, 31 Mar 2025 20:50:12 +0900 Subject: [PATCH 14/17] refactor: aligned preparation step list widget usecase center in widgetbook --- widgetbook/lib/preparation_step_tile.dart | 32 +++++++----- .../lib/preparatoin_step_list_widget.dart | 51 ++++++++++--------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/widgetbook/lib/preparation_step_tile.dart b/widgetbook/lib/preparation_step_tile.dart index d54869ac..b89d95b3 100644 --- a/widgetbook/lib/preparation_step_tile.dart +++ b/widgetbook/lib/preparation_step_tile.dart @@ -29,20 +29,28 @@ Widget preparationStepTileUseCase(BuildContext context) { initialOption: PreparationStateEnum.now, ); + final isLastItem = context.knobs.boolean( + label: 'Is Last Item', + initialValue: false, + ); + return Scaffold( backgroundColor: const Color.fromARGB(255, 243, 241, 241), - body: Center( - child: SizedBox( - width: 400, - height: 200, - child: PreparationStepTile( - stepIndex: index, - preparationName: '가방 챙기기', - preparationTime: '01:20', - isLastItem: false, - onSkip: () {}, - stepElapsedTime: elapsed, - preparationStepState: state, + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Center( + child: SizedBox( + width: 400, + height: 200, + child: PreparationStepTile( + stepIndex: index, + preparationName: '가방 챙기기', + preparationTime: '01:20', + isLastItem: isLastItem, + onSkip: () {}, + stepElapsedTime: elapsed, + preparationStepState: state, + ), ), ), ), diff --git a/widgetbook/lib/preparatoin_step_list_widget.dart b/widgetbook/lib/preparatoin_step_list_widget.dart index 8cc9df02..2f7c7be5 100644 --- a/widgetbook/lib/preparatoin_step_list_widget.dart +++ b/widgetbook/lib/preparatoin_step_list_widget.dart @@ -18,30 +18,35 @@ Widget preparationStepListWidgetUseCase(BuildContext context) { max: 1, ); - return SizedBox( - height: 400, - child: PreparationStepListWidget( - preparationSteps: [ - PreparationStepEntity( - id: const Uuid().v7(), - preparationName: '양치하기', - preparationTime: const Duration(seconds: 60), - nextPreparationId: const Uuid().v7(), + return Scaffold( + backgroundColor: const Color.fromARGB(255, 243, 241, 241), + body: Center( + child: SizedBox( + height: 400, + child: PreparationStepListWidget( + preparationSteps: [ + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '양치하기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '가방 챙기기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + ], + currentStepIndex: currentStepIndex, + stepElapsedTimes: const [15, 0], + preparationStepStates: const [ + PreparationStateEnum.now, + PreparationStateEnum.yet, + ], + onSkip: () {}, ), - PreparationStepEntity( - id: const Uuid().v7(), - preparationName: '가방 챙기기', - preparationTime: const Duration(seconds: 60), - nextPreparationId: const Uuid().v7(), - ), - ], - currentStepIndex: currentStepIndex, - stepElapsedTimes: const [15, 0], - preparationStepStates: const [ - PreparationStateEnum.now, - PreparationStateEnum.yet, - ], - onSkip: () {}, + ), ), ); } From f88617f42a7920e426ececae61ca660d242b2850 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Mon, 31 Mar 2025 22:50:46 +0900 Subject: [PATCH 15/17] refactor: add test values for widgetbook in preparation step list widget usecase --- .../lib/preparatoin_step_list_widget.dart | 114 +++++++++++++----- 1 file changed, 87 insertions(+), 27 deletions(-) diff --git a/widgetbook/lib/preparatoin_step_list_widget.dart b/widgetbook/lib/preparatoin_step_list_widget.dart index 2f7c7be5..1c4adae5 100644 --- a/widgetbook/lib/preparatoin_step_list_widget.dart +++ b/widgetbook/lib/preparatoin_step_list_widget.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:on_time_front/domain/entities/preparation_step_entity.dart'; +import 'package:on_time_front/presentation/alarm/bloc/alarm_timer/alarm_timer_bloc.dart'; import 'package:on_time_front/presentation/alarm/components/preparation_step_list_widget.dart'; import 'package:on_time_front/presentation/shared/constants/constants.dart'; import 'package:uuid/uuid.dart'; @@ -7,45 +9,103 @@ import 'package:widgetbook/widgetbook.dart'; import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; @widgetbook.UseCase( - name: 'Default', + name: 'Default (Bloc-based)', type: PreparationStepListWidget, ) Widget preparationStepListWidgetUseCase(BuildContext context) { + final listLength = context.knobs.int.slider( + label: 'Number of Steps', + initialValue: 3, + min: 1, + max: 6, + ); + + final stepElapsedTime = context.knobs.int.slider( + label: 'Step Elapsed Time (sec)', + initialValue: 15, + min: 0, + max: 120, + ); + + final preparationSteps = [ + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '양치하기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '가방 챙기기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '옷 갈아입기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '화장하기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '고양이 밥주기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + PreparationStepEntity( + id: const Uuid().v7(), + preparationName: '화분에 물주기', + preparationTime: const Duration(seconds: 60), + nextPreparationId: const Uuid().v7(), + ), + ].sublist(0, listLength); + final currentStepIndex = context.knobs.int.slider( label: 'Current Step Index', initialValue: 0, min: 0, - max: 1, + max: 6, + ); + + final stepStates = List.generate( + listLength, + (index) => index < currentStepIndex + ? PreparationStateEnum.done + : (index == currentStepIndex + ? PreparationStateEnum.now + : PreparationStateEnum.yet), ); return Scaffold( backgroundColor: const Color.fromARGB(255, 243, 241, 241), - body: Center( - child: SizedBox( - height: 400, - child: PreparationStepListWidget( - preparationSteps: [ - PreparationStepEntity( - id: const Uuid().v7(), - preparationName: '양치하기', - preparationTime: const Duration(seconds: 60), - nextPreparationId: const Uuid().v7(), - ), - PreparationStepEntity( - id: const Uuid().v7(), - preparationName: '가방 챙기기', - preparationTime: const Duration(seconds: 60), - nextPreparationId: const Uuid().v7(), + body: BlocProvider( + create: (context) => AlarmTimerBloc( + preparationSteps: preparationSteps, + beforeOutTime: 600, + isLate: false, + )..add(AlarmTimerStepsUpdated(preparationSteps)), + child: BlocBuilder( + builder: (context, state) { + return Center( + child: SizedBox( + height: 400, + child: PreparationStepListWidget( + preparationSteps: preparationSteps, + currentStepIndex: currentStepIndex, + stepElapsedTimes: + List.generate(listLength, (_) => stepElapsedTime), + preparationStepStates: stepStates, + onSkip: () {}, + ), ), - ], - currentStepIndex: currentStepIndex, - stepElapsedTimes: const [15, 0], - preparationStepStates: const [ - PreparationStateEnum.now, - PreparationStateEnum.yet, - ], - onSkip: () {}, - ), + ); + }, ), ), ); From b87770548e1d4b94f1334f6a428161b090abfe85 Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:04:29 +0900 Subject: [PATCH 16/17] chore: align alarm graph component in center --- widgetbook/lib/alarm_graph_component.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/widgetbook/lib/alarm_graph_component.dart b/widgetbook/lib/alarm_graph_component.dart index ecec15b0..2339790b 100644 --- a/widgetbook/lib/alarm_graph_component.dart +++ b/widgetbook/lib/alarm_graph_component.dart @@ -15,12 +15,16 @@ Widget alarmGraphComponentUseCase(BuildContext context) { max: 1, ); - return Container( - color: const Color(0xff5C79FB), - alignment: Alignment.center, - child: CustomPaint( - size: const Size(230, 115), - painter: AlarmGraphComponent(progress: progress), + return Scaffold( + backgroundColor: const Color(0xff5C79FB), + body: SizedBox( + height: 700, + child: Center( + child: CustomPaint( + size: const Size(230, 115), + painter: AlarmGraphComponent(progress: progress), + ), + ), ), ); } From 1083651850d58b3034d94ae344c71726825e63ca Mon Sep 17 00:00:00 2001 From: SeoHyeonSim <90302917+SeoHyeonSim@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:59:45 +0900 Subject: [PATCH 17/17] refactor: apply knobs in width in preparation step tile and preparation step list widget usecase --- widgetbook/lib/preparation_step_tile.dart | 9 ++++++++- widgetbook/lib/preparatoin_step_list_widget.dart | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/widgetbook/lib/preparation_step_tile.dart b/widgetbook/lib/preparation_step_tile.dart index b89d95b3..18a465f9 100644 --- a/widgetbook/lib/preparation_step_tile.dart +++ b/widgetbook/lib/preparation_step_tile.dart @@ -34,13 +34,20 @@ Widget preparationStepTileUseCase(BuildContext context) { initialValue: false, ); + final width = context.knobs.double.slider( + label: 'Width', + initialValue: 400, + min: 200, + max: 600, + ); + return Scaffold( backgroundColor: const Color.fromARGB(255, 243, 241, 241), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Center( child: SizedBox( - width: 400, + width: width, height: 200, child: PreparationStepTile( stepIndex: index, diff --git a/widgetbook/lib/preparatoin_step_list_widget.dart b/widgetbook/lib/preparatoin_step_list_widget.dart index 1c4adae5..e5549ec5 100644 --- a/widgetbook/lib/preparatoin_step_list_widget.dart +++ b/widgetbook/lib/preparatoin_step_list_widget.dart @@ -82,6 +82,13 @@ Widget preparationStepListWidgetUseCase(BuildContext context) { : PreparationStateEnum.yet), ); + final width = context.knobs.double.slider( + label: 'Width', + initialValue: 400, + min: 200, + max: 600, + ); + return Scaffold( backgroundColor: const Color.fromARGB(255, 243, 241, 241), body: BlocProvider( @@ -94,6 +101,7 @@ Widget preparationStepListWidgetUseCase(BuildContext context) { builder: (context, state) { return Center( child: SizedBox( + width: width, height: 400, child: PreparationStepListWidget( preparationSteps: preparationSteps,