From 5f065b421c9e7735cf41e99e3b28a04c072f4529 Mon Sep 17 00:00:00 2001 From: Rajshinde046 Date: Mon, 29 Apr 2024 12:40:16 +0530 Subject: [PATCH] create ticket --- lib/Utils/Common/custom_drop_down.dart | 24 +- lib/Utils/api_urls.dart | 5 + lib/controller/contact_us_controller.dart | 9 + lib/data/network/network_api_services.dart | 3 - .../ContactUsModel/contact_us_cat_model.dart | 53 +++ .../ContactUsModel/contact_us_model.dart | 157 +++++++ lib/view/Sidemenu/ContentByte/AudioMore.dart | 1 - lib/view/Sidemenu/ContentByte/ReadMore.dart | 43 +- lib/view/Sidemenu/Sidemenu.dart | 8 +- .../Sidemenu/contactUs/contact_us_main.dart | 375 +++++++++++----- .../contactUs/create_ticket_bottom_sheet.dart | 408 ++++++++++-------- .../ContactUsApi/contact_us_api.dart | 62 +++ 12 files changed, 850 insertions(+), 298 deletions(-) create mode 100644 lib/model/ContactUsModel/contact_us_cat_model.dart create mode 100644 lib/model/ContactUsModel/contact_us_model.dart create mode 100644 lib/view_model/ContactUsApi/contact_us_api.dart diff --git a/lib/Utils/Common/custom_drop_down.dart b/lib/Utils/Common/custom_drop_down.dart index 1fd63cb..d01cbf5 100644 --- a/lib/Utils/Common/custom_drop_down.dart +++ b/lib/Utils/Common/custom_drop_down.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:traderscircuit/controller/contact_us_controller.dart'; import 'package:traderscircuit/controller/risk_profile_controller.dart'; import '../text.dart'; @@ -21,8 +22,8 @@ class CustomDropDownWidget extends StatefulWidget { } class _CustomDropDownWidgetState extends State { - RxBool onDropTap = false.obs; - RxString selectedValue = "".obs; + ContactUsController contactUsController = Get.put(ContactUsController()); + RiskProfileController riskProfileController = Get.put(RiskProfileController()); @@ -57,7 +58,8 @@ class _CustomDropDownWidgetState extends State { children: [ InkWell( onTap: () { - onDropTap.value = !onDropTap.value; + contactUsController.onDropTap.value = + !contactUsController.onDropTap.value; }, child: SizedBox( width: 398, @@ -88,7 +90,7 @@ class _CustomDropDownWidgetState extends State { ], ), border: Border( - top: onDropTap.value + top: contactUsController.onDropTap.value ? const BorderSide( width: 0, color: Color(0xFF393939)) : const BorderSide( @@ -113,8 +115,8 @@ class _CustomDropDownWidgetState extends State { left: 14, top: 16, child: Text( - selectedValue.isNotEmpty - ? selectedValue.value + contactUsController.selectedValue.isNotEmpty + ? contactUsController.selectedValue.value : widget.header, style: const TextStyle( color: Color(0xFFADADAD), @@ -128,7 +130,7 @@ class _CustomDropDownWidgetState extends State { Positioned( right: 14, top: 16, - child: onDropTap.value + child: contactUsController.onDropTap.value ? const Icon( Icons.keyboard_arrow_up_rounded, color: Colors.white, @@ -141,7 +143,7 @@ class _CustomDropDownWidgetState extends State { ), ), ), - !onDropTap.value + !contactUsController.onDropTap.value ? const SizedBox() : Opacity( opacity: 0.50, @@ -172,8 +174,10 @@ class _CustomDropDownWidgetState extends State { itemBuilder: (context, index) { return InkWell( onTap: () { - selectedValue.value = widget.listData[index]; - onDropTap.value = !onDropTap.value; + contactUsController.selectedValue.value = + widget.listData[index]; + contactUsController.onDropTap.value = + !contactUsController.onDropTap.value; updateOrAddData( widget.title, widget.listData[index]); }, diff --git a/lib/Utils/api_urls.dart b/lib/Utils/api_urls.dart index e59e44c..8a97cda 100644 --- a/lib/Utils/api_urls.dart +++ b/lib/Utils/api_urls.dart @@ -53,4 +53,9 @@ class ApiUrls { //Profile static String Getprofile = "${base}getuserDetails"; static String updateprofile = "${base}updateuserDetails"; + + //contact us + static String contactuscategory = "${base}get-ticket-categories"; + static String addTicket = "${base}store-ticket"; + static String getcontactus = "${base}get-ticket-data"; } diff --git a/lib/controller/contact_us_controller.dart b/lib/controller/contact_us_controller.dart index 41c82be..34559a5 100644 --- a/lib/controller/contact_us_controller.dart +++ b/lib/controller/contact_us_controller.dart @@ -1,8 +1,11 @@ import 'dart:io'; import 'package:get/get.dart'; +import 'package:traderscircuit/model/ContactUsModel/contact_us_cat_model.dart'; +import 'package:traderscircuit/model/ContactUsModel/contact_us_model.dart'; class ContactUsController extends GetxController { + RxBool isLoading = true.obs; //contact us page controller RxList attachmentFileList = [File("")].obs; RxList attachmentPathNameList = [""].obs; @@ -11,6 +14,12 @@ class ContactUsController extends GetxController { RxList attachmentFileDetailsList = [File("")].obs; RxList attachmentPathNameDetailsList = [""].obs; + ContactUsCatModel contactCatModel = ContactUsCatModel(); + ContactUsModel contactModel = ContactUsModel(); + + RxBool onDropTap = false.obs; + RxString selectedValue = "".obs; + RxList contactUsDetailsChatContent = [ { "initial_name": "SM", diff --git a/lib/data/network/network_api_services.dart b/lib/data/network/network_api_services.dart index 38ffc6c..297b210 100644 --- a/lib/data/network/network_api_services.dart +++ b/lib/data/network/network_api_services.dart @@ -1,12 +1,9 @@ import 'dart:convert'; import 'dart:developer'; - import 'package:flutter/foundation.dart'; - import 'package:shared_preferences/shared_preferences.dart'; import 'package:dio/dio.dart'; import 'package:traderscircuit/Utils/utils.dart'; - import '../../Utils/base_manager.dart'; import 'base_api_services.dart'; diff --git a/lib/model/ContactUsModel/contact_us_cat_model.dart b/lib/model/ContactUsModel/contact_us_cat_model.dart new file mode 100644 index 0000000..b4d8591 --- /dev/null +++ b/lib/model/ContactUsModel/contact_us_cat_model.dart @@ -0,0 +1,53 @@ +class ContactUsCatModel { + String? status; + int? statusCode; + String? message; + List? data; + + ContactUsCatModel({this.status, this.statusCode, this.message, this.data}); + + ContactUsCatModel.fromJson(Map json) { + status = json['status']; + statusCode = json['status_code']; + message = json['message']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(new Data.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['status'] = this.status; + data['status_code'] = this.statusCode; + data['message'] = this.message; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Data { + int? id; + String? name; + int? isActive; + + Data({this.id, this.name, this.isActive}); + + Data.fromJson(Map json) { + id = json['id']; + name = json['name']; + isActive = json['is_active']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['is_active'] = this.isActive; + return data; + } +} diff --git a/lib/model/ContactUsModel/contact_us_model.dart b/lib/model/ContactUsModel/contact_us_model.dart new file mode 100644 index 0000000..b845e7e --- /dev/null +++ b/lib/model/ContactUsModel/contact_us_model.dart @@ -0,0 +1,157 @@ +class ContactUsModel { + String? status; + int? statusCode; + String? message; + List? data; + + ContactUsModel({this.status, this.statusCode, this.message, this.data}); + + ContactUsModel.fromJson(Map json) { + status = json['status']; + statusCode = json['status_code']; + message = json['message']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(new Data.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['status'] = this.status; + data['status_code'] = this.statusCode; + data['message'] = this.message; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Data { + int? id; + String? uniqueTicketId; + int? iamPrincipalXid; + int? ticketCategoryXid; + String? description; + int? status; + int? isActive; + String? createdAt; + TicketCategory? ticketCategory; + List? ticketFiles; + + Data( + {this.id, + this.uniqueTicketId, + this.iamPrincipalXid, + this.ticketCategoryXid, + this.description, + this.status, + this.isActive, + this.createdAt, + this.ticketCategory, + this.ticketFiles}); + + Data.fromJson(Map json) { + id = json['id']; + uniqueTicketId = json['unique_ticket_id']; + iamPrincipalXid = json['iam_principal_xid']; + ticketCategoryXid = json['ticket_category_xid']; + description = json['description']; + status = json['status']; + isActive = json['is_active']; + createdAt = json['created_at']; + ticketCategory = json['ticket_category'] != null + ? new TicketCategory.fromJson(json['ticket_category']) + : null; + if (json['ticket_files'] != null) { + ticketFiles = []; + json['ticket_files'].forEach((v) { + ticketFiles!.add(new TicketFiles.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['unique_ticket_id'] = this.uniqueTicketId; + data['iam_principal_xid'] = this.iamPrincipalXid; + data['ticket_category_xid'] = this.ticketCategoryXid; + data['description'] = this.description; + data['status'] = this.status; + data['is_active'] = this.isActive; + data['created_at'] = this.createdAt; + if (this.ticketCategory != null) { + data['ticket_category'] = this.ticketCategory!.toJson(); + } + if (this.ticketFiles != null) { + data['ticket_files'] = this.ticketFiles!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class TicketCategory { + int? id; + String? name; + int? isActive; + String? createdAt; + + TicketCategory({this.id, this.name, this.isActive, this.createdAt}); + + TicketCategory.fromJson(Map json) { + id = json['id']; + name = json['name']; + isActive = json['is_active']; + createdAt = json['created_at']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['is_active'] = this.isActive; + data['created_at'] = this.createdAt; + return data; + } +} + +class TicketFiles { + int? id; + int? iamPrincipalXid; + int? ticketXid; + String? file; + int? isActive; + String? createdAt; + + TicketFiles( + {this.id, + this.iamPrincipalXid, + this.ticketXid, + this.file, + this.isActive, + this.createdAt}); + + TicketFiles.fromJson(Map json) { + id = json['id']; + iamPrincipalXid = json['iam_principal_xid']; + ticketXid = json['ticket_xid']; + file = json['file']; + isActive = json['is_active']; + createdAt = json['created_at']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['iam_principal_xid'] = this.iamPrincipalXid; + data['ticket_xid'] = this.ticketXid; + data['file'] = this.file; + data['is_active'] = this.isActive; + data['created_at'] = this.createdAt; + return data; + } +} diff --git a/lib/view/Sidemenu/ContentByte/AudioMore.dart b/lib/view/Sidemenu/ContentByte/AudioMore.dart index af07bd1..ea83cda 100644 --- a/lib/view/Sidemenu/ContentByte/AudioMore.dart +++ b/lib/view/Sidemenu/ContentByte/AudioMore.dart @@ -236,7 +236,6 @@ class _VideosMoreState extends State { .contentBytesCategoriesModel .data![index] .id!; - log(contentBytesController.filterId.toString()); handleSearch(searchControllera.text, contentBytesController.filterId.toString()); diff --git a/lib/view/Sidemenu/ContentByte/ReadMore.dart b/lib/view/Sidemenu/ContentByte/ReadMore.dart index 998e786..2a2a905 100644 --- a/lib/view/Sidemenu/ContentByte/ReadMore.dart +++ b/lib/view/Sidemenu/ContentByte/ReadMore.dart @@ -16,6 +16,7 @@ import 'package:traderscircuit/resources/routes/route_name.dart'; import 'package:traderscircuit/view/Sidemenu/ContentByte/PlayerWidget.dart'; import 'package:traderscircuit/view/Sidemenu/ContentByte/read_pdf.dart'; import 'package:traderscircuit/view/onBoarding/splashScreen1.dart'; +import 'package:traderscircuit/view_model/ContentBytesApi/content_bytes_api.dart'; class ReadMore extends StatefulWidget { const ReadMore({super.key}); @@ -29,6 +30,29 @@ class _VideosMoreState extends State { Get.put(ContentBytesController()); var data; RxBool isLoading = false.obs; + TextEditingController searchControllerr = TextEditingController(); + + @override + void initState() { + ContentBytesApi().getContentBytesData("", "reads", "").then((value) { + contentBytesController.contentBytesModel = + ContentBytesModel.fromJson(value.data); + contentBytesController.isApiCalling.value = false; + setState(() {}); + }); + super.initState(); + } + + void handleSearch(String query, String category) async { + await ContentBytesApi() + .getContentBytesData( + query, "reads", contentBytesController.filterId.toString()) + .then((value) { + contentBytesController.contentBytesModel = + ContentBytesModel.fromJson(value.data); + setState(() {}); + }); + } @override Widget build(BuildContext context) { @@ -62,13 +86,22 @@ class _VideosMoreState extends State { Row( children: [ SizedBox( - width: 290.w, - child: CustomTextFormField( - leadingIcon: Icon(Icons.search), + width: 295.w, + child: TextField( + controller: searchControllerr, + onChanged: (value) { + // Call method to handle search + handleSearch(value, ""); + }, + decoration: InputDecoration( + prefixIcon: Icon(Icons.search), + hintText: 'Search videos', + border: OutlineInputBorder(), + ), ), ), SizedBox( - width: 10.w, + width: 12.w, ), filter(), ], @@ -202,6 +235,8 @@ class _VideosMoreState extends State { .id!; log(contentBytesController.filterId.toString()); + handleSearch(searchControllerr.text, + contentBytesController.filterId.toString()); }, child: itemFilter(index)); }), diff --git a/lib/view/Sidemenu/Sidemenu.dart b/lib/view/Sidemenu/Sidemenu.dart index b35bdb8..8462020 100644 --- a/lib/view/Sidemenu/Sidemenu.dart +++ b/lib/view/Sidemenu/Sidemenu.dart @@ -121,7 +121,9 @@ class _SideMenuState extends State { decoration: ShapeDecoration( image: DecorationImage( image: NetworkImage( - ProfileObj!.data!.profilePhoto ?? ""), + + // ProfileObj!.data!.profilePhoto ?? + ""), fit: BoxFit.fill, ), shape: OvalBorder(), @@ -131,7 +133,9 @@ class _SideMenuState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - text18W400(ProfileObj!.data!.userName ?? ""), + text18W400( + //ProfileObj!.data!.userName ?? + ""), sizedBoxHeight(4.h), text18W400('My Profile'), ], diff --git a/lib/view/Sidemenu/contactUs/contact_us_main.dart b/lib/view/Sidemenu/contactUs/contact_us_main.dart index dab369e..82fabe2 100644 --- a/lib/view/Sidemenu/contactUs/contact_us_main.dart +++ b/lib/view/Sidemenu/contactUs/contact_us_main.dart @@ -3,8 +3,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:gap/gap.dart'; import 'package:get/get.dart'; import 'package:traderscircuit/controller/contact_us_controller.dart'; +import 'package:traderscircuit/model/ContactUsModel/contact_us_cat_model.dart'; +import 'package:traderscircuit/model/ContactUsModel/contact_us_model.dart'; import 'package:traderscircuit/resources/routes/route_name.dart'; - +import 'package:traderscircuit/view_model/ContactUsApi/contact_us_api.dart'; import '../../../Utils/Common/CommonAppbar.dart'; import '../../../Utils/Common/commonBotton.dart'; import '../../../Utils/text.dart'; @@ -20,113 +22,130 @@ class ContactUsMainScreen extends StatefulWidget { class _ContactUsMainScreenState extends State { ContactUsController contactUsController = Get.put(ContactUsController()); + + @override + void initState() { + ContactUsApi().getContactUsCategoriesData().then((value) { + contactUsController.contactCatModel = + ContactUsCatModel.fromJson(value.data); + }); + ContactUsApi().getContactUsData().then((value) { + contactUsController.contactModel = ContactUsModel.fromJson(value.data); + }); + + super.initState(); + } + @override Widget build(BuildContext context) { - return DefaultTabController( - length: 4, - child: Scaffold( - appBar: CommonAppbar( - height: 75, - titleTxt: "", - customActionWidget: text16W400(""), - ), - backgroundColor: Colors.black, - extendBody: true, - bottomNavigationBar: Padding( - padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 40), - child: SizedBox( - width: Get.width, - child: kycBtn( - text: "Create Ticket", - onTap: () { - contactUsController.attachmentFileList.clear(); - contactUsController.attachmentPathNameList.clear(); - CreateTicketBottomSheet().bottomSheet(context); - }, - bgClr: const Color(0xFF6C0000), - borderClr: const Color(0xFF990000), + return Obx(() => DefaultTabController( + length: 4, + child: Scaffold( + appBar: CommonAppbar( + height: 75, + titleTxt: "", + customActionWidget: text16W400(""), + ), + backgroundColor: Colors.black, + extendBody: true, + bottomNavigationBar: Padding( + padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 40), + child: SizedBox( + width: Get.width, + child: kycBtn( + text: "Create Ticket", + onTap: () { + contactUsController.attachmentFileList.clear(); + contactUsController.attachmentPathNameList.clear(); + CreateTicketBottomSheet().bottomSheet(context); + }, + bgClr: const Color(0xFF6C0000), + borderClr: const Color(0xFF990000), + ), + ), + ), + body: Stack( + children: [ + const CommonBlurLeft(), + const CommonBlurRight(), + Stack(children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 16), + child: ListView( + physics: const NeverScrollableScrollPhysics(), + children: [ + text25W600("Contact Us"), + const Gap(20), + text16W400("Hi Afrid,"), + text16W400("We are here to help you Us"), + const Gap(12), + TabBar( + tabAlignment: TabAlignment.start, + labelStyle: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w400, + fontFamily: "hiragino", + ), + isScrollable: true, + labelColor: Colors.white, + unselectedLabelColor: const Color(0xFF464646), + indicatorColor: const Color(0xFF6C0000), + indicatorSize: TabBarIndicatorSize.tab, + unselectedLabelStyle: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w500, + fontFamily: "hiragino", + ), + tabs: [ + Tab( + text: + "All Tickets (${contactUsController.contactModel.data!.length.toString()})"), + Tab(text: "Open Tickets (2)"), + Tab(text: "Closed (1)"), + Tab(text: "Resolved (1)"), + ], + ), + SizedBox( + height: 0.5.sh, + child: TabBarView(children: [ + ListView.builder( + itemCount: contactUsController + .contactModel.data!.length, + itemBuilder: (ctx, index) { + return ticketCardWidget(index, "ALL"); + }), + ListView.builder( + itemCount: dataL.length, + itemBuilder: (ctx, index) { + return ticketCardWidget(index, "OPEN"); + }), + ListView.builder( + itemCount: dataL.length, + itemBuilder: (ctx, index) { + return ticketCardWidget(index, "CLOSED"); + }), + ListView.builder( + itemCount: dataL.length, + itemBuilder: (ctx, index) { + return ticketCardWidget(index, "RESOLVED"); + }), + ]), + ) + ], + )), + ]), + ], ), ), - ), - body: Stack( - children: [ - const CommonBlurLeft(), - const CommonBlurRight(), - Stack(children: [ - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - child: ListView( - physics: const NeverScrollableScrollPhysics(), - children: [ - text25W600("Contact Us"), - const Gap(20), - text16W400("Hi Afrid,"), - text16W400("We are here to help you Us"), - const Gap(12), - TabBar( - labelStyle: TextStyle( - fontSize: 18.sp, - fontWeight: FontWeight.w400, - fontFamily: "hiragino", - ), - isScrollable: true, - labelColor: Colors.white, - unselectedLabelColor: const Color(0xFF464646), - indicatorColor: const Color(0xFF6C0000), - indicatorSize: TabBarIndicatorSize.label, - unselectedLabelStyle: TextStyle( - fontSize: 18.sp, - fontWeight: FontWeight.w500, - fontFamily: "hiragino", - ), - tabs: const [ - Tab(text: "All Tickets (2)"), - Tab(text: "Open Tickets (2)"), - Tab(text: "Closed (1)"), - Tab(text: "Resolved (1)"), - ], - ), - SizedBox( - height: 0.5.sh, - child: TabBarView(children: [ - ListView.builder( - itemCount: dataL.length, - itemBuilder: (ctx, index) { - return ticketCardWidget(index, "ALL"); - }), - ListView.builder( - itemCount: dataL.length, - itemBuilder: (ctx, index) { - return ticketCardWidget(index, "OPEN"); - }), - ListView.builder( - itemCount: dataL.length, - itemBuilder: (ctx, index) { - return ticketCardWidget(index, "CLOSED"); - }), - ListView.builder( - itemCount: dataL.length, - itemBuilder: (ctx, index) { - return ticketCardWidget(index, "RESOLVED"); - }), - ]), - ) - ], - )), - ]), - ], - ), - ), - ); + )); } } Widget ticketCardWidget(index, type) { ContactUsController contactUsController = Get.put(ContactUsController()); - return dataL[index]["type"] != type && type != "ALL" - ? const SizedBox() - : InkWell( + return contactUsController.contactModel.data!.elementAt(index).status != 0 + ? InkWell( onTap: () { contactUsController.attachmentFileDetailsList.clear(); contactUsController.attachmentPathNameDetailsList.clear(); @@ -161,21 +180,48 @@ Widget ticketCardWidget(index, type) { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - text16W600(dataL[index]["id"]), + text16W600(contactUsController.contactModel.data! + .elementAt(index) + .uniqueTicketId + .toString()), Row( children: [ - text16W500(dataL[index]["type"], - clr: dataL[index]["type"] == "OPEN" + text16W500( + contactUsController.contactModel.data! + .elementAt(index) + .status == + 1 + ? "Open" + : contactUsController.contactModel.data! + .elementAt(index) + .status == + 2 + ? "Closed" + : "Resolved", + clr: contactUsController.contactModel.data! + .elementAt(index) + .status == + 1 ? const Color(0xFFFFAD31) - : dataL[index]["type"] == "CLOSED" + : contactUsController.contactModel.data! + .elementAt(index) + .status == + 2 ? const Color(0xFF95CCFF) : const Color(0xFF34C759)), const Gap(8), CircleAvatar( radius: 10, - backgroundColor: dataL[index]["type"] == "OPEN" + backgroundColor: contactUsController + .contactModel.data! + .elementAt(index) + .status == + 1 ? const Color(0xFFFFAD31) - : dataL[index]["type"] == "CLOSED" + : contactUsController.contactModel.data! + .elementAt(index) + .status == + 2 ? const Color(0xFF95CCFF) : const Color(0xFF34C759), child: const Center( @@ -191,9 +237,16 @@ Widget ticketCardWidget(index, type) { ], ), const Gap(10), - text16W600(dataL[index]["date"]), + text16W600(contactUsController.contactModel.data! + .elementAt(index) + .createdAt + .toString()), const Gap(5), - text16W400(dataL[index]["category"]), + text16W400(contactUsController.contactModel.data! + .elementAt(index) + .ticketCategory! + .name + .toString()), const Gap(22), Container( padding: const EdgeInsets.symmetric( @@ -210,7 +263,11 @@ Widget ticketCardWidget(index, type) { ), ), child: Center( - child: text16W400(dataL[index]["desc"], + child: text16W400( + contactUsController.contactModel.data! + .elementAt(index) + .description + .toString(), clr: const Color(0xFF9E9E9E), textOver: TextOverflow.ellipsis), ), @@ -219,7 +276,107 @@ Widget ticketCardWidget(index, type) { ), ), ), - ); + ) + : contactUsController.contactModel.data!.elementAt(index).status != 1 && + type != "ALL" + ? InkWell( + onTap: () { + contactUsController.attachmentFileDetailsList.clear(); + contactUsController.attachmentPathNameDetailsList.clear(); + Get.toNamed(RouteName.contactUsMainDetails); + }, + child: Container( + width: Get.width, + height: 190, + margin: EdgeInsets.only(bottom: 18, top: index == 0 ? 15 : 0), + decoration: ShapeDecoration( + gradient: LinearGradient( + begin: const Alignment(0.98, -0.21), + end: const Alignment(-0.98, 0.21), + colors: [ + Colors.white.withOpacity(0.03999999910593033), + Colors.white.withOpacity(0.05999999865889549) + ], + ), + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFF393939)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 15, + horizontal: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + text16W600(contactUsController.contactModel.data! + .elementAt(index) + .ticketCategoryXid + .toString()), + Row( + children: [ + text16W500(dataL[index]["type"], + clr: dataL[index]["type"] == "OPEN" + ? const Color(0xFFFFAD31) + : dataL[index]["type"] == "CLOSED" + ? const Color(0xFF95CCFF) + : const Color(0xFF34C759)), + const Gap(8), + CircleAvatar( + radius: 10, + backgroundColor: dataL[index]["type"] == "OPEN" + ? const Color(0xFFFFAD31) + : dataL[index]["type"] == "CLOSED" + ? const Color(0xFF95CCFF) + : const Color(0xFF34C759), + child: const Center( + child: Icon( + Icons.check_rounded, + size: 15, + color: Colors.white, + ), + ), + ) + ], + ), + ], + ), + const Gap(10), + text16W600(dataL[index]["date"]), + const Gap(5), + text16W400(dataL[index]["category"]), + const Gap(22), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + ), + width: Get.width, + height: 50, + decoration: ShapeDecoration( + color: Colors.black.withOpacity(0.03999999910593033), + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1, color: Color(0xFF393939)), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Center( + child: text16W400(dataL[index]["desc"], + clr: const Color(0xFF9E9E9E), + textOver: TextOverflow.ellipsis), + ), + ) + ], + ), + ), + ), + ) + : SizedBox(); } List dataL = [ diff --git a/lib/view/Sidemenu/contactUs/create_ticket_bottom_sheet.dart b/lib/view/Sidemenu/contactUs/create_ticket_bottom_sheet.dart index 0a2b31a..2402585 100644 --- a/lib/view/Sidemenu/contactUs/create_ticket_bottom_sheet.dart +++ b/lib/view/Sidemenu/contactUs/create_ticket_bottom_sheet.dart @@ -1,10 +1,15 @@ +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/svg.dart'; import 'package:gap/gap.dart'; -import 'package:get/get.dart'; +import 'package:get/get.dart' hide MultipartFile, FormData; +import 'package:traderscircuit/Utils/base_manager.dart'; import 'package:traderscircuit/Utils/text.dart'; +import 'package:traderscircuit/Utils/utils.dart'; +import 'package:traderscircuit/resources/routes/route_name.dart'; +import 'package:traderscircuit/view_model/ContactUsApi/contact_us_api.dart'; import '../../../Utils/Common/CustomTextFormField.dart'; import '../../../Utils/Common/FilePicker.dart'; @@ -12,13 +17,82 @@ import '../../../Utils/Common/commonBotton.dart'; import '../../../Utils/Common/custom_drop_down.dart'; import '../../../controller/contact_us_controller.dart'; import 'ticket_confirmed_bottom_sheet.dart'; +import 'package:path/path.dart' as path; class CreateTicketBottomSheet { + final GlobalKey _addTicketform = GlobalKey(); TextEditingController descriptionController = TextEditingController(); ContactUsController contactUsController = Get.put(ContactUsController()); + int? ticketid; + + // var ticketMulti; + bottomSheet( BuildContext context, ) { + //names + List namesList = []; + for (var item in contactUsController.contactCatModel.data!) { + namesList.add(item.name!); + } + + // Find id corresponding to selectedValue + for (var item in contactUsController.contactCatModel.data!) { + if (item.name == contactUsController.selectedValue.toString()) { + ticketid = item.id; + break; // Stop loop once match is found + } + } + + _addTicket() async { + List ticketlist = []; + + for (var file in contactUsController.attachmentFileList + .where((file) => file != null)) { + ticketlist.add( + await MultipartFile.fromFile( + file!.path, + filename: path.basename(file.path), + ), + ); + } + + // ticketMulti = await MultipartFile.fromFile( + // contactUsController.attachmentFileList, + // filename: + // path.basename(contactUsController.attachmentFileList.toString()), + // ); + + final isValid = _addTicketform.currentState?.validate(); + if (isValid!) { + Utils.loader(); + FormData formdata = FormData.fromMap({ + "description": descriptionController.text, + "ticket_category_xid": ticketid, + "files[]": ticketlist, + }); + + final resp = await ContactUsApi().addTicketApi(formdata); + if (resp.status == ResponseStatus.SUCCESS) { + Get.back(); + print("success"); + TicketConfirmedBottomSheet().bottomSheet(context); + } else if (resp.status == ResponseStatus.PRIVATE) { + Get.back(); + String? message = resp.data['message']; + Utils.showToast("$message"); + } else if (resp.status == ResponseStatus.ERROR) { + Get.back(); + String? message = resp.data['message']; + Utils.showToast("$message"); + } else { + Get.back(); + String? message = resp.data['message']; + Utils.showToast("$message"); + } + } + } + return showModalBottomSheet( useSafeArea: true, isScrollControlled: true, @@ -37,175 +111,171 @@ class CreateTicketBottomSheet { padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), child: Wrap( children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - GestureDetector( - onTap: () { - Get.back(); - }, - child: SvgPicture.asset( - "assets/images/svg/cross_cancel.svg")), - ], - ), - const Gap(16), - text18W600("Raise a Ticket"), - const Gap(20), - const CustomDropDownWidget( - header: "Choose your query", - listData: [ - "Account Management", - "Technical Support", - "Billing and Payments", - "Feedback and Suggestions", - "Complaints and Disputes", - "Subscriptions", - "Portfolio", - "Content Buytes", - "Market Insights" - ], - title: "", - ), - const Gap(14), - Stack( - children: [ - CustomTextFormField3( - texttype: TextInputType.multiline, - hintText: "Description (min 30 characters)", - textEditingController: descriptionController, - maxlines: 8, - validator: (value) { - if (value.isEmpty) { - return 'Enter your description'; - } else if (value.toString().length < 30) { - return 'Description should be minimum 30 characters'; - } - return null; - }, - inputFormatters: [ - LengthLimitingTextInputFormatter(150), - ], - ), - contactUsController.attachmentPathNameList.isEmpty - ? const SizedBox() - : Positioned( - bottom: 8, - left: 9, - right: 9, - child: SizedBox( - width: 1.sw, - height: 37.h, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: contactUsController - .attachmentPathNameList.length, - itemBuilder: (ctx, index) { - return Container( - width: 210.w, - height: 37.h, - margin: - const EdgeInsets.only(right: 5), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(8), - border: Border.all( - width: 1, - color: - const Color(0xFF3A3A3A))), - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - const Gap(6), - SvgPicture.asset( - "assets/images/svg/attachment_pin.svg"), - const Gap(6), - SizedBox( - width: 120, - child: FittedBox( - child: text12W400( - contactUsController - .attachmentPathNameList[ - index]))), - const Gap(15), - GestureDetector( - onTap: () { - contactUsController - .attachmentPathNameList - .removeAt(index); - contactUsController - .attachmentFileList - .removeAt(index); - }, - child: SvgPicture.asset( - "assets/images/svg/cross_cancel.svg", - color: - const Color(0xFF818181), - width: 8, - height: 8, - )), - ], - ), - ); - }), - )) - ], - ), - contactUsController.attachmentPathNameList.length >= 3 - ? const SizedBox() - : const Gap(10), - contactUsController.attachmentPathNameList.length >= 3 - ? const SizedBox() - : InkWell( - onTap: () async { - var result = await FilePickerMethod().pickFile(); - if (result != null) { - contactUsController.attachmentPathNameList - .clear(); - - for (var a in result) { - contactUsController.attachmentFileList.add(a); - } - - for (var a - in contactUsController.attachmentFileList) { - contactUsController.attachmentPathNameList - .add(FilePickerMethod() - .extractFileName(a?.path ?? '')); - } - } - }, - child: Row( - children: [ - SvgPicture.asset( - "assets/images/svg/attachment_pin.svg"), - const Gap(5), - text12W400( - "Add Attachment (Max 3 files of 2MB each / Optional)"), - ], - ), - ), - const Gap(20), - SizedBox( - width: Get.width, - child: kycBtn( - text: "Create Ticket", - onTap: () { - Get.back(); - TicketConfirmedBottomSheet().bottomSheet(context); - }, - bgClr: const Color(0xFF6C0000), - borderClr: const Color(0xFF990000), + Form( + key: _addTicketform, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () { + Get.back(); + }, + child: SvgPicture.asset( + "assets/images/svg/cross_cancel.svg")), + ], ), - ), - const Gap(30), - ], + const Gap(16), + text18W600("Raise a Ticket"), + const Gap(20), + CustomDropDownWidget( + header: "Choose your query", + listData: namesList, + title: "", + ), + const Gap(14), + Stack( + children: [ + CustomTextFormField3( + texttype: TextInputType.multiline, + hintText: "Description (min 30 characters)", + textEditingController: descriptionController, + maxlines: 8, + validator: (value) { + if (value.isEmpty) { + return 'Enter your description'; + } else if (value.toString().length < 30) { + return 'Description should be minimum 30 characters'; + } + return null; + }, + inputFormatters: [ + LengthLimitingTextInputFormatter(150), + ], + ), + contactUsController.attachmentPathNameList.isEmpty + ? const SizedBox() + : Positioned( + bottom: 8, + left: 9, + right: 9, + child: SizedBox( + width: 1.sw, + height: 37.h, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: contactUsController + .attachmentPathNameList.length, + itemBuilder: (ctx, index) { + return Container( + width: 210.w, + height: 37.h, + margin: + const EdgeInsets.only(right: 5), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(8), + border: Border.all( + width: 1, + color: const Color( + 0xFF3A3A3A))), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + const Gap(6), + SvgPicture.asset( + "assets/images/svg/attachment_pin.svg"), + const Gap(6), + SizedBox( + width: 120, + child: FittedBox( + child: text12W400( + contactUsController + .attachmentPathNameList[ + index]))), + const Gap(15), + GestureDetector( + onTap: () { + contactUsController + .attachmentPathNameList + .removeAt(index); + contactUsController + .attachmentFileList + .removeAt(index); + }, + child: SvgPicture.asset( + "assets/images/svg/cross_cancel.svg", + color: const Color( + 0xFF818181), + width: 8, + height: 8, + )), + ], + ), + ); + }), + )) + ], + ), + contactUsController.attachmentPathNameList.length >= 3 + ? const SizedBox() + : const Gap(10), + contactUsController.attachmentPathNameList.length >= 3 + ? const SizedBox() + : InkWell( + onTap: () async { + var result = + await FilePickerMethod().pickFile(); + if (result != null) { + contactUsController.attachmentPathNameList + .clear(); + + for (var a in result) { + contactUsController.attachmentFileList + .add(a); + } + + for (var a in contactUsController + .attachmentFileList) { + contactUsController.attachmentPathNameList + .add(FilePickerMethod() + .extractFileName(a?.path ?? '')); + } + } + }, + child: Row( + children: [ + SvgPicture.asset( + "assets/images/svg/attachment_pin.svg"), + const Gap(5), + text12W400( + "Add Attachment (Max 3 files of 2MB each / Optional)"), + ], + ), + ), + const Gap(20), + SizedBox( + width: Get.width, + child: kycBtn( + text: "Create Ticket", + onTap: () { + Get.back(); + // TicketConfirmedBottomSheet().bottomSheet(context); + _addTicket(); + }, + bgClr: const Color(0xFF6C0000), + borderClr: const Color(0xFF990000), + ), + ), + const Gap(30), + ], + ), ) ], ), diff --git a/lib/view_model/ContactUsApi/contact_us_api.dart b/lib/view_model/ContactUsApi/contact_us_api.dart new file mode 100644 index 0000000..67020d8 --- /dev/null +++ b/lib/view_model/ContactUsApi/contact_us_api.dart @@ -0,0 +1,62 @@ +import 'dart:developer'; + +import 'package:traderscircuit/Utils/api_urls.dart'; +import 'package:traderscircuit/Utils/base_manager.dart'; +import 'package:traderscircuit/data/network/network_api_services.dart'; + +class ContactUsApi { + Future> getContactUsCategoriesData() async { + final response = await NetworkApiServices() + .getApi(ApiUrls.contactuscategory, isAuth: true); + log(response.data.toString()); + if (response.status == ResponseStatus.SUCCESS) { + Map responseData = + Map.from(response.data); + if (responseData['status'] == "success") { + return response; + } else { + return ResponseData( + responseData['message'], ResponseStatus.FAILED); + } + } + return response; + } + + var data; + Future> addTicketApi(data) async { + final response = await NetworkApiServices().postApi( + // optionalpar: true, + data, + ApiUrls.addTicket, + ); + + if (response.status == ResponseStatus.SUCCESS) { + Map responseData = + Map.from(response.data); + if (responseData['status'] == "success") { + print("token is $response"); + } else { + return ResponseData( + responseData['message'], ResponseStatus.FAILED); + } + } + return response; + } + + Future> getContactUsData() async { + final response = + await NetworkApiServices().getApi(ApiUrls.getcontactus, isAuth: true); + log(response.data.toString()); + if (response.status == ResponseStatus.SUCCESS) { + Map responseData = + Map.from(response.data); + if (responseData['status'] == "success") { + return response; + } else { + return ResponseData( + responseData['message'], ResponseStatus.FAILED); + } + } + return response; + } +}