diff --git a/android/app/google-service.json b/android/app/google-service.json index ca6e22c..fddb1b2 100644 --- a/android/app/google-service.json +++ b/android/app/google-service.json @@ -1,4 +1,9 @@ -{"installed":{"client_id":"1068261222530-cqa1h83puodc9ngn79b04ot2ehq43o2d.apps.googleusercontent.com","project_id":"ontime-441411","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs"}} - - - +{ + "installed": { + "client_id": "1068261222530-cqa1h83puodc9ngn79b04ot2ehq43o2d.apps.googleusercontent.com", + "project_id": "ontime-441411", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs" + } +} diff --git a/lib/main.dart b/lib/main.dart index fc9e955..c0956c9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,34 @@ +// import 'package:flutter/material.dart'; +// import 'package:on_time_front/core/di/di_setup.dart'; +// import 'package:on_time_front/presentation/shared/router/go_router.dart'; +// import 'package:on_time_front/presentation/shared/theme/theme.dart'; + +// void main() async { +// configureDependencies(); +// runApp(MyApp()); +// WidgetsFlutterBinding.ensureInitialized(); +// } + +// class MyApp extends StatelessWidget { +// const MyApp({super.key}); + +// @override +// Widget build(BuildContext context) { +// return MaterialApp.router( +// routerConfig: goRouterConfig, +// theme: themeData, +// ); +// } +// } + import 'package:flutter/material.dart'; -import 'package:on_time_front/core/di/di_setup.dart'; -import 'package:on_time_front/presentation/shared/router/go_router.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:on_time_front/presentation/preparation/screens/schedule_list_screen.dart'; import 'package:on_time_front/presentation/shared/theme/theme.dart'; +import 'package:on_time_front/widgets/login_buttons/login_test_screen.dart'; void main() async { - configureDependencies(); - runApp(MyApp()); + runApp(const ProviderScope(child: MyApp())); WidgetsFlutterBinding.ensureInitialized(); } @@ -14,9 +37,13 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp.router( - routerConfig: goRouterConfig, + return MaterialApp( theme: themeData, + home: Scaffold( + backgroundColor: Colors.grey, + body: ScheduleListScreen(), + // body: LoginTestScreen(), + ), ); } } diff --git a/lib/widgets/login_buttons/google_login_button.dart b/lib/presentation/login/components/google_login_button.dart similarity index 100% rename from lib/widgets/login_buttons/google_login_button.dart rename to lib/presentation/login/components/google_login_button.dart diff --git a/lib/widgets/login_buttons/google_login_mobile.dart b/lib/presentation/login/components/google_login_mobile.dart similarity index 100% rename from lib/widgets/login_buttons/google_login_mobile.dart rename to lib/presentation/login/components/google_login_mobile.dart diff --git a/lib/widgets/login_buttons/google_login_test.dart b/lib/presentation/login/components/google_login_test.dart similarity index 100% rename from lib/widgets/login_buttons/google_login_test.dart rename to lib/presentation/login/components/google_login_test.dart diff --git a/lib/widgets/login_buttons/kakao_login_button.dart b/lib/presentation/login/components/kakao_login_button.dart similarity index 100% rename from lib/widgets/login_buttons/kakao_login_button.dart rename to lib/presentation/login/components/kakao_login_button.dart diff --git a/lib/widgets/login_buttons/kakao_login_mobile.dart b/lib/presentation/login/components/kakao_login_mobile.dart similarity index 100% rename from lib/widgets/login_buttons/kakao_login_mobile.dart rename to lib/presentation/login/components/kakao_login_mobile.dart diff --git a/lib/widgets/login_buttons/kakao_login_test.dart b/lib/presentation/login/components/kakao_login_test.dart similarity index 100% rename from lib/widgets/login_buttons/kakao_login_test.dart rename to lib/presentation/login/components/kakao_login_test.dart diff --git a/lib/widgets/login_buttons/login_test_screen.dart b/lib/presentation/login/screens/login_test_screen.dart similarity index 66% rename from lib/widgets/login_buttons/login_test_screen.dart rename to lib/presentation/login/screens/login_test_screen.dart index 7c5594b..cfb339e 100644 --- a/lib/widgets/login_buttons/login_test_screen.dart +++ b/lib/presentation/login/screens/login_test_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:on_time_front/widgets/login_buttons/google_login_button.dart'; -import 'package:on_time_front/widgets/login_buttons/kakao_login_button.dart'; +import 'package:on_time_front/presentation/login/components/google_login_button.dart'; +import 'package:on_time_front/presentation/login/components/kakao_login_button.dart'; class LoginTestScreen extends StatelessWidget { const LoginTestScreen({super.key}); diff --git a/lib/presentation/preparation/component/preparation_timer/preparation_step.dart b/lib/presentation/preparation/component/preparation_timer/preparation_step.dart deleted file mode 100644 index e6f2d04..0000000 --- a/lib/presentation/preparation/component/preparation_timer/preparation_step.dart +++ /dev/null @@ -1,156 +0,0 @@ -import 'package:flutter/material.dart'; - -class PreparationStep extends StatelessWidget { - final String preparationName; // 준비 과정 이름 - final String preparationTime; // 준비 과정 시간 (분/초로 포맷) - final String state; - - const PreparationStep({ - super.key, - required this.preparationName, - required this.preparationTime, - required this.state, - }); - - // 상태에 따른 원 색상 및 테두리 반환 - BoxDecoration getCircleDecoration() { - switch (state) { - case 'prev': - return BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: const Color(0xff5C79FB), - width: 1, - ), - ); - - case 'now': - return const BoxDecoration( - color: Color(0xff5C79FB), - shape: BoxShape.circle, - ); - - case 'done': - return const BoxDecoration( - color: Color(0xffB0C4FB), - shape: BoxShape.circle, - ); - - default: - return BoxDecoration(); - } - } - - // 상태에 따른 텍스트 색상 반환 - Color getTextColor() { - switch (state) { - case 'prev': - return Colors.grey; - - case 'now': - return const Color(0xff5C79FB); - - case 'done': - return const Color(0xffB0C4FB); - - default: - return Colors.grey; - } - } - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 329, - height: 50, - child: Stack( - children: [ - // 그림자 애니메이션 - if (state == 'now') - AnimatedOpacity( - opacity: state == 'now' ? 1.0 : 0.0, - duration: const Duration(milliseconds: 300), - curve: Curves.ease, - child: Container( - margin: const EdgeInsets.symmetric(vertical: 6), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 16, // 위아래 퍼짐 - offset: const Offset(10, 2), - ), - ], - ), - ), - ), - // 실제 컴포넌트 내용 - Align( - alignment: Alignment.center, - child: Row( - children: [ - // 원 컴포넌트 - AnimatedContainer( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - width: 10, - height: 10, - decoration: getCircleDecoration(), - ), - const SizedBox(width: 6), // 간격 - // 텍스트와 시간 - Expanded( - child: AnimatedContainer( - duration: const Duration(milliseconds: 300), - curve: Curves.ease, - decoration: BoxDecoration( - color: state == 'now' ? Colors.white : null, - borderRadius: - BorderRadius.circular(state == 'now' ? 8 : 0), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10, horizontal: 9), - child: Row( - children: [ - // 준비 과정 이름 - AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 300), - curve: Curves.ease, - style: TextStyle( - color: getTextColor(), - fontSize: state == 'now' ? 15 : 13, - fontWeight: state == 'now' - ? FontWeight.bold - : FontWeight.normal, - ), - child: Text(preparationName), - ), - const Spacer(), - // 준비 시간 - AnimatedDefaultTextStyle( - duration: const Duration(milliseconds: 200), - curve: Curves.ease, - style: TextStyle( - color: getTextColor(), - fontSize: state == 'now' ? 15 : 13, - fontWeight: state == 'now' - ? FontWeight.bold - : FontWeight.normal, - ), - child: Text(preparationTime), - ) - ], - ), - ), - ), - ), - ], - ), - ), - ], - ), - ); - } -} diff --git a/lib/presentation/preparation/component/preparation_timer/preparation_step_new.dart b/lib/presentation/preparation/component/preparation_timer/preparation_step_new.dart deleted file mode 100644 index 823622e..0000000 --- a/lib/presentation/preparation/component/preparation_timer/preparation_step_new.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'package:dotted_line/dotted_line.dart'; -import 'package:flutter/material.dart'; - -class PreparationStepNew extends StatefulWidget { - const PreparationStepNew({super.key}); - - @override - State createState() => _PreparationStepNewState(); -} - -class _PreparationStepNewState extends State { - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 358, - height: 62, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - color: Colors.white, - ), - child: Padding( - padding: EdgeInsets.all(12), - child: Column( - children: [ - Row( - children: [ - Stack( - alignment: Alignment.center, - children: [ - Container( - width: 34, - height: 34, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Color(0xffDCE3FF), - ), - ), - AnimatedDefaultTextStyle( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xff212F6F)), - duration: Duration(), - // child: Text("2"), - child: Icon(Icons.check), - ), - ], - ), - Padding( - padding: EdgeInsets.only(left: 20), - child: SizedBox( - height: 31, - child: Text( - '헤어', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - Spacer(), - SizedBox( - height: 31, - child: Text( - '20분', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xff5C79FB), - ), - ), - ), - ], - ), - ], - ), - ), - ), - ), - Padding( - padding: EdgeInsets.only(left: 30), - child: DottedLine( - direction: Axis.vertical, - lineLength: 23, - lineThickness: 3, - dashColor: Color(0xff5C79FB), - dashLength: 4, - dashGapLength: 5, - ), - ) - ], - ); - } -} diff --git a/lib/presentation/preparation/component/preparation_timer/preparation_step_new_active.dart b/lib/presentation/preparation/component/preparation_timer/preparation_step_new_active.dart deleted file mode 100644 index 485cf05..0000000 --- a/lib/presentation/preparation/component/preparation_timer/preparation_step_new_active.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:dotted_line/dotted_line.dart'; -import 'package:flutter/material.dart'; - -class PreparationStepNewActive extends StatefulWidget { - const PreparationStepNewActive({super.key}); - - @override - State createState() => - _PreparationStepNewActiveState(); -} - -class _PreparationStepNewActiveState extends State { - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 358, - height: 135, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - border: Border.all(color: Color(0xff5C79FB), width: 2), - color: Colors.white, - ), - child: Padding( - padding: EdgeInsets.all(12), - child: Column( - children: [ - Row( - children: [ - Stack( - alignment: Alignment.center, - children: [ - Container( - width: 34, - height: 34, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Color(0xffDCE3FF), - ), - ), - AnimatedDefaultTextStyle( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xff212F6F)), - duration: Duration(), - // child: Text("2"), - child: Icon(Icons.check), - ), - ], - ), - Padding( - padding: EdgeInsets.only(left: 20), - child: SizedBox( - height: 31, - child: Text( - '헤어', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - Spacer(), - SizedBox( - height: 31, - child: Text( - '20분', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xff5C79FB), - ), - ), - ) - ], - ), - // Button - Padding( - padding: EdgeInsets.only(top: 20), - child: SizedBox( - width: 326, - height: 53, - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: const Color(0xffDCE3FF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onPressed: () { - // 필요한 동작 - }, - child: const Text( - '이 단계 건너 뛰기', - style: TextStyle( - color: Color(0xff212F6F), - fontSize: 16, - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, // 텍스트 중앙 정렬 - ), - ), - ), - ) - ], - ), - ), - ), - ), - Padding( - padding: EdgeInsets.only(left: 30), - child: DottedLine( - direction: Axis.vertical, - lineLength: 23, - lineThickness: 3, - dashColor: Color(0xff5C79FB), - dashLength: 4, - dashGapLength: 5, - ), - ) - ], - ); - } -} diff --git a/lib/presentation/preparation/component/preparation_timer/preparation_step_tile_test.dart b/lib/presentation/preparation/component/preparation_timer/preparation_step_tile_test.dart deleted file mode 100644 index 22bd079..0000000 --- a/lib/presentation/preparation/component/preparation_timer/preparation_step_tile_test.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:dotted_line/dotted_line.dart'; - -class PreparationStepTileTest extends StatefulWidget { - final int stepIndex; - final String preparationName; - final String preparationTime; - final String state; - final VoidCallback? onSkip; - final int? previousElapsedTime; - - const PreparationStepTileTest({ - super.key, - required this.stepIndex, - required this.preparationName, - required this.preparationTime, - required this.state, - this.onSkip, - this.previousElapsedTime, - }); - - @override - _PreparationStepTileTestState createState() => - _PreparationStepTileTestState(); -} - -class _PreparationStepTileTestState extends State { - // 좌측 순서 및 체크 표시 - @override - Widget build(BuildContext context) { - Widget circleContent; - if (widget.state == 'done') { - circleContent = const Icon(Icons.check); - } else { - circleContent = Text( - '${widget.stepIndex}', - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xff212F6F), - ), - ); - } - - // 건너뛰기 버튼 - Widget? skipButton; - if (widget.state == 'now' && widget.onSkip != null) { - skipButton = Align( - alignment: Alignment.centerRight, - child: SizedBox( - width: 326, - height: 53, - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: const Color(0xffDCE3FF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onPressed: widget.onSkip, - child: const Text( - '이 단계 건너 뛰기', - style: TextStyle( - color: Color(0xff212F6F), - fontSize: 16, - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, // 텍스트 중앙 정렬 - ), - ), - ), - ); - } - - final boxChild = Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Stack( - alignment: Alignment.center, - children: [ - Container( - width: 34, - height: 34, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: Color(0xffDCE3FF), - ), - ), - circleContent, - ], - ), - const SizedBox(width: 20), - SizedBox( - height: 31, - child: Text( - widget.preparationName, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - const Spacer(), - SizedBox( - height: 31, - child: Text( - widget.preparationTime, // yet 상태에서는 지정된 시간 표시 - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Color(0xff5C79FB), - ), - ), - ), - ], - ), - ], - ); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AnimatedContainer( - duration: Duration(milliseconds: 300), - width: 358, - height: (widget.state == 'now' && skipButton != null) ? 135 : 62, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - border: (widget.state == 'now') - ? Border.all(color: Color(0xff5C79FB), width: 2) - : null, - color: Colors.white, - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - boxChild, - if (skipButton != null) ...[ - const SizedBox(height: 20), - Flexible( - child: skipButton, - ), - ] - ], - ), - ), - ), - ), - // 점선 - Padding( - padding: const EdgeInsets.only(left: 30), - child: DottedLine( - direction: Axis.vertical, - lineLength: 23, - lineThickness: 3, - dashColor: const Color(0xff5C79FB), - dashLength: 4, - dashGapLength: 5, - ), - ), - ], - ); - } -} diff --git a/lib/presentation/preparation/component/preparation_timer/arc_painter_no_marker.dart b/lib/presentation/preparation/components/preparation_timer/arc_painter_no_marker.dart similarity index 100% rename from lib/presentation/preparation/component/preparation_timer/arc_painter_no_marker.dart rename to lib/presentation/preparation/components/preparation_timer/arc_painter_no_marker.dart diff --git a/lib/presentation/preparation/component/preparation_timer/button.dart b/lib/presentation/preparation/components/preparation_timer/button.dart similarity index 100% rename from lib/presentation/preparation/component/preparation_timer/button.dart rename to lib/presentation/preparation/components/preparation_timer/button.dart diff --git a/lib/presentation/preparation/component/preparation_timer/preparation_step_list.dart b/lib/presentation/preparation/components/preparation_timer/preparation_step_list_widget.dart similarity index 93% rename from lib/presentation/preparation/component/preparation_timer/preparation_step_list.dart rename to lib/presentation/preparation/components/preparation_timer/preparation_step_list_widget.dart index 5d84e46..7256cfd 100644 --- a/lib/presentation/preparation/component/preparation_timer/preparation_step_list.dart +++ b/lib/presentation/preparation/components/preparation_timer/preparation_step_list_widget.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:on_time_front/presentation/preparation/component/preparation_timer/preparation_step_tile.dart'; +import 'package:on_time_front/presentation/preparation/components/preparation_timer/preparation_step_tile.dart'; -class PreparationStepList extends StatelessWidget { +class PreparationStepListWidget extends StatelessWidget { final List preparations; // 준비 과정 데이터 final int currentIndex; // 현재 실행 중인 준비 과정 인덱스 final Function onSkip; // "단계 건너뛰기" 콜백 - const PreparationStepList({ + const PreparationStepListWidget({ super.key, required this.preparations, required this.currentIndex, diff --git a/lib/presentation/preparation/component/preparation_timer/preparation_step_tile.dart b/lib/presentation/preparation/components/preparation_timer/preparation_step_tile.dart similarity index 100% rename from lib/presentation/preparation/component/preparation_timer/preparation_step_tile.dart rename to lib/presentation/preparation/components/preparation_timer/preparation_step_tile.dart diff --git a/lib/presentation/preparation/data/early_late_messages.dart b/lib/presentation/preparation/data/early_late_messages.dart deleted file mode 100644 index b93d15f..0000000 --- a/lib/presentation/preparation/data/early_late_messages.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'dart:math'; - -/// 지각 시 표시될 문구들 -final List lateMessages = [ - "지구의 자전이 너무 빨랐나 봐요!\n조금 늦었지만 괜찮아요!", - "시간이 당신을 기다리지 않았지만,\n사람들은 기다려줄 거예요. 아마도요.", - "‘시간은 금이다’고 했지만,\n오늘은 그 금을 잠시 빌려 쓴 것 같네요!", - "지각의 달인이 되고 싶지 않다면,\n조금 더 일찍 출발해보아요!", - "늦었다고 서두르다 넘어지면 더 늦어요.\n살짝 서둘러봐요!", - "시공간을 뛰어넘는\n타임머신이 있었으면 좋겠어요…!", - "조금 늦긴 했지만,\n오늘의 기분을 망칠 수는 없죠.\n어서 가보자구요!", - "늦은 것 자체가 죄는 아니지만,\n더 나은 시간을 만드는 건 우리의 몫이죠.", - "이미 마음은 현장에 도착해 있었는데,\n몸이 따라오질 않았네요.", - "영화 주인공은 늦게 등장하는 법이라던가…?\n그 기분으로 출발!", - "달력이 오늘을 운명의 날로 정해놨나 봐요.\n하지만 우린 이길 수 있어요!", - "시간은 도망갔지만,\n당신의 열정은 따라잡을 수 있어요!", - "오늘의 체크리스트는 완벽했지만,\n시간이 체크리스트에 없었던 건가요?", - "오늘의 지각은 역사를 만들었군요!\n다음엔 새로운 기록을 세우지 않도록 해봐요!", - "지각계의 마스터가 되어가고 있어요.\n하지만 이제 새로운 길을 찾아봐요!", -]; - -/// 일찍 준비 시, 분 단위 구간별 문구 맵 -final Map> earlyMessages = { - Range(0, 5): [ - "아슬아슬하게 지각을 피했어요!", - "우산을 깜빡하지 않을 여유를 벌었어요.", - ], - Range(6, 10): [ - "택시비를 아꼈어요!", - "심호흡 한 번 하고\n천천히 걸어갈 시간이 생겼어요.", - ], - Range(11, 15): [ - "즐거운 커피 한 잔의\n여유를 얻었어요.", - "횡단보도 신호를 기다릴\n스트레스에서 벗어났어요.", - ], - Range(16, 20): [ - "지하철 환승을 여유롭게 할 수 있어요.", - "친구를 만나기 전에\n간단히 메시지를 보낼 시간이 생겼어요.", - ], - Range(21, 30): [ - "출발 전에 잊은 물건을\n챙길 기회가 생겼어요!", - "예정 시간보다 빠르게 도착해서\n장소를 한 바퀴 둘러볼 수 있어요.", - ], - Range(31, 40): [ - "부모님께 전화를 걸\n여유로운 시간을 벌었어요.", - "조금 더 준비된 모습으로\n상대를 만날 수 있어요.", - ], - Range(41, 59): [ - "영화 예고편을 보며\n시간을 보낼 수 있어요!", - "약속 장소에서\n조용히 책 몇 페이지를 읽을 수 있어요.", - ], - Range(60, 99999999999): [ - // 1시간 이상 (60분 이상) - "삶의 소소한 여유를 얻었어요!", - "지각 걱정 없이 미리 가서\n주변을 살펴볼 수 있어요.", - ], -}; - -/// 범위를 다루기 위한 간단한 클래스 -class Range { - final int start; - final int end; - - Range(this.start, this.end); - - bool contains(int value) { - return value >= start && value <= end; - } -} - -/// [value] 분에 해당하는 문구 중 랜덤으로 하나를 반환 -String getEarlyMessage(int value) { - for (final range in earlyMessages.keys) { - if (range.contains(value)) { - final list = earlyMessages[range]!; - return list[Random().nextInt(list.length)]; - } - } - // 범위 밖(0분 이하)이면 특별 처리 - return "정확히 시간을 맞춰 준비했어요! 혹시 몸에 시계라도 있나요?"; -} - -/// 지각 시 랜덤 문구 -String getLateMessage() { - return lateMessages[Random().nextInt(lateMessages.length)]; -} diff --git a/lib/presentation/preparation/screens/alarm_screen.dart b/lib/presentation/preparation/screens/alarm_screen.dart index 32d2aae..32c22a9 100644 --- a/lib/presentation/preparation/screens/alarm_screen.dart +++ b/lib/presentation/preparation/screens/alarm_screen.dart @@ -5,9 +5,9 @@ import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:on_time_front/presentation/preparation/screens/early_late_screen.dart'; -import 'package:on_time_front/presentation/preparation/component/preparation_timer/button.dart'; -import 'package:on_time_front/presentation/preparation/component/preparation_timer/preparation_step_list.dart'; -import 'package:on_time_front/presentation/preparation/component/preparation_timer/arc_painter_no_marker.dart'; +import 'package:on_time_front/presentation/preparation/components/preparation_timer/button.dart'; +import 'package:on_time_front/presentation/preparation/components/preparation_timer/preparation_step_list_widget.dart'; +import 'package:on_time_front/presentation/preparation/components/preparation_timer/arc_painter_no_marker.dart'; import 'package:on_time_front/utils/time_format.dart'; @@ -432,7 +432,7 @@ class _AlarmScreenState extends State left: MediaQuery.of(context).size.width * 0.06, right: MediaQuery.of(context).size.width * 0.06, bottom: 100, - child: PreparationStepList( + child: PreparationStepListWidget( preparations: preparations, currentIndex: currentIndex, onSkip: skipCurrentPreparation, diff --git a/lib/presentation/preparation/screens/early_late_screen.dart b/lib/presentation/preparation/screens/early_late_screen.dart index 08d9d7c..d0420a5 100644 --- a/lib/presentation/preparation/screens/early_late_screen.dart +++ b/lib/presentation/preparation/screens/early_late_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:on_time_front/presentation/preparation/data/early_late_messages.dart'; +import 'package:on_time_front/presentation/shared/constants/constants.dart'; import 'package:on_time_front/utils/time_format.dart'; -import 'package:on_time_front/presentation/preparation/component/preparation_timer/button.dart'; +import 'package:on_time_front/presentation/preparation/components/preparation_timer/button.dart'; class EarlyLateScreen extends StatefulWidget { final int earlyLateTime; diff --git a/lib/presentation/preparation/screens/preparation_done.dart b/lib/presentation/preparation/screens/preparation_done.dart deleted file mode 100644 index 0e8b965..0000000 --- a/lib/presentation/preparation/screens/preparation_done.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:flutter/material.dart'; - -class PreparationDone extends StatefulWidget { - const PreparationDone({super.key}); - - @override - State createState() => _PreparationDoneState(); -} - -class _PreparationDoneState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 120), - child: Center( - child: Text( - "준비 끝! 어서 나가요!", - style: const TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, - ), - ), - ), - Padding( - padding: const EdgeInsets.only(top: 20), - child: Image.asset( - 'lib/images/ontime_mascot.png', - width: 204, - height: 269, - ), - ), - ], - ), - ); - } -} diff --git a/lib/presentation/preparation/screens/schedule_list_test.dart b/lib/presentation/preparation/screens/schedule_list_screen.dart similarity index 85% rename from lib/presentation/preparation/screens/schedule_list_test.dart rename to lib/presentation/preparation/screens/schedule_list_screen.dart index 14e3cee..7d7651f 100644 --- a/lib/presentation/preparation/screens/schedule_list_test.dart +++ b/lib/presentation/preparation/screens/schedule_list_screen.dart @@ -3,14 +3,16 @@ import 'package:flutter/material.dart'; import 'package:on_time_front/presentation/preparation/screens/schedule_start.dart'; import 'package:on_time_front/presentation/preparation/screens/server_data_loader.dart'; -class ScheduleListTest extends StatefulWidget { - const ScheduleListTest({super.key}); +// 해당 컴포넌트는 스케줄 데이터를 임시로 받아오는 화면. 실재 기능에서는 사용되지 않을 예정. + +class ScheduleListScreen extends StatefulWidget { + const ScheduleListScreen({super.key}); @override - _ScheduleListTestState createState() => _ScheduleListTestState(); + _ScheduleListScreenState createState() => _ScheduleListScreenState(); } -class _ScheduleListTestState extends State { +class _ScheduleListScreenState extends State { List schedules = []; @override diff --git a/lib/presentation/preparation/screens/schedule_start.dart b/lib/presentation/preparation/screens/schedule_start.dart index e6b3371..d11ab8a 100644 --- a/lib/presentation/preparation/screens/schedule_start.dart +++ b/lib/presentation/preparation/screens/schedule_start.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:on_time_front/presentation/preparation/component/preparation_timer/button.dart'; +import 'package:on_time_front/presentation/preparation/components/preparation_timer/button.dart'; import 'package:on_time_front/presentation/preparation/screens/alarm_screen.dart'; class ScheduleStart extends StatelessWidget { @@ -52,7 +52,7 @@ class ScheduleStart extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 20), child: Image.asset( - 'lib/images/ontime_mascot.png', + 'assets/character.png', width: 204, height: 269, ), diff --git a/lib/presentation/shared/constants/constants.dart b/lib/presentation/shared/constants/constants.dart index 32d9f4a..1612f3d 100644 --- a/lib/presentation/shared/constants/constants.dart +++ b/lib/presentation/shared/constants/constants.dart @@ -1 +1,88 @@ +import 'dart:math'; + const double appBarHeight = 56.0; + +/// 지각 시 표시될 문구들 +const List lateMessages = [ + "지구의 자전이 너무 빨랐나 봐요!\n조금 늦었지만 괜찮아요!", + "시간이 당신을 기다리지 않았지만,\n사람들은 기다려줄 거예요. 아마도요.", + "‘시간은 금이다’고 했지만,\n오늘은 그 금을 잠시 빌려 쓴 것 같네요!", + "지각의 달인이 되고 싶지 않다면,\n조금 더 일찍 출발해보아요!", + "늦었다고 서두르다 넘어지면 더 늦어요.\n살짝 서둘러봐요!", + "시공간을 뛰어넘는\n타임머신이 있었으면 좋겠어요…!", + "조금 늦긴 했지만,\n오늘의 기분을 망칠 수는 없죠.\n어서 가보자구요!", + "늦은 것 자체가 죄는 아니지만,\n더 나은 시간을 만드는 건 우리의 몫이죠.", + "이미 마음은 현장에 도착해 있었는데,\n몸이 따라오질 않았네요.", + "영화 주인공은 늦게 등장하는 법이라던가…?\n그 기분으로 출발!", + "달력이 오늘을 운명의 날로 정해놨나 봐요.\n하지만 우린 이길 수 있어요!", + "시간은 도망갔지만,\n당신의 열정은 따라잡을 수 있어요!", + "오늘의 체크리스트는 완벽했지만,\n시간이 체크리스트에 없었던 건가요?", + "오늘의 지각은 역사를 만들었군요!\n다음엔 새로운 기록을 세우지 않도록 해봐요!", + "지각계의 마스터가 되어가고 있어요.\n하지만 이제 새로운 길을 찾아봐요!", +]; + +/// 일찍 준비 시, 분 단위 구간별 문구 맵 +final Map> earlyMessages = { + Range(0, 5): [ + "아슬아슬하게 지각을 피했어요!", + "우산을 깜빡하지 않을 여유를 벌었어요.", + ], + Range(6, 10): [ + "택시비를 아꼈어요!", + "심호흡 한 번 하고\n천천히 걸어갈 시간이 생겼어요.", + ], + Range(11, 15): [ + "즐거운 커피 한 잔의\n여유를 얻었어요.", + "횡단보도 신호를 기다릴\n스트레스에서 벗어났어요.", + ], + Range(16, 20): [ + "지하철 환승을 여유롭게 할 수 있어요.", + "친구를 만나기 전에\n간단히 메시지를 보낼 시간이 생겼어요.", + ], + Range(21, 30): [ + "출발 전에 잊은 물건을\n챙길 기회가 생겼어요!", + "예정 시간보다 빠르게 도착해서\n장소를 한 바퀴 둘러볼 수 있어요.", + ], + Range(31, 40): [ + "부모님께 전화를 걸\n여유로운 시간을 벌었어요.", + "조금 더 준비된 모습으로\n상대를 만날 수 있어요.", + ], + Range(41, 59): [ + "영화 예고편을 보며\n시간을 보낼 수 있어요!", + "약속 장소에서\n조용히 책 몇 페이지를 읽을 수 있어요.", + ], + Range(60, null): [ + // 1시간 이상 (60분 이상) + "삶의 소소한 여유를 얻었어요!", + "지각 걱정 없이 미리 가서\n주변을 살펴볼 수 있어요.", + ], +}; + +/// 범위를 다루기 위한 간단한 클래스 +class Range { + final int start; + final int? end; + + Range(this.start, this.end); + + bool contains(int value) { + return value >= start && value <= end!; + } +} + +/// [value] 분에 해당하는 문구 중 랜덤으로 하나를 반환 +String getEarlyMessage(int value) { + for (final range in earlyMessages.keys) { + if (range.contains(value)) { + final list = earlyMessages[range]!; + return list[Random().nextInt(list.length)]; + } + } + // 범위 밖(0분 이하)이면 특별 처리 + return "정확히 시간을 맞춰 준비했어요! 혹시 몸에 시계라도 있나요?"; +} + +/// 지각 시 랜덤 문구 +String getLateMessage() { + return lateMessages[Random().nextInt(lateMessages.length)]; +}