first commit
This commit is contained in:
903
lib/Screens/subscription/purchase_premium_plan_screen.dart
Normal file
903
lib/Screens/subscription/purchase_premium_plan_screen.dart
Normal file
@@ -0,0 +1,903 @@
|
||||
import 'package:community_material_icon/community_material_icon.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:mobile_pos/Provider/profile_provider.dart';
|
||||
import 'package:mobile_pos/generated/l10n.dart' as lang;
|
||||
|
||||
import '../../GlobalComponents/go_to_subscription-package_page_popup_widget.dart';
|
||||
import '../../constant.dart';
|
||||
import '../../http_client/custome_http_client.dart';
|
||||
import '../../model/business_info_model.dart' as bInfo;
|
||||
import '../Currency/Model/currency_model.dart';
|
||||
import '../Currency/Provider/currency_provider.dart';
|
||||
import '../Home/home.dart';
|
||||
import '../../service/check_user_role_permission_provider.dart';
|
||||
import '../payment getway/payment_getway_screen.dart';
|
||||
import 'Model/subscription_plan_model.dart';
|
||||
import 'Provider/subacription_plan_provider.dart';
|
||||
import 'Repo/subscriptionPlanRepo.dart';
|
||||
|
||||
// class PurchasePremiumPlanScreenPrevious extends StatefulWidget {
|
||||
// const PurchasePremiumPlanScreenPrevious({super.key, required this.isCameBack, this.isExpired, this.enrolledPlan, this.willExpire});
|
||||
//
|
||||
// final bool isCameBack;
|
||||
// final bool? isExpired;
|
||||
// final bInfo.EnrolledPlan? enrolledPlan;
|
||||
// final String? willExpire;
|
||||
//
|
||||
// @override
|
||||
// State<PurchasePremiumPlanScreen> createState() => _PurchasePremiumPlanScreenState();
|
||||
// }
|
||||
//
|
||||
// class _PurchasePremiumPlanScreenState extends State<PurchasePremiumPlanScreen> {
|
||||
// SubscriptionPlanModelNew? selectedPlan;
|
||||
// bool isPlanExpiringIn7Days = false;
|
||||
//
|
||||
// List<String> imageList = [
|
||||
// 'images/sp1.png',
|
||||
// 'images/sp2.png',
|
||||
// 'images/sp3.png',
|
||||
// 'images/sp4.png',
|
||||
// 'images/sp5.png',
|
||||
// 'images/sp6.png',
|
||||
// ];
|
||||
//
|
||||
// List<String> planDetailsImages = [
|
||||
// 'images/plan_details_1.png',
|
||||
// 'images/plan_details_2.png',
|
||||
// 'images/plan_details_3.png',
|
||||
// 'images/plan_details_4.png',
|
||||
// 'images/plan_details_5.png',
|
||||
// 'images/plan_details_6.png',
|
||||
// ];
|
||||
//
|
||||
// @override
|
||||
// void didChangeDependencies() {
|
||||
// super.didChangeDependencies();
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// if (widget.isExpired == true) {
|
||||
// getUpgradeDialog();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// CurrencyModel? getDefoultCurrency({required List<CurrencyModel> currencies}) {
|
||||
// for (var element in currencies) {
|
||||
// if (element.isDefault ?? false) {
|
||||
// return element;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// // warning popup
|
||||
// void getUpgradeDialog() {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (BuildContext dialogContext) {
|
||||
// return goToPackagePagePopup(context: dialogContext, enrolledPlan: widget.enrolledPlan);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// bool _isRefreshing = false; // Prevents multiple refresh calls
|
||||
//
|
||||
// Future<void> refreshData(WidgetRef ref) async {
|
||||
// if (_isRefreshing) return; // Prevent duplicate refresh calls
|
||||
// _isRefreshing = true;
|
||||
//
|
||||
// ref.refresh(businessInfoProvider);
|
||||
// ref.refresh(subscriptionPlanProvider);
|
||||
// ref.refresh(getExpireDateProvider(ref));
|
||||
//
|
||||
// await Future.delayed(const Duration(seconds: 1)); // Optional delay
|
||||
// _isRefreshing = false;
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// // selectedPlan = SubscriptionPlanModel(id: widget.enrolledPlan?.planId);
|
||||
// if (widget.willExpire != null && DateTime.tryParse(widget.willExpire ?? '') != null) {
|
||||
// DateTime expiryDate = DateTime.parse(widget.willExpire!);
|
||||
// isPlanExpiringIn7Days = expiryDate.isBefore(DateTime.now().add(const Duration(days: 6)));
|
||||
// }
|
||||
//
|
||||
// super.initState();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// List<String> planDetailsText = [
|
||||
// lang.S.of(context).freeLifetimeUpdate,
|
||||
// lang.S.of(context).android,
|
||||
// lang.S.of(context).premiumCustomerSupport,
|
||||
// lang.S.of(context).customInvoiceBranding,
|
||||
// lang.S.of(context).unlimitedUsage,
|
||||
// lang.S.of(context).freeDataBackup,
|
||||
// ];
|
||||
// List<String> titleListData = [
|
||||
// lang.S.of(context).freeLifetimeUpdate,
|
||||
// lang.S.of(context).android,
|
||||
// lang.S.of(context).premiumCustomerSupport,
|
||||
// lang.S.of(context).customInvoiceBranding,
|
||||
// lang.S.of(context).unlimitedUsage,
|
||||
// lang.S.of(context).freeDataBackup,
|
||||
// ];
|
||||
//
|
||||
// return Consumer(builder: (context, ref, __) {
|
||||
// final subscriptionPlanData = ref.watch(subscriptionPlanProvider);
|
||||
// final businessInfo = ref.watch(businessInfoProvider);
|
||||
// final currencyData = ref.watch(currencyProvider);
|
||||
// return Scaffold(
|
||||
// backgroundColor: kWhite,
|
||||
// body: PopScope(
|
||||
// canPop: widget.isExpired != true,
|
||||
// child: RefreshIndicator(
|
||||
// onRefresh: () => refreshData(ref),
|
||||
// child: SingleChildScrollView(
|
||||
// physics: const AlwaysScrollableScrollPhysics(),
|
||||
// child: SafeArea(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(20.0),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// lang.S.of(context).purchasePremium,
|
||||
// style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
|
||||
// ),
|
||||
// GestureDetector(
|
||||
// onTap: widget.isExpired != true
|
||||
// ? () {
|
||||
// if (widget.isCameBack) {
|
||||
// Navigator.pop(context);
|
||||
// } else {
|
||||
// Navigator.pushAndRemoveUntil(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) => const Home()),
|
||||
// (Route<dynamic> route) => false,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// : () => Navigator.pushAndRemoveUntil(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) => const Home()),
|
||||
// (Route<dynamic> route) => false,
|
||||
// ),
|
||||
// // ScaffoldMessenger.of(context).showSnackBar(
|
||||
// // const SnackBar(
|
||||
// // backgroundColor: Colors.red,
|
||||
// // content: Text('Please update your plan'),
|
||||
// // ),
|
||||
// // ),
|
||||
//
|
||||
// child: Icon(
|
||||
// Icons.cancel_outlined,
|
||||
// color: widget.isExpired != true ? Colors.grey : Colors.black,
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(height: 20),
|
||||
// ListView.builder(
|
||||
// itemCount: imageList.length,
|
||||
// shrinkWrap: true,
|
||||
// physics: const NeverScrollableScrollPhysics(),
|
||||
// itemBuilder: (_, i) {
|
||||
// return Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 15),
|
||||
// child: GestureDetector(
|
||||
// onTap: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (BuildContext context) {
|
||||
// return Dialog(
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// const SizedBox(height: 20),
|
||||
// Row(
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
// children: [
|
||||
// GestureDetector(
|
||||
// child: const Icon(Icons.cancel),
|
||||
// onTap: () {
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// ),
|
||||
// const SizedBox(width: 20),
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(height: 20),
|
||||
// Image(
|
||||
// height: 200,
|
||||
// width: 200,
|
||||
// image: AssetImage(planDetailsImages[i]),
|
||||
// ),
|
||||
// const SizedBox(height: 20),
|
||||
// Text(
|
||||
// planDetailsText[i],
|
||||
// textAlign: TextAlign.center,
|
||||
// style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
// ),
|
||||
// const SizedBox(height: 15),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Text(lang.S.of(context).loremIpsumDolor,
|
||||
// //'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Natoque aliquet et, cur eget. Tellus sapien odio aliq.',
|
||||
// textAlign: TextAlign.center,
|
||||
// style: const TextStyle(fontSize: 16)),
|
||||
// ),
|
||||
// const SizedBox(height: 20),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// },
|
||||
// child: Container(
|
||||
// decoration: BoxDecoration(borderRadius: BorderRadius.circular(6), color: kWhite, boxShadow: [
|
||||
// BoxShadow(color: const Color(0xff0C1A4B).withOpacity(0.24), blurRadius: 1),
|
||||
// BoxShadow(color: const Color(0xff473232).withOpacity(0.05), offset: const Offset(0, 3), blurRadius: 8, spreadRadius: -1)
|
||||
// ]),
|
||||
// child: ListTile(
|
||||
// visualDensity: const VisualDensity(horizontal: -4),
|
||||
// contentPadding: const EdgeInsets.only(left: 8, right: 10),
|
||||
// leading: SizedBox(
|
||||
// height: 40,
|
||||
// width: 40,
|
||||
// child: Image(
|
||||
// image: AssetImage(imageList[i]),
|
||||
// ),
|
||||
// ),
|
||||
// title: Text(
|
||||
// titleListData[i],
|
||||
// style: const TextStyle(fontSize: 16),
|
||||
// ),
|
||||
// trailing: const Icon(
|
||||
// FeatherIcons.alertCircle,
|
||||
// color: kGreyTextColor,
|
||||
// size: 20,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }),
|
||||
// const SizedBox(height: 10),
|
||||
// Text(
|
||||
// lang.S.of(context).buyPremium,
|
||||
// style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
// ),
|
||||
//
|
||||
// ///_______Plans_List______________________________________________________________
|
||||
// subscriptionPlanData.when(data: (data) {
|
||||
// return SizedBox(
|
||||
// height: (context.width() / 2.5) + 18,
|
||||
// child: ListView.builder(
|
||||
// physics: const ClampingScrollPhysics(),
|
||||
// shrinkWrap: true,
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// itemCount: data.length,
|
||||
// itemBuilder: (BuildContext context, int index) {
|
||||
// return GestureDetector(
|
||||
// onTap: () {
|
||||
// setState(() {
|
||||
// selectedPlan = data[index];
|
||||
// });
|
||||
// },
|
||||
// child: (data[index].offerPrice != null && (data[index].offerPrice ?? 0) > 0)
|
||||
// ? Padding(
|
||||
// padding: const EdgeInsets.only(right: 10),
|
||||
// child: SizedBox(
|
||||
// height: (context.width() / 3) + 18,
|
||||
// child: Stack(
|
||||
// alignment: Alignment.center,
|
||||
// children: [
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 20, top: 20),
|
||||
// child: Container(
|
||||
// // height: (context.width() / 3) - 20,
|
||||
// width: (context.width() / 3) - 20,
|
||||
// decoration: BoxDecoration(
|
||||
// color: data[index].id == selectedPlan?.id ? kPremiumPlanColor2.withOpacity(0.1) : Colors.white,
|
||||
// borderRadius: const BorderRadius.all(
|
||||
// Radius.circular(10),
|
||||
// ),
|
||||
// border: Border.all(
|
||||
// width: 1,
|
||||
// color: data[index].id == selectedPlan?.id ? kPremiumPlanColor2 : kPremiumPlanColor,
|
||||
// ),
|
||||
// ),
|
||||
// child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text(
|
||||
// data[index].subscriptionName ?? '',
|
||||
// style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
// ),
|
||||
// Text(
|
||||
// '${data[index].duration} days',
|
||||
// textAlign: TextAlign.center,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 13,
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// '${getDefoultCurrency(currencies: currencyData.value ?? [])?.symbol ?? ''}${data[index].offerPrice}',
|
||||
// style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: kPremiumPlanColor2),
|
||||
// ),
|
||||
// Text(
|
||||
// '${getDefoultCurrency(currencies: currencyData.value ?? [])?.symbol ?? ''}${data[index].subscriptionPrice}',
|
||||
// style: const TextStyle(decoration: TextDecoration.lineThrough, fontSize: 14, color: Colors.grey),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Positioned(
|
||||
// top: 8,
|
||||
// left: 0,
|
||||
// child: Container(
|
||||
// height: 25,
|
||||
// width: 70,
|
||||
// decoration: const BoxDecoration(
|
||||
// color: kPremiumPlanColor2,
|
||||
// borderRadius: BorderRadius.only(
|
||||
// topLeft: Radius.circular(10),
|
||||
// bottomRight: Radius.circular(10),
|
||||
// ),
|
||||
// ),
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// // 'Save ${(100 - (((data[index].offerPrice ?? 0) * 100) / (data[index].subscriptionPrice ?? 0))).round().toString()}%',
|
||||
// '${lang.S.of(context).save} ${(100 - (((data[index].offerPrice ?? 0) * 100) / (data[index].subscriptionPrice ?? 0))).round().toString()}%',
|
||||
// style: const TextStyle(color: Colors.white),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// : Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 20, top: 20, right: 10),
|
||||
// child: Container(
|
||||
// width: (context.width() / 3) - 20,
|
||||
// decoration: BoxDecoration(
|
||||
// color: data[index].id == selectedPlan?.id ? kPremiumPlanColor2.withOpacity(0.1) : Colors.white,
|
||||
// borderRadius: const BorderRadius.all(
|
||||
// Radius.circular(10),
|
||||
// ),
|
||||
// border: Border.all(width: 1, color: data[index].id == selectedPlan?.id ? kPremiumPlanColor2 : kPremiumPlanColor),
|
||||
// ),
|
||||
// child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text(
|
||||
// data[index].subscriptionName ?? '',
|
||||
// style: const TextStyle(fontSize: 16),
|
||||
// ),
|
||||
// Text(
|
||||
// //'${data[index].duration} days',
|
||||
// '${data[index].duration} ${lang.S.of(context).days}',
|
||||
// textAlign: TextAlign.center,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 13,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 12),
|
||||
// Text(
|
||||
// '${getDefoultCurrency(currencies: currencyData.value ?? [])?.symbol ?? ''}${data[index].subscriptionPrice.toString()}',
|
||||
// style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: kPremiumPlanColor),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// }, error: (Object error, StackTrace? stackTrace) {
|
||||
// return Text(error.toString());
|
||||
// }, loading: () {
|
||||
// return const Center(child: CircularProgressIndicator());
|
||||
// }),
|
||||
// const SizedBox(height: 20),
|
||||
// Visibility(
|
||||
// visible: (selectedPlan != null &&
|
||||
// (widget.enrolledPlan?.planId != selectedPlan?.id || isPlanExpiringIn7Days) &&
|
||||
// ((widget.enrolledPlan?.duration ?? 0) < (selectedPlan?.duration ?? 0)) &&
|
||||
// (selectedPlan?.offerPrice != null ? selectedPlan!.offerPrice! > 0 : (selectedPlan?.subscriptionPrice ?? 0) > 0)),
|
||||
// child: GestureDetector(
|
||||
// onTap: () async {
|
||||
// if (selectedPlan != null) {
|
||||
// bool success = await Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => PaymentScreen(
|
||||
// planId: selectedPlan?.id.toString() ?? '',
|
||||
// businessId: businessInfo.value?.id.toString() ?? '',
|
||||
// ),
|
||||
// ));
|
||||
//
|
||||
// if (success) {
|
||||
// ref.refresh(businessInfoProvider);
|
||||
// ref.refresh(getExpireDateProvider(ref));
|
||||
// widget.isExpired == false;
|
||||
// EasyLoading.showSuccess(
|
||||
// lang.S.of(context).successfullyPaid,
|
||||
// // 'successfully paid'
|
||||
// );
|
||||
// Navigator.push(context, MaterialPageRoute(builder: (context) => const Home()));
|
||||
// } else {
|
||||
// EasyLoading.showError(
|
||||
// lang.S.of(context).field,
|
||||
// // 'Field'
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// child: Container(
|
||||
// height: 50,
|
||||
// decoration: const BoxDecoration(
|
||||
// color: kMainColor,
|
||||
// borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
// ),
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// lang.S.of(context).payForSubscribe,
|
||||
// style: const TextStyle(fontSize: 18, color: Colors.white),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
class PurchasePremiumPlanScreen extends ConsumerStatefulWidget {
|
||||
const PurchasePremiumPlanScreen({
|
||||
super.key,
|
||||
required this.isCameBack,
|
||||
this.isExpired,
|
||||
this.enrolledPlan,
|
||||
this.willExpire,
|
||||
});
|
||||
final bool isCameBack;
|
||||
final bool? isExpired;
|
||||
final bInfo.EnrolledPlan? enrolledPlan;
|
||||
final String? willExpire;
|
||||
|
||||
@override
|
||||
ConsumerState<PurchasePremiumPlanScreen> createState() => _SubscriptionPlanScreenState();
|
||||
}
|
||||
|
||||
class _SubscriptionPlanScreenState extends ConsumerState<PurchasePremiumPlanScreen> {
|
||||
SubscriptionPlanModelNew? selectedPlan;
|
||||
bool _isLoading = false;
|
||||
bool isPlanExpiringIn7Days = false;
|
||||
bool _isRefreshing = false;
|
||||
int? ineligibleIndex;
|
||||
|
||||
SubscriptionPlanRepo subscriptionRepo = SubscriptionPlanRepo();
|
||||
|
||||
Widget _buildFeatureItem(String featureKey, dynamic featureValue) {
|
||||
final isActive = featureValue is List && featureValue.length > 1 && featureValue[1] == "1";
|
||||
final featureText = featureValue is List ? featureValue[0].toString() : featureKey;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 8),
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Color(0xff473232).withValues(alpha: 0.05), blurRadius: 8, offset: Offset(0, 3), spreadRadius: -1),
|
||||
BoxShadow(
|
||||
color: Color(0xff0C1A4B).withValues(alpha: 0.024), blurRadius: 1, offset: Offset(0, 0), spreadRadius: 0)
|
||||
],
|
||||
),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
leading: Icon(
|
||||
isActive ? Icons.check_circle : CommunityMaterialIcons.close_circle,
|
||||
color: isActive ? Colors.green : Colors.red,
|
||||
),
|
||||
title: Text(
|
||||
featureText,
|
||||
style: TextStyle(
|
||||
color: kGreyTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
CurrencyModel? getDefoultCurrency({required List<CurrencyModel> currencies}) {
|
||||
for (var element in currencies) {
|
||||
if (element.isDefault ?? false) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int calculateDiscountPercent(double originalPrice, double offerPrice) {
|
||||
return ((1 - (offerPrice / originalPrice)) * 100).round();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (widget.willExpire != null && DateTime.tryParse(widget.willExpire ?? '') != null) {
|
||||
DateTime expiryDate = DateTime.parse(widget.willExpire!);
|
||||
isPlanExpiringIn7Days = expiryDate.isBefore(DateTime.now().add(const Duration(days: 6)));
|
||||
}
|
||||
|
||||
// Fetch plans and select initial plan
|
||||
subscriptionRepo.fetchAllPlans().then((plans) {
|
||||
if (plans.isNotEmpty) {
|
||||
final currentPlanId = widget.enrolledPlan?.planId;
|
||||
final matchedPlan = plans.firstWhere(
|
||||
(plan) => plan.id == currentPlanId,
|
||||
orElse: () => plans.first,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
selectedPlan = matchedPlan;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (widget.isExpired == true) {
|
||||
getUpgradeDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void getUpgradeDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return goToPackagePagePopup(
|
||||
context: dialogContext,
|
||||
enrolledPlan: widget.enrolledPlan,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> refreshData(WidgetRef ref) async {
|
||||
if (_isRefreshing) return;
|
||||
_isRefreshing = true;
|
||||
|
||||
ref.refresh(businessInfoProvider);
|
||||
ref.refresh(subscriptionPlanProvider);
|
||||
ref.refresh(getExpireDateProvider(ref));
|
||||
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
_isRefreshing = false;
|
||||
}
|
||||
|
||||
bool showIneligibleMessage = false;
|
||||
|
||||
@override
|
||||
@override
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final businessInfo = ref.watch(businessInfoProvider);
|
||||
final currencyData = ref.watch(currencyProvider);
|
||||
final theme = Theme.of(context);
|
||||
final permissionService = PermissionService(ref);
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
backgroundColor: kWhite,
|
||||
bottomNavigationBar: selectedPlan == null
|
||||
? const SizedBox.shrink()
|
||||
: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (!permissionService.hasPermission(Permit.subscriptionsRead.value)) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Colors.red,
|
||||
content: Text(lang.S.of(context).youDoNotHavePermissionToCreatePurchase),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
final plan = selectedPlan!;
|
||||
final isCurrentPlan = plan.id == widget.enrolledPlan?.planId;
|
||||
final isUpgradeEligible = (widget.enrolledPlan?.planId != plan.id || isPlanExpiringIn7Days) &&
|
||||
((widget.enrolledPlan?.duration ?? 0) < (plan.duration ?? 0));
|
||||
|
||||
if ((plan.subscriptionPrice ?? 0) <= 0) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(lang.S.of(context).thisPlanIsNotAvailableToPurchase)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUpgradeEligible || isCurrentPlan) {
|
||||
final success = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => PaymentScreen(
|
||||
planId: plan.id.toString(),
|
||||
businessId: businessInfo.value?.data?.id.toString() ?? '',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (success == true) {
|
||||
ref.refresh(businessInfoProvider);
|
||||
ref.refresh(getExpireDateProvider(ref));
|
||||
EasyLoading.showSuccess(lang.S.of(context).successfullyPaid);
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const Home()),
|
||||
);
|
||||
} else {
|
||||
EasyLoading.showError(lang.S.of(context).field);
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(lang.S.of(context).thisPlanIsEligibleForUpgrade)),
|
||||
);
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: kMainColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
selectedPlan?.id == widget.enrolledPlan?.planId
|
||||
? lang.S.of(context).extendPlan
|
||||
: lang.S.of(context).buyNow,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: FutureBuilder<List<SubscriptionPlanModelNew>>(
|
||||
future: subscriptionRepo.fetchAllPlans(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasError) return Center(child: Text('Error: ${snapshot.error}'));
|
||||
if (!snapshot.hasData) return const Center(child: CircularProgressIndicator());
|
||||
|
||||
final plans = snapshot.data!;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Features
|
||||
if (selectedPlan != null)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
lang.S.of(context).purchasePremium,
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500, color: kTitleColor),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: widget.isExpired != true
|
||||
? () {
|
||||
if (widget.isCameBack) {
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const Home()),
|
||||
(Route<dynamic> route) => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
: () => Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const Home()),
|
||||
(Route<dynamic> route) => false,
|
||||
),
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// const SnackBar(
|
||||
// backgroundColor: Colors.red,
|
||||
// content: Text('Please update your plan'),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: widget.isExpired != true ? Colors.grey : Colors.black,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
...selectedPlan!.features.entries.map((entry) => _buildFeatureItem(entry.key, entry.value)),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
|
||||
Text(
|
||||
lang.S.of(context).outPremiumPlan,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Horizontal Plan List
|
||||
SizedBox(
|
||||
height: 165,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: plans.length,
|
||||
itemBuilder: (context, index) {
|
||||
final plan = plans[index];
|
||||
final isSelected = selectedPlan?.id == plan.id;
|
||||
final hasOffer = plan.offerPrice != null && plan.offerPrice! > 0;
|
||||
final discountPercent =
|
||||
hasOffer ? calculateDiscountPercent(plan.subscriptionPrice, plan.offerPrice!) : null;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => setState(() => selectedPlan = plan),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
margin: const EdgeInsets.only(right: 16),
|
||||
width: 115,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
// Main card container (single instance now)
|
||||
Container(
|
||||
height: 145,
|
||||
width: 115,
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? const Color(0xffFEF0F1).withOpacity(0.2)
|
||||
: theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: isSelected ? kMainColor : const Color(0xffEAECF0),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
plan.subscriptionName,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 18,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'${plan.duration} ${lang.S.of(context).days}',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
if (hasOffer)
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
'${getDefoultCurrency(currencies: currencyData.value ?? [])?.symbol ?? ''}${plan.offerPrice}',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: isSelected ? kMainColor : kTitleColor,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${getDefoultCurrency(currencies: currencyData.value ?? [])?.symbol ?? ''}${plan.subscriptionPrice}',
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w400,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
],
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'${getDefoultCurrency(currencies: currencyData.value ?? [])?.symbol ?? ''}${plan.subscriptionPrice}',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: isSelected ? kMainColor : kTitleColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Offer banner
|
||||
if (hasOffer)
|
||||
Positioned(
|
||||
top: -8,
|
||||
left: 0,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
decoration: const BoxDecoration(
|
||||
color: kMainColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'${lang.S.of(context).save} $discountPercent%',
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user