Merge pull request #80 from WDI-Ideas/jayeshjain25

Jayeshjain25
This commit is contained in:
Jayesh jain
2024-06-19 17:47:56 +05:30
committed by GitHub
7 changed files with 1538 additions and 196 deletions

View File

@@ -1,9 +1,10 @@
import 'package:get/get.dart';
import 'package:traderscircuit/view/MainScreen/HomeScreen.dart';
import 'package:traderscircuit/view/MainScreen/PastPerformance.dart';
import 'package:traderscircuit/view/MainScreen/Portfolio/PortfolioEmpty.dart';
import 'package:traderscircuit/view/MainScreen/ShortTrade.dart';
import '../../view/MainScreen/Portfolio/small_case_user_portoflio.dart';
class MainController extends GetxController {
var selectedIndex = 0.obs;
@@ -11,7 +12,7 @@ class MainController extends GetxController {
const HomeScreen(),
const ShortTrade(),
const PastPerformance(),
const Portfolio(),
const SmallCaseUserPortoflio(),
].obs;
void updateTab(int index) {

View File

@@ -0,0 +1,13 @@
import 'package:get/get.dart';
import 'package:traderscircuit/model/SmallCaseModel/broker_account_model.dart';
import 'package:traderscircuit/model/SmallCaseModel/holding_data_model.dart';
class SmallCaseController extends GetxController {
RxInt selectedTabIndex = 0.obs;
RxBool noBrokerAvailable = true.obs;
RxBool holdingDataAvailable = false.obs;
RxBool isLoading = false.obs;
RxBool isHoldingLoading = false.obs;
BrokerAccountModel myBrokerAccounts = BrokerAccountModel();
HoldingDataModel holdingDataModel = HoldingDataModel();
}

View File

@@ -0,0 +1,112 @@
class HoldingDataModel {
String? status;
int? statusCode;
String? message;
List<Data>? data;
HoldingDataModel({this.status, this.statusCode, this.message, this.data});
HoldingDataModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
statusCode = json['status_code'];
message = json['message'];
if (json['data'] != null) {
data = <Data>[];
json['data'].forEach((v) {
data!.add(Data.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['status'] = status;
data['status_code'] = statusCode;
data['message'] = message;
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Data {
int? id;
int? iamPrincipalXid;
int? smallCaseUserXid;
String? brokerName;
String? smallcaseAuthId;
String? lastUpdate;
String? snapshotDate;
String? stockName;
String? isin;
String? bseTicker;
String? nseTicker;
int? transactableQuantity;
String? averagePrice;
int? smallcaseQuantity;
int? isActive;
String? createdAt;
String? updatedAt;
Data(
{this.id,
this.iamPrincipalXid,
this.smallCaseUserXid,
this.brokerName,
this.smallcaseAuthId,
this.lastUpdate,
this.snapshotDate,
this.stockName,
this.isin,
this.bseTicker,
this.nseTicker,
this.transactableQuantity,
this.averagePrice,
this.smallcaseQuantity,
this.isActive,
this.createdAt,
this.updatedAt});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
iamPrincipalXid = json['iam_principal_xid'];
smallCaseUserXid = json['small_case_user_xid'];
brokerName = json['broker_name'];
smallcaseAuthId = json['smallcaseAuthId'];
lastUpdate = json['lastUpdate'];
snapshotDate = json['snapshotDate'];
stockName = json['stock_name'];
isin = json['isin'];
bseTicker = json['bseTicker'];
nseTicker = json['nseTicker'];
transactableQuantity = json['transactableQuantity'];
averagePrice = json['average_price'];
smallcaseQuantity = json['smallcaseQuantity'];
isActive = json['is_active'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['iam_principal_xid'] = iamPrincipalXid;
data['small_case_user_xid'] = smallCaseUserXid;
data['broker_name'] = brokerName;
data['smallcaseAuthId'] = smallcaseAuthId;
data['lastUpdate'] = lastUpdate;
data['snapshotDate'] = snapshotDate;
data['stock_name'] = stockName;
data['isin'] = isin;
data['bseTicker'] = bseTicker;
data['nseTicker'] = nseTicker;
data['transactableQuantity'] = transactableQuantity;
data['average_price'] = averagePrice;
data['smallcaseQuantity'] = smallcaseQuantity;
data['is_active'] = isActive;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
return data;
}
}

View File

@@ -22,6 +22,8 @@ import '../../../Utils/Common/comonGlassmorphicContainer.dart';
import '../../../model/SmallCaseModel/broker_account_model.dart';
import '../../../view_model/SmallCaseApi/smallcase_api_methods.dart';
int selectedTabIndex = 0;
class Portfolio extends StatefulWidget {
const Portfolio({super.key});
@@ -31,7 +33,6 @@ class Portfolio extends StatefulWidget {
class _PortfolioState extends State<Portfolio> {
final GlobalKey<ScaffoldState> _scaffoldKey1 = GlobalKey<ScaffoldState>();
List<String> containerTexts = ["Swing Trade", "Multibagger", "Options"];
final selectedIndex = 0.obs;
RxBool noBrokerAvailable = true.obs;
@@ -43,7 +44,7 @@ class _PortfolioState extends State<Portfolio> {
fetchUserIdAndBrokerAccounts.add(fetchBrokerAccounts());
fetchUserIdAndBrokerAccounts.close();
fetchUserIdAndBrokerAccounts.future.then((value) {
log(value.toString());
// log(value.toString());
try {
myBrokerAccounts = value[0] as List<Data>;
@@ -53,7 +54,9 @@ class _PortfolioState extends State<Portfolio> {
if (myBrokerAccounts.isEmpty) {
noBrokerAvailable.value = true;
} else {
noBrokerAvailable.value = false;
fetchHoldingForDB(myBrokerAccounts[1].brokerName!).then((value) {
noBrokerAvailable.value = false;
});
}
});
@@ -72,25 +75,27 @@ class _PortfolioState extends State<Portfolio> {
sizedBoxHeight(25.h),
GestureDetector(
onTap: () {
log(myBrokerAccounts[selectedIndex.value].brokerName!);
log(myBrokerAccounts[selectedTabIndex].brokerName!);
ScgatewayFlutterPlugin.setConfigEnvironment(
GatewayEnvironment.PRODUCTION,
'traderscircuit',
false,
[myBrokerAccounts[selectedIndex.value].brokerName!],
[
myBrokerAccounts.elementAt(selectedTabIndex).brokerName!
],
);
fetchHoldingsImportTxnId(myBrokerAccounts
.elementAt(selectedIndex.value)
.elementAt(selectedTabIndex)
.authToken!)
.then((txnIdResponse) {
if (txnIdResponse != "Failed") {
fetchHoldingsImportTxnId(myBrokerAccounts
.elementAt(selectedIndex.value)
.elementAt(selectedTabIndex)
.authToken!)
.then((txnIdResponse) {
debugPrint('SESSION STARTED');
debugPrint(
'AUTH TOKEN: ${myBrokerAccounts.elementAt(selectedIndex.value).authToken!}');
'AUTH TOKEN: ${myBrokerAccounts.elementAt(selectedTabIndex).authToken!}');
String txnId = txnIdResponse;
debugPrint('TXN ID $txnId');
ScgatewayFlutterPlugin.triggerGatewayTransaction(
@@ -102,7 +107,7 @@ class _PortfolioState extends State<Portfolio> {
fetchHoldings(
//holdingsAuthToken
myBrokerAccounts
.elementAt(selectedIndex.value)
.elementAt(selectedTabIndex)
.authToken!)
.then(
(holdings) {
@@ -128,7 +133,7 @@ class _PortfolioState extends State<Portfolio> {
borderRadius: BorderRadius.circular(12),
color: const Color(0xff6C0000),
),
child: Center(child: text15W600("Update Stock's")),
child: Center(child: text15W600("Refresh Stock's")),
),
),
),
@@ -235,7 +240,7 @@ class _PortfolioState extends State<Portfolio> {
)
],
)
: selectedIndex == 1
: selectedIndex.value == 1
? const Column(
children: [],
)
@@ -246,110 +251,77 @@ class _PortfolioState extends State<Portfolio> {
}
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"),
),
],
)
],
),
builder: (context) => AlertDialog(
backgroundColor: const Color(0xFFFFF3E4),
title: const Text(
"Transaction Timeout",
),
content: const Text("You need to login again to continue"),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(false);
},
child: const Text(
'No',
style: TextStyle(
color: Color(0xff1B243D),
),
Visibility(
visible: replaceDialogContentWithLoader,
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 28.0),
child: Center(
child: CircularProgressIndicator(),
),
),
TextButton(
onPressed: () {
fetchAuthToken().then((fetchedAuthToken) {
debugPrint("fetchedAuthToken $fetchedAuthToken");
fetchBrokerConnectTxnId(authToken: fetchedAuthToken).then(
(txnId) => ScgatewayFlutterPlugin.initGateway(
fetchedAuthToken,
).then(
(value) =>
ScgatewayFlutterPlugin.triggerGatewayTransaction(
txnId,
).then(
(loginRes) {
if (loginRes != null) {
log(loginRes.toString());
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(
'Yes',
style: TextStyle(
color: Color(0xff1B243D),
),
),
)
],
));
}
@override
@@ -405,6 +377,13 @@ class _PortfolioState extends State<Portfolio> {
text25W600("My Portfolio"),
GestureDetector(
onTap: () {
ScgatewayFlutterPlugin
.setConfigEnvironment(
GatewayEnvironment.PRODUCTION,
'traderscircuit',
false,
[],
);
fetchAuthToken().then((fetchedAuthToken) {
debugPrint(
"fetchedAuthToken $fetchedAuthToken");
@@ -440,6 +419,33 @@ class _PortfolioState extends State<Portfolio> {
authToken,
txnId: txnId)
.then((isPosted) {
fetchUserIdAndBrokerAccounts
.add(
fetchBrokerAccounts());
fetchUserIdAndBrokerAccounts
.close();
fetchUserIdAndBrokerAccounts
.future
.then((value) {
log(value.toString());
try {
myBrokerAccounts =
value[0]
as List<Data>;
} catch (e) {}
debugPrint(
"myBrokerAccounts.length ${myBrokerAccounts.length}");
if (myBrokerAccounts
.isEmpty) {
noBrokerAvailable
.value = true;
} else {
noBrokerAvailable
.value = false;
}
});
ScaffoldMessenger.of(
context)
.clearSnackBars();
@@ -966,7 +972,7 @@ class HoldingsTabBar extends StatelessWidget {
indicatorColor: const Color(0xFFFFFFFF),
labelColor: Colors.white,
unselectedLabelColor: const Color(0xffFFFFFF),
overlayColor: MaterialStateProperty.all(const Color(0xFFFFFFFF)),
overlayColor: WidgetStateProperty.all(const Color(0xFFFFFFFF)),
tabs: const [
Tab(
text: 'Holdings',
@@ -979,7 +985,7 @@ class HoldingsTabBar extends StatelessWidget {
}
}
class PortfolioTabBar extends StatelessWidget {
class PortfolioTabBar extends StatefulWidget {
final int portfolioLength;
final List<Data> portoflioName;
const PortfolioTabBar({
@@ -988,13 +994,35 @@ class PortfolioTabBar extends StatelessWidget {
required this.portoflioName,
});
// Set the desired height
@override
State<PortfolioTabBar> createState() => _PortfolioTabBarState();
}
class _PortfolioTabBarState extends State<PortfolioTabBar>
with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: widget.portfolioLength, vsync: this);
_tabController.addListener(() {
selectedTabIndex = _tabController.index;
});
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
} // Set the desired height
@override
Widget build(BuildContext context) {
return TabBar(
tabAlignment: TabAlignment.start,
isScrollable: true,
controller: _tabController,
dividerColor: Colors.transparent,
labelStyle: TextStyle(
fontSize: 18.sp,
@@ -1006,10 +1034,10 @@ class PortfolioTabBar extends StatelessWidget {
indicatorColor: const Color(0xff6C0000),
labelColor: Colors.white,
unselectedLabelColor: const Color(0xFF464646),
overlayColor: MaterialStateProperty.all(const Color(0xFFFFFFFF)),
tabs: List.generate(portfolioLength, (counter) {
overlayColor: WidgetStateProperty.all(const Color(0xFFFFFFFF)),
tabs: List.generate(widget.portfolioLength, (counter) {
return Tab(
text: portoflioName[counter].brokerName,
text: widget.portoflioName[counter].brokerName,
);
}));
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,11 @@
import 'dart:convert';
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:scgateway_flutter_plugin/scgateway_flutter_plugin.dart';
import '../../Utils/api_urls.dart';
import '../../Utils/base_manager.dart';
import '../../data/network/network_api_services.dart';
import '../../model/SmallCaseModel/broker_account_model.dart';
// void openDashboardPage(BuildContext context) {
// Navigator.pushReplacement(
@@ -61,25 +57,6 @@ Future<bool> postBrokerAccount({
}
//fetch broker accounts
Future<List<Data>> fetchBrokerAccounts() async {
final response = await NetworkApiServices().getApi(
'${ApiUrls.base}get-broker-account-data',
);
// log(response.data.toString());
if (response.status == ResponseStatus.SUCCESS) {
Map<String, dynamic> responseData =
Map<String, dynamic>.from(response.data);
if (responseData['status'] == "success") {
BrokerAccountModel brokerAccountModel =
BrokerAccountModel.fromJson(responseData);
return brokerAccountModel.data!;
} else {
return [];
}
}
return [];
}
Future<String> fetchAuthToken() async {
final response = await NetworkApiServices().getApi(
@@ -98,6 +75,45 @@ Future<String> fetchAuthToken() async {
return "Failed";
}
Future<ResponseData<dynamic>> fetchBrokerAccounts() async {
final response = await NetworkApiServices().getApi(
'${ApiUrls.base}get-broker-account-data',
);
log(response.data.toString());
if (response.status == ResponseStatus.SUCCESS) {
Map<String, dynamic> responseData =
Map<String, dynamic>.from(response.data);
if (responseData['status'] == "success") {
return response;
} else {
return ResponseData<dynamic>(
responseData['message'], ResponseStatus.FAILED);
}
}
return response;
}
Future<ResponseData<dynamic>> fetchHoldingForDB(String brokerName) async {
final response = await NetworkApiServices().postApi(
FormData.fromMap({"broker_name": brokerName}),
'${ApiUrls.base}get-all-details-of-my-portfolio',
);
log(response.data.toString());
if (response.status == ResponseStatus.SUCCESS) {
Map<String, dynamic> responseData =
Map<String, dynamic>.from(response.data);
if (responseData['status'] == "success") {
return response;
} else {
return ResponseData<dynamic>(
responseData['message'], ResponseStatus.FAILED);
}
}
return response;
}
Future<String> fetchBrokerConnectTxnId({required String authToken}) async {
final response = await NetworkApiServices().postApi(
FormData.fromMap({"auth_token": authToken}),
@@ -130,6 +146,7 @@ Future<String> fetchHoldingsImportTxnId(String authToken) async {
if (responseData['status'] == "success" &&
!responseData.toString().contains(
"{status: error, status_code: 500, message: Something went wrong.}")) {
log("Transaction id --> ${response.data['data']["data"]['transactionId']}");
return response.data['data']["data"]
['transactionId']; // jsonDecode(response.body)
} else {
@@ -156,46 +173,3 @@ Future<Map<String, dynamic>> fetchHoldings(String authToken) async {
}
return {};
}
Future<String> fetchStocksOrderTxnId(String authToken, String body) async {
var response = await http.post(Uri.parse(
'${ApiUrls.base}api/create_post_transaction_stock_order?body=$body&auth_token=$authToken'));
var txnId = jsonDecode(response.body)['data']['transactionId'];
return txnId;
}
enum TradeType {
BUY,
SELL,
}
void loginNTrade(String ticker, int quantity, TradeType tradeType) {
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'];
String body =
'{"intent":"TRANSACTION","orderConfig":{"type":"SECURITIES","securities":[{"ticker":"$ticker","quantity":"$quantity","type":"${tradeType.name}"},{"ticker":"RELIANCE","quantity":1,"type":"BUY"}]}}';
fetchStocksOrderTxnId(authToken, body).then(
(stocksOrderTxnId) => ScgatewayFlutterPlugin
.triggerGatewayTransaction(stocksOrderTxnId)
.then(
(value) => debugPrint("Stocks Order res $value")));
}
}
},
),
),
);
});
}

View File

@@ -804,26 +804,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
version: "3.0.1"
lints:
dependency: transitive
description:
@@ -916,10 +916,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
version: "1.12.0"
mime:
dependency: transitive
description:
@@ -1361,10 +1361,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.0"
timeago:
dependency: "direct main"
description:
@@ -1538,10 +1538,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "13.0.0"
version: "14.2.1"
wakelock:
dependency: transitive
description: