From 177e402ce4ad2292b59d879917c3abd06d1510dd Mon Sep 17 00:00:00 2001 From: choichangyeon Date: Sat, 18 May 2024 15:01:48 +0900 Subject: [PATCH 1/4] checkPoint --- frontend/lib/http.dart | 47 +- frontend/lib/main.dart | 7 + .../lib/screens/book/book_content_screen.dart | 7 +- .../lib/screens/book/book_info_screen.dart | 441 +++++++++--------- .../bookreport/bookreport_viewing_screen.dart | 21 +- .../bookreport/bookreport_writing_screen.dart | 313 +++++++------ .../lib/screens/home/group/group_screen.dart | 109 +++-- .../screens/home/group/group_screen_util.dart | 18 +- .../group/in_group/group_info_screen.dart | 35 +- .../in_group/groupbook_select_screen.dart | 2 +- .../in_group/post/homework_list_screen.dart | 18 +- .../post/homework_memberlist_screen.dart | 56 ++- .../in_group/post/notice_list_screen.dart | 4 +- .../group/in_group/post/post_list_screen.dart | 4 +- .../home/group/in_group/post/post_screen.dart | 62 +-- .../group/in_group/voicecall/voice_class.dart | 135 ++++-- .../screens/home/search/search_screen.dart | 14 +- .../home/search/search_screen_util.dart | 35 +- frontend/lib/screens/login/login_screen.dart | 12 - 19 files changed, 762 insertions(+), 578 deletions(-) delete mode 100644 frontend/lib/screens/login/login_screen.dart diff --git a/frontend/lib/http.dart b/frontend/lib/http.dart index 5f6e271d0c..a49b19cd2e 100644 --- a/frontend/lib/http.dart +++ b/frontend/lib/http.dart @@ -10,6 +10,30 @@ const String NaverBookSearchURL = const String NaverBookISBNSearchURL = "https://openapi.naver.com/v1/search/book_adv.xml"; +const String AgoraTokenURL = + 'https://agora-token-service-example.up.railway.app'; + +//아고라 토큰 가져오기 +Future agoraToken(String uid, String channel) async { + var address = Uri.parse(AgoraTokenURL + "/fetchToken"); + http.Response res = await http.post( + address, + headers: { + "Content-Type": "application/json", + }, + body: json.encode({ + "tokenType": "rtc", + "uid": uid, + "role": "publisher", + "channel": channel, + }), + ); + final data = json.decode(utf8.decode(res.bodyBytes)); + // print(data); + + return data; +} + //네이버 책 검색 Future> SearchBook(String SearchString) async { List bookData = []; @@ -211,7 +235,7 @@ Future contentCreate( var address; // print(clubId); if (clubId == null) { - print(clubId); + // print(clubId); address = Uri.parse("$BASE_URL/content/create?"); } else { address = Uri.parse("$BASE_URL/content/create?clubId=$clubId&asId=$asId"); @@ -224,7 +248,7 @@ Future contentCreate( }, body: json.encode({ "addBookRequest": { - "isbn": isbn, + "isbn": isbn, "title": booktitle, "author": author, "publisher": publisher, @@ -240,7 +264,7 @@ Future contentCreate( ); final data = res.body; // final data = json.decode(utf8.decode(res.bodyBytes)); - print(data); + // print(data); return data; } @@ -266,7 +290,7 @@ Future quizCreate( String endDate) async { var address; if (clubId == null) { - print(clubId); + // print(clubId); address = Uri.parse("$BASE_URL/quiz/create?"); } else { address = Uri.parse("$BASE_URL/quiz/create?clubId=$clubId&asId=$asId"); @@ -279,7 +303,7 @@ Future quizCreate( }, body: json.encode({ "addBookRequest": { - "isbn": isbn, + "isbn": isbn, "title": booktitle, "author": author, "publisher": publisher, @@ -287,7 +311,7 @@ Future quizCreate( "imageUrl": imageUrl, }, "type": type, - "description" : description, + "description": description, "answer": answer, "example1": example1, "example2": example2, @@ -298,7 +322,7 @@ Future quizCreate( }), ); final data = res.body; - print(data); + // print(data); return data; } @@ -333,6 +357,7 @@ Future> bookcontentLoad(String ISBN, String content) async { for (int i = 0; i < data.length; i++) { contentList.add(data[i]); } + print(data); return contentList; } @@ -387,7 +412,7 @@ Future groupOut(String token, int clubId) async { Future groupExpel(String token, String memberId, int clubId) async { var address = Uri.parse(BASE_URL + "/club/expel?memberId=$memberId&clubId=$clubId"); - http.Response res = await http.get( + http.Response res = await http.delete( address, headers: { "Content-Type": "application/json", @@ -395,6 +420,7 @@ Future groupExpel(String token, String memberId, int clubId) async { }, ); final data = res.body; + // print(data); return data; } @@ -431,6 +457,7 @@ Future groupBookSelect( body: json.encode({ "isbn": bookdata['isbn'], "title": bookdata['title'], + "description" : bookdata['description'], "author": bookdata['author'], "publisher": bookdata['publisher'], "publishDate": formattedDate, @@ -449,6 +476,7 @@ Future bookAdd(Map bookdata) async { RegExp(r'(\d{4})(\d{2})(\d{2})'), (Match m) => '${m[1]}-${m[2]}-${m[3]}')); String formattedDate = DateFormat('yyyy-MM-dd').format(parsedDate); + // print(bookdata); var address = Uri.parse(BASE_URL + "/book/add"); http.Response res = await http.post( address, @@ -458,6 +486,7 @@ Future bookAdd(Map bookdata) async { body: json.encode({ "isbn": bookdata['isbn'], "title": bookdata['title'], + "description" : bookdata['description'], "author": bookdata['author'], "publisher": bookdata['publisher'], "publishDate": formattedDate, @@ -640,6 +669,6 @@ Future addBooksToLibrary( body: json.encode(books), ); final data = res.body; - print(data); + // print(data); return data; } diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 896fb285b1..19bd990cc7 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -99,10 +99,14 @@ final GoRouter router = GoRouter( int index = extraData['index'] as int; dynamic clubId = extraData['clubId'] as dynamic; dynamic asId = extraData['asId'] as dynamic; + dynamic isbn = extraData['isbn'] as dynamic; + dynamic dateInfo = extraData['dateInfo'] as dynamic; return BookReportWritingScreen( index: index, clubId: clubId, asId: asId, + isbn: isbn, + dateInfo: dateInfo, ); }, ), @@ -148,9 +152,11 @@ final GoRouter router = GoRouter( Map extraData = state.extra as Map; int clubId = extraData['clubId'] as int; String managerId = extraData['managerId'] as String; + dynamic bookInfo = extraData['bookInfo'] as dynamic; return HomeworkListScreen( clubId: clubId, managerId: managerId, + bookInfo: bookInfo, ); }, ), @@ -273,6 +279,7 @@ class App extends StatelessWidget { // 다른 프로바이더도 여기에 추가 ], child: MaterialApp.router( + debugShowCheckedModeBanner: false, routerConfig: router, theme: ThemeData( fontFamily: 'pretendard', diff --git a/frontend/lib/screens/book/book_content_screen.dart b/frontend/lib/screens/book/book_content_screen.dart index 1cc57802ae..1e50add478 100644 --- a/frontend/lib/screens/book/book_content_screen.dart +++ b/frontend/lib/screens/book/book_content_screen.dart @@ -35,6 +35,7 @@ class _BookContentState extends State { setState(() { id = _id; token = _token; + print(id); }); } @@ -99,7 +100,7 @@ class _BookContentState extends State { ), centerTitle: true, ), - floatingActionButton: FloatingActionButton( + floatingActionButton: (id != null && token != null)?FloatingActionButton( onPressed: () { context.push( '/bookreport_writing', @@ -107,6 +108,8 @@ class _BookContentState extends State { "index": typeCheck(widget.type), "clubId": null, "asId": null, + "isbn": widget.isbn, + "dateInfo":null, }, ).then((result) async { updatePostList(); @@ -114,7 +117,7 @@ class _BookContentState extends State { }, shape: const CircleBorder(), child: const Icon(Icons.add), - ), + ):null, body: SingleChildScrollView( child: Column( children: _buildPostListView(posts), diff --git a/frontend/lib/screens/book/book_info_screen.dart b/frontend/lib/screens/book/book_info_screen.dart index e02913f103..69f460f3c1 100644 --- a/frontend/lib/screens/book/book_info_screen.dart +++ b/frontend/lib/screens/book/book_info_screen.dart @@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; +import 'dart:async'; class BookInfoScreen extends StatefulWidget { final Map data; //책 정보 @@ -24,7 +25,7 @@ class _BookInfoState extends State { var secureStorage; var id, token; var review, shortreview, quotation, quiz; - // var userInfo; + bool _isLoading = true; List _selectType = [true, false, false]; List postType(BuildContext context, List type) { @@ -77,10 +78,10 @@ class _BookInfoState extends State { shortreview = _shortreview; quotation = _quotation; quiz = _quiz; - // print(review); - // print(shortreview); - // print(quotation); - // print(quiz); + print(review); + print(shortreview); + print(quotation); + print(quiz); }); } @@ -103,10 +104,19 @@ class _BookInfoState extends State { } } + Future _loadData(int term) async { + Timer(Duration(milliseconds: term), () { + setState(() { + _isLoading = false; + }); + }); + } + @override void initState() { super.initState(); secureStorage = Provider.of(context, listen: false); + _loadData(500); _initUserState(); updateBookcontent(); } @@ -130,229 +140,236 @@ class _BookInfoState extends State { ), centerTitle: true, ), - body: Column( - children: [ - Container( - width: double.infinity, - height: 180.h, - decoration: const BoxDecoration( - color: Color(0xFF0E9913), - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(50), - bottomRight: Radius.circular(50), - ), - ), - child: Container( - child: Row( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Container( - width: ScreenUtil().setWidth(80), - height: ScreenUtil().setHeight(105), - decoration: ShapeDecoration( - image: DecorationImage( - image: NetworkImage(widget.data['image']), - fit: BoxFit.fill, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(3)), - ), - ), - ), - ], + body: _isLoading + ? const Center( + child: CircularProgressIndicator(), // 로딩 애니매이션 + ) + : Column( + children: [ + Container( + width: double.infinity, + height: 180.h, + decoration: const BoxDecoration( + color: Color(0xFF0E9913), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(50), + bottomRight: Radius.circular(50), + ), ), - Expanded( - child: Padding( - padding: EdgeInsets.only( - left: 10.w, - right: 20.w, - bottom: 20.h, - ), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Container( - child: Text( - widget.data['description'], - style: const TextStyle( - color: Colors.black, - fontSize: 12, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, + child: Container( + child: Row( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20.0), + child: Container( + width: ScreenUtil().setWidth(80), + height: ScreenUtil().setHeight(105), + decoration: ShapeDecoration( + image: DecorationImage( + image: NetworkImage(widget.data['image']), + fit: BoxFit.fill, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3)), + ), + ), ), - ), + ], ), - ), - ), - ), - ], - ), - ), - ), - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - children: [ - SizedBox( - height: 30, - ), - Ink( - width: 350.w, - height: 120.h, - decoration: ShapeDecoration( - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6)), - shadows: const [ - BoxShadow( - color: Color(0x3F000000), - blurRadius: 6, - offset: Offset(0, 4), - spreadRadius: 0, - ) - ], - ), - child: InkWell( - borderRadius: BorderRadius.circular(6), - onTap: () { - context.push('/book_content', extra: { - "posts": quiz, - "type": "Quiz", - "isbn": widget.data['isbn'], - }).then((value) async { - updateBookcontent(); - }); - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Padding( + Expanded( + child: Padding( padding: EdgeInsets.only( - left: 5.0, - top: 3.0, + left: 10.w, + right: 20.w, + bottom: 20.h, ), - child: Text( - '퀴즈', - style: TextStyle( - color: Colors.black, - fontSize: 16, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Container( + child: Text( + widget.data['description'], + style: const TextStyle( + color: Colors.black, + fontSize: 12, + fontFamily: 'Noto Sans KR', + fontWeight: FontWeight.w700, + ), + ), ), ), ), - SizedBox( - height: 5.h, - ), - Expanded( - child: ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric( - horizontal: 50.0), - children: _buildTaskList(context, '퀴즈'), - ), - ), - ], - ), + ), + ], ), ), - SizedBox( - height: 30, - ), - Column( - children: [ - Row( - children: postType(context, ['독후감', '한줄평', '인용구']), - ), - Ink( - width: 350.w, - height: 120.h, - decoration: ShapeDecoration( - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6)), - shadows: const [ - BoxShadow( - color: Color(0x3F000000), - blurRadius: 6, - offset: Offset(0, 4), - spreadRadius: 0, - ) - ], + ), + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + SizedBox( + height: 30, ), - child: InkWell( - borderRadius: BorderRadius.circular(6), - onTap: () { - var post, type; - if (_selectType[0]) { - post = review; - type = "Review"; - } else if (_selectType[1]) { - post = shortreview; - type = "ShortReview"; - } else if (_selectType[2]) { - post = quotation; - type = "Quotation"; - } - context.push('/book_content', extra: { - "posts": post, - "type": type, - "isbn": widget.data['isbn'], - }).then((value) async { - updateBookcontent(); - }); - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (_selectType[0]) - ? Expanded( - child: ListView( - shrinkWrap: true, - padding: const EdgeInsets.symmetric( - horizontal: 50.0), - children: - _buildTaskList(context, '독후감'), - ), - ) - : (_selectType[1]) - ? Expanded( - child: ListView( - shrinkWrap: true, - padding: - const EdgeInsets.symmetric( - horizontal: 50.0), - children: _buildTaskList( - context, '한줄평'), - ), - ) - : Expanded( - child: ListView( - shrinkWrap: true, - padding: - const EdgeInsets.symmetric( - horizontal: 50.0), - children: _buildTaskList( - context, '인용구'), - ), - ), + Ink( + width: 350.w, + height: 120.h, + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6)), + shadows: const [ + BoxShadow( + color: Color(0x3F000000), + blurRadius: 6, + offset: Offset(0, 4), + spreadRadius: 0, + ) ], ), + child: InkWell( + borderRadius: BorderRadius.circular(6), + onTap: () { + context.push('/book_content', extra: { + "posts": quiz, + "type": "Quiz", + "isbn": widget.data['isbn'], + }).then((value) async { + updateBookcontent(); + }); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Padding( + padding: EdgeInsets.only( + left: 5.0, + top: 3.0, + ), + child: Text( + '퀴즈', + style: TextStyle( + color: Colors.black, + fontSize: 16, + fontFamily: 'Noto Sans KR', + fontWeight: FontWeight.w700, + ), + ), + ), + SizedBox( + height: 5.h, + ), + Expanded( + child: ListView( + shrinkWrap: true, + padding: const EdgeInsets.symmetric( + horizontal: 50.0), + children: _buildTaskList(context, '퀴즈'), + ), + ), + ], + ), + ), + ), + SizedBox( + height: 30, ), - ), - ], + Column( + children: [ + Row( + children: + postType(context, ['독후감', '한줄평', '인용구']), + ), + Ink( + width: 350.w, + height: 120.h, + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6)), + shadows: const [ + BoxShadow( + color: Color(0x3F000000), + blurRadius: 6, + offset: Offset(0, 4), + spreadRadius: 0, + ) + ], + ), + child: InkWell( + borderRadius: BorderRadius.circular(6), + onTap: () { + var post, type; + if (_selectType[0]) { + post = review; + type = "Review"; + } else if (_selectType[1]) { + post = shortreview; + type = "ShortReview"; + } else if (_selectType[2]) { + post = quotation; + type = "Quotation"; + } + context.push('/book_content', extra: { + "posts": post, + "type": type, + "isbn": widget.data['isbn'], + }).then((value) async { + updateBookcontent(); + }); + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + (_selectType[0]) + ? Expanded( + child: ListView( + shrinkWrap: true, + padding: + const EdgeInsets.symmetric( + horizontal: 50.0), + children: _buildTaskList( + context, '독후감'), + ), + ) + : (_selectType[1]) + ? Expanded( + child: ListView( + shrinkWrap: true, + padding: const EdgeInsets + .symmetric( + horizontal: 50.0), + children: _buildTaskList( + context, '한줄평'), + ), + ) + : Expanded( + child: ListView( + shrinkWrap: true, + padding: const EdgeInsets + .symmetric( + horizontal: 50.0), + children: _buildTaskList( + context, '인용구'), + ), + ), + ], + ), + ), + ), + ], + ), + ], + ), ), - ], - ), + ), + ], ), - ), - ], - ), ), ); } diff --git a/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart b/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart index e187d4fda2..8db2a459cb 100644 --- a/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart +++ b/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart @@ -32,16 +32,9 @@ class _BookReportViewingState extends State { String _category = ''; String _answer = ''; bool _oxanswer = false; - // String _example1 = ''; - // String _example2 = ''; - // String _example3 = ''; - // String _example4 = ''; + List _exampleList = [null, null, null, null]; List _multipleanswer = [false, false, false, false]; - // bool _answer1 = false; - // bool _answer2 = false; - // bool _answer3 = false; - // bool _answer4 = false; var token; void initializeClubContentData(dynamic content) { @@ -169,9 +162,13 @@ class _BookReportViewingState extends State { const SizedBox(height: 15), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), - child: Expanded( + child: Row( + children: [ + Expanded( child: _buildTemplateUI(_template), ), + ], + ), ), const SizedBox(height: 15), ], @@ -248,9 +245,13 @@ class _BookReportViewingState extends State { const SizedBox(height: 15), Padding( padding: const EdgeInsets.symmetric(horizontal: 0), - child: Expanded( + child: Row( + children: [ + Expanded( child: _buildQuizUI(_category), ), + ], + ), ), const SizedBox(height: 10), Row( diff --git a/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart b/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart index e90060f122..d0a2a69c5c 100644 --- a/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart +++ b/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart @@ -14,11 +14,15 @@ class BookReportWritingScreen extends StatefulWidget { required this.index, required this.clubId, required this.asId, + required this.isbn, + required this.dateInfo, }); final int index; final dynamic clubId; final dynamic asId; + final dynamic isbn; + final dynamic dateInfo; @override State createState() => _BookReportWritingState(); @@ -32,7 +36,6 @@ class _BookReportWritingState extends State { final TextEditingController _bookTitleController = TextEditingController(); DateTime _startDate = DateTime.now(); DateTime _endDate = DateTime.now(); - bool _isPublic = false; String _template = ""; final TextEditingController _writingController = TextEditingController(); String? selectedCategory = '단답형'; @@ -40,10 +43,10 @@ class _BookReportWritingState extends State { final TextEditingController _answerController = TextEditingController(); bool _isOX = true; List _multipleanswer = [false, false, false, false]; - final TextEditingController _answerController1 = TextEditingController(); - final TextEditingController _answerController2 = TextEditingController(); - final TextEditingController _answerController3 = TextEditingController(); - final TextEditingController _answerController4 = TextEditingController(); + final List _answerControllers = List.generate( + 4, + (index) => TextEditingController(), + ); var token; List BookData = []; String _author = "작가"; @@ -58,6 +61,7 @@ class _BookReportWritingState extends State { @override void initState() { super.initState(); + checkHW(); _initUserState(); // Initialize _keyboardVisibilityObserver and _keyboardVisibilityObserverWrapper @@ -84,12 +88,35 @@ class _BookReportWritingState extends State { token = await secureStorage.readData("token"); } + void checkHW() async { + if (widget.isbn != null) { + var bookInfo = await getBookInfo(widget.isbn); + + setState(() { + _author = bookInfo['author']; + _publisher = bookInfo['publisher']; + _isbn = widget.isbn; + _publisherDate = bookInfo['publisherDate']; + _imageUrl = bookInfo['imageUrl']; + }); + } + if (widget.dateInfo != null) { + setState(() { + _startDate = widget.dateInfo['startDate']; + _endDate = widget.dateInfo['endDate']; + }); + } + } + @override void dispose() { // Remove the keyboard visibility listener WidgetsBinding.instance.removeObserver(_keyboardVisibilityObserverWrapper); _questionController.dispose(); _answerController.dispose(); + for (var controller in _answerControllers) { + controller.dispose(); + } super.dispose(); } @@ -102,7 +129,6 @@ class _BookReportWritingState extends State { _bookTitleController.text = book.title; _startDate = book.startDate; _endDate = book.endDate; - _isPublic = book.isPublic; _template = book.template; } else { // 책이 없는 경우에 대한 처리 @@ -137,16 +163,16 @@ class _BookReportWritingState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox(height: 20), + SizedBox(height: 5.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( children: [ const Text('도서: '), - const SizedBox(width: 10), + SizedBox(width: 10.w), Expanded( child: SizedBox( - width: _screenWidth * 0.7, + width: _screenWidth * 0.7.w, child: TextField( style: const TextStyle(fontSize: 14), controller: _bookTitleController, @@ -202,7 +228,7 @@ class _BookReportWritingState extends State { ], ), ), - const SizedBox(height: 10), + SizedBox(height: 5.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( @@ -212,25 +238,25 @@ class _BookReportWritingState extends State { ], ), ), - const SizedBox(height: 15), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: Container( - decoration: BoxDecoration( - border: Border.all( - width: 1, - color: const Color(0xFFA9AFB7), - ), - ), - ), - ), - const SizedBox(height: 15), + SizedBox(height: 5.h), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10), + // child: Container( + // decoration: BoxDecoration( + // border: Border.all( + // width: 1.w, + // color: const Color(0xFFA9AFB7), + // ), + // ), + // ), + // ), + // SizedBox(height: 5.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( children: [ const Text('독서 기간: ', style: TextStyle(color: Colors.black)), - const SizedBox(width: 3), + SizedBox(width: 3.w), TextButton( onPressed: () async { final DateTime? picked = await showDatePicker( @@ -275,85 +301,89 @@ class _BookReportWritingState extends State { ], ), ), - const SizedBox(height: 20), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - children: [ - const Text('공개 여부: ', style: TextStyle(color: Colors.black)), - const SizedBox(width: 3), - GestureDetector( - onTap: () { - setState(() { - _isPublic = true; - }); - }, - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.black, - width: 0.5, - ), - borderRadius: BorderRadius.circular(5), - color: _isPublic ? Colors.green : Colors.white, - ), - padding: const EdgeInsets.symmetric(horizontal: 5), - child: const Text( - '공개', - style: TextStyle( - color: Colors.black, - ), - ), - ), - ), - const SizedBox(width: 10), - GestureDetector( - onTap: () { - setState(() { - _isPublic = false; - }); - }, - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.black, - width: 0.5, - ), - borderRadius: BorderRadius.circular(5), - color: !_isPublic ? Colors.green : Colors.white, - ), - padding: const EdgeInsets.symmetric(horizontal: 5), - child: const Text( - '비공개', - style: TextStyle( - color: Colors.black, - ), - ), - ), - ), - ], - ), - ), - const SizedBox(height: 15), + // SizedBox(height: 20.h), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 20), + // child: Row( + // children: [ + // const Text('공개 여부: ', style: TextStyle(color: Colors.black)), + // SizedBox(width: 3.w), + // GestureDetector( + // onTap: () { + // setState(() { + // _isPublic = true; + // }); + // }, + // child: Container( + // decoration: BoxDecoration( + // border: Border.all( + // color: Colors.black, + // width: 0.5.w, + // ), + // borderRadius: BorderRadius.circular(5), + // color: _isPublic ? Colors.green : Colors.white, + // ), + // padding: const EdgeInsets.symmetric(horizontal: 5), + // child: const Text( + // '공개', + // style: TextStyle( + // color: Colors.black, + // ), + // ), + // ), + // ), + // SizedBox(width: 10.w), + // GestureDetector( + // onTap: () { + // setState(() { + // _isPublic = false; + // }); + // }, + // child: Container( + // decoration: BoxDecoration( + // border: Border.all( + // color: Colors.black, + // width: 0.5.w, + // ), + // borderRadius: BorderRadius.circular(5), + // color: !_isPublic ? Colors.green : Colors.white, + // ), + // padding: const EdgeInsets.symmetric(horizontal: 5), + // child: const Text( + // '비공개', + // style: TextStyle( + // color: Colors.black, + // ), + // ), + // ), + // ), + // ], + // ), + // ), + SizedBox(height: 5.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Container( decoration: BoxDecoration( border: Border.all( - width: 1, + width: 1.w, color: const Color(0xFFA9AFB7), ), ), ), ), - const SizedBox(height: 15), + SizedBox(height: 15.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), - child: Expanded( - child: _buildTemplateUI(_template), + child: Row( + children: [ + Expanded( + child: _buildTemplateUI(_template), + ), + ], ), ), - const SizedBox(height: 15), + SizedBox(height: 15.h), ], ), ), @@ -408,16 +438,14 @@ class _BookReportWritingState extends State { selectedCategory.toString(), _questionController.text, ansnum, - _answerController1.text, - _answerController2.text, - _answerController3.text, - _answerController4.text, + _answerControllers[0].text, + _answerControllers[1].text, + _answerControllers[2].text, + _answerControllers[3].text, _startDate.toString(), _endDate.toString()); break; case "O/X": - print(selectedCategory); - print(_isOX); await quizCreate( token, widget.clubId, @@ -505,11 +533,11 @@ class _BookReportWritingState extends State { controller: _writingController, textAlign: TextAlign.center, maxLines: 10, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: '인용문을 작성해주세요', hintStyle: TextStyle( // 힌트 텍스트 정중앙 정렬 - height: 15, + height: 15.h, ), border: InputBorder.none, ), @@ -543,14 +571,13 @@ class _BookReportWritingState extends State { fontSize: 15, fontFamily: 'Noto Sans KR', fontWeight: FontWeight.w400, - height: 0, letterSpacing: -0.17, ), ), - const SizedBox(width: 3), + SizedBox(width: 3.w), SizedBox( - width: 121, - height: 22, + width: 121.w, + height: 22.h, child: DropdownButton( value: selectedCategory, onChanged: (String? newValue) { @@ -570,18 +597,21 @@ class _BookReportWritingState extends State { fontFamily: 'Noto Sans KR', fontWeight: FontWeight.w400, color: Colors.black, - height: 0, ), underline: Container(), ), ), ], ), - const SizedBox(height: 15), + SizedBox(height: 15.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 0), - child: Expanded( - child: _buildQuizUI(selectedCategory!), + child: Row( + children: [ + Expanded( + child: _buildQuizUI(selectedCategory!), + ), + ], ), ), ], @@ -597,20 +627,20 @@ class _BookReportWritingState extends State { return Column( children: [ SizedBox( - width: 350, - height: 190, + width: 350.w, + height: 150.h, child: Stack( children: [ Positioned( left: 0, top: 0, child: Container( - width: 350, - height: 190, + width: 350.w, + height: 150.h, decoration: BoxDecoration( color: const Color(0xFFE7FFEB), borderRadius: BorderRadius.circular(20), - border: Border.all(width: 1), + border: Border.all(width: 1.w), ), ), ), @@ -619,10 +649,10 @@ class _BookReportWritingState extends State { child: Row( children: [ const Text('Q: '), - const SizedBox(width: 10), + SizedBox(width: 10.w), Expanded( child: SizedBox( - width: _screenWidth * 0.7, + width: _screenWidth * 0.7.w, child: TextField( style: const TextStyle(fontSize: 14), controller: _questionController, @@ -644,10 +674,10 @@ class _BookReportWritingState extends State { child: Row( children: [ const Text('A: '), - const SizedBox(width: 10), + SizedBox(width: 10.w), Expanded( child: SizedBox( - width: _screenWidth * 0.7, + width: _screenWidth * 0.7.w, child: TextField( style: const TextStyle(fontSize: 14), controller: _answerController, @@ -667,20 +697,20 @@ class _BookReportWritingState extends State { return Column( children: [ SizedBox( - width: 350, - height: 190, + width: 350.w, + height: 150.h, child: Stack( children: [ Positioned( left: 0, top: 0, child: Container( - width: 350, - height: 190, + width: 350.w, + height: 150.h, decoration: BoxDecoration( color: const Color(0xFFE7FFEB), borderRadius: BorderRadius.circular(20), - border: Border.all(width: 1), + border: Border.all(width: 1.w), ), ), ), @@ -689,10 +719,10 @@ class _BookReportWritingState extends State { child: Row( children: [ const Text('Q: '), - const SizedBox(width: 10), + SizedBox(width: 10.w), Expanded( child: SizedBox( - width: _screenWidth * 0.7, + width: _screenWidth * 0.7.w, child: TextField( style: const TextStyle(fontSize: 14), controller: _questionController, @@ -709,10 +739,11 @@ class _BookReportWritingState extends State { ], ), ), - const SizedBox(height: 15), + SizedBox(height: 15.h), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: EdgeInsets.symmetric(horizontal: 20.w), child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( onPressed: () { @@ -724,14 +755,14 @@ class _BookReportWritingState extends State { foregroundColor: Colors.black, backgroundColor: _isOX ? Colors.green : Colors.white, elevation: 0, - side: const BorderSide(width: 0.5), + side: BorderSide(width: 0.5.w), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20)), minimumSize: const Size(140, 140), ), child: const Text('O'), ), - const SizedBox(width: 30), + SizedBox(width: 30.w), ElevatedButton( onPressed: () { setState(() { @@ -742,7 +773,7 @@ class _BookReportWritingState extends State { foregroundColor: Colors.black, backgroundColor: !_isOX ? Colors.green : Colors.white, elevation: 0, - side: const BorderSide(width: 0.5), + side: BorderSide(width: 0.5.w), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20)), minimumSize: const Size(140, 140), @@ -758,20 +789,20 @@ class _BookReportWritingState extends State { return Column( children: [ SizedBox( - width: 350, - height: 190, + width: 350.w, + height: 150.h, child: Stack( children: [ Positioned( left: 0, top: 0, child: Container( - width: 350, - height: 190, + width: 350.w, + height: 150.h, decoration: BoxDecoration( color: const Color(0xFFE7FFEB), borderRadius: BorderRadius.circular(20), - border: Border.all(width: 1), + border: Border.all(width: 1.w), ), ), ), @@ -780,10 +811,10 @@ class _BookReportWritingState extends State { child: Row( children: [ const Text('Q: '), - const SizedBox(width: 10), + SizedBox(width: 10.w), Expanded( child: SizedBox( - width: _screenWidth * 0.7, + width: _screenWidth * 0.7.w, child: TextField( style: const TextStyle(fontSize: 14), controller: _questionController, @@ -800,9 +831,9 @@ class _BookReportWritingState extends State { ], ), ), - const SizedBox(height: 15), + SizedBox(height: 15.h), Padding( - padding: const EdgeInsets.symmetric(horizontal: 0), + padding: EdgeInsets.symmetric(horizontal: 0.w), child: Column( children: [ for (int i = 0; i < 4; i++) @@ -831,31 +862,31 @@ class _BookReportWritingState extends State { color: Colors.grey), ), ), - const SizedBox(width: 5), + SizedBox(width: 5.w), Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors.black, - width: 0.5, + width: 0.5.w, ), color: _multipleanswer[i] ? Colors.green : Colors.white, ), - height: 24, + height: 24.h, alignment: Alignment.center, child: Row( children: [ - const SizedBox(width: 10), + SizedBox(width: 10.w), const Text('A: '), Expanded( child: SizedBox( - width: _screenWidth * 0.7, + width: _screenWidth * 0.7.w, child: TextField( style: const TextStyle(fontSize: 10), - controller: _answerController1, + controller: _answerControllers[i], decoration: const InputDecoration( hintText: '답을 입력해주세요.', contentPadding: EdgeInsets.all(10), diff --git a/frontend/lib/screens/home/group/group_screen.dart b/frontend/lib/screens/home/group/group_screen.dart index 19bab20155..0e7d83506a 100644 --- a/frontend/lib/screens/home/group/group_screen.dart +++ b/frontend/lib/screens/home/group/group_screen.dart @@ -9,7 +9,6 @@ import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; -// final List Thema = ['역사', '경제', '종교', '사회', '시집']; final List realThema = [ '예술과 문학', '금융/경제/투자', @@ -25,8 +24,8 @@ final List Thema = [ '자기계발', '역사', '취미', + '내 모임', '추천', - '내 모임' ]; final List ThemaIcon = [ Icons.palette_outlined, @@ -35,16 +34,11 @@ final List ThemaIcon = [ Icons.self_improvement, Icons.history_edu, Icons.hail_outlined, + // Icons.group + Icons.collections_bookmark_outlined, // Icons.local_play_outlined, Icons.memory, - // Icons.group - Icons.collections_bookmark_outlined - - ]; -//수정 전 - 역사, 경제, 종교, 사회, 시집 -//수정 - 예술과 문학, 금융/경제/투자, 과학과 철학, 자기개발, 역사, 취미 -//삭제 - 시집 List> _GroupList = [[], [], [], [], [], [], [], []]; class GroupScreen extends StatefulWidget { @@ -63,8 +57,8 @@ class _GroupState extends State { Future _makeGroupList() async { _GroupList = await groupSerachforTopic(realThema); + await _initUserState(); _GroupList.add([]); //추천 받아오기 - _initUserState(); } @override @@ -126,7 +120,7 @@ class _GroupState extends State { int startIndex = i * 4; int endIndex = (i + 1) * 4; if (endIndex > Thema.length) endIndex = Thema.length; - + List rowButtons = []; for (int j = startIndex; j < endIndex; j++) { rowButtons.add( @@ -145,7 +139,6 @@ class _GroupState extends State { }, icon: Icon( ThemaIcon[j], - // size:, ), ), Text( @@ -197,9 +190,7 @@ class _GroupState extends State { ], ), SizedBox( - height: (index != 7) - ? ScreenUtil().setHeight(10) - : ScreenUtil().setHeight(500), + height: (index != 7) ? 10.h : 500.h, ), ], ); @@ -212,7 +203,6 @@ class _GroupState extends State { builder: (context, child) => Scaffold( appBar: AppBar( scrolledUnderElevation: 0, - // toolbarHeight: 35.h, backgroundColor: const Color(0xFF0E9913), title: const Text( '모임', @@ -225,42 +215,49 @@ class _GroupState extends State { ), centerTitle: true, ), - floatingActionButton: FloatingActionButton( - onPressed: () { - context.push('/group_make').then((value) async { - if (value == true) { - _isLoading = true; - _loadData(); - _makeGroupList(); - } - }); - }, - shape: const CircleBorder(), - child: const Icon(Icons.add), - ), - body: _isLoading - ? const Center( - child: CircularProgressIndicator(), // 로딩 애니매이션 + floatingActionButton: (userInfo != null) + ? FloatingActionButton( + onPressed: () { + context.push('/group_make').then((value) async { + if (value == true) { + _isLoading = true; + _loadData(); + _makeGroupList(); + } + }); + }, + shape: const CircleBorder(), + child: const Icon(Icons.add), ) - : Center( - child: Column( - children: [ - Container( - height: 150.h, - width: 390.w, - decoration: const BoxDecoration( - color: Color(0xFF0E9913), - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(50), - bottomRight: Radius.circular(50), - ), - ), - child: SizedBox( - width: 390.w, - child: _ThemaList(context, Thema), - ), - ), - Expanded( + : null, + body: Center( + child: Column( + children: [ + Container( + height: 150.h, + width: 390.w, + decoration: BoxDecoration( + color: const Color(0xFF0E9913), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(50.r), + bottomRight: Radius.circular(50.r), + ), + ), + child: SizedBox( + width: 390.w, + height: 90.h, + child: _ThemaList(context, Thema), + ), + ), + _isLoading + ? Center( + child: Padding( + padding: EdgeInsets.symmetric( + vertical: 100.h), + child: const CircularProgressIndicator(), + ), // 로딩 애니매이션 + ) + : Expanded( child: RefreshIndicator( onRefresh: () async { setState(() { @@ -286,18 +283,18 @@ class _GroupState extends State { groupList(4), //5 groupList(5), - //추천 - groupList(6), //내 모임 + groupList(6), + //추천 groupList(7), ], ), ), ), ), - ], - ), - ), + ], + ), + ), ), ); } diff --git a/frontend/lib/screens/home/group/group_screen_util.dart b/frontend/lib/screens/home/group/group_screen_util.dart index 73109d9f6a..a113050ec0 100644 --- a/frontend/lib/screens/home/group/group_screen_util.dart +++ b/frontend/lib/screens/home/group/group_screen_util.dart @@ -55,13 +55,13 @@ class _GroupListItemState extends State { return Row( children: [ Ink( - width: ScreenUtil().setWidth(170), - height: ScreenUtil().setHeight(95), + width: 170.w, + height: 95.h, decoration: ShapeDecoration( color: Colors.white, shape: RoundedRectangleBorder( - side: const BorderSide( - width: 2, + side: BorderSide( + width: 2.w, strokeAlign: BorderSide.strokeAlignOutside, color: Color(0xFFEEF1F4), ), @@ -127,7 +127,7 @@ class _GroupListItemState extends State { Expanded( child: Padding( padding: EdgeInsets.symmetric( - horizontal: ScreenUtil().setWidth(7), + horizontal: 7.w, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -135,7 +135,7 @@ class _GroupListItemState extends State { children: [ Text('주제:${widget.data['topic']}', style: TextStyle(fontSize: 13.sp)), - SizedBox(height: ScreenUtil().setHeight(4)), + SizedBox(height: 4.h), Text( widget.data['name'], style: TextStyle( @@ -143,13 +143,13 @@ class _GroupListItemState extends State { overflow: TextOverflow.ellipsis, ), SizedBox( - height: ScreenUtil().setHeight(3), + height: 3.h, ), Row( children: [ Icon( Icons.people, - size: ScreenUtil().setWidth(13), + size: 13.w, color: (widget.data['memberCnt'] == widget.data['maximum']) ? Colors.red @@ -168,7 +168,7 @@ class _GroupListItemState extends State { ], ), SizedBox( - height: ScreenUtil().setHeight(3), + height: 3.h, ), Text( (widget.data['publicstatus'] == 'PUBLIC') diff --git a/frontend/lib/screens/home/group/in_group/group_info_screen.dart b/frontend/lib/screens/home/group/in_group/group_info_screen.dart index 8d4aee2df6..3a09e677d1 100644 --- a/frontend/lib/screens/home/group/in_group/group_info_screen.dart +++ b/frontend/lib/screens/home/group/in_group/group_info_screen.dart @@ -224,9 +224,9 @@ class _GroupInfoState extends State { ), ElevatedButton( - onPressed: (){ + onPressed: () { context.push('/voicecall'); - }, + }, child: Text('test voice'), ), ], @@ -484,6 +484,8 @@ class _GroupInfoState extends State { borderRadius: BorderRadius.circular(25), ), child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( onPressed: () { @@ -511,12 +513,16 @@ class _GroupInfoState extends State { ), SizedBox( width: 260.w, + height: 40.h, child: TextField( controller: _textControllers, - decoration: const InputDecoration( - hintText: '대표책을 검색해주세요.', + decoration: InputDecoration( + hintText: (clubData['book'] == null)?'대표책을 설정해주세요.':'대표책을 검색해주세요.', border: InputBorder.none, ), + style: TextStyle( + fontSize: 18.sp, + ), onChanged: (value) { setState(() {}); }, @@ -645,8 +651,8 @@ class _GroupInfoState extends State { decoration: ShapeDecoration( color: Colors.white, shape: RoundedRectangleBorder( - side: const BorderSide( - width: 2, + side: BorderSide( + width: 2.w, strokeAlign: BorderSide.strokeAlignOutside, color: Color(0xFFEEF1F4), ), @@ -675,13 +681,13 @@ class _GroupInfoState extends State { } }, borderRadius: BorderRadius.circular(15), - child: const Center( + child: Center( child: Text( '가입하기', textAlign: TextAlign.center, style: TextStyle( color: Colors.black, - fontSize: 15, + fontSize: 15.sp, fontFamily: 'Noto Sans KR', fontWeight: FontWeight.w700, ), @@ -785,6 +791,7 @@ class _GroupInfoState extends State { context.push('/homework_list', extra: { "clubId": clubData['id'], "managerId": clubData['managerId'], + "bookInfo": clubData['book'], }).then((value) async { await _clubGetInfo(); await _clubGetAssign(); @@ -988,11 +995,11 @@ class _GroupInfoState extends State { cnt++; tasks.add(_buildTaskEntry(context, post, true)); tasks.add(Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 1, + width: 1.w, ), ), ), @@ -1014,11 +1021,11 @@ class _GroupInfoState extends State { cnt++; tasks.add(_buildTaskEntry(context, post, true)); tasks.add(Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 1, + width: 1.w, ), ), ), @@ -1043,11 +1050,11 @@ class _GroupInfoState extends State { cnt++; tasks.add(_buildTaskEntry(context, post, false)); tasks.add(Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 1, + width: 1.w, ), ), ), diff --git a/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart b/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart index 4c6423672e..3d435715ce 100644 --- a/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart +++ b/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart @@ -65,7 +65,7 @@ class _GroupBookSelectState extends State { child: Column( children: [ SizedBox( - height: ScreenUtil().setHeight(5), + height: 5.h, ), if(BookData.isNotEmpty) for (int i = 0; i < BookData.length; i++) diff --git a/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart index 50a209ec4d..a6ff833431 100644 --- a/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart @@ -10,11 +10,13 @@ import 'package:provider/provider.dart'; class HomeworkListScreen extends StatefulWidget { final String managerId; final int clubId; + final dynamic bookInfo; const HomeworkListScreen({ super.key, required this.managerId, required this.clubId, + required this.bookInfo, }); @override @@ -23,6 +25,7 @@ class HomeworkListScreen extends StatefulWidget { class _HomeworkListScreenState extends State { List posts = []; + bool isBook = true; var secureStorage; var id; var token; @@ -46,10 +49,19 @@ class _HomeworkListScreenState extends State { }); } + void checkBook(dynamic Book){ + if(Book == null){ + setState(() { + isBook = false; + }); + } + } + @override void initState() { super.initState(); secureStorage = Provider.of(context, listen: false); + checkBook(widget.bookInfo); initUserInfo(); updatePostList(); } @@ -73,7 +85,7 @@ class _HomeworkListScreenState extends State { ), centerTitle: true, ), - floatingActionButton: (id == widget.managerId) + floatingActionButton: (id == widget.managerId && isBook) ? FloatingActionButton( onPressed: () { context @@ -134,11 +146,11 @@ class _HomeworkListScreenState extends State { ), ), Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 0.5, + width: 0.5.w, ), ), ), diff --git a/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart b/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart index 384e5b485b..c33e555fe0 100644 --- a/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart @@ -23,10 +23,12 @@ class HomeworkMemberlistScreen extends StatefulWidget { class _HomeworkMemberistState extends State { List HwList = []; + bool LimitCheck = true; var secureStorage; var id; var token; var HW; + var isbn; Future initUserInfo() async { var _id = await secureStorage.readData("id"); @@ -39,6 +41,7 @@ class _HomeworkMemberistState extends State { Future updateHwList() async { var _posts = await getAssign(widget.clubId); + var _club = await groupSerachforId(widget.clubId); var _HwList, _hw; for (Map hw in _posts) { if (hw['id'] == widget.post['id']) { @@ -50,6 +53,7 @@ class _HomeworkMemberistState extends State { setState(() { HW = _hw; HwList = _HwList; + isbn = _club['book']['isbn']; }); } @@ -68,10 +72,23 @@ class _HomeworkMemberistState extends State { } } + void dateCheck(String date) { + DateTime limitDate = DateTime.parse(date); + DateTime now = DateTime.now(); + + if (limitDate.isBefore(now)) { + setState(() { + LimitCheck = false; + }); + } + } + @override void initState() { super.initState(); secureStorage = Provider.of(context, listen: false); + dateCheck(widget.post['endDate']); + print(widget.post); initUserInfo(); updateHwList(); } @@ -95,20 +112,27 @@ class _HomeworkMemberistState extends State { ), centerTitle: true, ), - floatingActionButton: FloatingActionButton( - onPressed: () { - //퀴즈 999, 인용구 998, 한줄평 997, 독후감 996 - context.push("/bookreport_writing", extra: { - "index": typeCheck(HW), - "clubId": widget.clubId, - "asId": HW['id'], - }).then((value) async { - updateHwList(); - }); - }, - shape: const CircleBorder(), - child: const Icon(Icons.add), - ), + floatingActionButton: (LimitCheck) + ? FloatingActionButton( + onPressed: () { + //퀴즈 999, 인용구 998, 한줄평 997, 독후감 996 + context.push("/bookreport_writing", extra: { + "index": typeCheck(HW), + "clubId": widget.clubId, + "asId": HW['id'], + "isbn": isbn, + "dateInfo": { + "startDate": widget.post['startDate'], + "endDate": widget.post['endDate'] + } + }).then((value) async { + updateHwList(); + }); + }, + shape: const CircleBorder(), + child: const Icon(Icons.add), + ) + : null, body: SingleChildScrollView( child: Column( children: _buildHWListView(HwList), @@ -153,11 +177,11 @@ class _HomeworkMemberistState extends State { ), ), Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 0.5, + width: 0.5.w, ), ), ), diff --git a/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart index af75329a93..00736fcadf 100644 --- a/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart @@ -118,11 +118,11 @@ class _NoticeListScreenState extends State { ), ), Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 0.5, + width: 0.5.w, ), ), ), diff --git a/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart index 7d4aa84dd5..8b06463943 100644 --- a/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart @@ -126,11 +126,11 @@ class _PostListScreenState extends State { ), ), Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey, - width: 0.5, + width: 0.5.w, ), ), ), diff --git a/frontend/lib/screens/home/group/in_group/post/post_screen.dart b/frontend/lib/screens/home/group/in_group/post/post_screen.dart index d26a12dfdf..f45e73ece1 100644 --- a/frontend/lib/screens/home/group/in_group/post/post_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/post_screen.dart @@ -107,7 +107,7 @@ class _PostScreenState extends State { fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 16), + SizedBox(height: 16.h), Text( data['body'], style: const TextStyle( @@ -128,10 +128,10 @@ class _PostScreenState extends State { ListTile( title: Text(comments[index]['writer']), subtitle: Text(comments[index]['body'])), - const Divider( - height: 2, // 선의 높이를 조절할 수 있습니다. - thickness: 0.2, // 선의 두께를 조절할 수 있습니다. - color: Colors.grey, // 선의 색상을 설정할 수 있습니다. + Divider( + height: 2.h, + thickness: 0.2, + color: Colors.grey, ), ], ); @@ -140,11 +140,11 @@ class _PostScreenState extends State { ), //댓글 입력창 Container( - padding: const EdgeInsets.only( - left: 16, - right: 16, - top: 8, - bottom: 30, + padding: EdgeInsets.only( + left: 16.w, + right: 16.w, + top: 8.h, + bottom: 30.h, ), decoration: BoxDecoration( border: Border( @@ -154,28 +154,30 @@ class _PostScreenState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - SizedBox( - width: 350, - child: TextField( - controller: _commentController, - decoration: InputDecoration( - hintText: ' 댓글을 입력하세요...', - border: InputBorder.none, - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: - const BorderSide(color: Color(0xFF0E9913)), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: - const BorderSide(color: Colors.blueGrey), + Expanded( + child: SizedBox( + width: 350.w, + child: TextField( + controller: _commentController, + decoration: InputDecoration( + hintText: ' 댓글을 입력하세요...', + border: InputBorder.none, + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: + const BorderSide(color: Color(0xFF0E9913)), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: + const BorderSide(color: Colors.blueGrey), + ), ), + maxLines: null, + onChanged: (text) { + setState(() {}); + }, ), - maxLines: null, - onChanged: (text) { - setState(() {}); - }, ), ), IconButton( diff --git a/frontend/lib/screens/home/group/in_group/voicecall/voice_class.dart b/frontend/lib/screens/home/group/in_group/voicecall/voice_class.dart index 52cfa95586..d4c5304e75 100644 --- a/frontend/lib/screens/home/group/in_group/voicecall/voice_class.dart +++ b/frontend/lib/screens/home/group/in_group/voicecall/voice_class.dart @@ -1,8 +1,8 @@ import "package:agora_rtc_engine/agora_rtc_engine.dart"; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:agora_rtm/agora_rtm.dart'; +import 'package:flutter/widgets.dart'; import 'package:frontend/secret.dart'; +import 'package:frontend/http.dart'; import 'package:permission_handler/permission_handler.dart'; class VoiceCallScreen extends StatefulWidget { @@ -13,12 +13,21 @@ class VoiceCallScreen extends StatefulWidget { } class _VoiceCallState extends State { + TextEditingController _channelName = TextEditingController(); String channelName = 'testChannel'; int uid = 0; int? _remoteUid; bool _localUserJoined = false; late RtcEngine _engine; + final GlobalKey scaffoldMessengerKey = + GlobalKey(); + + showMessage(String message) { + scaffoldMessengerKey.currentState + ?.showSnackBar(SnackBar(content: Text(message))); + } + @override void initState() { super.initState(); @@ -38,26 +47,26 @@ class _VoiceCallState extends State { _engine.registerEventHandler( RtcEngineEventHandler( onJoinChannelSuccess: (RtcConnection connection, int elapsed) { - debugPrint("local user ${connection.localUid} joined"); + showMessage("local user ${connection.localUid} joined"); setState(() { _localUserJoined = true; }); }, onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) { - debugPrint("remote user $remoteUid joined"); + showMessage("remote user $remoteUid joined"); setState(() { _remoteUid = remoteUid; }); }, onUserOffline: (RtcConnection connection, int remoteUid, UserOfflineReasonType reason) { - debugPrint("remote user $remoteUid left channel"); + showMessage("remote user $remoteUid left channel"); setState(() { _remoteUid = null; }); }, onTokenPrivilegeWillExpire: (RtcConnection connection, String token) { - debugPrint( + showMessage( '[onTokenPrivilegeWillExpire] connection: ${connection.toJson()}, token: $token'); }, ), @@ -65,19 +74,19 @@ class _VoiceCallState extends State { // await _engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster); // await _engine.enableVideo(); - await _engine.enableAudio(); - await _engine.setEnableSpeakerphone(true); - await _engine.startPreview(); - - await _engine.joinChannel( - token: Agora_Token, - channelId: channelName, - uid: uid, - options: const ChannelMediaOptions( - clientRoleType: ClientRoleType.clientRoleBroadcaster, - channelProfile: ChannelProfileType.channelProfileCommunication, - ), - ); + // await _engine.enableAudio();s + // await _engine.setEnableSpeakerphone(true); + // await _engine.startPreview(); + + // await _engine.joinChannel( + // token: Agora_Token, + // channelId: channelName, + // uid: uid, + // options: const ChannelMediaOptions( + // clientRoleType: ClientRoleType.clientRoleBroadcaster, + // channelProfile: ChannelProfileType.channelProfileLiveBroadcasting, + // ), + // ); } void join() async { @@ -93,9 +102,9 @@ class _VoiceCallState extends State { } @override - void dispose() { + void dispose() async { + await _engine.leaveChannel(); super.dispose(); - leave(); } void leave() { @@ -120,30 +129,82 @@ class _VoiceCallState extends State { body: Stack( children: [ Center( - child: _remoteVideo(), + child: _status(), ), - Align( - alignment: Alignment.topLeft, - child: SizedBox( - width: 100, - height: 150, - child: Center( - child: _localUserJoined - ? AgoraVideoView( - controller: VideoViewController( - rtcEngine: _engine, - canvas: const VideoCanvas(uid: 0), - ), - ) - : const CircularProgressIndicator(), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(20.0), + child: TextField( + controller: _channelName, + + ), ), - ), + Row( + children: [ + Expanded( + child: ElevatedButton( + child: const Text("Join"), + onPressed: () => {join()}, + ), + ), + const SizedBox(width: 10), + Expanded( + child: ElevatedButton( + child: const Text("Leave"), + onPressed: () => {leave()}, + ), + ), + const SizedBox(width: 10), + Expanded( + child: ElevatedButton( + child: const Text("token"), + onPressed: () async{ + await agoraToken(uid.toString(), channelName); + }, + ), + ), + ], + ), + ], ), + // Align( + // alignment: Alignment.topLeft, + // child: SizedBox( + // width: 100, + // height: 150, + // child: Center( + // child: _localUserJoined + // ? AgoraVideoView( + // controller: VideoViewController( + // rtcEngine: _engine, + // canvas: const VideoCanvas(uid: 0), + // ), + // ) + // : const CircularProgressIndicator(), + // ), + // ), + // ), ], ), ); } + Widget _status() { + String statusText; + + if (!_localUserJoined) { + statusText = 'Join a channel'; + } else if (_remoteUid == null) { + statusText = 'Waiting for a remote user to join...'; + } else { + statusText = 'Connected to remote user, uid:$_remoteUid'; + } + return Text( + statusText, + ); + } + Widget _remoteVideo() { if (_remoteUid != null) { return AgoraVideoView( diff --git a/frontend/lib/screens/home/search/search_screen.dart b/frontend/lib/screens/home/search/search_screen.dart index a19fe3eabe..e00148a4d7 100644 --- a/frontend/lib/screens/home/search/search_screen.dart +++ b/frontend/lib/screens/home/search/search_screen.dart @@ -117,7 +117,7 @@ class _SearchState extends State { children: [ Container( width: double.infinity, - height: ScreenUtil().setHeight(120), + height: 120.h, decoration: const BoxDecoration( color: Color(0xFF0E9913), borderRadius: BorderRadius.only( @@ -131,12 +131,14 @@ class _SearchState extends State { margin: EdgeInsets.only(top: 20.h, left: 20.w, right: 20.w), padding: EdgeInsets.only(left: 10.w), - height: ScreenUtil().setHeight(40), + height: 40.h, decoration: BoxDecoration( color: const Color(0xFFF2F2F2), borderRadius: BorderRadius.circular(25), ), child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( onPressed: () { @@ -154,13 +156,17 @@ class _SearchState extends State { icon: const Icon(Icons.search), ), SizedBox( - width: ScreenUtil().setWidth(260), + width: 260.w, + height: 40.h, child: TextField( controller: _textControllers, decoration: const InputDecoration( hintText: '책 제목을 검색해주세요', border: InputBorder.none, ), + style: TextStyle( + fontSize: 18.sp, + ), onChanged: (value) { setState(() {}); }, @@ -197,7 +203,7 @@ class _SearchState extends State { controller: _scrollController, child: Column( children: [ - if (check && GroupData.isEmpty) Text("검색 결과가 없습니다"), + if (check && GroupData.isEmpty) const Text("모임 검색 결과가 없습니다"), ElevatedButton( onPressed: () async { dynamic userInfo = diff --git a/frontend/lib/screens/home/search/search_screen_util.dart b/frontend/lib/screens/home/search/search_screen_util.dart index 641ed5a39c..c0abe84bce 100644 --- a/frontend/lib/screens/home/search/search_screen_util.dart +++ b/frontend/lib/screens/home/search/search_screen_util.dart @@ -36,20 +36,20 @@ class _SearchListItemState extends State { return Column( children: [ Ink( - width: ScreenUtil().setWidth(370), - height: ScreenUtil().setHeight(105), + width: 370.w, + height: 105.h, child: InkWell( onTap: () async{ switch (widget.type) { case "search": var result = await bookAdd(widget.data); - print(result); - if(result == "도서 추가 완료"){ // 새로운 책 + // print(result); + // if(result == "도서 추가 완료"){ // 새로운 책 - } - else{ //이미 있는 책 - await getBookInfo(widget.data['isbn']); - } + // } + // else{ //이미 있는 책 + // await getBookInfo(widget.data['isbn']); + // } context.push( '/book_info', extra: widget.data, @@ -69,8 +69,8 @@ class _SearchListItemState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - width: ScreenUtil().setWidth(80), - height: ScreenUtil().setHeight(105), + width: 80.w, + height: 105.h, decoration: ShapeDecoration( image: DecorationImage( image: NetworkImage(widget.data['image']), @@ -81,27 +81,26 @@ class _SearchListItemState extends State { ), ), SizedBox( - width: ScreenUtil().setWidth(5), + width: 5.w, ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - width: ScreenUtil().setWidth(280), + width: 280.w, child: Text( - (widget.data['title'].length > 100)?widget.data['title'].substring(0,100) + '...':widget.data['title'], + widget.data['title'], style: TextStyle( color: Colors.black, - fontSize: - (widget.data['title'].length < 50) ? 20 : - (widget.data['title'].length < 100)? 15 : 12, + fontSize: 20.sp, fontFamily: 'Noto Sans KR', fontWeight: FontWeight.w700, ), + overflow: TextOverflow.ellipsis, ), ), SizedBox( - height: ScreenUtil().setHeight(5), + height: 5.h, ), Container( width: ScreenUtil().setWidth(280), @@ -123,7 +122,7 @@ class _SearchListItemState extends State { ), ), SizedBox( - height: ScreenUtil().setHeight(10), + height: 10.h, ) ], ); diff --git a/frontend/lib/screens/login/login_screen.dart b/frontend/lib/screens/login/login_screen.dart deleted file mode 100644 index 4e1adbd7bb..0000000000 --- a/frontend/lib/screens/login/login_screen.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter/material.dart'; - -class LoginScreen extends StatelessWidget { - const LoginScreen({super.key}); - - @override - Widget build(BuildContext context) { - return const Center( - - ); - } -} From b0f735f0b51444d368943b2d320700549b4f6059 Mon Sep 17 00:00:00 2001 From: choichangyeon Date: Sun, 19 May 2024 20:36:43 +0900 Subject: [PATCH 2/4] checkPoint --- frontend/lib/http.dart | 39 ++- .../lib/screens/book/book_content_screen.dart | 165 ++++++--- .../lib/screens/book/book_info_screen.dart | 197 ++++++----- .../bookreport/bookreport_viewing_screen.dart | 174 +++++++--- .../bookreport/bookreport_writing_screen.dart | 21 +- .../lib/screens/home/group/group_screen.dart | 136 +++++--- .../screens/home/group/group_screen_util.dart | 52 +-- .../group/in_group/group_info_screen.dart | 313 ++++++++++-------- .../in_group/groupbook_select_screen.dart | 34 +- .../in_group/post/homework_list_screen.dart | 179 ++++++++-- .../post/homework_memberlist_screen.dart | 88 ++++- .../post/make_post/homework_make_screen.dart | 46 ++- .../post/make_post/post_make_screen.dart | 73 ++-- .../in_group/post/notice_list_screen.dart | 105 +++++- .../group/in_group/post/post_list_screen.dart | 118 +++++-- .../home/group/in_group/post/post_screen.dart | 104 ++++-- .../group/make_group/group_make_screen.dart | 140 +++++--- .../screens/home/search/search_screen.dart | 50 ++- .../home/search/search_screen_util.dart | 26 +- .../screens/home/shorts/shorts_screen.dart | 8 +- 20 files changed, 1426 insertions(+), 642 deletions(-) diff --git a/frontend/lib/http.dart b/frontend/lib/http.dart index 664447d53d..afdcb2b416 100644 --- a/frontend/lib/http.dart +++ b/frontend/lib/http.dart @@ -46,8 +46,9 @@ Future> SearchBook(String SearchString) async { "X-Naver-Client-Secret": NaverSecret, }); final data = json.decode(utf8.decode(res.bodyBytes)); + // print(data); while (iter != 100) { - if (data['total'] <= iter) { + if (data['total'] <= iter) { break; } else if (data['items'][iter]['title'].toString().contains('시리즈')) { } else if (data['items'][iter]['title'].toString().contains('세트')) { @@ -111,7 +112,7 @@ Future login(String email) async { }), ); final data = json.decode(utf8.decode(res.bodyBytes)); - + // print(data); return data; } @@ -132,7 +133,7 @@ Future getUserInfo(String id, String token) async { //모임 목록 가져오기(주제를 기반으로)› Future>> groupSerachforTopic(List topic) async { - List> groupList = [[], [], [], [], [], []]; + List> groupList = [[], [], [], [], [], [], [], []]; for (int i = 0; i < topic.length; i++) { String temp = topic[i]; var address = Uri.parse(BASE_URL + "/club/search/topic?topic=$temp"); @@ -359,7 +360,7 @@ Future> bookcontentLoad(String ISBN, String content) async { for (int i = 0; i < data.length; i++) { contentList.add(data[i]); } - print(data); + // print(data); return contentList; } @@ -676,3 +677,33 @@ Future addBooksToLibrary( // print(data); return data; } + + +// 추천 리스트 받아오기(로그인) +Future getRecommend(String token) async { + var address = Uri.parse(BASE_URL + "/rec/member"); + http.Response res = await http.get( + address, + headers: { + "Content-Type": "application/json", + "Authorization": 'Bearer $token', + }, + ); + final data = json.decode(utf8.decode(res.bodyBytes)); + // print(data); + return data; +} + +// 추천 리스트 받아오기(비로그인) +Future getRecommendAnony() async { + var address = Uri.parse(BASE_URL + "/rec/anonymous"); + http.Response res = await http.get( + address, + headers: { + "Content-Type": "application/json", + }, + ); + final data = json.decode(utf8.decode(res.bodyBytes)); + // print(data); + return data; +} \ No newline at end of file diff --git a/frontend/lib/screens/book/book_content_screen.dart b/frontend/lib/screens/book/book_content_screen.dart index 1e50add478..4188e2c2cb 100644 --- a/frontend/lib/screens/book/book_content_screen.dart +++ b/frontend/lib/screens/book/book_content_screen.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; +import 'package:intl/intl.dart'; //책의 컨텐츠 목록 @@ -35,7 +36,6 @@ class _BookContentState extends State { setState(() { id = _id; token = _token; - print(id); }); } @@ -77,6 +77,8 @@ class _BookContentState extends State { initUserInfo(); setState(() { posts = widget.posts; + print(posts); + print(widget.type); }); // updatePostList(); } @@ -90,34 +92,31 @@ class _BookContentState extends State { scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), title: Text( - widget.type, - style: const TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + contentType(widget.type), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), - floatingActionButton: (id != null && token != null)?FloatingActionButton( - onPressed: () { - context.push( - '/bookreport_writing', - extra: { - "index": typeCheck(widget.type), - "clubId": null, - "asId": null, - "isbn": widget.isbn, - "dateInfo":null, - }, - ).then((result) async { - updatePostList(); - }); - }, - shape: const CircleBorder(), - child: const Icon(Icons.add), - ):null, + floatingActionButton: (id != null && token != null) + ? FloatingActionButton( + onPressed: () { + context.push( + '/bookreport_writing', + extra: { + "index": typeCheck(widget.type), + "clubId": null, + "asId": null, + "isbn": widget.isbn, + "dateInfo": null, + }, + ).then((result) async { + updatePostList(); + }); + }, + shape: const CircleBorder(), + child: const Icon(Icons.add), + ) + : null, body: SingleChildScrollView( child: Column( children: _buildPostListView(posts), @@ -145,19 +144,60 @@ class _BookContentState extends State { extra: post, ); }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - (widget.type == "Quiz") - ? post['description'] - : post['title'], - style: const TextStyle( - fontSize: 20, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.bold, - letterSpacing: -0.17, + // child: Padding( + // padding: const EdgeInsets.all(8.0), + // child: Text( + // (widget.type == "Quiz") + // ? post['description'] + // : post['title'], + // style: textStyle(20, null, true), + // ), + // ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + (widget.type == "Quiz") + ? post['description'] + : post['title'], + style: textStyle(18, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + "작성자 ${post['writer']}", + style: textStyle(12, null, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + (widget.type != 'Quiz') + ? contentType(post['type']) + : quizType(post['type']), + style: textStyle(13, null, false), + ), + ), + ], + ), + ], ), - ), + ], ), ), ), @@ -179,3 +219,52 @@ class _BookContentState extends State { return items; } } + +String contentType(String type) { + switch (type) { + case 'Review': + return '독후감'; + case 'ShortReview': + return '한줄평'; + case 'Quotation': + return '인용구'; + default: + return '퀴즈'; + } +} + +String quizType(String quiz) { + switch (quiz) { + case 'ShortAnswer': + return '단답형'; + case 'MultipleChoice': + return '객관식'; + case 'OX': + return 'O/X'; + default: + return ''; + } +} + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + + return formattedDate; +} + +bool limitDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + DateTime nowTime = DateTime.now(); + + return dateTime.isAfter(nowTime); +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/book/book_info_screen.dart b/frontend/lib/screens/book/book_info_screen.dart index 69f460f3c1..85c3800a77 100644 --- a/frontend/lib/screens/book/book_info_screen.dart +++ b/frontend/lib/screens/book/book_info_screen.dart @@ -1,13 +1,14 @@ -import 'package:agora_rtc_engine/agora_rtc_engine.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:frontend/screens/home/bookreport/bookreport_viewing_screen.dart'; import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; import 'dart:async'; +import 'package:intl/intl.dart'; class BookInfoScreen extends StatefulWidget { final Map data; //책 정보 @@ -53,8 +54,8 @@ class _BookInfoState extends State { child: Text( type[i], style: TextStyle( - color: _selectType[i] ? Color(0xFF0E9913) : Colors.black, - fontSize: 16, + color: _selectType[i] ? const Color(0xFF0E9913) : Colors.black, + fontSize: 16.sp, fontFamily: 'Noto Sans KR', fontWeight: FontWeight.w700, ), @@ -78,10 +79,10 @@ class _BookInfoState extends State { shortreview = _shortreview; quotation = _quotation; quiz = _quiz; - print(review); - print(shortreview); - print(quotation); - print(quiz); + // print(review); + // print(shortreview); + // print(quotation); + // print(quiz); }); } @@ -129,15 +130,7 @@ class _BookInfoState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: Text( - widget.data['title'], - style: const TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), - ), + title: Text("책 정보", style: textStyle(22, Colors.white, true)), centerTitle: true, ), body: _isLoading @@ -156,55 +149,67 @@ class _BookInfoState extends State { bottomRight: Radius.circular(50), ), ), - child: Container( - child: Row( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Container( - width: ScreenUtil().setWidth(80), - height: ScreenUtil().setHeight(105), - decoration: ShapeDecoration( - image: DecorationImage( - image: NetworkImage(widget.data['image']), - fit: BoxFit.fill, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(3)), + child: Row( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20.0), + child: Container( + width: ScreenUtil().setWidth(80), + height: ScreenUtil().setHeight(105), + decoration: ShapeDecoration( + image: DecorationImage( + image: NetworkImage(widget.data['image']), + fit: BoxFit.fill, ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3)), ), ), - ], - ), - Expanded( - child: Padding( - padding: EdgeInsets.only( - left: 10.w, - right: 20.w, - bottom: 20.h, - ), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Container( - child: Text( + ), + ], + ), + Expanded( + child: Padding( + padding: EdgeInsets.only( + left: 10.w, + right: 20.w, + bottom: 20.h, + ), + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.data['title'], + style: textStyle(20, Colors.white, true), + overflow: TextOverflow.ellipsis, + ), + SizedBox( + height: 5.h, + ), + Text( + "${(widget.data['author'] == '') ? '저자 미상' : widget.data['author']} | ${widget.data['publisher']}", + style: textStyle(14, Colors.white, true), + overflow: TextOverflow.ellipsis, + ), + SizedBox( + height: 5.h, + ), + Text( widget.data['description'], - style: const TextStyle( - color: Colors.black, - fontSize: 12, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(13, Colors.white, false), ), - ), + ], ), ), ), - ], - ), + ), + ], ), ), Expanded( @@ -213,7 +218,7 @@ class _BookInfoState extends State { child: Column( children: [ SizedBox( - height: 30, + height: 30.h, ), Ink( width: 350.w, @@ -245,19 +250,14 @@ class _BookInfoState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Padding( - padding: EdgeInsets.only( + Padding( + padding: const EdgeInsets.only( left: 5.0, top: 3.0, ), child: Text( '퀴즈', - style: TextStyle( - color: Colors.black, - fontSize: 16, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(16, null, true), ), ), SizedBox( @@ -276,7 +276,7 @@ class _BookInfoState extends State { ), ), SizedBox( - height: 30, + height: 30.h, ), Column( children: [ @@ -385,11 +385,11 @@ class _BookInfoState extends State { break; } temp = quiz; - // temp.sort((a, b) { - // DateTime dateTimeA = DateTime.parse(a["endDate"]); - // DateTime dateTimeB = DateTime.parse(b["endDate"]); - // return dateTimeB.compareTo(dateTimeA); - // }); + temp.sort((a, b) { + DateTime dateTimeA = DateTime.parse(a["endDate"]); + DateTime dateTimeB = DateTime.parse(b["endDate"]); + return dateTimeB.compareTo(dateTimeA); + }); for (var post in temp) { if (cnt > 4) { break; @@ -413,13 +413,13 @@ class _BookInfoState extends State { break; } temp = review; - // temp.sort((a, b) { - // DateTime dateTimeA = DateTime.parse(a["endDate"]); - // DateTime dateTimeB = DateTime.parse(b["endDate"]); - // return dateTimeB.compareTo(dateTimeA); - // }); + temp.sort((a, b) { + DateTime dateTimeA = DateTime.parse(a["endDate"]); + DateTime dateTimeB = DateTime.parse(b["endDate"]); + return dateTimeB.compareTo(dateTimeA); + }); for (var post in temp) { - if (cnt > 3) { + if (cnt > 4) { break; } cnt++; @@ -441,13 +441,13 @@ class _BookInfoState extends State { break; } temp = shortreview; - // temp.sort((a, b) { - // DateTime dateTimeA = DateTime.parse(a["endDate"]); - // DateTime dateTimeB = DateTime.parse(b["endDate"]); - // return dateTimeB.compareTo(dateTimeA); - // }); + temp.sort((a, b) { + DateTime dateTimeA = DateTime.parse(a["endDate"]); + DateTime dateTimeB = DateTime.parse(b["endDate"]); + return dateTimeB.compareTo(dateTimeA); + }); for (var post in temp) { - if (cnt > 3) { + if (cnt > 4) { break; } cnt++; @@ -469,13 +469,13 @@ class _BookInfoState extends State { break; } temp = quotation; - // temp.sort((a, b) { - // DateTime dateTimeA = DateTime.parse(a["endDate"]); - // DateTime dateTimeB = DateTime.parse(b["endDate"]); - // return dateTimeB.compareTo(dateTimeA); - // }); + temp.sort((a, b) { + DateTime dateTimeA = DateTime.parse(a["endDate"]); + DateTime dateTimeB = DateTime.parse(b["endDate"]); + return dateTimeB.compareTo(dateTimeA); + }); for (var post in temp) { - if (cnt > 3) { + if (cnt > 4) { break; } cnt++; @@ -523,9 +523,26 @@ class _BookInfoState extends State { ), child: Text( isQuiz ? post['description'] : post['title'], + style: textStyle(14, null, false), ), ), ), ); } } + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + + return formattedDate; +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart b/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart index 60949dc17c..046646c7f4 100644 --- a/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart +++ b/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; +import 'package:intl/intl.dart'; class BookReportViewingScreen extends StatefulWidget { final dynamic contentData; @@ -16,8 +17,8 @@ class BookReportViewingScreen extends StatefulWidget { class _BookReportViewingState extends State { final TextEditingController _answerController = TextEditingController(); // List _contentData = []; - final dynamic _startDate = DateTime.now(); - final dynamic _endDate = DateTime.now(); + dynamic _startDate = DateTime.now(); + dynamic _endDate = DateTime.now(); //bool _isPublic = false; String _template = ''; String _writer = ''; @@ -40,11 +41,14 @@ class _BookReportViewingState extends State { _writer = content['writer']; _author = content['book']['author']; _publisher = content['book']['publisher']; - print(_template); + _booktitle = content['book']['title']; + _startDate = formatDate(content['startDate']); + _endDate = formatDate(content['endDate']); + print(_startDate); + print(_endDate); if (_template == "독후감" || _template == "한줄평" || _template == "인용구") { _body = content['body']; _title = content['title']; - _booktitle = content['book']['title']; } else { _category = quizCategory(content['type']); _answer = content['answer']; @@ -106,12 +110,7 @@ class _BookReportViewingState extends State { return Scaffold( appBar: AppBar( title: Text(_template), - titleTextStyle: const TextStyle( - color: Colors.white, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - fontSize: 20, - ), + titleTextStyle: textStyle(22, Colors.white, true), backgroundColor: const Color(0xFF0E9913), centerTitle: true, leading: IconButton( @@ -123,35 +122,99 @@ class _BookReportViewingState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox(height: 20), + (_template != '퀴즈') + ? Column( + children: [ + SizedBox(height: 10.h), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + children: [ + Text( + '제목 : ', + style: textStyle(15, null, false), + ), + Text( + _title, + style: textStyle(15, null, false), + ), + ], + ), + ), + SizedBox(height: 10.h), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Container( + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: const Color(0xFFA9AFB7), + ), + ), + ), + ), + ], + ) + : Container(), + SizedBox(height: 10.h), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: EdgeInsets.symmetric(horizontal: 20.w), child: Row( children: [ - Text(_title), + Text( + _booktitle, + style: textStyle(15, null, true), + ), ], ), ), - const SizedBox(height: 10), + SizedBox(height: 10.h), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: EdgeInsets.symmetric(horizontal: 20.w), child: Row( children: [ - Text(_booktitle), + Text( + '$_author | $_publisher', + style: textStyle(13, null, false), + ), ], ), ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - children: [ - Text('$_author | $_publisher', - style: const TextStyle(color: Colors.black)), - ], - ), + SizedBox(height: 10.h), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(left: 20.w), + child: Text( + '독서기간 :', + style: textStyle(13, null, false), + ), + ), + Padding( + padding: EdgeInsets.only(left: 5.w), + child: Text( + _startDate, + style: textStyle(13, null, false), + ), + ), + Padding( + padding: EdgeInsets.only(left: 10.w), + child: Text( + '~', + style: textStyle(13, null, false), + ), + ), + Padding( + padding: EdgeInsets.only(left: 10.w), + child: Text( + _endDate, + style: textStyle(13, null, false), + ), + ), + ], ), - const SizedBox(height: 15), + SizedBox(height: 10.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Container( @@ -163,18 +226,18 @@ class _BookReportViewingState extends State { ), ), ), - const SizedBox(height: 15), + SizedBox(height: 15.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( children: [ Expanded( - child: _buildTemplateUI(_template), - ), + child: _buildTemplateUI(_template), + ), ], ), ), - const SizedBox(height: 15), + SizedBox(height: 15.h), ], ), ), @@ -184,9 +247,15 @@ class _BookReportViewingState extends State { Widget _buildTemplateUI(String template) { switch (template) { case "독후감": - return Text(_body); + return Text( + _body, + style: textStyle(14, null, false), + ); case "한줄평": - return Text(_body); + return Text( + _body, + style: textStyle(14, null, false), + ); case "인용구": return Align( alignment: Alignment.center, @@ -196,6 +265,7 @@ class _BookReportViewingState extends State { padding: const EdgeInsets.symmetric(horizontal: 15), child: Text( _body, + style: textStyle(14, null, false), textAlign: TextAlign.center, maxLines: 10, ), @@ -218,16 +288,9 @@ class _BookReportViewingState extends State { children: [ Row( children: [ - const Text( + Text( '카테고리: ', - style: TextStyle( - color: Colors.black, - fontSize: 15, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w400, - height: 0, - letterSpacing: -0.17, - ), + style: textStyle(15, null, false), ), const SizedBox(width: 3), SizedBox( @@ -235,25 +298,19 @@ class _BookReportViewingState extends State { height: 22, child: Text( _category, - style: const TextStyle( - fontSize: 14, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w400, - color: Colors.black, - height: 0, - ), + style: textStyle(14, null, false), ), ), ], ), - const SizedBox(height: 15), + SizedBox(height: 15.h), Padding( padding: const EdgeInsets.symmetric(horizontal: 0), child: Row( children: [ Expanded( - child: _buildQuizUI(_category), - ), + child: _buildQuizUI(_category), + ), ], ), ), @@ -634,3 +691,18 @@ class _BookReportViewingState extends State { ); } } + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy-MM-dd').format(dateTime); + return formattedDate; +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart b/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart index 0e59ba1f71..545b2aa0fe 100644 --- a/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart +++ b/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/bookinfo_provider.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; +import 'package:frontend/screens/home/bookreport/bookreport_viewing_screen.dart'; import 'package:frontend/screens/home/bookreport/booksearch_screen_util.dart' as searchutil; import 'package:go_router/go_router.dart'; @@ -91,21 +92,24 @@ class _BookReportWritingState extends State { } void checkHW() async { + print(widget.isbn); + print(widget.dateInfo); if (widget.isbn != null) { var bookInfo = await getBookInfo(widget.isbn); - + print(bookInfo); setState(() { + _bookTitleController.text = bookInfo['title']; _author = bookInfo['author']; _publisher = bookInfo['publisher']; _isbn = widget.isbn; - _publisherDate = bookInfo['publisherDate']; + _publisherDate = bookInfo['publishDate']; _imageUrl = bookInfo['imageUrl']; }); } if (widget.dateInfo != null) { setState(() { - _startDate = widget.dateInfo['startDate']; - _endDate = widget.dateInfo['endDate']; + _startDate = DateTime.parse(widget.dateInfo['startDate']); + _endDate = DateTime.parse(widget.dateInfo['endDate']); }); } } @@ -166,7 +170,7 @@ class _BookReportWritingState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 5.h), - Padding( + (_template != '퀴즈')?Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( children: [ @@ -187,7 +191,7 @@ class _BookReportWritingState extends State { ), ], ), - ), + ):Container(), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( @@ -459,7 +463,10 @@ class _BookReportWritingState extends State { } context.pop(true); }, - child: const Text('저장'), + child: Text( + '저장', + style: textStyle(13, null, false), + ), ), ), ), diff --git a/frontend/lib/screens/home/group/group_screen.dart b/frontend/lib/screens/home/group/group_screen.dart index 0e7d83506a..7c0533712f 100644 --- a/frontend/lib/screens/home/group/group_screen.dart +++ b/frontend/lib/screens/home/group/group_screen.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/screens/home/group/in_group/group_info_screen.dart'; import 'package:frontend/screens/home/group/group_screen_util.dart'; import 'package:frontend/screens/home/group/make_group/group_make_screen.dart'; +import 'package:frontend/screens/home/search/search_screen_util.dart'; import 'dart:async'; import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; @@ -58,7 +60,6 @@ class _GroupState extends State { Future _makeGroupList() async { _GroupList = await groupSerachforTopic(realThema); await _initUserState(); - _GroupList.add([]); //추천 받아오기 } @override @@ -68,8 +69,8 @@ class _GroupState extends State { } Future _initUserState() async { - List myList = []; - + List myList = [], recBook = []; + dynamic recList; try { var id = await secureStorage.readData('id'); var token = await secureStorage.readData('token'); @@ -80,13 +81,25 @@ class _GroupState extends State { myList.add(temp); } + recList = await getRecommend(token); + print(recList); + for (int i = 0; i < recList['isbnList'].length; i++) { + recBook.add(await SearchISBNBook(recList['isbnList'][i])); + } + + // print(recBook); setState(() { userInfo = _userInfo; - _GroupList.add(myList); + _GroupList[6] = myList; + _GroupList[7] = recBook; }); } catch (e) { + recList = await getRecommendAnony(); + for (int i = 0; i < recList['isbnList'].length; i++) { + recBook.add(await SearchISBNBook(recList['isbnList'][i])); + } setState(() { - _GroupList.add(myList); + _GroupList[7] = recBook; }); } } @@ -109,7 +122,7 @@ class _GroupState extends State { } //테마별로 리스트 버튼 구현 + 스크롤 이동 구현 - Widget _ThemaList( + Widget ThemaList( BuildContext context, List Thema, ) { @@ -139,14 +152,12 @@ class _GroupState extends State { }, icon: Icon( ThemaIcon[j], + color: Colors.white, ), ), Text( Thema[j], - style: TextStyle( - fontSize: 13.sp, - fontWeight: FontWeight.w700, - ), + style: textStyle(13, Colors.white, false), ), ], ), @@ -174,19 +185,36 @@ class _GroupState extends State { padding: const EdgeInsets.all(10.0), child: Text( Thema[index], + style: textStyle(14, Colors.black, true), ), ), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: List.generate(_GroupList[index].length, (int i) { - return GroupListItem( - data: _GroupList[index][i], - userInfo: userInfo, - ); - }), + if (index != 7) + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.generate(_GroupList[index].length, (int i) { + return GroupListItem( + data: _GroupList[index][i], + userInfo: userInfo, + ); + }), + ), + ), + if (index == 7) + SizedBox( + width: double.infinity, + height: 120.h, + child: PageView.builder( + itemCount: _GroupList[index].length, + itemBuilder: (context, i) { + return SearchListItem( + data: _GroupList[index][i], + type: "search", + clubId: 0, + ); + }, + ), ), - ), ], ), SizedBox( @@ -204,14 +232,9 @@ class _GroupState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: const Text( + title: Text( '모임', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -246,14 +269,13 @@ class _GroupState extends State { child: SizedBox( width: 390.w, height: 90.h, - child: _ThemaList(context, Thema), + child: ThemaList(context, Thema), ), ), _isLoading ? Center( child: Padding( - padding: EdgeInsets.symmetric( - vertical: 100.h), + padding: EdgeInsets.symmetric(vertical: 100.h), child: const CircularProgressIndicator(), ), // 로딩 애니매이션 ) @@ -269,25 +291,32 @@ class _GroupState extends State { child: SingleChildScrollView( controller: _scrollController, scrollDirection: Axis.vertical, - child: Column( - children: [ - //0 - groupList(0), - //1 - groupList(1), - //2 - groupList(2), - //3 - groupList(3), - //4 - groupList(4), - //5 - groupList(5), - //내 모임 - groupList(6), - //추천 - groupList(7), - ], + child: Padding( + padding: EdgeInsets.only( + left: 10.w, + right: 10.w, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + //0 + groupList(0), + //1 + groupList(1), + //2 + groupList(2), + //3 + groupList(3), + //4 + groupList(4), + //5 + groupList(5), + //내 모임 + groupList(6), + //추천 + groupList(7), + ], + ), ), ), ), @@ -299,3 +328,12 @@ class _GroupState extends State { ); } } + +TextStyle textStyle(int fontsize, Color color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke)?FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} \ No newline at end of file diff --git a/frontend/lib/screens/home/group/group_screen_util.dart b/frontend/lib/screens/home/group/group_screen_util.dart index a113050ec0..0296372a71 100644 --- a/frontend/lib/screens/home/group/group_screen_util.dart +++ b/frontend/lib/screens/home/group/group_screen_util.dart @@ -25,8 +25,8 @@ class _GroupListItemState extends State { final bool LoginCheck = true; bool memberCheck(dynamic data) { - print(data); - if(widget.userInfo == null){ + // print(data); + if (widget.userInfo == null) { return false; } for (dynamic member in data['memberList']) { @@ -63,7 +63,7 @@ class _GroupListItemState extends State { side: BorderSide( width: 2.w, strokeAlign: BorderSide.strokeAlignOutside, - color: Color(0xFFEEF1F4), + color: const Color(0xFFEEF1F4), ), borderRadius: BorderRadius.circular(15), ), @@ -133,13 +133,12 @@ class _GroupListItemState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text('주제:${widget.data['topic']}', - style: TextStyle(fontSize: 13.sp)), + Text('주제 : ${widget.data['topic']}', + style: textStyle(13, null, false)), SizedBox(height: 4.h), Text( widget.data['name'], - style: TextStyle( - fontSize: 15.sp, fontWeight: FontWeight.bold), + style: textStyle(15, null, true), overflow: TextOverflow.ellipsis, ), SizedBox( @@ -158,13 +157,10 @@ class _GroupListItemState extends State { SizedBox(width: 3.w), Text( '${widget.data['memberCnt']} / ${widget.data['maximum']}', - style: TextStyle( - fontSize: 14.sp, - color: (widget.data['memberCnt'] == - widget.data['maximum']) - ? Colors.red - : null, - )), + style: (widget.data['memberCnt'] == + widget.data['maximum']) + ? textStyle(14, Colors.red, true) + : textStyle(14, null, false)), ], ), SizedBox( @@ -174,7 +170,7 @@ class _GroupListItemState extends State { (widget.data['publicstatus'] == 'PUBLIC') ? '공개' : '비공개', - style: TextStyle(fontSize: 13.sp)), + style: textStyle(13, null, false)), ], ), ), @@ -197,14 +193,19 @@ void _showWrongDialog(BuildContext context) { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text('비밀번호를 틀렸습니다.'), - content: Text('다시 입력해주세요.'), + title: const Text('비밀번호를 틀렸습니다.'), + titleTextStyle: textStyle(20, Colors.black, true), + content: const Text('다시 입력해주세요.'), + contentTextStyle: textStyle(14, Colors.black, false), actions: [ TextButton( onPressed: () { context.pop(); }, - child: const Text("확인"), + child: Text( + "확인", + style: textStyle(14, null, false), + ), ), ], ); @@ -220,6 +221,7 @@ Future _showPasswordDialog(BuildContext context, int password) async { builder: (BuildContext context) { return AlertDialog( title: const Text("비밀번호를 입력해주세요."), + titleTextStyle: textStyle(20, Colors.black, true), content: TextField( controller: _textController, inputFormatters: [FilteringTextInputFormatter.digitsOnly], @@ -238,7 +240,10 @@ Future _showPasswordDialog(BuildContext context, int password) async { } } }, - child: const Text("확인"), + child: Text( + "확인", + style: textStyle(14, null, false), + ), ), ], ); @@ -246,3 +251,12 @@ Future _showPasswordDialog(BuildContext context, int password) async { ) ?? 2; //기본값 2 } + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/group_info_screen.dart b/frontend/lib/screens/home/group/in_group/group_info_screen.dart index 3a09e677d1..8acc496e6b 100644 --- a/frontend/lib/screens/home/group/in_group/group_info_screen.dart +++ b/frontend/lib/screens/home/group/in_group/group_info_screen.dart @@ -1,16 +1,13 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart'; import 'dart:async'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:frontend/screens/home/group/in_group/post/post_screen.dart'; -import 'package:get/get.dart'; +import 'package:frontend/screens/home/group/group_screen.dart'; +import 'package:frontend/screens/home/group/group_screen_util.dart'; +import 'package:frontend/screens/home/group/make_group/group_make_screen.dart'; import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; -import 'package:frontend/screens/home/group/in_group/groupbook_select_screen.dart'; //그룹 상세 페이지 @@ -76,6 +73,7 @@ class _GroupInfoState extends State { Widget _generateMember(String memName, int index) { return ListTile( title: Text(memName), + titleTextStyle: textStyle(18, Colors.black, true), contentPadding: const EdgeInsets.symmetric(horizontal: 16), trailing: Visibility( visible: _isManage && _isGroupManager, @@ -117,6 +115,7 @@ class _GroupInfoState extends State { //모임원 목록 사이드 바 Widget _buildGroupList(BuildContext context) { return Drawer( + width: MediaQuery.of(context).size.width * 0.5, child: ListView( padding: EdgeInsets.zero, children: [ @@ -128,10 +127,7 @@ class _GroupInfoState extends State { children: [ Text( userdata['name'], - style: const TextStyle( - color: Colors.black, - fontSize: 24, - ), + style: textStyle(23, null, true), ), IconButton( onPressed: () async { @@ -149,6 +145,7 @@ class _GroupInfoState extends State { _isGroupMember = false; await _clubGetInfo(); await _clubGetAssign(); + context.pop(); } } } @@ -156,6 +153,10 @@ class _GroupInfoState extends State { icon: _isGroupManager ? const Icon(Icons.settings) : const Icon(Icons.logout)), + Text( + _isGroupManager ? '설정' : '나가기', + style: textStyle(13, null, false), + ), ], ), ), @@ -216,19 +217,20 @@ class _GroupInfoState extends State { _isManage = false; }); }, - child: const Text( + child: Text( '확인', + style: textStyle(12, null, false), ), ), ), ), - ElevatedButton( - onPressed: () { - context.push('/voicecall'); - }, - child: Text('test voice'), - ), + // ElevatedButton( + // onPressed: () { + // context.push('/voicecall'); + // }, + // child: Text('test voice'), + // ), ], ), ); @@ -240,20 +242,28 @@ class _GroupInfoState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text("마지막으로 확인하겠습니다"), - content: Text("나가시겠습니까?"), + title: const Text("마지막으로 확인하겠습니다"), + titleTextStyle: textStyle(20, Colors.black, true), + content: const Text("나가시겠습니까?"), + contentTextStyle: textStyle(14, Colors.black, false), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(false); // 취소 버튼 클릭 시 false 반환 }, - child: Text("취소"), + child: Text( + "취소", + style: textStyle(13, null, false), + ), ), TextButton( onPressed: () { Navigator.of(context).pop(true); // 확인 버튼 클릭 시 true 반환 }, - child: Text("확인"), + child: Text( + "확인", + style: textStyle(13, null, false), + ), ), ], ); @@ -272,25 +282,42 @@ class _GroupInfoState extends State { child: ListBody( children: [ ListTile( - title: const Text('추방하기'), + title: Text( + '추방하기', + style: textStyle(18, null, true), + ), onTap: () { - setState(() { - _isKicked = true; - _isManage = true; - updateGroupList(); - }); - Navigator.pop(context); + if (clubData['memberCnt'] == 1) { + context.pop(); + _showlimitDialog("최소인원"); + } else { + setState(() { + _isKicked = true; + _isManage = true; + updateGroupList(); + }); + + context.pop(); + } }, ), ListTile( - title: const Text('모임장 위임하기'), + title: Text( + '모임장 위임하기', + style: textStyle(18, null, true), + ), onTap: () { - setState(() { - _isKicked = false; - _isManage = true; - updateGroupList(); - }); - Navigator.pop(context); + if (clubData['memberCnt'] == 1) { + context.pop(); + _showlimitDialog("최소인원"); + } else { + setState(() { + _isKicked = false; + _isManage = true; + updateGroupList(); + }); + context.pop(); + } }, ), ], @@ -308,20 +335,30 @@ class _GroupInfoState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text("마지막으로 확인하겠습니다"), - content: (kickState) ? Text("추방하시겠습니까?") : Text("임명하시겠습니까?"), + title: const Text("마지막으로 확인하겠습니다."), + titleTextStyle: textStyle(20, Colors.black, true), + content: (kickState) + ? const Text("추방하시겠습니까?") + : const Text("모임장으로 임명하시겠습니까?"), + contentTextStyle: textStyle(15, Colors.black, false), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(false); // 취소 버튼 클릭 시 false 반환 }, - child: Text("취소"), + child: Text( + "취소", + style: textStyle(13, null, false), + ), ), TextButton( onPressed: () { Navigator.of(context).pop(true); // 확인 버튼 클릭 시 true 반환 }, - child: Text("확인"), + child: Text( + "확인", + style: textStyle(13, null, false), + ), ), ], ); @@ -331,45 +368,83 @@ class _GroupInfoState extends State { } // 제한인원 초과 경우 - void _showMaxlimitDialog() { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text('가입 실패'), - content: Text('모임의 정원이 초과되었습니다.'), - actions: [ - TextButton( - onPressed: () { - context.pop(); - }, - child: const Text("확인"), - ), - ], + void _showlimitDialog(String type) { + switch (type) { + case "정원초과": + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('가입 실패'), + content: const Text('모임의 정원이 초과되었습니다.'), + titleTextStyle: textStyle(20, Colors.black, true), + contentTextStyle: textStyle(14, Colors.black, false), + actions: [ + TextButton( + onPressed: () { + context.pop(); + }, + child: Text( + "확인", + style: textStyle(13, null, false), + ), + ), + ], + ); + }, ); - }, - ); - } - - // 로그인을 안한 경우 - void _showLoginlimitDialog() { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text('가입 실패'), - content: Text('로그인이 필요한 기능입니다.'), - actions: [ - TextButton( - onPressed: () { - context.pop(); - }, - child: const Text("확인"), - ), - ], + break; + case "최소인원": + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('인원 오류'), + content: const Text('모임의 최소 인원이 부족합니다.'), + titleTextStyle: textStyle(20, Colors.black, true), + contentTextStyle: textStyle(14, Colors.black, false), + actions: [ + TextButton( + onPressed: () { + context.pop(); + }, + child: Text( + "확인", + style: textStyle(13, null, false), + ), + ), + ], + ); + }, ); - }, - ); + break; + case "비로그인": + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('가입 실패'), + content: const Text('로그인이 필요한 기능입니다.'), + titleTextStyle: textStyle(20, Colors.black, true), + contentTextStyle: textStyle(14, Colors.black, false), + actions: [ + TextButton( + onPressed: () { + context.pop(); + }, + child: Text( + "확인", + style: textStyle(13, null, false), + ), + ), + ], + ); + }, + ); + break; + default: + break; + } } final TextEditingController _textControllers = TextEditingController(); @@ -402,7 +477,6 @@ class _GroupInfoState extends State { Future _clubGetInfo() async { clubData = await groupSerachforId(widget.clubId); - setState(() {}); } @@ -449,7 +523,6 @@ class _GroupInfoState extends State { bool isGroupMember = await userState(id, token); await _clubGetInfo(); - await _clubGetAssign(); if (id == clubData['managerId']) { @@ -513,11 +586,13 @@ class _GroupInfoState extends State { ), SizedBox( width: 260.w, - height: 40.h, child: TextField( controller: _textControllers, decoration: InputDecoration( - hintText: (clubData['book'] == null)?'대표책을 설정해주세요.':'대표책을 검색해주세요.', + hintText: (clubData['book'] == null) + ? '대표책을 설정해주세요.' + : '대표책을 검색해주세요.', + hintStyle: textStyle(16, Colors.grey, false), border: InputBorder.none, ), style: TextStyle( @@ -566,12 +641,7 @@ class _GroupInfoState extends State { children: [ Text( '대표책', - style: TextStyle( - color: Colors.white, - fontSize: 14.sp, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(14, Colors.white, true), ), Container( width: 80.w, @@ -596,12 +666,7 @@ class _GroupInfoState extends State { width: 250.w, child: Text( clubData['book']['title'], - style: TextStyle( - color: Colors.white, - fontSize: 22.sp, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), overflow: TextOverflow.ellipsis, ), ), @@ -609,12 +674,7 @@ class _GroupInfoState extends State { width: 250.w, child: Text( "${(clubData['book']['author'].length != 0) ? clubData['book']['author'] : '저자 미상'} | ${clubData['book']['publisher']}", - style: TextStyle( - color: Colors.white, - fontSize: 12.sp, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(12, Colors.white, true), overflow: TextOverflow.ellipsis, ), ), @@ -639,6 +699,7 @@ class _GroupInfoState extends State { scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), title: Text(widget.groupName), + titleTextStyle: textStyle(20, null, true), centerTitle: true, actions: [ Padding( @@ -654,7 +715,7 @@ class _GroupInfoState extends State { side: BorderSide( width: 2.w, strokeAlign: BorderSide.strokeAlignOutside, - color: Color(0xFFEEF1F4), + color: const Color(0xFFEEF1F4), ), borderRadius: BorderRadius.circular(15), ), @@ -662,10 +723,10 @@ class _GroupInfoState extends State { child: InkWell( onTap: () async { if (id == null || token == null) { - _showLoginlimitDialog(); + _showlimitDialog("비로그인"); } else if (clubData['maximum'] == clubData['memberCnt']) { - _showMaxlimitDialog(); + _showlimitDialog("정원초과"); } else { // 회원 가입 동작 String result = @@ -685,12 +746,7 @@ class _GroupInfoState extends State { child: Text( '가입하기', textAlign: TextAlign.center, - style: TextStyle( - color: Colors.black, - fontSize: 15.sp, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(15, null, true), ), ), ), @@ -801,19 +857,14 @@ class _GroupInfoState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Padding( - padding: EdgeInsets.only( + Padding( + padding: const EdgeInsets.only( left: 5.0, top: 3.0, ), child: Text( '과제', - style: TextStyle( - color: Colors.black, - fontSize: 16, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(15, null, true), ), ), SizedBox( @@ -867,19 +918,14 @@ class _GroupInfoState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Padding( - padding: EdgeInsets.only( + Padding( + padding: const EdgeInsets.only( left: 5.0, top: 3.0, ), child: Text( '공지사항', - style: TextStyle( - color: Colors.black, - fontSize: 16, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(15, null, true), ), ), SizedBox( @@ -934,19 +980,14 @@ class _GroupInfoState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Padding( - padding: EdgeInsets.only( + Padding( + padding: const EdgeInsets.only( left: 5.0, top: 3.0, ), child: Text( '게시판', - style: TextStyle( - color: Colors.black, - fontSize: 16, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(15, null, true), ), ), SizedBox( @@ -1110,9 +1151,19 @@ class _GroupInfoState extends State { ), child: Text( (isPost) ? post['title'] : post['name'], + style: textStyle(14, null, false), ), ), ), ); } } + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart b/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart index 3d435715ce..3b288a8372 100644 --- a/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart +++ b/frontend/lib/screens/home/group/in_group/groupbook_select_screen.dart @@ -2,9 +2,12 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:frontend/screens/home/group/group_screen.dart'; +import 'package:frontend/screens/home/group/group_screen_util.dart'; import 'package:frontend/screens/home/search/search_screen_util.dart' as SearchUtil; import 'package:frontend/http.dart'; +import 'package:get/get_connect/http/src/utils/utils.dart'; import 'package:go_router/go_router.dart'; //그룹 대표책 설정 페이지 @@ -47,13 +50,8 @@ class _GroupBookSelectState extends State { backgroundColor: const Color(0xFF0E9913), title: const Text( '대표책 검색', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), ), + titleTextStyle: textStyle(22, null, true), centerTitle: true, ), body: Center( @@ -67,11 +65,18 @@ class _GroupBookSelectState extends State { SizedBox( height: 5.h, ), - if(BookData.isNotEmpty) + if (BookData.isNotEmpty) for (int i = 0; i < BookData.length; i++) - SearchUtil.SearchListItem(data: BookData[i], type: "select", clubId: widget.clubId,), - if(BookData.isEmpty) - const Text('검색된 책이 없습니다.'), + SearchUtil.SearchListItem( + data: BookData[i], + type: "select", + clubId: widget.clubId, + ), + if (BookData.isEmpty) + Text( + '검색된 책이 없습니다.', + style: textStyle(14, null, true), + ), ], ), ), @@ -83,3 +88,12 @@ class _GroupBookSelectState extends State { ); } } + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart index a6ff833431..ee8afd6d2c 100644 --- a/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; +import 'package:intl/intl.dart'; //과제 목록 페이지 @@ -41,7 +42,7 @@ class _HomeworkListScreenState extends State { Future updatePostList() async { var _posts = await getAssign(widget.clubId); - if(_posts.runtimeType == Map){ + if (_posts.runtimeType == Map) { _posts = []; } setState(() { @@ -49,8 +50,8 @@ class _HomeworkListScreenState extends State { }); } - void checkBook(dynamic Book){ - if(Book == null){ + void checkBook(dynamic Book) { + if (Book == null) { setState(() { isBook = false; }); @@ -74,14 +75,9 @@ class _HomeworkListScreenState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: const Text( + title: Text( '과제', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -94,9 +90,7 @@ class _HomeworkListScreenState extends State { extra: widget.clubId, ) .then((result) async { - if (result == true) { - updatePostList(); - } + updatePostList(); }); }, shape: const CircleBorder(), @@ -128,19 +122,118 @@ class _HomeworkListScreenState extends State { context.push('/homeworkmember_make', extra: { 'post': post, 'clubId': widget.clubId, - }); + }).then((value) async { + updatePostList(); + }); }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - post['name'], - style: const TextStyle( - fontSize: 20, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.bold, - letterSpacing: -0.17, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + post['name'], + style: textStyle(20, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + HwType(post['type']), + style: textStyle(14, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + '과제기한:', + style: textStyle(12, Colors.grey, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + post['startDate'], + style: textStyle(12, Colors.grey, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + '~', + style: textStyle(12, Colors.grey, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + post['endDate'], + style: textStyle(12, Colors.grey, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + (limitDate(post['endDate'])) + ? "제출가능" + : "제출마감", + style: (limitDate(post['endDate'])) + ? textStyle(12, Colors.grey, false) + : textStyle(12, Colors.red, true), + ), + ), + ], + ), + ], + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + width: 30.w, + height: 47.h, + decoration: ShapeDecoration( + color: const Color(0xFFE4E7EA), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3)), + ), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 4.h), + child: Text( + '${post['contentList'].length}', + style: textStyle(13, null, false), + ), + ), + SizedBox( + height: 4.h, + ), + Text( + '과제', + style: textStyle(13, Colors.grey, false), + textAlign: TextAlign.center, + ), + ], + ), + ), ), - ), + ], ), ), ), @@ -162,3 +255,41 @@ class _HomeworkListScreenState extends State { return items; } } + +String HwType(String type) { + switch (type) { + case 'Review': + return '독후감'; + case 'ShortReview': + return '한줄평'; + case 'Quotation': + return '인용구'; + case 'Quiz': + return '퀴즈'; + default: + return ''; + } +} + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + + return formattedDate; +} + +bool limitDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + DateTime nowTime = DateTime.now(); + + return dateTime.isAfter(nowTime); +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart b/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart index c33e555fe0..af45dc1415 100644 --- a/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:provider/provider.dart'; +import 'package:intl/intl.dart'; //멤버들 과제 리스트 @@ -54,6 +55,7 @@ class _HomeworkMemberistState extends State { HW = _hw; HwList = _HwList; isbn = _club['book']['isbn']; + print(HW); }); } @@ -88,7 +90,6 @@ class _HomeworkMemberistState extends State { super.initState(); secureStorage = Provider.of(context, listen: false); dateCheck(widget.post['endDate']); - print(widget.post); initUserInfo(); updateHwList(); } @@ -103,12 +104,7 @@ class _HomeworkMemberistState extends State { backgroundColor: const Color(0xFF0E9913), title: Text( widget.post['name'], - style: const TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -161,17 +157,47 @@ class _HomeworkMemberistState extends State { extra: post, ); }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - post['title'], - style: const TextStyle( - fontSize: 20, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.bold, - letterSpacing: -0.17, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + post['title'], + style: textStyle(20, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + HwType(post['type']), + style: textStyle(14, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + "작성자 ${post['writer']}", + style: textStyle(12, Colors.grey, false), + ), + ), + ], + ), + ], ), - ), + ], ), ), ), @@ -193,3 +219,31 @@ class _HomeworkMemberistState extends State { return items; } } + +String HwType(String type) { + switch (type) { + case 'Review': + return '독후감'; + case 'ShortReview': + return '한줄평'; + case 'Quotation': + return '인용구'; + default: + return '퀴즈'; + } +} + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + return formattedDate; +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/make_post/homework_make_screen.dart b/frontend/lib/screens/home/group/in_group/post/make_post/homework_make_screen.dart index 2b4089dd76..3644fdd402 100644 --- a/frontend/lib/screens/home/group/in_group/post/make_post/homework_make_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/make_post/homework_make_screen.dart @@ -1,12 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/http.dart'; -import 'package:get/get.dart'; -import 'package:get/get_connect/http/src/utils/utils.dart'; +import 'package:frontend/screens/home/bookreport/bookreport_viewing_screen.dart'; +import 'package:frontend/screens/home/group/group_screen_util.dart'; import 'package:go_router/go_router.dart'; -import 'package:frontend/screens/home/group/group_screen.dart'; import 'package:provider/provider.dart'; -import 'package:flutter/services.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; //모임 생성 페이지 @@ -67,6 +65,7 @@ class _HomeworkMakeState extends State { builder: (context, child) => Scaffold( appBar: AppBar( title: const Text('과제 만들기'), + titleTextStyle: textStyle(22, const Color(0xFF0E9913), true), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), @@ -76,9 +75,12 @@ class _HomeworkMakeState extends State { // 과제 이름 설정 TextField( controller: _nameController, - decoration: const InputDecoration( + style: textStyle(18, null, false), + decoration: InputDecoration( labelText: '과제 이름', - hintText: '과제이름', + hintText: '과제명', + labelStyle: textStyle(18, null, true), + hintStyle: textStyle(16, Colors.grey, false), ), onChanged: (value) { setState(() { @@ -89,13 +91,17 @@ class _HomeworkMakeState extends State { SizedBox(height: 16.h), // 과제 타입 설정 DropdownButtonFormField( - decoration: const InputDecoration( + decoration: InputDecoration( labelText: '과제 주제', + labelStyle: textStyle(18, null, true), ), items: type .map((type) => DropdownMenuItem( value: type, - child: Text(type), + child: Text( + type, + style: textStyle(18, null, false), + ), )) .toList(), onChanged: (value) { @@ -123,12 +129,13 @@ class _HomeworkMakeState extends State { _startDate.toString().substring(0, 10), _endDate.toString().substring(0, 10)); if (result == '과제 생성 완료') { - context.pop(true); + context.pop(); } } : null, - child: const Text( + child: Text( '생성하기', + style: textStyle(14, null, false), ), ), ], @@ -142,12 +149,12 @@ class _HomeworkMakeState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + SizedBox( + height: 10.h, + ), + Text( "기한 설정", - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w700, - ), + style: textStyle(18, null, true), ), Row( children: [ @@ -204,3 +211,12 @@ class _HomeworkMakeState extends State { ); } } + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/make_post/post_make_screen.dart b/frontend/lib/screens/home/group/in_group/post/make_post/post_make_screen.dart index 071ea26832..8e72f77afc 100644 --- a/frontend/lib/screens/home/group/in_group/post/make_post/post_make_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/make_post/post_make_screen.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; +import 'package:frontend/screens/home/bookreport/bookreport_viewing_screen.dart'; +import 'package:frontend/screens/home/group/group_screen.dart'; +import 'package:frontend/screens/home/group/group_screen_util.dart'; +import 'package:frontend/screens/home/group/make_group/group_make_screen.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:frontend/http.dart'; @@ -33,7 +37,6 @@ class _PostMakeState extends State { bool _isFieldEmpty(TextEditingController controller) { return controller.text.trim().isEmpty; } - Future _checkManager() async { if (widget.managerId == await secureStorage.readData('id')) { @@ -76,14 +79,9 @@ class _PostMakeState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: const Text( + title: Text( '게시글', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -92,27 +90,25 @@ class _PostMakeState extends State { child: Align( alignment: Alignment.bottomRight, child: ElevatedButton( - onPressed: ()async { - if(_isFieldEmpty(_postTitleController)){ - - } - else if(_isFieldEmpty(_postbodyController)){ - - } - else{ + onPressed: () async { + if (_isFieldEmpty(_postTitleController)) { + } else if (_isFieldEmpty(_postbodyController)) { + } else { String result = await postCreate( - token, - widget.clubId, - _postTitleController.text, - _postbodyController.text, - isSticky); - if(result == '게시글 생성'){ + token, + widget.clubId, + _postTitleController.text, + _postbodyController.text, + isSticky); + if (result == '게시글 생성') { context.pop(true); } } - }, - child: const Text('등록')), + child: Text( + '등록', + style: textStyle(14, null, false), + )), ), ), body: Padding( @@ -125,16 +121,20 @@ class _PostMakeState extends State { const SizedBox(height: 6), Row( children: [ - const Text('제목: '), + Text( + '제목: ', + style: textStyle(15, null, false), + ), const SizedBox(width: 10), Expanded( child: SizedBox( width: _screenWidth * 0.7, child: TextField( - style: const TextStyle(fontSize: 14), + style: textStyle(14, null, false), controller: _postTitleController, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: '제목을 입력하세요.', + hintStyle: textStyle(14, null, false), border: InputBorder.none, ), ), @@ -146,7 +146,10 @@ class _PostMakeState extends State { visible: isGroupManager, child: Row( children: [ - const Text('공지사항'), + Text( + '공지사항', + style: textStyle(15, null, false), + ), Checkbox( value: isSticky, onChanged: (newValue) { @@ -167,11 +170,12 @@ class _PostMakeState extends State { ), ), TextField( - style: const TextStyle(fontSize: 14), + style: textStyle(14, null, false), controller: _postbodyController, maxLines: null, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: ' 자유롭게 글을 작성해주세요.', + hintStyle: textStyle(14, Colors.grey, false), border: InputBorder.none, ), ), @@ -182,3 +186,12 @@ class _PostMakeState extends State { )); } } + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart index 00736fcadf..e54f0c86a8 100644 --- a/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/notice_list_screen.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:frontend/screens/home/group/group_screen_util.dart'; import 'package:go_router/go_router.dart'; import 'package:frontend/http.dart'; +import 'package:intl/intl.dart'; //공지사항 목록 페이지 @@ -11,7 +13,7 @@ class NoticeListScreen extends StatefulWidget { const NoticeListScreen({ super.key, - required this.managerId, + required this.managerId, required this.clubId, }); @@ -43,14 +45,9 @@ class _NoticeListScreenState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: const Text( + title: Text( '공지사항', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -102,17 +99,74 @@ class _NoticeListScreenState extends State { }, ); }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - post['title'], - style: const TextStyle( - fontSize: 20, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.bold, - letterSpacing: -0.17, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + post['title'], + style: textStyle(20, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + "작성자 ${post['writer']}", + style: textStyle(12, null, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 14.w, bottom: 5.h, top: 5.h), + child: Text( + formatDate(post['createdAt']), + style: textStyle(12, Colors.grey, false), + ), + ), + ], + ), + ], ), - ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + width: 30.w, + height: 47.h, + decoration: ShapeDecoration( + color: const Color(0xFFE4E7EA), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3)), + ), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 4.h), + child: Text( + '${post['commentResponseList'].length}', + style: textStyle(13, null, false), + ), + ), + SizedBox( + height: 4.h, + ), + Text( + '댓글', + style: textStyle(13, Colors.grey, false), + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ], ), ), ), @@ -135,3 +189,18 @@ class _NoticeListScreenState extends State { return items; } } + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + return formattedDate; +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart index 8b06463943..4fc46ed222 100644 --- a/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/post_list_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/http.dart'; import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; //게시글 목록 페이지 @@ -40,14 +41,9 @@ class _PostListScreenState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: const Text( + title: Text( '게시판', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -94,32 +90,85 @@ class _PostListScreenState extends State { "clubId": post['clubId'], }); }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 10.w, top: 10.w), + child: Text( + post['title'], + style: textStyle(20, null, false), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + Row( + children: [ + Padding( + padding: EdgeInsets.only( + left: 10.w, bottom: 5.h, top: 5.h), + child: Text( + "작성자 ${post['writer']}", + style: textStyle(12, null, false), + ), + ), + Padding( + padding: EdgeInsets.only( + left: 14.w, bottom: 5.h, top: 5.h), + child: Text( + formatDate(post['createdAt']), + style: textStyle(12, Colors.grey, false), + ), + ), + (post['isSticky']) + ? Padding( + padding: EdgeInsets.only(left: 14.w), + child: Text('공지사항', + style: + textStyle(12, Colors.red, true)), + ) + : Container(), + ], + ), + ], + ), Padding( padding: const EdgeInsets.all(8.0), - child: Text( - post['title'], - style: const TextStyle( - fontSize: 20, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.bold, - letterSpacing: -0.17, + child: Container( + width: 30.w, + height: 47.h, + decoration: ShapeDecoration( + color: const Color(0xFFE4E7EA), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3)), ), - ), - ), - (post['isSticky']) - ? Padding( - padding: const EdgeInsets.only(left: 10.0), - child: Text( - '공지사항', - style: TextStyle( - color: Colors.red, + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 4.h), + child: Text( + '${post['commentResponseList'].length}', + style: textStyle(13, null, false), ), ), - ) - : Container(), + SizedBox( + height: 4.h, + ), + Text( + '댓글', + style: textStyle(13, Colors.grey, false), + textAlign: TextAlign.center, + ), + ], + ), + ), + ), ], ), ), @@ -142,3 +191,18 @@ class _PostListScreenState extends State { return items; } } + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + return formattedDate; +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/in_group/post/post_screen.dart b/frontend/lib/screens/home/group/in_group/post/post_screen.dart index f45e73ece1..5808b0246e 100644 --- a/frontend/lib/screens/home/group/in_group/post/post_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/post_screen.dart @@ -1,9 +1,6 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; import 'package:frontend/http.dart'; import 'dart:async'; import 'package:frontend/provider/secure_storage_provider.dart'; @@ -64,6 +61,7 @@ class _PostScreenState extends State { setState(() { data = tempdata; comments = data['commentResponseList']; + print(data); }); } @@ -72,7 +70,7 @@ class _PostScreenState extends State { return ScreenUtilInit( designSize: const Size(390, 675), builder: (context, child) => _isLoading - ? Center( + ? const Center( child: CircularProgressIndicator(), // 로딩 애니매이션 ) : Scaffold( @@ -81,12 +79,7 @@ class _PostScreenState extends State { backgroundColor: const Color(0xFF0E9913), title: Text( (data['isSticky']) ? "공지사항" : "게시글", - style: const TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -96,22 +89,32 @@ class _PostScreenState extends State { //본문 내용 + 댓글창 Expanded( child: SingleChildScrollView( - padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - data['title'], - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), + Padding( + padding: EdgeInsets.all(13.w), + child: Text(data['title'], style: textStyle(23, null, false)), + ), + Padding( + padding: EdgeInsets.only(left:13.w, bottom: 5.h), + child: Text("작성자 ${data['writer']}",style: textStyle(15, null, false),), + ), + Padding( + padding: EdgeInsets.only(left:13.w, bottom: 5.h), + child: Text(formatDate(data['createdAt']), style: textStyle(12, Colors.grey, false)), + ), + Divider( + height: 1.h, + thickness: 0.2, + color: Colors.grey, ), - SizedBox(height: 16.h), - Text( - data['body'], - style: const TextStyle( - fontSize: 16, + SizedBox(height: 5.h), + Padding( + padding: EdgeInsets.all(14.w), + child: Text( + data['body'], + style: textStyle(16, null, false), ), ), ], @@ -119,19 +122,46 @@ class _PostScreenState extends State { ), ), // 댓글창 + Divider( + height: 1.h, + thickness: 0.2, + color: Colors.grey, + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Text( + "댓글 ${comments.length}", + style: textStyle(16, null, false), + ), + ), Expanded( child: ListView.builder( itemCount: comments.length, itemBuilder: (context, index) { return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ ListTile( - title: Text(comments[index]['writer']), - subtitle: Text(comments[index]['body'])), + title: Text(comments[index]['writer']), + titleTextStyle: textStyle(16, Colors.black, true), + subtitle: Padding( + padding: EdgeInsets.only(top: 5.h), + child: Text(comments[index]['body']), + ), + subtitleTextStyle: + textStyle(16, Colors.black, false), + ), + Padding( + padding: EdgeInsets.only(left: 15.w, bottom: 8.h), + child: Text( + formatDate(comments[index]['createdAt']), + style: textStyle(12, Colors.grey, false), + ), + ), Divider( - height: 2.h, + height: 1.h, thickness: 0.2, - color: Colors.grey, + color: Colors.grey, ), ], ); @@ -161,11 +191,12 @@ class _PostScreenState extends State { controller: _commentController, decoration: InputDecoration( hintText: ' 댓글을 입력하세요...', + hintStyle: textStyle(17, Colors.grey, false), border: InputBorder.none, focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), - borderSide: - const BorderSide(color: Color(0xFF0E9913)), + borderSide: const BorderSide( + color: Color(0xFF0E9913)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), @@ -207,3 +238,18 @@ class _PostScreenState extends State { ); } } + +String formatDate(String dateString) { + DateTime dateTime = DateTime.parse(dateString); + String formattedDate = DateFormat('yyyy.MM.dd. HH:mm').format(dateTime); + return formattedDate; +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/group/make_group/group_make_screen.dart b/frontend/lib/screens/home/group/make_group/group_make_screen.dart index c7456269ff..3b3fd89636 100644 --- a/frontend/lib/screens/home/group/make_group/group_make_screen.dart +++ b/frontend/lib/screens/home/group/make_group/group_make_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/http.dart'; +import 'package:frontend/screens/home/group/group_screen_util.dart'; import 'package:go_router/go_router.dart'; import 'package:frontend/screens/home/group/group_screen.dart'; import 'package:provider/provider.dart'; @@ -95,10 +96,12 @@ class _GroupMakeState extends State { decoration: const InputDecoration( labelText: '모임 주제', ), - items: realThema.map((theme) => DropdownMenuItem( - value: theme, - child: Text(theme), - )).toList(), + items: realThema + .map((theme) => DropdownMenuItem( + value: theme, + child: Text(theme), + )) + .toList(), onChanged: (value) { setState(() { _textControllers[1].text = value.toString(); @@ -152,14 +155,20 @@ class _GroupMakeState extends State { } }); }, - children: const [ + children: [ Padding( - padding: EdgeInsets.all(8.0), - child: Text('공개'), + padding: const EdgeInsets.all(8.0), + child: Text( + '공개', + style: textStyle(14, null, false), + ), ), Padding( - padding: EdgeInsets.all(8.0), - child: Text('비공개'), + padding: const EdgeInsets.all(8.0), + child: Text( + '비공개', + style: textStyle(14, null, false), + ), ), ], ), @@ -187,51 +196,45 @@ class _GroupMakeState extends State { // 생성하기 버튼 ElevatedButton( onPressed: _isCreateButtonEnabled() - ? () async { - //모임 목록을 백으로 보내는 코드 작성 - String publication; - dynamic result; - var token = await secureStorage.readData("token"); - if (_isPublic[0]) { - publication = '공개'; - result = await groupCreate( - token, - _textControllers[0].text, - _textControllers[1].text, - int.parse(_textControllers[2].text), - publication, - null); - } else { - publication = '비공개'; - result = await groupCreate( - token, - _textControllers[0].text, - _textControllers[1].text, - int.parse(_textControllers[2].text), - publication, - int.parse(_textControllers[3].text)); - } + ? (int.parse(_textControllers[2].text) == 0) + ? () { + _showLimitDialog(context); + } + : () async { + //모임 목록을 백으로 보내는 코드 작성 + String publication; + dynamic result; + var token = await secureStorage.readData("token"); + if (_isPublic[0]) { + publication = '공개'; + result = await groupCreate( + token, + _textControllers[0].text, + _textControllers[1].text, + int.parse(_textControllers[2].text), + publication, + null); + } else { + publication = '비공개'; + result = await groupCreate( + token, + _textControllers[0].text, + _textControllers[1].text, + int.parse(_textControllers[2].text), + publication, + int.parse(_textControllers[3].text)); + } - if (result.toString() == "모임 생성 완료") { - context.pop(true); - } else { - // 모임 생성 실패시 코드 작성 - } - } + if (result.toString() == "모임 생성 완료") { + context.pop(true); + } else { + // 모임 생성 실패시 코드 작성 + } + } : null, - child: const Text( + child: Text( '생성하기', - ), - ), - ElevatedButton( - onPressed: () { - print(_textControllers[0].text); - print(_textControllers[1].text); - print(_textControllers[2].text); - print(_textControllers[3].text); - }, - child: const Text( - 'test', + style: textStyle(13, null, false), ), ), ], @@ -241,3 +244,38 @@ class _GroupMakeState extends State { ); } } + +// 모임인원이 0명인 경우 +void _showLimitDialog(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('제한인원 설정 오류'), + titleTextStyle: textStyle(20, Colors.black, true), + content: const Text('모임 제한 인원은\n최소 1명 이상으로 설정해야 합니다.'), + contentTextStyle: textStyle(14, Colors.black, false), + actions: [ + TextButton( + onPressed: () { + context.pop(); + }, + child: Text( + "확인", + style: textStyle(13, null, false), + ), + ), + ], + ); + }, + ); +} + +TextStyle textStyle(int fontsize, var color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/search/search_screen.dart b/frontend/lib/screens/home/search/search_screen.dart index d130a3ea4f..f6d91256c8 100644 --- a/frontend/lib/screens/home/search/search_screen.dart +++ b/frontend/lib/screens/home/search/search_screen.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/http.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; +import 'package:frontend/screens/home/group/group_screen.dart'; import 'package:frontend/screens/home/group/group_screen_util.dart' as GroupUtil; import 'package:frontend/screens/home/search/search_screen_util.dart' @@ -100,14 +101,9 @@ class _SearchState extends State { appBar: AppBar( scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), - title: const Text( + title: Text( '검색', - style: TextStyle( - color: Colors.white, - fontSize: 25, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(22, Colors.white, true), ), centerTitle: true, ), @@ -156,16 +152,15 @@ class _SearchState extends State { ), SizedBox( width: 260.w, - height: 40.h, child: TextField( controller: _textControllers, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: '책 제목을 검색해주세요', + hintStyle: textStyle(18, Colors.grey, false), border: InputBorder.none, + alignLabelWithHint: true, ), - style: TextStyle( - fontSize: 18.sp, - ), + style: textStyle(18, Colors.black, true), onChanged: (value) { setState(() {}); }, @@ -191,8 +186,7 @@ class _SearchState extends State { _isLoading ? Center( child: Padding( - padding: EdgeInsets.only( - top: 200.h), + padding: EdgeInsets.only(top: 200.h), child: const CircularProgressIndicator(), ), // 로딩 애니매이션 ) @@ -202,12 +196,22 @@ class _SearchState extends State { controller: _scrollController, child: Column( children: [ - if (check && GroupData.isEmpty) const Text("모임 검색 결과가 없습니다"), + if (check && GroupData.isEmpty) + Text( + "모임 검색 결과가 없습니다.", + style: textStyle(15, Colors.black, true), + ), ElevatedButton( onPressed: () async { - await secureStorage.saveData('name', '이현준'); - await secureStorage.saveData('age', '23'); - await secureStorage.saveData('gender', '남자'); + dynamic userInfo = + await login("test13@gmail.com"); + // dynamic userInfo = await singup("test13@gmail.com", "한지민", ?, "여자"); + print(userInfo['token']); + print(userInfo['id']); + await secureStorage.saveData( + "token", userInfo['token']); + await secureStorage.saveData( + "id", userInfo['id']); }, child: Text('한지민'), ), @@ -253,6 +257,7 @@ class _SearchState extends State { onPressed: () async { await secureStorage.deleteData("token"); await secureStorage.deleteData("id"); + await secureStorage.deleteAllData(); }, child: Text('토큰 삭제'), ), @@ -293,3 +298,12 @@ class _SearchState extends State { ); } } + +TextStyle textStyle(int fontsize, Color color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke)?FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} diff --git a/frontend/lib/screens/home/search/search_screen_util.dart b/frontend/lib/screens/home/search/search_screen_util.dart index c0abe84bce..80fc83f831 100644 --- a/frontend/lib/screens/home/search/search_screen_util.dart +++ b/frontend/lib/screens/home/search/search_screen_util.dart @@ -5,6 +5,7 @@ import 'package:frontend/screens/home/search/search_screen.dart'; import 'package:provider/provider.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:frontend/http.dart'; + //검색의 리스트 아이템 템플릿 class SearchListItem extends StatefulWidget { @@ -42,7 +43,7 @@ class _SearchListItemState extends State { onTap: () async{ switch (widget.type) { case "search": - var result = await bookAdd(widget.data); + await bookAdd(widget.data); // print(result); // if(result == "도서 추가 완료"){ // 새로운 책 @@ -90,12 +91,7 @@ class _SearchListItemState extends State { width: 280.w, child: Text( widget.data['title'], - style: TextStyle( - color: Colors.black, - fontSize: 20.sp, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(20, Colors.black, true), overflow: TextOverflow.ellipsis, ), ), @@ -106,12 +102,7 @@ class _SearchListItemState extends State { width: ScreenUtil().setWidth(280), child: Text( "${(widget.data['author'] == '') ? '저자 미상' : widget.data['author']} | ${widget.data['publisher']}", - style: TextStyle( - color: Colors.black, - fontSize: 11.sp, - fontFamily: 'Noto Sans KR', - fontWeight: FontWeight.w700, - ), + style: textStyle(11, Colors.black, false), overflow: TextOverflow.ellipsis, ), ), @@ -128,3 +119,12 @@ class _SearchListItemState extends State { ); } } + +TextStyle textStyle(int fontsize, Color color, bool isStroke) { + return TextStyle( + fontSize: fontsize.sp, + fontWeight: (isStroke)?FontWeight.bold : FontWeight.normal, + fontFamily: 'Noto Sans KR', + color: color, + ); +} \ No newline at end of file diff --git a/frontend/lib/screens/home/shorts/shorts_screen.dart b/frontend/lib/screens/home/shorts/shorts_screen.dart index 052a55b449..6b91666e8f 100644 --- a/frontend/lib/screens/home/shorts/shorts_screen.dart +++ b/frontend/lib/screens/home/shorts/shorts_screen.dart @@ -1,8 +1,13 @@ import 'package:flutter/material.dart'; -class ShortsScreen extends StatelessWidget { +class ShortsScreen extends StatefulWidget { const ShortsScreen({super.key}); + @override + State createState() => _ShortsState(); +} + +class _ShortsState extends State { @override Widget build(BuildContext context) { return const Center( @@ -15,3 +20,4 @@ class ShortsScreen extends StatelessWidget { ); } } + From 9481a91ed06f355ae3d9eecd4e1bb76dcaa8ba00 Mon Sep 17 00:00:00 2001 From: choichangyeon Date: Mon, 20 May 2024 04:11:29 +0900 Subject: [PATCH 3/4] checkpoint2 --- frontend/lib/http.dart | 2 - .../bookreport/bookreport_viewing_screen.dart | 15 +- .../bookreport/bookreport_writing_screen.dart | 44 ++-- .../lib/screens/home/group/group_screen.dart | 2 +- .../group/in_group/group_info_screen.dart | 44 +++- .../in_group/post/homework_list_screen.dart | 7 +- .../post/homework_memberlist_screen.dart | 17 +- .../screens/home/mypage/mypage_screen.dart | 66 +++--- .../screens/home/search/search_screen.dart | 29 ++- .../screens/home/shorts/shorts_screen.dart | 189 +++++++++++++++++- 10 files changed, 323 insertions(+), 92 deletions(-) diff --git a/frontend/lib/http.dart b/frontend/lib/http.dart index afdcb2b416..2529940d78 100644 --- a/frontend/lib/http.dart +++ b/frontend/lib/http.dart @@ -293,7 +293,6 @@ Future quizCreate( String endDate) async { var address; if (clubId == null) { - // print(clubId); address = Uri.parse("$BASE_URL/quiz/create?"); } else { address = Uri.parse("$BASE_URL/quiz/create?clubId=$clubId&asId=$asId"); @@ -325,7 +324,6 @@ Future quizCreate( }), ); final data = res.body; - // print(data); return data; } diff --git a/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart b/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart index 046646c7f4..2c06cc9aa6 100644 --- a/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart +++ b/frontend/lib/screens/home/bookreport/bookreport_viewing_screen.dart @@ -1,4 +1,6 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/provider/secure_storage_provider.dart'; import 'package:go_router/go_router.dart'; @@ -35,7 +37,6 @@ class _BookReportViewingState extends State { var token; void initializeClubContentData(dynamic content) { - print(content); setState(() { _template = contentTypeCheck(content['type']); _writer = content['writer']; @@ -44,8 +45,6 @@ class _BookReportViewingState extends State { _booktitle = content['book']['title']; _startDate = formatDate(content['startDate']); _endDate = formatDate(content['endDate']); - print(_startDate); - print(_endDate); if (_template == "독후감" || _template == "한줄평" || _template == "인용구") { _body = content['body']; _title = content['title']; @@ -137,6 +136,7 @@ class _BookReportViewingState extends State { Text( _title, style: textStyle(15, null, false), + overflow: TextOverflow.ellipsis, ), ], ), @@ -161,9 +161,12 @@ class _BookReportViewingState extends State { padding: EdgeInsets.symmetric(horizontal: 20.w), child: Row( children: [ - Text( - _booktitle, - style: textStyle(15, null, true), + Expanded( + child: Text( + _booktitle, + style: textStyle(15, null, true), + overflow: TextOverflow.ellipsis, + ), ), ], ), diff --git a/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart b/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart index 545b2aa0fe..28e2d288e0 100644 --- a/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart +++ b/frontend/lib/screens/home/bookreport/bookreport_writing_screen.dart @@ -170,28 +170,30 @@ class _BookReportWritingState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 5.h), - (_template != '퀴즈')?Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - children: [ - const Text('제목: '), - const SizedBox(width: 10), - Expanded( - child: SizedBox( - width: _screenWidth * 0.7.w, - child: TextField( - style: const TextStyle(fontSize: 14), - controller: _titleController, - decoration: const InputDecoration( - hintText: '제목을 입력하세요.', - border: InputBorder.none, + (_template != '퀴즈') + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + children: [ + const Text('제목: '), + const SizedBox(width: 10), + Expanded( + child: SizedBox( + width: _screenWidth * 0.7.w, + child: TextField( + style: const TextStyle(fontSize: 14), + controller: _titleController, + decoration: const InputDecoration( + hintText: '제목을 입력하세요.', + border: InputBorder.none, + ), + ), + ), ), - ), + ], ), - ), - ], - ), - ):Container(), + ) + : Container(), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( @@ -385,8 +387,6 @@ class _BookReportWritingState extends State { _startDate.toString(), _endDate.toString()); } else { - // print(selectedCategory); - // print(_answerController.text); switch (selectedCategory) { case "객관식": var ansnum; diff --git a/frontend/lib/screens/home/group/group_screen.dart b/frontend/lib/screens/home/group/group_screen.dart index 7c0533712f..ba86724fd3 100644 --- a/frontend/lib/screens/home/group/group_screen.dart +++ b/frontend/lib/screens/home/group/group_screen.dart @@ -114,7 +114,7 @@ class _GroupState extends State { } Future _loadData() async { - Timer(const Duration(milliseconds: 800), () { + Timer(const Duration(milliseconds: 1000), () { setState(() { _isLoading = false; }); diff --git a/frontend/lib/screens/home/group/in_group/group_info_screen.dart b/frontend/lib/screens/home/group/in_group/group_info_screen.dart index 8acc496e6b..bd48dc34af 100644 --- a/frontend/lib/screens/home/group/in_group/group_info_screen.dart +++ b/frontend/lib/screens/home/group/in_group/group_info_screen.dart @@ -219,7 +219,7 @@ class _GroupInfoState extends State { }, child: Text( '확인', - style: textStyle(12, null, false), + style: textStyle(14, null, false), ), ), ), @@ -524,7 +524,8 @@ class _GroupInfoState extends State { await _clubGetInfo(); await _clubGetAssign(); - + print(clubData['managerId']); + print(id); if (id == clubData['managerId']) { isGroupManager = true; } @@ -661,6 +662,7 @@ class _GroupInfoState extends State { Padding( padding: EdgeInsets.only(top: 30.h), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 250.w, @@ -674,10 +676,17 @@ class _GroupInfoState extends State { width: 250.w, child: Text( "${(clubData['book']['author'].length != 0) ? clubData['book']['author'] : '저자 미상'} | ${clubData['book']['publisher']}", - style: textStyle(12, Colors.white, true), + style: textStyle(13, Colors.white, true), overflow: TextOverflow.ellipsis, ), ), + SizedBox(height: 10.h,), + Text('[최근 공지사항]',style: textStyle(13, Colors.white, true),), + SizedBox(height: 2.h,), + SizedBox( + width: 250.w, + child: recentSticky(), + ), ], ), ) @@ -685,6 +694,21 @@ class _GroupInfoState extends State { ); } + Widget recentSticky() { + var temp = clubData['posts']; + temp.sort((a, b) { + DateTime dateTimeA = DateTime.parse(a["createdAt"]); + DateTime dateTimeB = DateTime.parse(b["createdAt"]); + return dateTimeB.compareTo(dateTimeA); + }); + for (var post in temp) { + if (post['isSticky'] == true) { + return _buildTaskEntry(context, post, true, Colors.white); + } + } + return Container(); + } + @override Widget build(BuildContext context) { return ScreenUtilInit( @@ -699,7 +723,7 @@ class _GroupInfoState extends State { scrolledUnderElevation: 0, backgroundColor: const Color(0xFF0E9913), title: Text(widget.groupName), - titleTextStyle: textStyle(20, null, true), + titleTextStyle: textStyle(25, null, true), centerTitle: true, actions: [ Padding( @@ -1034,7 +1058,7 @@ class _GroupInfoState extends State { break; } cnt++; - tasks.add(_buildTaskEntry(context, post, true)); + tasks.add(_buildTaskEntry(context, post, true, null)); tasks.add(Container( decoration: BoxDecoration( border: Border( @@ -1060,7 +1084,7 @@ class _GroupInfoState extends State { break; } cnt++; - tasks.add(_buildTaskEntry(context, post, true)); + tasks.add(_buildTaskEntry(context, post, true, null)); tasks.add(Container( decoration: BoxDecoration( border: Border( @@ -1089,7 +1113,7 @@ class _GroupInfoState extends State { break; } cnt++; - tasks.add(_buildTaskEntry(context, post, false)); + tasks.add(_buildTaskEntry(context, post, false, null)); tasks.add(Container( decoration: BoxDecoration( border: Border( @@ -1110,7 +1134,7 @@ class _GroupInfoState extends State { } //각 게시판의 최신글 - Widget _buildTaskEntry(BuildContext context, var post, bool isPost) { + Widget _buildTaskEntry(BuildContext context, var post, bool isPost, var colors) { return InkWell( onTap: () { //글 목록 탭 됐을 때 @@ -1141,7 +1165,7 @@ class _GroupInfoState extends State { child: Container( width: 50.w, margin: const EdgeInsets.only(bottom: 2), // 각 항목 사이의 간격 설정 - padding: const EdgeInsets.all(4), // 내부 패딩 설정 + // padding: const EdgeInsets.all(4), // 내부 패딩 설정 decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), ), @@ -1151,7 +1175,7 @@ class _GroupInfoState extends State { ), child: Text( (isPost) ? post['title'] : post['name'], - style: textStyle(14, null, false), + style: textStyle(15, colors, false), ), ), ), diff --git a/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart b/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart index ee8afd6d2c..7f1b2d4375 100644 --- a/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/homework_list_screen.dart @@ -47,6 +47,7 @@ class _HomeworkListScreenState extends State { } setState(() { posts = _posts; + print(posts); }); } @@ -138,7 +139,7 @@ class _HomeworkListScreenState extends State { padding: EdgeInsets.only(left: 10.w, top: 10.w), child: Text( post['name'], - style: textStyle(20, null, false), + style: textStyle(18, null, false), overflow: TextOverflow.ellipsis, ), ), @@ -217,7 +218,9 @@ class _HomeworkListScreenState extends State { Padding( padding: EdgeInsets.only(top: 4.h), child: Text( - '${post['contentList'].length}', + (post['type'] == 'Quiz') + ? '${post['quizList'].length}' + : '${post['contentList'].length}', style: textStyle(13, null, false), ), ), diff --git a/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart b/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart index af45dc1415..27e29ea0d5 100644 --- a/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart +++ b/frontend/lib/screens/home/group/in_group/post/homework_memberlist_screen.dart @@ -25,6 +25,7 @@ class HomeworkMemberlistScreen extends StatefulWidget { class _HomeworkMemberistState extends State { List HwList = []; bool LimitCheck = true; + dynamic hwType; var secureStorage; var id; var token; @@ -46,7 +47,12 @@ class _HomeworkMemberistState extends State { var _HwList, _hw; for (Map hw in _posts) { if (hw['id'] == widget.post['id']) { - _HwList = hw['contentList']; + if (hw['type'] == 'Quiz') { + _HwList = hw['quizList']; + } else { + _HwList = hw['contentList']; + } + hwType = hw['type']; _hw = hw; break; } @@ -55,7 +61,7 @@ class _HomeworkMemberistState extends State { HW = _hw; HwList = _HwList; isbn = _club['book']['isbn']; - print(HW); + // print(HwList); }); } @@ -92,6 +98,7 @@ class _HomeworkMemberistState extends State { dateCheck(widget.post['endDate']); initUserInfo(); updateHwList(); + // print(HwList); } @override @@ -121,7 +128,7 @@ class _HomeworkMemberistState extends State { "startDate": widget.post['startDate'], "endDate": widget.post['endDate'] } - }).then((value) async { + }).then((value) { updateHwList(); }); }, @@ -168,7 +175,9 @@ class _HomeworkMemberistState extends State { Padding( padding: EdgeInsets.only(left: 10.w, top: 10.w), child: Text( - post['title'], + (hwType == 'Quiz') + ? post['description'] + : post['title'], style: textStyle(20, null, false), overflow: TextOverflow.ellipsis, ), diff --git a/frontend/lib/screens/home/mypage/mypage_screen.dart b/frontend/lib/screens/home/mypage/mypage_screen.dart index 0c1926095b..727044d67e 100644 --- a/frontend/lib/screens/home/mypage/mypage_screen.dart +++ b/frontend/lib/screens/home/mypage/mypage_screen.dart @@ -182,42 +182,44 @@ class _MypageScreenState extends State class LoggedWidget extends StatelessWidget { const LoggedWidget({super.key}); + + @override Widget build(BuildContext context) { return FutureBuilder( - future: Provider.of(context, listen: false) - .readData("name"), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const CircularProgressIndicator(); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else { - final name = snapshot.data ?? ''; - return Container( - padding: EdgeInsets.all(15.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.grey[200], - ), - child: Row( - children: [ - Icon( - Icons.account_circle, - size: 70.w, - ), - SizedBox(width: 16.w), - Text( - name, - style: - TextStyle(fontSize: 20.sp, fontWeight: FontWeight.bold), - ), - ], - ), + future: Provider.of(context, listen: false) + .readData("name"), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const CircularProgressIndicator(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + final name = snapshot.data ?? ''; + return Container( + padding: EdgeInsets.all(15.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.grey[200], + ), + child: Row( + children: [ + Icon( + Icons.account_circle, + size: 70.w, + ), + SizedBox(width: 16.w), + Text( + name, + style: TextStyle( + fontSize: 20.sp, fontWeight: FontWeight.bold), + ), + ], + ), + ); + } + }, ); - } - }, - ); } } diff --git a/frontend/lib/screens/home/search/search_screen.dart b/frontend/lib/screens/home/search/search_screen.dart index f6d91256c8..e8400c2635 100644 --- a/frontend/lib/screens/home/search/search_screen.dart +++ b/frontend/lib/screens/home/search/search_screen.dart @@ -1,5 +1,4 @@ import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:frontend/http.dart'; @@ -197,9 +196,29 @@ class _SearchState extends State { child: Column( children: [ if (check && GroupData.isEmpty) - Text( - "모임 검색 결과가 없습니다.", - style: textStyle(15, Colors.black, true), + Column( + children: [ + SizedBox( + height: 20.h, + ), + Text( + "모임 검색 결과가 없습니다.", + style: textStyle(15, Colors.black, true), + ), + ], + ), + + if (check && BookData.isEmpty) + Column( + children: [ + SizedBox( + height: 20.h, + ), + Text( + "책 검색 결과가 없습니다.", + style: textStyle(15, Colors.black, true), + ), + ], ), ElevatedButton( onPressed: () async { @@ -302,7 +321,7 @@ class _SearchState extends State { TextStyle textStyle(int fontsize, Color color, bool isStroke) { return TextStyle( fontSize: fontsize.sp, - fontWeight: (isStroke)?FontWeight.bold : FontWeight.normal, + fontWeight: (isStroke) ? FontWeight.bold : FontWeight.normal, fontFamily: 'Noto Sans KR', color: color, ); diff --git a/frontend/lib/screens/home/shorts/shorts_screen.dart b/frontend/lib/screens/home/shorts/shorts_screen.dart index 6b91666e8f..d0cfcb96d0 100644 --- a/frontend/lib/screens/home/shorts/shorts_screen.dart +++ b/frontend/lib/screens/home/shorts/shorts_screen.dart @@ -1,4 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:frontend/http.dart'; +import 'package:frontend/screens/home/bookreport/bookreport_viewing_screen.dart'; +import 'package:frontend/provider/secure_storage_provider.dart'; +import 'package:provider/provider.dart'; +import 'dart:async'; class ShortsScreen extends StatefulWidget { const ShortsScreen({super.key}); @@ -8,16 +15,182 @@ class ShortsScreen extends StatefulWidget { } class _ShortsState extends State { + List review = []; + List quotation = []; + List shortreview = []; + List quiz = []; + var userInfo; + var secureStorage; + bool _isLoading = true; + late PageController _pageController; + Timer? _pageTimer; + int _currentPage = 0; + int sumPages = 0; + // List allShorts = []; + + Future shortsList() async { + List _review = []; + List _quotation = []; + List _shortreview = []; + List _quiz = []; + var isbnList; + + try { + // var id = await secureStorage.readData('id'); + var token = await secureStorage.readData('token'); + isbnList = await getRecommend(token); + } catch (e) { + isbnList = await getRecommendAnony(); + } + + for (String isbn in isbnList['isbnList']) { + _review.add(await bookcontentLoad(isbn, 'Review')); + _quotation.add(await bookcontentLoad(isbn, 'Quotation')); + _shortreview.add(await bookcontentLoad(isbn, 'ShortReview')); + _quiz.add(await bookQuizLoad(isbn)); + } + + setState(() { + print(isbnList); + review = _review; //각각 10개의 리스트들이 존재 + quotation = _quotation; + shortreview = _shortreview; + quiz = _quiz; + // allShorts = [quiz, quotation, shortreview, review]; + // print(review[0].isEmpty); + // print(quotation); + // print(shortreview); + // print(quiz); + // print(allShorts.isEmpty); + }); + } + + List shortsPage(List posts) { + List temp = []; + int chekpoint = 0; + for (int i = 0; i < posts.length; i++) { + if (posts[i].isNotEmpty) { + for (var post in posts[i]) { + temp.add(BookReportViewingScreen(contentData: post)); + chekpoint++; + } + } else { + temp.add(Center(child: SizedBox(child: Text('컨텐츠가 존재하지 않습니다.')))); + chekpoint++; + } + } + sumPages += chekpoint; + return temp; + } + + Future _loadData() async { + Timer(const Duration(milliseconds: 1500), () { + setState(() { + _isLoading = false; + _startPageTimer(); + }); + }); + } + + // void _startPageTimer() { + // _pageTimer = Timer.periodic(const Duration(seconds: 3), (timer) { + // if (_pageController.hasClients) { + // _currentPage++; + // print(_currentPage); + // print(_pageController.positions.length); + // if (_currentPage < 0) { + // _currentPage = _pageController.positions.length - 1; + // } + // _pageController.animateToPage( + // _currentPage, + // duration: const Duration(milliseconds: 500), + // curve: Curves.easeInOut, + // ); + // } + // }); + // } + + void _startPageTimer() { + _pageTimer = Timer.periodic(const Duration(seconds: 3), (timer) { + if (_pageController.hasClients) { + _currentPage++; + print(_currentPage); + if (_currentPage >= sumPages) { + _currentPage = 0; + } + _pageController.animateToPage( + _currentPage, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOut, + ); + } + }); + } + + void _resetPageTimer() { + _pageTimer?.cancel(); + _startPageTimer(); + } + + @override + void initState() { + super.initState(); + secureStorage = Provider.of(context, listen: false); + _pageController = PageController(); + shortsList(); + _loadData(); + } + + @override + void dispose() { + _pageController.dispose(); + _pageTimer?.cancel(); + super.dispose(); + } + @override Widget build(BuildContext context) { - return const Center( - child: Text( - '쇼츠 들어갈 페이지', - style: TextStyle( - fontSize: 50, - ), - ), + return ScreenUtilInit( + designSize: const Size(390, 675), + builder: (context, child) => _isLoading + ? Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 100.h), + child: const CircularProgressIndicator(), + ), + ) + : GestureDetector( + onPanDown: (details) { + _pageTimer?.cancel(); + setState(() { + + }); + }, + onPanEnd: (details) { + _resetPageTimer(); + setState(() { + + }); + }, + onTapUp: (details) { + _resetPageTimer(); + setState(() { + + }); + }, + child: Center( + child: PageView( + controller: _pageController, + scrollDirection: Axis.vertical, + children: [ + ...shortsPage(review), + ...shortsPage(quotation), + ...shortsPage(quiz), + ...shortsPage(shortreview), + ], + ), + ), + ), ); } } - From 05a2c9dcf49ea599335e7fd8bb330e6c4eacb551 Mon Sep 17 00:00:00 2001 From: choichangyeon Date: Mon, 20 May 2024 04:52:31 +0900 Subject: [PATCH 4/4] Fix Ui --- .idea/capstone-2024-39.iml | 42 ++++++++++++++++++++++++ frontend/android/app/google-service.json | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/.idea/capstone-2024-39.iml b/.idea/capstone-2024-39.iml index 34057bbd58..afefe2dafd 100644 --- a/.idea/capstone-2024-39.iml +++ b/.idea/capstone-2024-39.iml @@ -72,6 +72,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/android/app/google-service.json b/frontend/android/app/google-service.json index d035e9ad45..77fe4b8044 100644 --- a/frontend/android/app/google-service.json +++ b/frontend/android/app/google-service.json @@ -1 +1 @@ -{"installed":{"client_id":"801277628829-qba15ch2hanumq1v4hpe94c7rmt6k8ch.apps.googleusercontent.com","project_id":"bookmeeting-422618","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"}} \ No newline at end of file +{"installed":{"client_id":"801277628829-bhffdbgr4iql30md3952qbmv07lei8g6.apps.googleusercontent.com","project_id":"bookmeeting-422618","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"}}