import 'dart:js_util';
import 'package:finbox_v2/feature/analysis/model/analytics_data.dart';
import 'package:finbox_v2/feature/analysis/widget/analysis_news_post.dart';
import 'package:finbox_v2/feature/news/model/news_data.dart';
import 'package:finbox_v2/feature/news/widget/news_post.dart';
import 'package:finbox_v2/feature/notification/model/noti_data_request.dart';
import 'package:finbox_v2/feature/notification/model/notification.dart' as n;
import 'package:finbox_v2/feature/notification/provider/noti_provider.dart';
import 'package:finbox_v2/feature/notification/repository/noti_repository.dart';
import 'package:finbox_v2/feature/notification/widget/common/noti_common_derivative_order.dart';
import 'package:finbox_v2/feature/notification/widget/common/noti_common_news.dart';
import 'package:finbox_v2/feature/notification/widget/common/noti_common_signal.dart';
import 'package:finbox_v2/feature/recommendations/widget/recommendations_page.dart';
import 'package:finbox_v2/feature/ticker/model/ticker_detail_model.dart';
import 'package:finbox_v2/feature/ticker/provider/active_tickers_provider.dart';
import 'package:finbox_v2/feature/ticker/widget/technical_chart_page.dart';
import 'package:finbox_v2/shared/model/user.dart';
import 'package:finbox_v2/shared/util/navigation_util.dart';
import 'package:finbox_v2/theme/finbox_theme.dart';
import 'package:finbox_v2/widgets/loadding_news.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
class SystemTab extends ConsumerStatefulWidget {
const SystemTab({required this.user, this.loadingCount = 3, Key? key})
: super(key: key);
final int loadingCount;
final User user;
@override
ConsumerState<SystemTab> createState() => SystemTabState();
}
class SystemTabState extends ConsumerState<SystemTab>
with SingleTickerProviderStateMixin {
final int _visibleNotiCommonCount = 8;
int page = 1;
bool isLoading = false;
bool isFirstLoad = true;
bool isRefreshed = false;
final ScrollController _scrollController = ScrollController();
// ignore: strict_raw_type
List<n.Notification> listNoti = [];
Future<void> _loadData() async {
final requestData = <String, dynamic>{
'limit': _visibleNotiCommonCount,
'page': page,
'userId': widget.user.id,
};
final request = NotiDataRequest.fromJson(requestData);
await ref.read(notiProvider.notifier).getNoti(request);
}
@override
void initState() {
_loadData();
_scrollController.addListener(() async {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent + 50) {
if (!isLoading) {
await _loadData();
}
}
});
super.initState();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print('is invoked');
var mapTicker = <String, TickerDetailModel>{};
final listTicker = <String>[];
late final finboxColors = Theme.of(context).extension<FinboxColors>()!;
final notiDataState = ref.watch(notiProvider);
final _notiDataProvider = ref.read(notiDataProvider.notifier);
final notis = ref.watch(notiDataProvider);
late NewsData news;
late AnalyticsData analytics;
// ignore: cascade_invocations
notiDataState
..whenOrNull(
listNotiLoaded: (loadedNoti) {
isFirstLoad = false;
page++;
// listNoti.addAll(loadedNoti);
_notiDataProvider.addNoti(loadedNoti);
},
)
..maybeWhen(
loading: () => isLoading = true,
orElse: () => isLoading = false,
);
for (var noti in notis) {
if (noti.notification.type == 'Signals' &&
(!listTicker.contains(noti.notification.ticker))) {
listTicker.add(noti.notification.ticker!);
}
}
if (ref.read(activeTickersProvider.notifier).addTickers(listTicker)) {
ref.read(activeTickersProvider.notifier).fetchTickers();
}
final tickers = ref.watch(activeTickersProvider);
mapTicker = tickers;
return Container(
margin: const EdgeInsets.only(left: 16),
padding: const EdgeInsets.only(top: 24),
child: RefreshIndicator(
onRefresh: _refresh,
color: finboxColors.dark3,
child: ListView.builder(
controller: _scrollController,
physics: const BouncingScrollPhysics(),
itemCount: notis.length + widget.loadingCount,
// +1 for the "Watch More" button
itemBuilder: (context, index) {
if (index < notis.length) {
if ('Signals' == notis[index].notification.type) {
final title =
"${notis[index].notification.ticker!} - ${notis[index].notification.action!}${notis[index].notification.signal!}";
final price = 'Giá KN: ${notis[index].notification.price!}';
return GestureDetector(
onTap: () {
notiDataState.maybeWhen(
error: (e) => null,
orElse: () {
ref
.watch(notiProvider.notifier)
.readNotification(notis[index]);
NavigationUtil.nav(
context,
TechnicalChartersOverview(
tickerName:
mapTicker[notis[index].notification.ticker]
?.ticker ??
'',
initialTicker:
mapTicker[notis[index].notification.ticker],
),
);
},
);
},
child: Stack(
alignment: Alignment.center,
children: [
NotiCommonSignal(
time: convertTimeString(notis[index].created),
title: title,
price: price,
),
if (notis[index].read)
Icon(Icons.check, color: Color(0xFF0063F7)),
// Hiển thị dấu tick nếu thông báo đã xem
],
),
);
}
if ('DerivativeOrder' == notis[index].notification.type) {
var title = 'Phái sinh - Đã có tín hiệu ' +
notis[index].notification.signal!;
var price =
'Giá KN: ' + notis[index].notification.price!.toString();
return GestureDetector(
onTap: () {
notiDataState.maybeWhen(
error: (e) => null,
orElse: () {
ref
.watch(notiProvider.notifier)
.readNotification(notis[index]);
NavigationUtil.pushNamedRoute(
context,
'/recommendations',
);
},
);
// Handle onPress event here
// You can perform any desired actions
print('NotiCommonSignal pressed');
},
child: Stack(
alignment: Alignment.center,
children: [
NotiCommonDerivative(
time: convertTimeString(notis[index].created),
title: title,
price: price,
),
if (notis[index].read)
Icon(Icons.check, color: Color(0xFF0063F7)),
// Hiển thị dấu tick nếu thông báo đã xem
],
),
);
}
if ('DerivativeTurn' == notis[index].notification.type) {
var title = 'Phái sinh - Đã tiệm cận điểm đảo chiều';
var price = 'Giá hiện tại: ' +
notis[index].notification.price!.toString();
return GestureDetector(
onTap: () {
notiDataState.maybeWhen(
error: (e) => null,
orElse: () {
ref
.watch(notiProvider.notifier)
.readNotification(notis[index]);
NavigationUtil.nav(
context,
const RecommendationsPage(),
);
},
);
// Handle onPress event here
// You can perform any desired actions
print('NotiCommonSignal pressed');
},
child: Stack(
alignment: Alignment.center,
children: [
NotiCommonDerivative(
time: convertTimeString(notis[index].created),
title: title,
price: price,
),
if (notis[index].read)
Icon(Icons.check, color: Color(0xFF0063F7)),
// Hiển thị dấu tick nếu thông báo đã xem
],
),
);
}
if ('NewsDefautSet' == notis[index].notification.type) {
var title = notis[index].notification.ticker! +
' - ' +
notis[index].notification.content!;
var price = 'Nguồn: ' + notis[index].notification.source!;
return GestureDetector(
onTap: () {
notiDataState.maybeWhen(
error: (e) => null,
orElse: () {
ref
.watch(notiProvider.notifier)
.readNotification(notis[index]);
},
);
NavigationUtil.nav(
context,
NewsPost(
slang: notis[index].notification.slang!,
),
);
// Handle onPress event here
// You can perform any desired actions
print('NotiCommonSignal pressed');
},
child: Stack(
alignment: Alignment.center,
children: [
NotiCommonNews(
time: convertTimeString(notis[index].created),
title: title,
price: price,
),
if (notis[index].read)
Icon(Icons.check, color: Color(0xFF0063F7)),
// Hiển thị dấu tick nếu thông báo đã xem
],
),
);
}
if ('FinboxNews' == notis[index].notification.type) {
var title = notis[index].notification.ticker! +
' - ' +
notis[index].notification.content!;
var price = 'Nguồn: Finbox';
return GestureDetector(
onTap: () {
notiDataState.maybeWhen(
error: (e) => null,
orElse: () {
ref
.watch(notiProvider.notifier)
.readNotification(notis[index]);
},
);
NavigationUtil.nav(
context,
AnalysisNewsPost(
slang: notis[index].notification.slang!,
),
);
// Handle onPress event here
// You can perform any desired actions
print('NotiCommonSignal pressed');
},
child: Stack(
alignment: Alignment.center,
children: [
NotiCommonNews(
time: convertTimeString(notis[index].created),
title: title,
price: price,
),
if (notis[index].read)
Icon(Icons.check, color: Color(0xFF0063F7)),
// Hiển thị dấu tick nếu thông báo đã xem
],
),
);
}
return NotiCommonSignal(
time: notis[index].created,
title: '',
price: '1000',
);
} else {
return notiDataState.maybeWhen(
loading: () => const SizedBox(),
orElse: () => const Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(top: 20),
child: NewsCardLoading(isWatchlist: true),
)
],
),
);
}
},
),
),
);
}
Future<void> _refresh() async {
// ignore: inference_failure_on_instance_creation
setState(() {
listNoti = [];
page = 1;
_loadData();
isFirstLoad = true;
isRefreshed = true;
});
}
String convertTimeString(String time) {
// Create a DateTime object from the input string
DateTime dateTime = DateTime.parse(time);
// Add 7 hours to the DateTime object
DateTime updatedDateTime = dateTime.add(Duration(hours: 7));
// Format the updated DateTime to the desired output format
DateFormat formatter = DateFormat('HH:mm dd/MM/yyyy');
String output = formatter.format(updatedDateTime);
return output;
}
}