// 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 {
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)),
);
}
}