import 'dart:async'; import 'dart:convert'; import 'dart:developer'; import 'package:async/async.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:glassmorphism/glassmorphism.dart'; import 'package:lottie/lottie.dart'; import 'package:scgateway_flutter_plugin/scgateway_flutter_plugin.dart'; import 'package:traderscircuit/Utils/Common/CommonBottomNavigation.dart'; import 'package:traderscircuit/Utils/Common/commonBotton.dart'; import 'package:traderscircuit/Utils/Common/sized_box.dart'; import 'package:traderscircuit/Utils/text.dart'; import 'package:traderscircuit/view/MainScreen/MainScreen.dart'; import 'package:traderscircuit/view/Sidemenu/Sidemenu.dart'; import 'package:traderscircuit/view/onBoarding/splashScreen1.dart'; import '../../../Utils/Common/comonGlassmorphicContainer.dart'; import '../../../model/SmallCaseModel/broker_account_model.dart'; import '../../../view_model/SmallCaseApi/smallcase_api_methods.dart'; class Portfolio extends StatefulWidget { const Portfolio({super.key}); @override State createState() => _PortfolioState(); } class _PortfolioState extends State { final GlobalKey _scaffoldKey1 = GlobalKey(); List containerTexts = ["Swing Trade", "Multibagger", "Options"]; final selectedIndex = 0.obs; RxBool noBrokerAvailable = true.obs; FutureGroup fetchUserIdAndBrokerAccounts = FutureGroup(); List myBrokerAccounts = []; @override void initState() { fetchUserIdAndBrokerAccounts.add(fetchBrokerAccounts()); fetchUserIdAndBrokerAccounts.close(); fetchUserIdAndBrokerAccounts.future.then((value) { log(value.toString()); try { myBrokerAccounts = value[0] as List; } catch (e) {} debugPrint("myBrokerAccounts.length ${myBrokerAccounts.length}"); if (myBrokerAccounts.isEmpty) { noBrokerAvailable.value = true; } else { noBrokerAvailable.value = false; } }); super.initState(); } Widget holdings() { return Obx(() { WidgetsBinding.instance.addPostFrameCallback((_) { if (selectedIndex.value == 1) _unlockbottomsheet(); }); return selectedIndex.value == 0 ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ sizedBoxHeight(25.h), GestureDetector( onTap: () { log(myBrokerAccounts[selectedIndex.value].brokerName!); ScgatewayFlutterPlugin.setConfigEnvironment( GatewayEnvironment.PRODUCTION, 'traderscircuit', false, [myBrokerAccounts[selectedIndex.value].brokerName!], ); fetchHoldingsImportTxnId(myBrokerAccounts .elementAt(selectedIndex.value) .authToken!) .then((txnIdResponse) { if (txnIdResponse != "Failed") { fetchHoldingsImportTxnId(myBrokerAccounts .elementAt(selectedIndex.value) .authToken!) .then((txnIdResponse) { debugPrint('SESSION STARTED'); debugPrint( 'AUTH TOKEN: ${myBrokerAccounts.elementAt(selectedIndex.value).authToken!}'); String txnId = txnIdResponse; debugPrint('TXN ID $txnId'); ScgatewayFlutterPlugin.triggerGatewayTransaction( txnId) .then( (txnRes) { debugPrint('TXN RES $txnRes'); if (txnRes != null) { fetchHoldings( //holdingsAuthToken myBrokerAccounts .elementAt(selectedIndex.value) .authToken!) .then( (holdings) { setState(() {}); }, ); } }, ); }); } else { debugPrint('SESSION EXPIRED'); onTxnTimeout(); } }); }, child: Align( alignment: Alignment.centerRight, child: Container( width: 180, padding: const EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: const Color(0xff6C0000), ), child: Center(child: text15W600("Update Stock's")), ), ), ), sizedBoxHeight(25.h), Table( children: [ TableRow( children: [ TableCell( child: Text( "Stock Name", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), ), ), TableCell( child: Text( "AVG Price", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), ), ), TableCell( child: Text( "Quantity", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), ), ), ], ), ], ), const Divider( color: Color(0xFF3A3A3A), ), Expanded( child: ListView.separated( physics: const BouncingScrollPhysics(), shrinkWrap: true, itemCount: 16, itemBuilder: ((context, index) { return Table( children: [ TableRow( children: [ TableCell( child: Text( "TATA MOTORS", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), ), ), TableCell( child: Text( "416.66", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), ), ), TableCell( child: Text( "3", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), ), ), ], ), ], ); }), separatorBuilder: (BuildContext context, int index) { return const Divider(); }, ), ), SizedBox( height: 30.h, ) ], ) : selectedIndex == 1 ? const Column( children: [], ) : const Column( children: [], ); }); } void onTxnTimeout() { bool showDialogContent = true; bool replaceDialogContentWithLoader = false; showDialog( barrierDismissible: false, context: context, builder: (context) => AlertDialog(content: StatefulBuilder( builder: (context, setDialogState) { return Column( mainAxisSize: MainAxisSize.min, children: [ Visibility( visible: showDialogContent, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text("Transaction Timeout", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, )), const SizedBox(height: 18), const Text("You need to login again to continue"), const SizedBox(height: 18), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ OutlinedButton( onPressed: () { Get.back(); }, child: const Text("Cancel"), ), const SizedBox(width: 12), ElevatedButton( onPressed: () { setDialogState(() { showDialogContent = false; replaceDialogContentWithLoader = true; }); //login again fetchAuthToken().then((fetchedAuthToken) { debugPrint( "fetchedAuthToken $fetchedAuthToken"); fetchBrokerConnectTxnId( authToken: fetchedAuthToken) .then( (txnId) => ScgatewayFlutterPlugin.initGateway( fetchedAuthToken, ).then( (value) => ScgatewayFlutterPlugin .triggerGatewayTransaction( txnId, ).then( (loginRes) { if (loginRes != null) { var data = jsonDecode(loginRes)['data']; if (data != null) { String authToken = jsonDecode( data)['smallcaseAuthToken']; String brokerName = jsonDecode(data)['broker']; String txnId = jsonDecode( data)['transactionId']; postBrokerAccount( brokerName: brokerName, authToken: authToken, txnId: txnId) .then((isPosted) { if (isPosted) { Get.back(); } }); } } }, ), ), ); }); }, child: const Text("Login Again"), ), ], ) ], ), ), Visibility( visible: replaceDialogContentWithLoader, child: const Padding( padding: EdgeInsets.symmetric(vertical: 28.0), child: Center( child: CircularProgressIndicator(), ), ), ) ], ); }, ))); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { _onBackButtonPressed(context); return true; // Return true to allow the pop action }, child: Scaffold( key: _scaffoldKey1, backgroundColor: Colors.black, drawerEnableOpenDragGesture: false, drawer: const SideMenu(), extendBody: true, appBar: AppBar( scrolledUnderElevation: 0.0, backgroundColor: Colors.black, elevation: 0, automaticallyImplyLeading: false, titleSpacing: 0, leading: InkWell( onTap: () { _scaffoldKey1.currentState?.openDrawer(); }, child: Center( child: Image.asset( 'assets/images/png/menu.png', height: 15.h, width: 20.w, ), ), ), ), body: Obx( () => Stack( children: [ const CommonBlurLeft(), const CommonBlurRight(), !noBrokerAvailable.value ? Stack( children: [ Padding( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 16), child: ListView( physics: const NeverScrollableScrollPhysics(), children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ text25W600("My Portfolio"), GestureDetector( onTap: () { fetchAuthToken().then((fetchedAuthToken) { debugPrint( "fetchedAuthToken $fetchedAuthToken"); fetchBrokerConnectTxnId( authToken: fetchedAuthToken) .then( (txnId) => ScgatewayFlutterPlugin .initGateway(fetchedAuthToken) .then( (value) => ScgatewayFlutterPlugin .triggerGatewayTransaction( txnId, ).then( (loginRes) { log(loginRes.toString()); if (loginRes != null) { var data = jsonDecode( loginRes)['data']; if (data != null) { String authToken = jsonDecode(data)[ 'smallcaseAuthToken']; String brokerName = jsonDecode( data)['broker']; String txnId = jsonDecode( data)['transactionId']; postBrokerAccount( brokerName: brokerName, authToken: authToken, txnId: txnId) .then((isPosted) { ScaffoldMessenger.of( context) .clearSnackBars(); ScaffoldMessenger.of( context) .showSnackBar( const SnackBar( content: Text( 'New broker account is added'))); }); } } }, ), ), ); }); setState(() {}); }, child: Container( width: 80, padding: const EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: const Color(0xff6C0000), ), child: Center(child: text15W600("ADD")), ), ), ], ), const SizedBox( height: 10, ), DefaultTabController( length: myBrokerAccounts.length, // initialIndex: selectedIndex.value, child: Column( children: [ PortfolioTabBar( portfolioLength: myBrokerAccounts.length, portoflioName: myBrokerAccounts, ), SizedBox( height: 30.h, ), SizedBox( height: 570.h, child: TabBarView( children: List.generate( myBrokerAccounts.length, (count) { return DefaultTabController( length: 2, child: Column( children: [ const HoldingsTabBar(), Expanded( child: TabBarView( children: [ holdings(), PortfolioReview(), ], ), ), ], ), ); }), ), ), ], ), ), sizedBoxHeight(40.h), ], ), ), ], ) : Stack( children: [ Padding( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 16), child: Column( children: [ Row( children: [ text25W600("My Portfolio"), ], ), SizedBox( height: 30.h, ), Text( 'Please click the "Add" button below to add a portfolio.', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'hiragino', color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w400, ), ), const Spacer(), LottieBuilder.asset( "assets/images/png/TAdlX7YnR7 (1).json", width: 200.w, height: 200.h, ), const Spacer(), CommonBtn( text: "Add", onTap: () { fetchAuthToken().then((fetchedAuthToken) { debugPrint( "fetchedAuthToken $fetchedAuthToken"); fetchBrokerConnectTxnId( authToken: fetchedAuthToken) .then( (txnId) => ScgatewayFlutterPlugin.initGateway( fetchedAuthToken) .then( (value) => ScgatewayFlutterPlugin .triggerGatewayTransaction( txnId, ).then( (loginRes) { log(loginRes.toString()); if (loginRes != null) { var data = jsonDecode( loginRes)['data']; if (data != null) { String authToken = jsonDecode(data)[ 'smallcaseAuthToken']; String brokerName = jsonDecode( data)['broker']; String txnId = jsonDecode( data)['transactionId']; postBrokerAccount( brokerName: brokerName, authToken: authToken, txnId: txnId) .then((isPosted) { ScaffoldMessenger.of( context) .clearSnackBars(); ScaffoldMessenger.of( context) .showSnackBar( const SnackBar( content: Text( 'New broker account is added'))); fetchUserIdAndBrokerAccounts .add( fetchBrokerAccounts()); fetchUserIdAndBrokerAccounts .close(); fetchUserIdAndBrokerAccounts .future .then((value) { log(value.toString()); try { myBrokerAccounts = value[0] as List; } catch (e) {} debugPrint( "myBrokerAccounts.length ${myBrokerAccounts.length}"); if (myBrokerAccounts .isEmpty) { noBrokerAvailable .value = true; } else { noBrokerAvailable .value = false; } }); setState(() {}); }); } } }, ), ), ); }); }), const Spacer(), ], ), ), ], ) ], ), ), bottomNavigationBar: bottomnavigationbar(mainController), ), ); } Widget topContainer(String text, int index) { return Obx(() { return selectedIndex.value == index ? Container( height: 40.h, width: 126.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), color: const Color(0Xff6C0000), ), child: Center(child: text16W500(text)), ) : commonGlassContainer( width: 126.w, height: 40.h, borderradius: 5, customWidget: Center(child: text16W400(text)), ); }); } void _unlockbottomsheet() { Get.bottomSheet( SizedBox( height: 200, child: commonGlassContainer( width: double.infinity, height: 200, borderradius: 2, customWidget: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image.asset( // 'assets/images/png/Group 1000003722.png', // height: 100.h, // ), // sizedBoxHeight(25.h), text20W400('Please subscribed to unlock'), sizedBoxHeight(30.h), CommonBtn(text: 'Subscribe Now'), ], ), ), ), backgroundColor: Colors.black.withOpacity(0.3), ); } Widget PortfolioReview() { List> cardSwing = [ { 'text': 'Performance Overview:', 'content': 'Your portfolio has generated a total return of 15% over the past six months, outperforming the S&P 500 index by 5%.', }, { 'text': 'Asset Allocation:', 'content': 'Your portfolio is well-diversified, with 60% allocated to equities, 30% to bonds, and 10% to cash equivalents.', }, { 'text': 'Individual Holdings Analysis:', 'content': 'Your investment in Company XYZ has performed exceptionally well, with a 25% increase in share price since purchase, driven by strong quarterly earnings.', }, ]; return SingleChildScrollView( child: Column( children: [ sizedBoxHeight(20.h), Obx(() { return selectedIndex.value == 0 ? Column( children: List.generate(cardSwing.length, (index) { return Column( children: [ PortfolioCard( text: cardSwing[index]['text']!, content: cardSwing[index]['content']!, ), sizedBoxHeight(20.h) ], ); }), ) : selectedIndex.value == 1 ? Column( children: List.generate(cardSwing.length, (index) { return Column( children: [ PortfolioCard( text: cardSwing[index]['text']!, content: cardSwing[index]['content']!, ), sizedBoxHeight(20.h) ], ); }), ) : Column( children: List.generate(cardSwing.length, (index) { return Column( children: [ PortfolioCard( text: cardSwing[index]['text']!, content: cardSwing[index]['content']!, ), sizedBoxHeight(20.h) ], ); }), ); }), sizedBoxHeight(200.h) ], ), ); } Widget PortfolioCard({ required String text, required String content, }) { return commonGlassContainer( width: double.infinity, height: 166.h, borderradius: 8, customWidget: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 16.w), child: Row( children: [ Container( decoration: BoxDecoration( color: const Color(0xFF6C0000), borderRadius: BorderRadius.circular(2), ), height: 25.h, width: 4.w, ), sizedBoxWidth(15.w), text18W600(text), const Spacer(), ], ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 18), child: text16W400(content), ) ], ), ); } Widget HoldingCard({ required String text, required String content, }) { return commonGlassContainer( width: double.infinity, height: 166.h, borderradius: 8, customWidget: Column( children: [ Padding( padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 16.w), child: Row( children: [ GlassmorphicContainer( width: 47.w, height: 47.h, borderRadius: 100, blur: 10, alignment: Alignment.center, border: 0.9, linearGradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xff3A3A3A), Color(0xFF3A3A3A), ], ), borderGradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color.fromRGBO(70, 5, 1, 0.8), Color.fromRGBO(102, 102, 102, 0.8), ], ), child: Center( child: Image.asset( 'assets/images/png/TATAMOTORS.NS_BIG 1.png', width: 26.w, height: 23.h, ), ), ), sizedBoxWidth(15.w), text18W600(text), const Spacer(), ], ), ), Container( width: double.infinity, height: 1.h, color: const Color(0xFF3A3A3A), ), Padding( padding: const EdgeInsets.all(18), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ text14W400_979797('Portfolio Value'), sizedBoxHeight(5.h), SizedBox(width: 150.w, child: text15W600("₹ 40,000")) ], ), sizedBoxWidth(30.w), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ text14W400_979797('%P/L'), sizedBoxHeight(5.h), text14W400_00FF19("-36.006%") ], ) ], ), ], ), ) ], ), ); } Future _onBackButtonPressed(BuildContext context) async { bool? exitApp = await showDialog( context: context, builder: (context) { return AlertDialog( backgroundColor: const Color(0xFFFFF3E4), title: const Text('Exit App'), content: const Text('Do you really want to close the app?'), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(false); }, child: const Text( 'No', style: TextStyle( color: Color(0xff1B243D), ), ), ), TextButton( onPressed: () { SystemNavigator.pop(); Navigator.pop(context); }, child: const Text( 'Yes', style: TextStyle( color: Color(0xff1B243D), ), ), ) ], ); }); return exitApp ?? false; } } class HoldingsTabBar extends StatelessWidget { const HoldingsTabBar({super.key}); // Set the desired height @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( border: Border.all(color: const Color(0Xff3A3A3A)), borderRadius: BorderRadius.circular(8.r), ), padding: const EdgeInsets.all(8.0), // Set the desired padding child: TabBar( indicator: BoxDecoration( color: const Color(0xff6C0000), borderRadius: BorderRadius.circular(5), ), dividerColor: Colors.transparent, labelStyle: TextStyle( fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), indicatorSize: TabBarIndicatorSize.tab, indicatorColor: const Color(0xFFFFFFFF), labelColor: Colors.white, unselectedLabelColor: const Color(0xffFFFFFF), overlayColor: WidgetStateProperty.all(const Color(0xFFFFFFFF)), tabs: const [ Tab( text: 'Holdings', ), Tab( text: 'Portfolio Reviews', ), ]), ); } } class PortfolioTabBar extends StatelessWidget { final int portfolioLength; final List portoflioName; const PortfolioTabBar({ super.key, required this.portfolioLength, required this.portoflioName, }); // Set the desired height @override Widget build(BuildContext context) { return TabBar( tabAlignment: TabAlignment.start, isScrollable: true, dividerColor: Colors.transparent, labelStyle: TextStyle( fontSize: 18.sp, color: Colors.white, fontWeight: FontWeight.w500, fontFamily: 'hiragino'), indicatorSize: TabBarIndicatorSize.tab, indicatorWeight: 2, indicatorColor: const Color(0xff6C0000), labelColor: Colors.white, unselectedLabelColor: const Color(0xFF464646), overlayColor: WidgetStateProperty.all(const Color(0xFFFFFFFF)), tabs: List.generate(portfolioLength, (counter) { return Tab( text: portoflioName[counter].brokerName, ); })); } }