// ignore_for_file: use_build_context_synchronously, deprecated_member_use_from_same_package import 'dart:math'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hoshan/core/gen/assets.gen.dart'; import 'package:hoshan/data/model/plans_model.dart'; import 'package:hoshan/data/repository/paymant_repository.dart'; import 'package:hoshan/ui/theme/colors.dart'; import 'package:hoshan/ui/theme/cubit/theme_mode_cubit.dart'; import 'package:hoshan/ui/theme/text.dart'; import 'package:hoshan/ui/widgets/components/button/loading_button.dart'; import 'package:hoshan/ui/widgets/components/dialog/dialog_handler.dart'; import 'package:hoshan/ui/widgets/components/image/network_image.dart'; import 'package:hoshan/ui/widgets/components/purchase/cubit/discount_cubit.dart'; import 'package:hoshan/ui/widgets/components/shapes/vertical_ribbon.dart'; import 'package:hoshan/ui/widgets/components/snackbar/snackbar_manager.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:url_launcher/url_launcher.dart'; class PurchaseCard extends StatefulWidget { final Plans plan; final String? label; final double? height; final Widget Function()? button; const PurchaseCard({ super.key, required this.plan, this.label, this.height, this.button, }); @override State createState() => _PurchaseCardState(); } class _PurchaseCardState extends State { ValueNotifier loading = ValueNotifier(false); ValueNotifier showDiscount = ValueNotifier(false); final TextEditingController discountTextEditingController = TextEditingController(); String? discountCode; late final pr = widget.plan; @override Widget build(BuildContext context) { return BlocProvider( create: (context) => DiscountCubit(), child: Padding( padding: const EdgeInsets.all(16.0), child: Stack( children: [ Container( height: widget.height, padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), color: Theme.of(context).colorScheme.surface), child: Column( children: [ Padding( padding: const EdgeInsets.all(12), child: ImageNetwork( url: pr.image, radius: 360, width: 94, height: 94, ), ), const SizedBox( height: 8, ), Text( widget.plan.title ?? '', style: AppTextStyles.headline5.copyWith( color: Theme.of(context).colorScheme.onSurface), ), if (widget.plan.desc != null) Column( children: [ const SizedBox( height: 4, ), Text( widget.plan.desc!, style: AppTextStyles.body4.copyWith( color: AppColors.gray[ context.read().isDark() ? 600 : 900]), ), const SizedBox( height: 16, ), ], ), const SizedBox( height: 8, ), if (pr.price != null) Column( children: [ Text( '${pr.coins} سکه هوشان + ${pr.freeCoins} سکه رایگان', style: AppTextStyles.body4.copyWith( color: Theme.of(context).colorScheme.onSurface), textAlign: TextAlign.center, textDirection: TextDirection.rtl, ), const SizedBox( height: 12, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.end, textDirection: TextDirection.rtl, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text(':مبلغ قابل پرداخت', style: AppTextStyles.body3.copyWith( color: Theme.of(context) .colorScheme .primary)), ], ), Row( children: [ if (pr.oldPrice != null) Stack( children: [ Text( '${'${pr.oldPrice}'.seRagham()} تومان', style: AppTextStyles.body4.copyWith( color: AppColors .gray.defaultShade)), Positioned.fill( child: Divider( color: AppColors.gray.defaultShade, thickness: 4, )) ], ), if (pr.oldPrice != null) Text(' - ', style: AppTextStyles.body4.copyWith( color: AppColors.green.defaultShade)), Text('${'${pr.price}'.seRagham()} تومان', style: AppTextStyles.body4.copyWith( color: AppColors.green.defaultShade)), ], ) ], ), ), const SizedBox( height: 32, ), ValueListenableBuilder( valueListenable: showDiscount, builder: (context, show, _) { return show ? BlocConsumer( listener: (context, state) { if (state is DiscountSuccess) { final p = pr.price! - (state.discount.percent != null ? min( (pr.price! * state.discount .percent!) ~/ 100, state.discount .maxValue!) : state.discount.value!) .toInt(); pr.oldPrice = pr.price; pr.price = p.round(); setState(() { discountCode = state.code; }); } }, builder: (context, state) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( flex: 1, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ LoadingButton( loading: state is DiscountLoading, onPressed: () { if (discountTextEditingController .text.isEmpty) { return; } if (state is DiscountSuccess) { pr.price = pr.oldPrice; pr.oldPrice = null; setState(() { discountCode = null; }); context .read< DiscountCubit>() .refresh(); return; } context .read< DiscountCubit>() .verifyDiscount( discountTextEditingController .text, pr.id ?? ''); }, color: state is DiscountSuccess ? AppColors .red.defaultShade : AppColors.green .defaultShade, child: Text( state is DiscountSuccess ? 'حذف' : 'اعمال', style: AppTextStyles .body4 .copyWith( color: Colors .white, fontWeight: FontWeight .bold), )) ], ), ), Expanded( flex: 2, child: Directionality( textDirection: TextDirection.rtl, child: TextField( controller: discountTextEditingController, maxLength: 8, maxLines: 1, style: TextStyle( color: Theme.of(context) .colorScheme .onSurface), enabled: state is! DiscountSuccess && state is! DiscountLoading, buildCounter: (context, {required currentLength, required isFocused, required maxLength}) => const SizedBox.shrink(), onChanged: (value) { if (state is! DiscountInitial) { context .read() .refresh(); } }, decoration: InputDecoration( error: state is DiscountFail ? Text( state.message ?? 'مشکلی پیش آمده لحظاتی دیگر دوباره امتحان کنید', style: AppTextStyles .body5 .copyWith( color: AppColors .red .defaultShade), ) : null, suffixIcon: GestureDetector( onTap: () async { ClipboardData? clipboardData = await Clipboard .getData( 'text/plain'); if (clipboardData != null && clipboardData .text != null) { discountTextEditingController .text = clipboardData .text!; } }, child: const Icon( Icons .paste_rounded)), hintText: 'کد تخفیف دارید؟', hintStyle: AppTextStyles.body4), ), ), ) ], ); }, ) : GestureDetector( onTap: () => showDiscount.value = !show, child: Text( 'کد تخفیف دارید؟ اینجا کلیک کنید.', textDirection: TextDirection.rtl, style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context) .colorScheme .primary), ), ); }), Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ValueListenableBuilder( valueListenable: loading, builder: (context, load, _) { return LoadingButton( loading: load, onPressed: context .watch() .state is DiscountLoading ? null : () async { try { loading.value = true; final link = await PaymantRepository .getLinkPaymant( pr.oldPrice ?? pr.price ?? 0, code: discountCode); await launchUrl(Uri.parse(link), mode: LaunchMode .externalApplication) .onError( (error, stackTrace) { if (kDebugMode) { print( 'error open Link is: $error'); } return false; }, ); } on DioException catch (e) { SnackBarManager(context, id: 'error-bazar-paymant') .show( status: SnackBarStatus.error, message: 'پرداخت ناموفق بود'); if (kDebugMode) { print("Dio Error is: $e"); } } loading.value = false; }, radius: 360, color: AppColors.primaryColor.defaultShade, width: MediaQuery.sizeOf(context).width, height: 48, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'خرید بسته ${pr.title ?? ''}', style: AppTextStyles.body4 .copyWith(color: Colors.white), ), const SizedBox( width: 8, ), Padding( padding: const EdgeInsets.only( bottom: 4.0), child: Assets.icon.outline.crown.svg( color: Colors.white, width: 18, ), ), ], )); }), ), ], ), if (widget.button != null) widget.button!.call() ], ), ), if (widget.label != null) Positioned( top: 0, left: 36, child: VerticalRibbon(text: widget.label!)), if (pr.title != 'بسته ویژه سازمان‌ها') Positioned( top: 16, right: 16, child: GestureDetector( onTap: () { DialogHandler(context: context).showExtras(); }, child: Assets.icon.outline.infoCircle.svg( color: AppColors.gray[ context.read().isDark() ? 600 : 900], width: 32, height: 32), )) ], ), ), ); } }