diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index d6d2867..c8532e5 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -309,7 +309,8 @@ "Slight_Defect": "SLIGHT_DEFECT", "Used": "USED", "sale": "SELL", - "sold-out":"SOLD_OUT", + "sold-out":"END", + "search1": "Type Keyword", "search2": "Search for posts!" diff --git a/lib/apis/apis.dart b/lib/apis/apis.dart index daa89ec..60fa7a4 100644 --- a/lib/apis/apis.dart +++ b/lib/apis/apis.dart @@ -1630,6 +1630,9 @@ class APIs { request.fields['content'] = marketArticle.content!; request.fields['price'] = marketArticle.price.toString(); request.fields['productStatus'] = marketArticle.productStatus!; + request.fields['marketArticleStatus'] = marketArticle.marketArticleStatus!; + + // 이미지 파일 필드 추가 if (marketArticle.imageUrls != null && @@ -1650,11 +1653,14 @@ class APIs { var response = await request.send(); // 성공 - if (response.statusCode == 201) { + if (response.statusCode == 200) { print('상품 판매글 생성'); + print(await response.stream.bytesToString()); return true; } else { final responseBody = await response.stream.bytesToString(); + print(await response.stream.bytesToString()); + final errorCode = json.decode(responseBody)['code']; if (errorCode == 'AT-C-002') { @@ -1676,14 +1682,16 @@ class APIs { } /*특정 판매글 수정*/ - static Future updateMarketArticle(int articleId, - Map updateData) async { + + static Future updateMarketArticle(int articleId, Map updateData) async { try { + print('Starting updateMarketArticle with articleId: $articleId'); + var jwtToken = await storage.read(key: 'token'); final accessToken = json.decode(jwtToken!)['data']['accessToken']; - final url = Uri.parse( - 'http://3.34.2.246:8080/api/v2/market-articles/$articleId'); + final url = Uri.parse('http://3.34.2.246:8080/api/v2/market-articles/$articleId'); + print('Update Data: $updateData'); final response = await http.patch( url, @@ -1696,8 +1704,12 @@ class APIs { if (response.statusCode == 200) { final responseBody = json.decode(utf8.decode(response.bodyBytes)); - final message = responseBody['message']; - return message; + print('Successful Response Body: $responseBody'); + return true; + } else if (response.statusCode == 500) { + final responseBody = json.decode(utf8.decode(response.bodyBytes)); + print('500 Error Response Body: $responseBody'); + return false; } else { final responseBody = json.decode(utf8.decode(response.bodyBytes)); final errorCode = responseBody['code']; @@ -1729,6 +1741,7 @@ class APIs { url, headers: { 'Authorization': 'Bearer $accessToken', + 'Content-Type': 'application/json', }, ); diff --git a/lib/views/components/board_drawer_widget.dart b/lib/views/components/board_drawer_widget.dart index 6a018d0..1de1750 100644 --- a/lib/views/components/board_drawer_widget.dart +++ b/lib/views/components/board_drawer_widget.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:aliens/mockdatas/mockdata_model.dart'; import 'package:aliens/models/chatRoom_model.dart'; import 'package:aliens/models/memberDetails_model.dart'; import 'package:aliens/models/screenArgument.dart'; @@ -23,18 +24,22 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:web_socket_channel/status.dart'; import '../../apis/apis.dart'; +import '../../mockdatas/mockdata_model.dart'; +import '../../mockdatas/mockdata_model.dart'; import '../../models/market_articles.dart'; +import '../../models/members.dart'; import '../../repository/sql_message_repository.dart'; import '../pages/board/market_posting_board_page.dart'; class BoardDrawerWidget extends StatefulWidget { - const BoardDrawerWidget({super.key, required this.screenArguments, required this.isTotalBoard, required this.onpressd, this.marketBoard}); + const BoardDrawerWidget({super.key, required this.screenArguments, required this.isTotalBoard, required this.onpressd, this.marketBoard, this.memberDetails}); final ScreenArguments screenArguments; final MarketBoard? marketBoard; - //final MemberDetails memberDetails; + final MemberDetails? memberDetails; final bool isTotalBoard; final VoidCallback onpressd; @@ -51,12 +56,14 @@ class _BoardDrawerWidgetState extends State { @override Widget build(BuildContext context) { + return Container( decoration: BoxDecoration( color: Color(0xffEBEBEB), ), child: ListView( children: [ + InkWell( onTap: () async { if(widget.isTotalBoard){ @@ -451,7 +458,7 @@ class _BoardDrawerWidgetState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => MarketBoardPage(screenArguments: widget.screenArguments, marketBoard: widget.marketBoard, index:0,)), + builder: (context) => MarketBoardPage(screenArguments: widget.screenArguments, marketBoard: widget.marketBoard, memberDetails: widget.screenArguments.memberDetails!)), ); } @@ -460,7 +467,7 @@ class _BoardDrawerWidgetState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => MarketBoardPage(screenArguments: widget.screenArguments, marketBoard: widget.marketBoard, index:0,)), + builder: (context) => MarketBoardPage(screenArguments: widget.screenArguments, marketBoard: widget.marketBoard, memberDetails:widget.screenArguments.memberDetails!)), ); } }, diff --git a/lib/views/components/market_dialog_widget.dart b/lib/views/components/market_dialog_widget.dart new file mode 100644 index 0000000..0e2f896 --- /dev/null +++ b/lib/views/components/market_dialog_widget.dart @@ -0,0 +1,255 @@ +import 'package:aliens/models/memberDetails_model.dart'; +import 'package:aliens/models/partner_model.dart'; +import 'package:aliens/models/screenArgument.dart'; +import 'package:aliens/repository/board_provider.dart'; +import 'package:aliens/views/components/block_dialog_widget.dart'; +import 'package:aliens/views/components/report_dialog_widget.dart'; +import 'package:aliens/views/components/report_iOS_dialog_widget.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; +import 'dart:io' show Platform; +import 'package:aliens/models/market_articles.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:provider/provider.dart'; + +import '../../apis/apis.dart'; +import '../../models/board_model.dart'; +import '../../models/market_articles.dart'; +import '../pages/board/market_board_page.dart'; +import '../pages/board/market_posting_board_page.dart'; + + +class MarketBoardDialog extends StatelessWidget{ + final BuildContext context; + final MarketBoard marketBoard; + final MemberDetails memberDetails; + final ScreenArguments screenArguments; + + + + + const MarketBoardDialog({Key? key, required this.context, required this.marketBoard, required this.memberDetails, required this.screenArguments}) : super(key:key); + + @override + Widget build(BuildContext context) { + if(Platform.isAndroid) + return androidDialog(); + else + return iOSDialog(); + } + + Widget androidDialog(){ + return Dialog( + elevation: 0, + backgroundColor: Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0).r, + ), + child: Container( + padding: EdgeInsets.all(30).r, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'chatting-dialog1'.tr(), + style: TextStyle( + fontSize: 16.spMin, + fontWeight: FontWeight.bold), + ), + SizedBox(height: 25.h,), + //report + InkWell( + onTap: (){ + Navigator.pop(context); + showDialog( + context: context, + builder: (builder) => ReportDialog(partner: Partner(), context: context)); + }, + child: Container( + padding: EdgeInsets.all(13).r, + decoration: BoxDecoration( + color: Color(0xff7898FF), + borderRadius: BorderRadius.circular(5).r), + alignment: Alignment.center, + child: Text( + 'chatting-report1'.tr(), + style: TextStyle(color: Colors.white), + ), + ), + ), + SizedBox(height: 25.h,), + memberDetails.email == marketBoard.member!.email ? + Column( + children: [ + //delete + InkWell( + onTap: (){ + showDialog( + context: context, + builder: (_) => FutureBuilder( + future: APIs.deleteMarketArticle(marketBoard.articleId ?? 0), + builder: (BuildContext context, + AsyncSnapshot snapshot) { + if (snapshot.hasData == false) { + //받아오는 동안 + return Container( + child: Image( + image: AssetImage( + "assets/illustration/loading_01.gif"))); + } else{ + //받아온 후 + WidgetsBinding.instance.addPostFrameCallback((_) { + Navigator.pop(context); + Navigator.pop(context); + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (BuildContext context) => MarketBoardPage( + screenArguments: screenArguments, + memberDetails:memberDetails, + marketBoard: marketBoard, + ), + )); + + + }); + return Container( + child: Image( + image: AssetImage( + "assets/illustration/loading_01.gif"))); + } + + })); + }, + child: Container( + padding: EdgeInsets.all(13).r, + decoration: BoxDecoration( + color: Color(0xff7898FF), + borderRadius: BorderRadius.circular(5).r), + alignment: Alignment.center, + child: Text( + 'delete'.tr(), + style: TextStyle(color: Colors.white), + ), + ), + ), + SizedBox(height: 25.h,), + //modify + InkWell( + onTap: (){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MarketBoardPostPage( + screenArguments: screenArguments, + marketBoard: marketBoard,// 수정 모드에서 데이터 전달 + ), + ) + ); + }, + child: Container( + padding: EdgeInsets.all(13).r, + decoration: BoxDecoration( + color: Color(0xff7898FF), + borderRadius: BorderRadius.circular(5).r), + alignment: Alignment.center, + child: Text( + 'modity'.tr(), + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ): SizedBox(), + ], + ), + ), + ); + } + + Widget iOSDialog(){ + + return Dialog( + elevation: 0, + backgroundColor: Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0).r, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20.0), + topRight: Radius.circular(20.0), + ).r, + onTap: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (builder) => iOSReportDialog()); + }, + child: Container( + height: 80.h, + alignment: Alignment.center, + child: Text( + 'chatting-report1'.tr(), + style: TextStyle( + fontSize: 16.0.spMin, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + memberDetails.email == marketBoard.member!.email ? Divider(thickness: 1,):SizedBox(), + memberDetails.email == marketBoard.member!.email ? InkWell( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20.0), + bottomRight: Radius.circular(20.0), + ).r, + onTap: () { + showDialog( + context: context, + builder: (_) => FutureBuilder( + future: APIs.deleteArticles(marketBoard.articleId ?? 0), + builder: (BuildContext context, + AsyncSnapshot snapshot) { + if (snapshot.hasData == false) { + //받아오는 동안 + return Container( + child: Image( + image: AssetImage( + "assets/illustration/loading_01.gif"))); + } else{ + //받아온 후 + WidgetsBinding.instance.addPostFrameCallback((_) { + Navigator.pop(context); + Navigator.pop(context); + + }); + return Container( + child: Image( + image: AssetImage( + "assets/illustration/loading_01.gif"))); + } + + })); + }, + child: Container( + height: 80.h, + alignment: Alignment.center, + child: Text( + 'delete'.tr(), + style: TextStyle( + fontSize: 16.0.spMin, + fontWeight: FontWeight.bold, + ), + ), + ), + ): SizedBox(), + ], + ) + ); + } + +} + diff --git a/lib/views/pages/board/market_board_page.dart b/lib/views/pages/board/market_board_page.dart index cac77d9..bdfb728 100644 --- a/lib/views/pages/board/market_board_page.dart +++ b/lib/views/pages/board/market_board_page.dart @@ -21,15 +21,15 @@ import '../../../models/market_articles.dart'; import '../../../models/message_model.dart'; import '../../../providers/bookmarks_provider.dart'; import '../../components/board_drawer_widget.dart'; +import '../../components/market_dialog_widget.dart'; class MarketBoardPage extends StatefulWidget { - const MarketBoardPage({super.key, required this.screenArguments, required this.marketBoard, required this.index,}); + const MarketBoardPage({super.key, required this.screenArguments, required this.marketBoard, required this.memberDetails}); final ScreenArguments screenArguments; final MarketBoard? marketBoard; - final int index; - - //final MemberDetails memberDetails; + final MemberDetails memberDetails; + // final int index; @@ -47,17 +47,16 @@ class _MarketBoardPageState extends State { void initState() { super.initState(); - _fetchMarketArticles(); + fetchMarketArticles(); final bookmarkProvider = Provider.of(context, listen: false); print(10); bookmarkProvider.getbookmarksCounts(); print(11); - print('북마크될라나: ${bookmarkProvider.marketArticleBookmarkCount?[widget.index]}'); - print('북마크: ${bookmarkProvider.marketArticleBookmarkCount?[widget.index] == 0}'); + } - Future _fetchMarketArticles() async { + Future fetchMarketArticles() async { try { var fetchedData = await APIs.getMarketArticles(); // API 호출 함수 호출 print(fetchedData); @@ -70,13 +69,6 @@ class _MarketBoardPageState extends State { // print('comment:${marketBoard.commentsCount}'); } - /*final bookmarkProvider = Provider.of(context, listen: false); - print(10); - bookmarkProvider.getbookmarksCounts(); - print(11); - print('북마크될라나: ${bookmarkProvider.marketArticleBookmarkCount?[widget.index]}'); - print('북마크: ${bookmarkProvider.marketArticleBookmarkCount?[widget.index] == 0}'); - print('북마크개수:${bookmarkProvider.marketArticleBookmarkCount}');*/ }); } catch (error) { @@ -313,29 +305,10 @@ class _MarketBoardPageState extends State { ), ), InkWell( - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return SimpleDialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 20.0), - ), - children: [ - SimpleDialogOption( - child: Text('${'modify'.tr()}'), - onPressed: () {}, - ), - SimpleDialogOption( - child: Text( - '${'chatting-report1'.tr()}'), - onPressed: () {}, - ), - ], - ); - }, - ); + onTap: (){ + showDialog(context: context, builder: (builder){ + return MarketBoardDialog(context: context, marketBoard: marketBoard, memberDetails: widget.memberDetails, screenArguments: widget.screenArguments,); + }); }, child: SvgPicture.asset( 'assets/icon/ICON_more.svg', diff --git a/lib/views/pages/board/market_posting_board_page.dart b/lib/views/pages/board/market_posting_board_page.dart index 8b50765..0a842f5 100644 --- a/lib/views/pages/board/market_posting_board_page.dart +++ b/lib/views/pages/board/market_posting_board_page.dart @@ -20,13 +20,13 @@ import 'package:multiple_images_picker/multiple_images_picker.dart'; import 'package:image_picker/image_picker.dart'; import '../../components/button.dart'; +import 'market_board_page.dart'; class MarketBoardPostPage extends StatefulWidget { - - const MarketBoardPostPage({super.key,required this.screenArguments, this.marketBoard, }); -final ScreenArguments screenArguments; -final MarketBoard? marketBoard; + const MarketBoardPostPage({super.key,required this.screenArguments, this.marketBoard}); + final ScreenArguments screenArguments; + final MarketBoard? marketBoard; @override @@ -36,6 +36,7 @@ final MarketBoard? marketBoard; class _MarketBoardPostPageState extends State { final GlobalKey _formKey = GlobalKey(); bool _isButtonEnabled = false; + bool _isEditMode = false; //수정여부 TextEditingController _titleController = TextEditingController(); TextEditingController _priceController = TextEditingController(); @@ -46,6 +47,10 @@ class _MarketBoardPostPageState extends State { ]; String productStatus = ''; + final _marketArticleStatusList = ['sale'.tr(), 'sold-out'.tr()]; + String? marketArticleStatus = 'sale'.tr(); + + //List images = []; final picker = ImagePicker(); @@ -122,6 +127,22 @@ class _MarketBoardPostPageState extends State { } } + void initState() { + super.initState(); + + // 수정 모드인 경우, 전달된 게시물 데이터 초기화 + if (widget.marketBoard != null) { + _isEditMode = true; + _titleController.text = widget.marketBoard!.title!; + _priceController.text = widget.marketBoard!.price.toString(); + _contentController.text = widget.marketBoard!.content!; + productStatus = getProductStatusText(widget.marketBoard!.productStatus!); + marketArticleStatus = getStatusText(widget.marketBoard!.marketArticleStatus!); + + _images = widget.marketBoard!.imageUrls!.map((imageUrl) => XFile(imageUrl)).toList(); + } + } + @override Widget build(BuildContext context) { final double screenWidth = MediaQuery.of(context).size.height; @@ -205,27 +226,65 @@ class _MarketBoardPostPageState extends State { border: Border.all(color: Color(0xFFEBEBEB)), borderRadius: BorderRadius.circular(10), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child:_isEditMode + ? + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SizedBox(width: 15.w), + SizedBox(width: 5.w,), SvgPicture.asset( 'assets/icon/icon_dropdown.svg', width: 4.r, height: 4.r, color: Color(0xff888888), ), - Text('sale'.tr(), - style: TextStyle( - color: Color(0xff888888), - fontSize:14.spMin + DropdownButtonHideUnderline( + child: DropdownButton( + icon: const SizedBox.shrink(), + style: TextStyle( + color: Color(0xff888888), + fontSize: 14.spMin, + ), + items: _marketArticleStatusList.map((value) { + return DropdownMenuItem( + child: Text( + value, + style: TextStyle( + fontSize: 14.spMin, + color: Color(0xff888888), + ), + ), + value: value, + ); + }).toList(), + value: marketArticleStatus, + onChanged: (value) { + setState(() { + marketArticleStatus = value; + }); + }, ), ), - SizedBox(width: 15.w), ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SvgPicture.asset( + 'assets/icon/icon_dropdown.svg', + width: 4.r, + height: 4.r, + color: Color(0xff888888), + ), + Text('sale'.tr(), + style: TextStyle( + color: Color(0xff888888), + fontSize:14.spMin + ), ), - ) - ], + + ]) + )], ), //제목 Divider(thickness: 1.h,color:Color(0xffEBEBEB)), Row( @@ -429,26 +488,62 @@ class _MarketBoardPostPageState extends State { content: _contentController.text, price: int.parse(_priceController.text), productStatus: productStatus, + marketArticleStatus: marketArticleStatus, imageUrls: _images.map((image) => image.path).toList(), ); try { - bool success = await APIs.createMarketArticle(marketArticle); + if (_isEditMode) { + // 수정 모드인 경우 게시물 업데이트 + Map updateData = { + 'title': _titleController.text, + 'content': _contentController.text, + 'price': int.parse(_priceController.text), + 'productStatus': productStatus, + 'marketArticleStatus':marketArticleStatus, + 'imageUrls': _images.map((image) => image.path).toList(), + }; + print(marketArticleStatus); - if (success) { - print('게시물 생성 성공!!!'); + bool success = await APIs.updateMarketArticle(widget.marketBoard!.articleId ?? 0, updateData); + print('1'); + print(updateData); Navigator.of(context).pop(); // 이전 페이지로 이동 - } else { - print('게시물 생성 실패...'); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Fail'), - duration: Duration(seconds: 3), - ), - ); + + + if (success) { + print('게시물 수정 성공!!!'); + Navigator.of(context).pop(); + } else { + print('게시물 수정 실패...'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Fail'), + duration: Duration(seconds: 3), + ), + ); + } + } else + { + // 생성 모드인 경우 게시물 생성 + bool success = await APIs.createMarketArticle(marketArticle); + Navigator.of(context).pop(); // 이전 페이지로 이동 + + if (success) { + print('게시물 생성 성공!!!'); + Navigator.of(context).pop(); // 이전 페이지로 이동 + } else { + print('게시물 생성 실패...'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Fail'), + duration: Duration(seconds: 3), + ), + ); + } } } catch (error) { - print('Error creating market article: $error'); + print('Error: $error'); } } }, @@ -473,3 +568,40 @@ class _MarketBoardPostPageState extends State { _images.isNotEmpty; } } +String getProductStatusText(String? productStatus) { + List whatStatus = [ + 'Brand_New'.tr(), + 'Almost_New'.tr(), + 'Slight_Defect'.tr(), + 'Used'.tr(), + ]; + + switch (productStatus) { + case '새 것': + return whatStatus[0]; + case '거의 새 것': + return whatStatus[1]; + case '약간의 하자': + return whatStatus[2]; + case '사용감 있음': + return whatStatus[3]; + default: + return ''; + } +} + +String getStatusText(String? marketArticleStatus){ + List Status = [ + 'sale'.tr(), + 'sold-out'.tr(), + ]; + + switch (marketArticleStatus) { + case '판매 중': + return Status[0]; + case '판매 완료': + return Status[1]; + default: + return ''; + } +} \ No newline at end of file