Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 28 KiB |
@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.93712 2.25C5.05309 2.24995 4.28757 2.2499 3.67381 2.33562C3.01162 2.4281 2.38072 2.63711 1.87303 3.16449C1.37047 3.68654 1.17623 4.32619 1.08959 4.99561C1.00807 5.62545 1.0081 6.41382 1.00815 7.33738L1.00815 7.40177C1.00815 7.65552 1.00591 7.89931 1.00378 8.13142C0.998266 8.73244 0.993469 9.25515 1.0301 9.66981C1.08709 10.315 1.25466 10.9156 1.76284 11.4435C2.14586 11.8414 2.77891 11.8535 3.17679 11.4704C3.57468 11.0874 3.58672 10.4544 3.2037 10.0565C3.12657 9.97636 3.05658 9.88147 3.02234 9.49383C2.99474 9.18135 2.99819 8.80852 3.00318 8.27087C3.0055 8.02045 3.00815 7.73426 3.00815 7.40177C3.00815 6.39595 3.01012 5.73847 3.07304 5.25232C3.13273 4.79115 3.23113 4.63751 3.31389 4.55154C3.39151 4.47092 3.52427 4.37592 3.95045 4.31639C4.40942 4.25229 5.0335 4.25001 6.00488 4.25001L17.9951 4.25001C18.9664 4.25001 19.5905 4.25229 20.0495 4.3164C20.4757 4.37592 20.6084 4.47092 20.686 4.55155C20.7688 4.63751 20.8672 4.79115 20.9269 5.25232C20.9898 5.73847 20.9918 6.39595 20.9918 7.40177C20.9918 7.73233 20.9944 8.01713 20.9967 8.26653C21.0016 8.80612 21.005 9.18046 20.9773 9.4935C20.9429 9.88104 20.8729 9.97616 20.7956 10.0565C20.4125 10.4544 20.4246 11.0874 20.8225 11.4704C21.2203 11.8535 21.8534 11.8414 22.2364 11.4435C22.7444 10.9158 22.9123 10.3154 22.9695 9.67014C23.0063 9.25455 23.0016 8.73073 22.9961 8.12825C22.994 7.89711 22.9918 7.65439 22.9918 7.40177L22.9918 7.33739C22.9918 6.41387 22.9919 5.62543 22.9103 4.99561C22.8237 4.32619 22.6295 3.68654 22.1269 3.16449C21.6192 2.63711 20.9883 2.4281 20.3261 2.33562C19.7124 2.2499 18.9468 2.24995 18.0628 2.25L5.93712 2.25Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1978 6.25C14.9586 6.24998 15.598 6.24996 16.1143 6.31403C16.6617 6.38197 17.1602 6.5306 17.5912 6.89146C18.0222 7.25232 18.2562 7.71697 18.4193 8.24389C18.5731 8.74084 18.6855 9.3703 18.8192 10.1193L19.4895 13.8726C19.7725 15.4578 19.9993 16.7275 20.0348 17.7329C20.0715 18.7716 19.9118 19.6676 19.2925 20.4073C18.6731 21.1471 17.8191 21.4618 16.7902 21.6082C15.7942 21.75 14.5044 21.75 12.8942 21.75H11.1065C9.49624 21.75 8.20645 21.75 7.21049 21.6082C6.18153 21.4618 5.32758 21.1471 4.70822 20.4073C4.08886 19.6676 3.92921 18.7716 3.96588 17.7329C4.00137 16.7275 4.22812 15.4578 4.51121 13.8727L5.18145 10.1193C5.31517 9.37034 5.42756 8.74084 5.58139 8.24389C5.74449 7.71697 5.97845 7.25232 6.40946 6.89146C6.84047 6.5306 7.339 6.38197 7.8864 6.31403C8.40264 6.24996 9.04206 6.24998 9.80289 6.25H14.1978ZM12 9.75C12.4142 9.75 12.75 10.0858 12.75 10.5V15.6893L13.9697 14.4697C14.2626 14.1768 14.7374 14.1768 15.0303 14.4697C15.3232 14.7626 15.3232 15.2374 15.0303 15.5303L12.5303 18.0303C12.2374 18.3232 11.7626 18.3232 11.4697 18.0303L8.96967 15.5303C8.67678 15.2374 8.67678 14.7626 8.96967 14.4697C9.26256 14.1768 9.73744 14.1768 10.0303 14.4697L11.25 15.6893V10.5C11.25 10.0858 11.5858 9.75 12 9.75Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,318 @@
|
||||
class LakumInquiryInformationResponseModel {
|
||||
int? accountNumber;
|
||||
String? accountStatus;
|
||||
String? barCode;
|
||||
num? consumedPoints;
|
||||
dynamic consumedPointsAmount;
|
||||
dynamic consumedPointsAmountPerYear;
|
||||
|
||||
// List<Null>? consumedPointsDetails;
|
||||
String? createdDate;
|
||||
num? expiredPoints;
|
||||
String? expiryDate;
|
||||
num? gainedPoints;
|
||||
num? gainedPointsAmount;
|
||||
List<GainedPointsAmountPerYear>? gainedPointsAmountPerYear;
|
||||
|
||||
// List<Null>? gainedPointsDetails;
|
||||
String? lakumMessageStatus;
|
||||
String? memberName;
|
||||
String? memberUniversalId;
|
||||
String? mobileNumber;
|
||||
num? pointsBalance;
|
||||
num? pointsBalanceAmount;
|
||||
num? pointsWillBeExpired;
|
||||
String? prefLang;
|
||||
num? statusCode;
|
||||
num? transferPoints;
|
||||
dynamic transferPointsAmountPerYear;
|
||||
|
||||
// List<Null>? transferPointsDetails;
|
||||
num? waitingPoints;
|
||||
num? loyalityAmount;
|
||||
num? loyalityPoints;
|
||||
num? purchaseRate;
|
||||
|
||||
LakumInquiryInformationResponseModel(
|
||||
{this.accountNumber,
|
||||
this.accountStatus,
|
||||
this.barCode,
|
||||
this.consumedPoints,
|
||||
this.consumedPointsAmount,
|
||||
this.consumedPointsAmountPerYear,
|
||||
// this.consumedPointsDetails,
|
||||
this.createdDate,
|
||||
this.expiredPoints,
|
||||
this.expiryDate,
|
||||
this.gainedPoints,
|
||||
this.gainedPointsAmount,
|
||||
this.gainedPointsAmountPerYear,
|
||||
// this.gainedPointsDetails,
|
||||
this.lakumMessageStatus,
|
||||
this.memberName,
|
||||
this.memberUniversalId,
|
||||
this.mobileNumber,
|
||||
this.pointsBalance,
|
||||
this.pointsBalanceAmount,
|
||||
this.pointsWillBeExpired,
|
||||
this.prefLang,
|
||||
this.statusCode,
|
||||
this.transferPoints,
|
||||
this.transferPointsAmountPerYear,
|
||||
// this.transferPointsDetails,
|
||||
this.waitingPoints,
|
||||
this.loyalityAmount,
|
||||
this.loyalityPoints,
|
||||
this.purchaseRate});
|
||||
|
||||
LakumInquiryInformationResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
accountNumber = json['AccountNumber'];
|
||||
accountStatus = json['AccountStatus'];
|
||||
barCode = json['BarCode'];
|
||||
consumedPoints = json['ConsumedPoints'];
|
||||
consumedPointsAmount = json['ConsumedPointsAmount'];
|
||||
consumedPointsAmountPerYear = json['ConsumedPointsAmountPerYear'];
|
||||
// if (json['ConsumedPointsDetails'] != null) {
|
||||
// consumedPointsDetails = <Null>[];
|
||||
// json['ConsumedPointsDetails'].forEach((v) {
|
||||
// consumedPointsDetails!.add(new Null.fromJson(v));
|
||||
// });
|
||||
// }
|
||||
createdDate = json['CreatedDate'];
|
||||
expiredPoints = json['ExpiredPoints'];
|
||||
expiryDate = json['ExpiryDate'];
|
||||
gainedPoints = json['GainedPoints'];
|
||||
gainedPointsAmount = json['GainedPointsAmount'];
|
||||
if (json['GainedPointsAmountPerYear'] != null) {
|
||||
gainedPointsAmountPerYear = <GainedPointsAmountPerYear>[];
|
||||
json['GainedPointsAmountPerYear'].forEach((v) {
|
||||
gainedPointsAmountPerYear!.add(new GainedPointsAmountPerYear.fromJson(v));
|
||||
});
|
||||
}
|
||||
// if (json['GainedPointsDetails'] != null) {
|
||||
// gainedPointsDetails = <Null>[];
|
||||
// json['GainedPointsDetails'].forEach((v) {
|
||||
// gainedPointsDetails!.add(new Null.fromJson(v));
|
||||
// });
|
||||
// }
|
||||
lakumMessageStatus = json['LakumMessageStatus'];
|
||||
memberName = json['MemberName'];
|
||||
memberUniversalId = json['MemberUniversalId'];
|
||||
mobileNumber = json['MobileNumber'];
|
||||
pointsBalance = json['PointsBalance'];
|
||||
pointsBalanceAmount = json['PointsBalanceAmount'];
|
||||
pointsWillBeExpired = json['PointsWillBeExpired'];
|
||||
prefLang = json['PrefLang'];
|
||||
statusCode = json['StatusCode'];
|
||||
transferPoints = json['TransferPoints'];
|
||||
transferPointsAmountPerYear = json['TransferPointsAmountPerYear'];
|
||||
// if (json['TransferPointsDetails'] != null) {
|
||||
// transferPointsDetails = <Null>[];
|
||||
// json['TransferPointsDetails'].forEach((v) {
|
||||
// transferPointsDetails!.add(new Null.fromJson(v));
|
||||
// });
|
||||
// }
|
||||
waitingPoints = json['WaitingPoints'];
|
||||
loyalityAmount = json['loyalityAmount'];
|
||||
loyalityPoints = json['loyalityPoints'];
|
||||
purchaseRate = json['purchaseRate'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['AccountNumber'] = this.accountNumber;
|
||||
data['AccountStatus'] = this.accountStatus;
|
||||
data['BarCode'] = this.barCode;
|
||||
data['ConsumedPoints'] = this.consumedPoints;
|
||||
data['ConsumedPointsAmount'] = this.consumedPointsAmount;
|
||||
data['ConsumedPointsAmountPerYear'] = this.consumedPointsAmountPerYear;
|
||||
// if (this.consumedPointsDetails != null) {
|
||||
// data['ConsumedPointsDetails'] = this.consumedPointsDetails!.map((v) => v.toJson()).toList();
|
||||
// }
|
||||
data['CreatedDate'] = this.createdDate;
|
||||
data['ExpiredPoints'] = this.expiredPoints;
|
||||
data['ExpiryDate'] = this.expiryDate;
|
||||
data['GainedPoints'] = this.gainedPoints;
|
||||
data['GainedPointsAmount'] = this.gainedPointsAmount;
|
||||
if (this.gainedPointsAmountPerYear != null) {
|
||||
data['GainedPointsAmountPerYear'] = this.gainedPointsAmountPerYear!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
// if (this.gainedPointsDetails != null) {
|
||||
// data['GainedPointsDetails'] = this.gainedPointsDetails!.map((v) => v.toJson()).toList();
|
||||
// }
|
||||
data['LakumMessageStatus'] = this.lakumMessageStatus;
|
||||
data['MemberName'] = this.memberName;
|
||||
data['MemberUniversalId'] = this.memberUniversalId;
|
||||
data['MobileNumber'] = this.mobileNumber;
|
||||
data['PointsBalance'] = this.pointsBalance;
|
||||
data['PointsBalanceAmount'] = this.pointsBalanceAmount;
|
||||
data['PointsWillBeExpired'] = this.pointsWillBeExpired;
|
||||
data['PrefLang'] = this.prefLang;
|
||||
data['StatusCode'] = this.statusCode;
|
||||
data['TransferPoints'] = this.transferPoints;
|
||||
data['TransferPointsAmountPerYear'] = this.transferPointsAmountPerYear;
|
||||
// if (this.transferPointsDetails != null) {
|
||||
// data['TransferPointsDetails'] = this.transferPointsDetails!.map((v) => v.toJson()).toList();
|
||||
// }
|
||||
data['WaitingPoints'] = this.waitingPoints;
|
||||
data['loyalityAmount'] = this.loyalityAmount;
|
||||
data['loyalityPoints'] = this.loyalityPoints;
|
||||
data['purchaseRate'] = this.purchaseRate;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class GainedPointsAmountPerYear {
|
||||
num? amountPerYear;
|
||||
List<PointsAmountPerMonth>? pointsAmountPerMonth;
|
||||
num? pointsPerYear;
|
||||
int? year;
|
||||
|
||||
GainedPointsAmountPerYear({this.amountPerYear, this.pointsAmountPerMonth, this.pointsPerYear, this.year});
|
||||
|
||||
GainedPointsAmountPerYear.fromJson(Map<String, dynamic> json) {
|
||||
amountPerYear = json['AmountPerYear'];
|
||||
if (json['PointsAmountPerMonth'] != null) {
|
||||
pointsAmountPerMonth = <PointsAmountPerMonth>[];
|
||||
json['PointsAmountPerMonth'].forEach((v) {
|
||||
pointsAmountPerMonth!.add(new PointsAmountPerMonth.fromJson(v));
|
||||
});
|
||||
}
|
||||
pointsPerYear = json['PointsPerYear'];
|
||||
year = json['Year'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['AmountPerYear'] = this.amountPerYear;
|
||||
if (this.pointsAmountPerMonth != null) {
|
||||
data['PointsAmountPerMonth'] = this.pointsAmountPerMonth!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['PointsPerYear'] = this.pointsPerYear;
|
||||
data['Year'] = this.year;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class PointsAmountPerMonth {
|
||||
num? amountPerMonth;
|
||||
String? month;
|
||||
num? monthNumber;
|
||||
List<PointsAmountPerday>? pointsAmountPerday;
|
||||
num? pointsPerMonth;
|
||||
|
||||
PointsAmountPerMonth({this.amountPerMonth, this.month, this.monthNumber, this.pointsAmountPerday, this.pointsPerMonth});
|
||||
|
||||
PointsAmountPerMonth.fromJson(Map<String, dynamic> json) {
|
||||
amountPerMonth = json['AmountPerMonth'];
|
||||
month = json['Month'];
|
||||
monthNumber = json['MonthNumber'];
|
||||
if (json['PointsAmountPerday'] != null) {
|
||||
pointsAmountPerday = <PointsAmountPerday>[];
|
||||
json['PointsAmountPerday'].forEach((v) {
|
||||
pointsAmountPerday!.add(new PointsAmountPerday.fromJson(v));
|
||||
});
|
||||
}
|
||||
pointsPerMonth = json['PointsPerMonth'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['AmountPerMonth'] = this.amountPerMonth;
|
||||
data['Month'] = this.month;
|
||||
data['MonthNumber'] = this.monthNumber;
|
||||
if (this.pointsAmountPerday != null) {
|
||||
data['PointsAmountPerday'] = this.pointsAmountPerday!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['PointsPerMonth'] = this.pointsPerMonth;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class PointsAmountPerday {
|
||||
num? amountPerDay;
|
||||
String? day;
|
||||
List<PointsDetails>? pointsDetails;
|
||||
num? pointsPerDay;
|
||||
String? transationDate;
|
||||
|
||||
PointsAmountPerday({this.amountPerDay, this.day, this.pointsDetails, this.pointsPerDay, this.transationDate});
|
||||
|
||||
PointsAmountPerday.fromJson(Map<String, dynamic> json) {
|
||||
amountPerDay = json['AmountPerDay'];
|
||||
day = json['Day'];
|
||||
if (json['PointsDetails'] != null) {
|
||||
pointsDetails = <PointsDetails>[];
|
||||
json['PointsDetails'].forEach((v) {
|
||||
pointsDetails!.add(new PointsDetails.fromJson(v));
|
||||
});
|
||||
}
|
||||
pointsPerDay = json['PointsPerDay'];
|
||||
transationDate = json['TransationDate'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['AmountPerDay'] = this.amountPerDay;
|
||||
data['Day'] = this.day;
|
||||
if (this.pointsDetails != null) {
|
||||
data['PointsDetails'] = this.pointsDetails!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['PointsPerDay'] = this.pointsPerDay;
|
||||
data['TransationDate'] = this.transationDate;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class PointsDetails {
|
||||
int? accNumber;
|
||||
String? accountStatus;
|
||||
num? amount;
|
||||
int? lineItemNo;
|
||||
String? operationType;
|
||||
num? points;
|
||||
num? purchasePoints;
|
||||
int? subTransactionType;
|
||||
String? subTransactionTypeDescription;
|
||||
String? transactionDate;
|
||||
|
||||
PointsDetails(
|
||||
{this.accNumber,
|
||||
this.accountStatus,
|
||||
this.amount,
|
||||
this.lineItemNo,
|
||||
this.operationType,
|
||||
this.points,
|
||||
this.purchasePoints,
|
||||
this.subTransactionType,
|
||||
this.subTransactionTypeDescription,
|
||||
this.transactionDate});
|
||||
|
||||
PointsDetails.fromJson(Map<String, dynamic> json) {
|
||||
accNumber = json['AccNumber'];
|
||||
accountStatus = json['AccountStatus'];
|
||||
amount = json['Amount'];
|
||||
lineItemNo = json['LineItemNo'];
|
||||
operationType = json['OperationType'];
|
||||
points = json['Points'];
|
||||
purchasePoints = json['PurchasePoints'];
|
||||
subTransactionType = json['SubTransactionType'];
|
||||
subTransactionTypeDescription = json['SubTransactionTypeDescription'];
|
||||
transactionDate = json['TransactionDate'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['AccNumber'] = this.accNumber;
|
||||
data['AccountStatus'] = this.accountStatus;
|
||||
data['Amount'] = this.amount;
|
||||
data['LineItemNo'] = this.lineItemNo;
|
||||
data['OperationType'] = this.operationType;
|
||||
data['Points'] = this.points;
|
||||
data['PurchasePoints'] = this.purchasePoints;
|
||||
data['SubTransactionType'] = this.subTransactionType;
|
||||
data['SubTransactionTypeDescription'] = this.subTransactionTypeDescription;
|
||||
data['TransactionDate'] = this.transactionDate;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,431 @@
|
||||
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<AppState>();
|
||||
|
||||
return CollapsingListView(
|
||||
title: LocaleKeys.lakumPoints.tr(context: context),
|
||||
child: Consumer<HabibWalletViewModel>(
|
||||
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 Utils.getNoDataWidget(context);
|
||||
// return Center(
|
||||
// child: Padding(
|
||||
// padding: EdgeInsets.all(32.w),
|
||||
// child: LocaleKeys.lakumMsg.tr().toText14(
|
||||
// color: AppColors.greyTextColor,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
|
||||
// Get all transactions
|
||||
List<PointsDetails> 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<PointsDetails> 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;
|
||||
}
|
||||
Loading…
Reference in New Issue