import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/models/lakum_inquiry_information_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; class LakumWalletDetails extends StatelessWidget { const LakumWalletDetails({super.key}); @override Widget build(BuildContext context) { AppState appState = getIt.get(); return CollapsingListView( title: LocaleKeys.lakumPoints.tr(context: context), child: Consumer( builder: (context, viewModel, child) { // Check if loading if (viewModel.isLakumAccountInfoLoading) { return Center( child: Padding( padding: EdgeInsets.all(32.w), child: CircularProgressIndicator( color: AppColors.primaryRedColor, ), ), ); } // Check if account number is not available if (viewModel.yahalaAccountNumber == "0" || viewModel.yahalaAccountNumber.isEmpty) { return Center( child: Padding( padding: EdgeInsets.all(32.w), child: LocaleKeys.lakumMsg.tr().toText14( color: AppColors.greyTextColor, ), ), ); } // Get all transactions List transactions = viewModel.getAllLakumTransactions(); // Display main UI return SingleChildScrollView( child: Padding( padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Main Lakum Card with gradient and user info _buildLakumMainCard(viewModel.lakumAccountInfo, appState), SizedBox(height: 24.h), // Redeem Button _buildRedeemButton(context), SizedBox(height: 24.h), // Transaction List Header Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LocaleKeys.transactions.tr(context: context).toText16(isBold: true), if (transactions.isNotEmpty) "${transactions.length} Records".toText12(color: AppColors.greyTextColor), ], ), SizedBox(height: 12.h), // Transaction List Container if (transactions.isEmpty) _buildEmptyTransactions() else _buildTransactionsList(transactions), SizedBox(height: 24.h), ], ), ), ); }, ), ); } Widget _buildLakumMainCard(LakumInquiryInformationResponseModel accountInfo, AppState appState) { return Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.habibPharmacyColor, AppColors.habibPharmacyColor.withAlpha(220), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(24.r), boxShadow: [ BoxShadow( color: AppColors.habibPharmacyColor.withAlpha(76), blurRadius: 16, offset: Offset(0, 8), ), ], ), child: Padding( padding: EdgeInsets.all(20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Top Row: User Info and Grid Icon Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "${appState.getAuthenticatedUser()?.firstName ?? ''} ${appState.getAuthenticatedUser()?.lastName ?? ''}".toText18( isBold: true, color: Colors.white, ), SizedBox(height: 4.h), (accountInfo.accountNumber ?? 0).toString().toText14( color: Colors.white.withAlpha(230), ), ], ), ), Utils.buildImgWithAssets( icon: AppAssets.lakumLogoWhite, width: 80.h, height: 80.h, ), ], ), // SizedBox(height: 24.h), LocaleKeys.lakumPoints.tr().toText18(color: Colors.white.withAlpha(230), isBold: true), SizedBox(height: 8.h), // Points Balance Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ (accountInfo.pointsBalance?.toString() ?? "0").toText44( isBold: true, color: Colors.white, ), SizedBox(width: 8.w), LocaleKeys.points .tr() .toText18( color: Colors.white.withAlpha(230), isBold: true, ) .paddingOnly(bottom: 8.h), ], ), SizedBox(height: 4.h), // Balance Amount in SAR "≈ ${accountInfo.pointsBalanceAmount?.toStringAsFixed(2) ?? "0.00"} SAR".toText18( color: Colors.white.withAlpha(204), ), SizedBox(height: 20.h), // Stats Row Row( children: [ Expanded( child: _buildStatChip( LocaleKeys.gained.tr(), accountInfo.gainedPoints?.toString() ?? "0", Icons.arrow_circle_up, ), ), SizedBox(width: 8.w), Expanded( child: _buildStatChip( LocaleKeys.consumed.tr(), accountInfo.consumedPoints?.toString() ?? "0", Icons.arrow_circle_down, ), ), ], ), ], ), ), ); } Widget _buildStatChip(String label, String value, IconData icon) { return Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.h), decoration: BoxDecoration( color: Colors.white.withAlpha(51), borderRadius: BorderRadius.circular(12.r), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: Colors.white, size: 16.f), SizedBox(width: 6.w), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ value.toText14(color: Colors.white, isBold: true), label.toText10(color: Colors.white.withAlpha(204)), ], ), ], ), ); } Widget _buildRedeemButton(BuildContext context) { return CustomButton( height: 46.h, icon: AppAssets.redeem_icon, iconColor: AppColors.whiteColor, iconSize: 24.h, backgroundColor: AppColors.habibPharmacyColor, textColor: AppColors.whiteColor, text: LocaleKeys.redeem.tr(context: context), borderWidth: 0.w, fontWeight: FontWeight.w600, borderColor: AppColors.habibPharmacyColor.withAlpha(15), padding: EdgeInsets.fromLTRB(4, 0, 12, 0), fontSize: 14.f, onPressed: () { Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); launchUrl(uri, mode: LaunchMode.externalApplication); }, ); } Widget _buildEmptyTransactions() { return Container( padding: EdgeInsets.all(32.w), decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 16.r, hasShadow: false, ), child: Center( child: Column( children: [ Icon(Icons.receipt_long_outlined, size: 48.f, color: AppColors.greyTextColor), SizedBox(height: 12.h), "No transactions found".toText14( color: AppColors.greyTextColor, isCenter: true, ), ], ), ), ); } Widget _buildTransactionsList(List transactions) { return Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 16.r, hasShadow: false, ), child: ListView.separated( padding: EdgeInsets.all(16.w), shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemCount: transactions.length, separatorBuilder: (context, index) => Divider( color: AppColors.dividerColor, height: 24.h, ), itemBuilder: (context, index) { return _buildTransactionItem(transactions[index]); }, ), ); } Widget _buildTransactionItem(PointsDetails transaction) { // Determine if points were gained or used bool isGained = transaction.operationType?.toLowerCase() == 'gain' || transaction.operationType?.toLowerCase() == 'credit' || (transaction.points ?? 0) > 0; Color transactionColor = isGained ? AppColors.habibPharmacyColor : AppColors.primaryRedColor; String pointsText = "${isGained ? '+' : '-'}${transaction.points?.abs() ?? 0}"; // Format date String formattedDate = ""; if (transaction.transactionDate != null) { try { formattedDate = DateUtil.formatDateToDate( DateUtil.convertStringToDate(transaction.transactionDate!), false, ); } catch (e) { formattedDate = transaction.transactionDate ?? ""; } } return Row( children: [ // Transaction Icon Container( width: 44.w, height: 44.h, decoration: BoxDecoration( color: transactionColor.withAlpha(25), borderRadius: BorderRadius.circular(12.r), ), child: Icon( isGained ? Icons.add_rounded : Icons.remove_rounded, color: transactionColor, size: 24.f, ), ), SizedBox(width: 12.w), // Transaction Details Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ (transaction.subTransactionTypeDescription ?? transaction.operationType ?? "Transaction").toText14( isBold: true, maxlines: 2, ), SizedBox(height: 2.h), formattedDate.toText12(color: AppColors.greyTextColor), ], ), ), // Points Value Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ pointsText.toText18( isBold: true, color: transactionColor, ), if (transaction.amount != null && transaction.amount! > 0) "${transaction.amount?.toStringAsFixed(2) ?? "0.00"} SAR".toText11( color: AppColors.greyTextColor, ), ], ), ], ); } } // Custom painter for wavy background pattern class _WavyBackgroundPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { // Base color from AppColors final baseColor = AppColors.habibPharmacyColor; final paint = Paint() ..color = Colors.white.withAlpha(25) ..style = PaintingStyle.fill; // Draw multiple wave patterns final path1 = Path(); path1.moveTo(0, size.height * 0.3); path1.quadraticBezierTo( size.width * 0.25, size.height * 0.2, size.width * 0.5, size.height * 0.3, ); path1.quadraticBezierTo( size.width * 0.75, size.height * 0.4, size.width, size.height * 0.3, ); path1.lineTo(size.width, 0); path1.lineTo(0, 0); path1.close(); canvas.drawPath(path1, paint); // Second wave with darker shade paint.color = Colors.black.withAlpha(15); final path2 = Path(); path2.moveTo(0, size.height * 0.6); path2.quadraticBezierTo( size.width * 0.3, size.height * 0.5, size.width * 0.6, size.height * 0.6, ); path2.quadraticBezierTo( size.width * 0.8, size.height * 0.7, size.width, size.height * 0.6, ); path2.lineTo(size.width, size.height); path2.lineTo(0, size.height); path2.close(); canvas.drawPath(path2, paint); // Decorative circles with white overlay paint.color = Colors.white.withAlpha(20); canvas.drawCircle(Offset(size.width * 0.85, size.height * 0.15), 30, paint); paint.color = Colors.white.withAlpha(10); canvas.drawCircle(Offset(size.width * 0.15, size.height * 0.75), 40, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }