Untitled
unknown
plain_text
a year ago
18 kB
1
Indexable
Never
// noti_edit // ignore: directives_ordering 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/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/ticker/model/ticker_detail_model.dart'; import 'package:finbox_v2/l10n/l10n.dart'; import 'package:finbox_v2/shared/model/user.dart'; import 'package:finbox_v2/theme/finbox_theme.dart'; import 'package:finbox_v2/widgets/gradient_button_common.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:finbox_v2/feature/ticker/provider/active_tickers_provider.dart'; import 'package:finbox_v2/shared/util/navigation_util.dart'; import 'package:finbox_v2/feature/recommendations/widget/recommendations_page.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/analysis/widget/analysis_news_post.dart'; import 'package:finbox_v2/widgets/loadding_news.dart'; import 'package:finbox_v2/feature/ticker/widget/technical_chart_page.dart'; import 'package:finbox_v2/feature/news/widget/news_post.dart'; import 'package:finbox_v2/shared/repository/user_repository.dart'; class NotiEdit extends ConsumerStatefulWidget { NotiEdit({required this.user, dynamic loadingCount = 1, Key? key}) : super(key: key); User user; @override ConsumerState<NotiEdit> createState() => NotiEditState(); } class NotiEditState extends ConsumerState<NotiEdit> with SingleTickerProviderStateMixin { final int _visibleNotiCommonCount = 8; final ScrollController _scrollController = ScrollController(); List<n.Notification> listNoti = []; bool isFirstLoad = true; bool isLoading = false; bool isRefreshed = false; int page = 1; @override void initState() { print('initState::'); // ref.refresh(notiProvider); _scrollController.addListener(() async { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { if (!isLoading && listNoti.isNotEmpty) { await _loadData(); } // ref.read(pageProvider.notifier).incrementPage(); } }); super.initState(); } 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); Future(() { ref.read(notiProvider.notifier).getNoti(request); }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { late final finboxColors = Theme.of(context).extension<FinboxColors>()!; var mapTicker = <String, TickerDetailModel>{}; final listTicker = <String>[]; // ref.invalidate(notiProvider); final notiDataState = ref.watch(notiProvider); final user = ref.watch(userDataProvider); if (isFirstLoad) { isFirstLoad = false; _loadData(); } notiDataState ..whenOrNull( listNotiLoaded: (loadedNotis) { isFirstLoad = false; page++; print('noti edit page::${page}'); for (final loadedNoti in loadedNotis) { if (!listNoti.contains(loadedNoti)) { listNoti = [...listNoti, loadedNoti]; } } }, ) ..maybeWhen( loading: () => isLoading = true, orElse: () => isLoading = false) ..whenOrNull( notiDetailLoaded: (notification) { for (int i = 0; i < listNoti.length; i++) { if (listNoti[i]?.id == notification?.id && !listNoti[i].read) { listNoti[i] = listNoti[i].copyWith(read: true); } } }, ) ..maybeWhen( loading: () => isLoading = true, orElse: () => isLoading = false); for (var noti in listNoti) { 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(); } void getTiker() async { final tickers = await ref.watch(activeTickersProvider.notifier).getTickerMap(); mapTicker = tickers; } getTiker(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Container( // margin: const EdgeInsets.only(left: 16), padding: const EdgeInsets.only(top: 24), child: RefreshIndicator( onRefresh: _refresh, color: finboxColors.dark3, child: (listNoti.isEmpty && !isLoading) ? const Center(child: Text('Không tìm thấy thông báo nào')) : ListView.builder( controller: _scrollController, physics: const BouncingScrollPhysics(), itemCount: listNoti.length.toInt(), // +1 for the "Watch More" button itemBuilder: (context, index) { if (index < listNoti.length) { if ('Signals' == listNoti[index].notification.type) { final title = "${listNoti[index].notification.ticker!} - ${listNoti[index].notification.action!}${listNoti[index].notification.signal!}"; final price = 'Giá KN: ${listNoti[index].notification.price!}'; return WidgetGestureCommon( notiStatus: listNoti[index].read, time: convertTimeString(listNoti[index].created), title: title, price: price, child: NotiCommonSignal( time: convertTimeString(listNoti[index].created), title: title, price: price, )); } if ('DerivativeOrder' == listNoti[index].notification.type) { var title = 'Phái sinh - Đã có tín hiệu ' + listNoti[index].notification.signal!; var price = 'Giá KN: ' + listNoti[index].notification.price!.toString(); return WidgetGestureCommon( notiStatus: listNoti[index].read, time: convertTimeString(listNoti[index].created), title: title, price: price, child: NotiCommonDerivative( time: convertTimeString(listNoti[index].created), title: title, price: price, )); } if ('DerivativeTurn' == listNoti[index].notification.type) { var title = 'Phái sinh - Đã tiệm cận điểm đảo chiều'; var price = 'Giá hiện tại: ' + listNoti[index].notification.price!.toString(); return WidgetGestureCommon( notiStatus: listNoti[index].read, time: convertTimeString(listNoti[index].created), title: title, price: price, child: NotiCommonDerivative( time: convertTimeString(listNoti[index].created), title: title, price: price, )); } if ('NewsDefautSet' == listNoti[index].notification.type) { var title = listNoti[index].notification.ticker! + ' - ' + listNoti[index].notification.content!; var price = 'Nguồn: ' + listNoti[index].notification.source!; return WidgetGestureCommon( notiStatus: listNoti[index].read, time: convertTimeString(listNoti[index].created), title: title, price: price, child: NotiCommonNews( time: convertTimeString(listNoti[index].created), title: title, price: price, ), ); } if ('FinboxNews' == listNoti[index].notification.type) { var title = listNoti[index].notification.ticker! + ' - ' + listNoti[index].notification.content!; var price = 'Nguồn: Finbox'; return WidgetGestureCommon( notiStatus: listNoti[index].read, time: convertTimeString(listNoti[index].created), title: title, price: price, child: NotiCommonNews( time: convertTimeString(listNoti[index].created), title: title, price: price, )); } if ('DerivativeCloseHd' == listNoti[index].notification.type) { final title = "Phái sinh - Đóng hợp đồng ngày đáo hạn"; final price = 'Giá KN: ${listNoti[index].notification.price!}'; // print('/:${title}:::${price}'); return NotiCommonSignal( time: convertTimeString(listNoti[index].created), title: title, price: price, ); } } else { print('else'); return notiDataState.maybeWhen( loading: () => const SizedBox(), orElse: () => Column( mainAxisSize: MainAxisSize.min, children: const [ Padding( padding: EdgeInsets.only(top: 12), child: NewsCardLoading(isWatchlist: true), ) ], ), ); } }, ), ), ), ), Align( alignment: Alignment.bottomCenter, child: buttonPopup(context, user?.id), ) ], ); } Future<void> _refresh() async { // ignore: inference_failure_on_instance_creation // ref.refresh(notiProvider); setState(() { listNoti = []; page = 1; _loadData(); isFirstLoad = true; isRefreshed = true; }); } String convertTimeString(String time) { // Create a DateTime object from the input string final dateTime = DateTime.parse(time); // Add 7 hours to the DateTime object final updatedDateTime = dateTime.add(const Duration(hours: 7)); // Format the updated DateTime to the desired output format final formatter = DateFormat('HH:mm dd/MM/yyyy'); final output = formatter.format(updatedDateTime); return output; } Widget buttonPopup(BuildContext context, String? userId) { final finboxColor = Theme.of(context).extension<FinboxColors>()!; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), //Custom child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Flexible( child: GradientButtonCommon( backgroundColor: finboxColor.dark4, content: Text( context.l10n.da_doc_tat_ca.toUpperCase(), style: Theme.of(context).textTheme.bodyLarge?.copyWith( fontWeight: FinboxFontWeight.semiBold.value, color: Colors.black, //Custom ), ), onPressed: () => { ref .watch(notiProvider.notifier) .readAllNotification(userId?? ''), showSuccessMessage(context.l10n.danh_dau_la_da_doc) }, ), ), const SizedBox( width: 10, ), Flexible( child: GradientButtonCommon( content: Text( context.l10n.xoa_tat_ca.toUpperCase(), style: Theme.of(context).textTheme.bodyLarge?.copyWith( fontWeight: FinboxFontWeight.semiBold.value, color: Colors.white, //Custom ), ), gradient: finboxColor.buttonColor1!, onPressed: () { showDialog<void>( context: context, builder: (BuildContext context) { return Dialog( backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), child: SizedBox( width: double.infinity, height: 180, child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Text( context.l10n.ban_co_chac_chan_muon_xoa_tat_ca_cac_thong_bao, style: finboxColor.fontBodyMedium1!.copyWith( fontWeight: FinboxFontWeight.regular.value, color: finboxColor.dark3, ), textAlign: TextAlign.center, ), Container( width: double.infinity, height: 1, margin: const EdgeInsets.only( top: 10, ), decoration: BoxDecoration( color: finboxColor.dark4, ), ), Container( margin: const EdgeInsets.only( top: 20, left: 24, right: 24, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: TextButton( style: TextButton.styleFrom( foregroundColor: finboxColor.dark4, // Text Color ), child: Text( context.l10n.huy, style: const TextStyle( color: Colors.black, fontWeight: FontWeight.w600, fontSize: 16, ), ), onPressed: () => Navigator.pop( context, ), ), ), Expanded( child: GradientButtonCommon( content: Text( context.l10n.xoa.toUpperCase(), style: finboxColor.fontButton1!.copyWith( fontFamily: 'inter', color: finboxColor.dark4, ), ), gradient: finboxColor.buttonColor3, onPressed: () => { ref .watch(notiProvider.notifier) .deleteUserNotification( userId ?? '', listNoti.length), Navigator.pop( context, ) }, ), ), ], ), ), ], ), ), ); }, ); }, ), ), ], ), ); } Widget WidgetGestureCommon( { required bool notiStatus, required String time, required String title, required String price, required Widget child}) { return GestureDetector( child: Container( padding: const EdgeInsets.only(right: 8, top: 8), color: notiStatus ? Colors.transparent : const Color(0xFFDFE7F3), child: Stack( alignment: Alignment.center, children: [ child, ], ), )); } void showSuccessMessage(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message)), ); } }