diff --git a/lib/constants/paths.dart b/lib/constants/paths.dart index 4d29b92..baf9667 100644 --- a/lib/constants/paths.dart +++ b/lib/constants/paths.dart @@ -35,4 +35,7 @@ abstract class Paths { static const String myMentorIntroduce = '/my_mentor_introduce'; static const String timeSetting = '/time_setting'; static const String timeChecking = '/time_checking'; + + static const String report = '/report'; + static const String reportDetail = '/report_detail'; } diff --git a/lib/features/home/profile/profile_detail_screen.dart b/lib/features/home/profile/profile_detail_screen.dart index 0bf996d..1300cf3 100644 --- a/lib/features/home/profile/profile_detail_screen.dart +++ b/lib/features/home/profile/profile_detail_screen.dart @@ -1,9 +1,11 @@ import 'package:cogo/common/widgets/atoms/texts/styles.dart'; import 'package:cogo/common/widgets/components/basic_button.dart'; import 'package:cogo/constants/colors.dart'; +import 'package:cogo/constants/paths.dart'; import 'package:cogo/features/home/profile/profile_detail_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; class ProfileDetailScreen extends StatelessWidget { @@ -28,6 +30,23 @@ class ProfileDetailScreen extends StatelessWidget { icon: SvgPicture.asset('assets/icons/button/chevron_left.svg'), onPressed: () => Navigator.of(context).pop(), ), + actions: [ + IconButton( + onPressed: () { + showModalBottomSheet( + context: context, + backgroundColor: CogoColor.white50, + shape: const RoundedRectangleBorder( + borderRadius: + BorderRadius.vertical(top: Radius.circular(16)), + ), + builder: (BuildContext context) { + return _buildBottomSheetContent(context); + }, + ); + }, + icon: const Icon(Icons.more_vert)) + ], title: Consumer( builder: (context, viewModel, child) { if (viewModel.isLoading) { @@ -175,4 +194,26 @@ class ProfileDetailScreen extends StatelessWidget { ), ); } + + Widget _buildBottomSheetContent(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + leading: const Icon(Icons.flag), + title: const Text( + '신고하기', + style: CogoTextStyle.body16, + ), + onTap: () { + context.push(Paths.report); + // 설정 메뉴 선택 + }, + ), + ], + ), + ); + } } diff --git a/lib/features/home/report/report_detail_screen.dart b/lib/features/home/report/report_detail_screen.dart new file mode 100644 index 0000000..bf52edf --- /dev/null +++ b/lib/features/home/report/report_detail_screen.dart @@ -0,0 +1,89 @@ +import 'package:cogo/common/widgets/atoms/texts/styles.dart'; +import 'package:cogo/common/widgets/components/basic_button.dart'; +import 'package:cogo/common/widgets/components/basic_textfield.dart'; +import 'package:cogo/common/widgets/components/secondary_button.dart'; +import 'package:cogo/constants/colors.dart'; +import 'package:cogo/features/home/report/report_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:provider/provider.dart'; + +class ReportDetailScreen extends StatelessWidget { + const ReportDetailScreen({super.key}); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => ReportViewModel(), + child: Scaffold( + backgroundColor: CogoColor.white50, + resizeToAvoidBottomInset: true, + appBar: AppBar( + backgroundColor: CogoColor.white50, + title: const Text( + "신고하기", + style: CogoTextStyle.body20, + ), + centerTitle: true, + leading: IconButton( + icon: SvgPicture.asset('assets/icons/button/chevron_left.svg'), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: SingleChildScrollView( + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Consumer( + builder: (context, viewModel, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "신고 세부 내용", + style: CogoTextStyle.body16, + ), + const SizedBox(height: 10), + BasicTextField( + controller: viewModel.reportController, + hintText: '신고하실 내용을 자세히 작성해주세요', + currentCount: viewModel.reportCharCount, + maxCount: 200, + size: BasicTextFieldSize.LARGE, + maxLines: 1, + ), + const SizedBox(height: 10), + const Text('유의사항', style: CogoTextStyle.bodySB14), + const SizedBox(height: 10), + const Text( + '신고 후 신고 내역에 따라 해당 유저에게 안내가 이루어질 예정입니다.\n각 항목 별 세부 사항은 다음과 같습니다.\n\n' + '멘토링의 목적이 아닌것\n- 종교단체\n - 사업목적 (보험, 광고, etc)\n- 기타 멘토링으로 의도되지 않는 모든 행위\n\n' + '멘토링 과정에서 비매너 행위 발생\n- 잘못된 정보 제공\n- 상대방에 부적절한 언행\n- 기타 양자간 분쟁 가능성이 있는 비매너 행위', + style: CogoTextStyle.body9, + ), + const SizedBox(height: 80), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SecondaryButton( + text: '취소', + onPressed: () => Navigator.of(context).pop(), + ), + const SizedBox(width: 16), // 버튼들 사이에 16만큼 간격을 추가 + BasicButton( + text: '신고', + isClickable: true, + onPressed: viewModel.postReport, + ) + ], + ) + ], + ); + }), + ), + ), + ), + ), + ); + } +} diff --git a/lib/features/home/report/report_screen.dart b/lib/features/home/report/report_screen.dart new file mode 100644 index 0000000..972c3b0 --- /dev/null +++ b/lib/features/home/report/report_screen.dart @@ -0,0 +1,89 @@ +import 'package:cogo/common/widgets/atoms/texts/styles.dart'; +import 'package:cogo/constants/colors.dart'; +import 'package:cogo/constants/paths.dart'; +import 'package:cogo/features/home/report/report_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; + +class ReportScreen extends StatelessWidget { + const ReportScreen({super.key}); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (context) => ReportViewModel(), + child: Scaffold( + backgroundColor: CogoColor.white50, + resizeToAvoidBottomInset: true, + appBar: AppBar( + backgroundColor: CogoColor.white50, + title: const Text( + "신고하기", + style: CogoTextStyle.body20, + ), + centerTitle: true, + leading: IconButton( + icon: SvgPicture.asset('assets/icons/button/chevron_left.svg'), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: SingleChildScrollView( + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Consumer( + builder: (context, viewModel, child) { + return Column( + children: [ + ListTile( + title: const Text( + '멘토링의 목적을 가지고 멘토가 만난것 같지 않아요', + style: CogoTextStyle.body16, + ), + trailing: const Icon(Icons.chevron_right), + onTap: () { + context.push(Paths.reportDetail); + }, + ), + const Divider(height: 1, color: CogoColor.systemGray02), + ListTile( + title: const Text( + '멘토링 중에 분쟁 발생했어요', + style: CogoTextStyle.body16, + ), + trailing: const Icon(Icons.chevron_right), + onTap: () { + context.push(Paths.reportDetail); + }, + ), + const Divider(height: 1, color: CogoColor.systemGray02), + ListTile( + title: const Text( + '멘토의 소속이나, 인적사항이 거짓인것 같아요', + style: CogoTextStyle.body16, + ), + trailing: const Icon(Icons.chevron_right), + onTap: () { + context.push(Paths.reportDetail); + }, + ), + const Divider(height: 1, color: CogoColor.systemGray02), + ListTile( + title: const Text('기타 부적절한 행위가 있었어요', + style: CogoTextStyle.body16), + trailing: const Icon(Icons.chevron_right), + onTap: () { + context.push(Paths.reportDetail); + }), + ], + ); + }), + ), + ), + ), + ), + ); + } +} diff --git a/lib/features/home/report/report_view_model.dart b/lib/features/home/report/report_view_model.dart new file mode 100644 index 0000000..2dd71ef --- /dev/null +++ b/lib/features/home/report/report_view_model.dart @@ -0,0 +1,17 @@ +import 'package:flutter/cupertino.dart'; + +class ReportViewModel extends ChangeNotifier { + final TextEditingController reportController = TextEditingController(); + + int get reportCharCount => reportController.text.length; + + ReportViewModel() { + reportController.addListener(() { + notifyListeners(); + }); + } + + bool postReport() { + return true; + } +} diff --git a/lib/route/routes.dart b/lib/route/routes.dart index 449354e..ff6c910 100644 --- a/lib/route/routes.dart +++ b/lib/route/routes.dart @@ -22,6 +22,8 @@ import 'package:cogo/features/home/mentor_detail/views/mentor_introduction_scree import 'package:cogo/features/home/mentor_detail/views/mentor_question1_screen.dart'; import 'package:cogo/features/home/mentor_detail/views/mentor_question2_screen.dart'; import 'package:cogo/features/home/profile/profile_detail_screen.dart'; +import 'package:cogo/features/home/report/report_detail_screen.dart'; +import 'package:cogo/features/home/report/report_screen.dart'; import 'package:cogo/features/home/search/search_screen.dart'; import 'package:cogo/features/mypage/mentor_introduce/my_mentor_introduce_screen.dart'; import 'package:cogo/features/mypage/mentor_time_checking/mentor_time_checking_screen.dart'; @@ -242,6 +244,20 @@ final AppRouter = GoRouter( child: const MentorTimeCheckingScreen(), ), ), + GoRoute( + path: Paths.report, + pageBuilder: (context, state) => MaterialPage( + key: state.pageKey, + child: const ReportScreen(), + ), + ), + GoRoute( + path: Paths.reportDetail, + pageBuilder: (context, state) => MaterialPage( + key: state.pageKey, + child: const ReportDetailScreen(), + ), + ), StatefulShellRoute.indexedStack( builder: (context, state, navigationShell) { return ScaffoldWithNestedNavigation(