Skip to content

Commit

Permalink
feat: purchasing event with coins integration
Browse files Browse the repository at this point in the history
  • Loading branch information
AhsanRns committed May 29, 2024
1 parent 5c1f994 commit 93dc8a0
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 49 deletions.
5 changes: 4 additions & 1 deletion evently/lib/evently_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,15 @@ class EventlyProvider extends ChangeNotifier {
step: '',
);

final String prices = isFreeDrop == FreeDrop.yes ? "0" : _selectedDenom.formatAmount(price: price.toString());


final recipe = event.createRecipe(
cookbookId: _cookbookId!,
recipeId: _recipeId,
isFreeDrop: isFreeDrop,
symbol: selectedDenom.symbol,
price: price.toString(),
price: prices,
);

final response = await PylonsWallet.instance.txCreateRecipe(recipe, requestResponse: false);
Expand Down
4 changes: 3 additions & 1 deletion evently/lib/models/events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ extension CreateRecipe on Events {
description: description.trim(),
version: kVersion,
coinInputs: [
if (isFreeDrop == FreeDrop.no)
if (isFreeDrop == FreeDrop.yes)
CoinInput()
else
CoinInput(
coins: [Coin(amount: price, denom: symbol)],
)
Expand Down
26 changes: 26 additions & 0 deletions wallet/lib/model/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,32 @@ class Events extends Equatable {
return map;
}

factory Events.fromJson(Map<String, dynamic> json) {
final List<PerksModel> listOfPerks = [];

json['listOfPerks'].map((jsonData) => listOfPerks.add(PerksModel.fromJson(jsonData as Map<String, dynamic>))).toList();

return Events(
recipeID: json['recipeID'] as String,
eventName: json['eventName'] as String,
hostName: json['hostName'] as String,
thumbnail: json['thumbnail'] as String,
startDate: json['startDate'] as String,
endDate: json['endDate'] as String,
startTime: json['startTime'] as String,
endTime: json['endTime'] as String,
location: json['location'] as String,
description: json['description'] as String,
numberOfTickets: json['numberOfTickets'] as String,
price: json['price'] as String,
isFreeDrops: json['isFreeDrops'] as String,
cookbookID: json['cookbookID'] as String,
step: json['step'] as String,
listOfPerks: listOfPerks,
denom: json['denom'].toString().toIBCCoinsEnumforEvent(),
);
}

Future<String> getOwnerAddress() async {
if (ownerAddress.isEmpty) {
final walletsStore = GetIt.I.get<WalletsStore>();
Expand Down
153 changes: 132 additions & 21 deletions wallet/lib/pages/events/event_purchase_view.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import 'dart:convert';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:provider/provider.dart';
import 'package:pylons_wallet/components/loading.dart';
import 'package:pylons_wallet/components/space_widgets.dart';
import 'package:pylons_wallet/model/event.dart';
import 'package:pylons_wallet/pages/home/currency_screen/model/ibc_coins.dart';
import 'package:pylons_wallet/pages/purchase_item/purchase_item_view_model.dart';
import 'package:pylons_wallet/pages/purchase_item/widgets/trade_receipt_dialog.dart';
import 'package:pylons_wallet/pages/purchase_item/widgets/transaction_complete_dialog.dart';
import 'package:pylons_wallet/pylons_app.dart';
import 'package:pylons_wallet/utils/constants.dart';
import 'package:pylons_wallet/utils/dependency_injection/dependency_injection.dart';
import 'package:pylons_wallet/utils/route_util.dart';
import '../../modules/Pylonstech.pylons.pylons/module/client/pylons/execution.pb.dart';

class EventPurchaseView extends StatefulWidget {
const EventPurchaseView({super.key, required this.events});
Expand All @@ -23,35 +34,129 @@ class _EventPurchaseViewState extends State<EventPurchaseView> {
super.initState();
}

final viewModel = sl<PurchaseItemViewModel>();

@override
Widget build(BuildContext context) {
return EventPassViewContent(
events: widget.events,
return ChangeNotifierProvider.value(
value: viewModel,
child: EventPassViewContent(
events: widget.events,
),
);
}
}

class EventPassViewContent extends StatelessWidget {
EventPassViewContent({
class EventPassViewContent extends StatefulWidget {
const EventPassViewContent({
super.key,
required this.events,
});

final Events events;

@override
State<EventPassViewContent> createState() => _EventPassViewContentState();
}

class _EventPassViewContentState extends State<EventPassViewContent> {
late Rect scanWindow;

MobileScannerController cameraController = MobileScannerController(
formats: const [BarcodeFormat.qrCode],
autoStart: true,
detectionSpeed: DetectionSpeed.noDuplicates,
);

void _foundBarcode(BarcodeCapture barcodeCapture) {
debugPrint('$barcodeCapture');
final String code = barcodeCapture.barcodes.last.displayValue ?? '';
debugPrint('Code: $code');
// context.read<QRScannerBloc>().add(ScannerTextEvent(scannedText: code));
bool isCapture = false;

Future<void> executeRecipe(BuildContext context) async {
final provider = context.read<PurchaseItemViewModel>();
final ibcEnumCoins = provider.getEvents.denom;

if (ibcEnumCoins == IBCCoins.ustripeusd) {
// stripePaymentForRecipe(context, provider.getEvents);
print('needed to work for this');
} else {
paymentByCoins();
}
}

Future<void> paymentByCoins() async {
final navigator = Navigator.of(navigatorKey.currentState!.overlay!.context);
final provider = context.read<PurchaseItemViewModel>();
final executionResponse = await provider.paymentForEventRecipe();

navigator.pop();
if (!executionResponse.success) {
executionResponse.error.show();
navigator.pushNamed(Routes.transactionFailure.name);
return;
}

showTransactionCompleteDialog(execution: executionResponse.data!);
}

void showTransactionCompleteDialog({required Execution execution}) {
final viewModel = context.read<PurchaseItemViewModel>();

var price = double.parse(viewModel.nft.price);
final fee = double.parse(viewModel.nft.price) * 0.1;
price = price - fee;

final txId = execution.hasId() ? execution.id : "";

final txTime = getTransactionTimeStamp(execution.hasTxTime() ? execution.txTime.toInt() : null);

final model = viewModel.createTradeReciptModel(
fee: fee,
price: price,
txId: txId,
txTime: txTime,
);

final TradeCompleteDialog tradeCompleteDialog = TradeCompleteDialog(
model: model,
context: context,
onBackPressed: () {
showReceiptDialog(model);
},
);
tradeCompleteDialog.show();
}

void showReceiptDialog(TradeReceiptModel model) {
final TradeReceiptDialog tradeReceiptDialog = TradeReceiptDialog(context: context, model: model);
tradeReceiptDialog.show();
}

String getTransactionTimeStamp(int? time) {
final formatter = DateFormat('MMM dd yyyy HH:mm');
if (time == null) {
return "${formatter.format(DateTime.now().toUtc())} $kUTC";
}

final int timeStamp = time * kDateConverterConstant;
final DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timeStamp, isUtc: true);
return "${formatter.format(dateTime)} $kUTC";
}

Future<void> onDetect(BarcodeCapture barCodeCapture, PurchaseItemViewModel viewModel, BuildContext context) async {
if (isCapture) {
return;
}
if (!isCapture) {
setState(() => isCapture = true);

final String? displayValue = barCodeCapture.barcodes.first.displayValue;

final map = jsonDecode(displayValue!);

final event = Events.fromJson(map as Map<String, dynamic>);

viewModel.setEvents = event;

await executeRecipe(context);
}
}

@override
Expand All @@ -62,6 +167,11 @@ class EventPassViewContent extends StatelessWidget {
height: 100.r,
);

final viewModel = context.watch<PurchaseItemViewModel>();
final coinWithDenom = widget.events.denom.getAbbrev() == kPYLN_ABBREVATION
? "\$${widget.events.denom.pylnToCredit(widget.events.denom.getCoinWithProperDenomination(widget.events.price))} ${widget.events.denom.getAbbrev()}"
: "${widget.events.denom.getCoinWithProperDenomination(widget.events.price)} ${widget.events.denom.getAbbrev()}";

return ColoredBox(
color: AppColors.kBlack87,
child: SafeArea(
Expand Down Expand Up @@ -102,12 +212,13 @@ class EventPassViewContent extends StatelessWidget {
margin: EdgeInsets.symmetric(horizontal: 20.w),
height: 200.h,
child: MobileScanner(
onDetect: (_) {
print(_);
},
onDetect: (BarcodeCapture barCodeCapture) => onDetect(
barCodeCapture,
viewModel,
context,
),
),
),

],
),
Container(
Expand All @@ -118,7 +229,7 @@ class EventPassViewContent extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
events.eventName,
widget.events.eventName,
style: Theme.of(context).textTheme.displayLarge?.copyWith(fontSize: 25.sp, fontWeight: FontWeight.w700, color: AppColors.kWhite),
),
VerticalSpace(20.h),
Expand All @@ -133,7 +244,7 @@ class EventPassViewContent extends StatelessWidget {
style: Theme.of(context).textTheme.displayLarge?.copyWith(fontSize: 11.sp, fontWeight: FontWeight.w400, color: AppColors.kWhite),
),
Text(
events.startDate,
widget.events.startDate,
style: Theme.of(context).textTheme.labelSmall?.copyWith(fontSize: 15.sp, fontWeight: FontWeight.w700, color: AppColors.kWhite),
),
],
Expand All @@ -146,7 +257,7 @@ class EventPassViewContent extends StatelessWidget {
style: Theme.of(context).textTheme.displayLarge?.copyWith(fontSize: 11.sp, fontWeight: FontWeight.w400, color: AppColors.kWhite),
),
Text(
events.startTime,
widget.events.startTime,
style: Theme.of(context).textTheme.labelSmall?.copyWith(fontSize: 15.sp, fontWeight: FontWeight.w700, color: AppColors.kWhite),
),
],
Expand All @@ -165,7 +276,7 @@ class EventPassViewContent extends StatelessWidget {
style: Theme.of(context).textTheme.displayLarge?.copyWith(fontSize: 11.sp, fontWeight: FontWeight.w400, color: AppColors.kWhite),
),
Text(
events.location,
widget.events.location,
style: Theme.of(context).textTheme.labelSmall?.copyWith(fontSize: 15.sp, fontWeight: FontWeight.w700, color: AppColors.kWhite),
),
],
Expand All @@ -178,7 +289,7 @@ class EventPassViewContent extends StatelessWidget {
style: Theme.of(context).textTheme.displayLarge?.copyWith(fontSize: 11.sp, fontWeight: FontWeight.w400, color: AppColors.kWhite),
),
Text(
events.price == "0" ? "Free" : '${events.price} ${events.denom.getName()}',
coinWithDenom,
style: Theme.of(context).textTheme.labelSmall?.copyWith(fontSize: 15.sp, fontWeight: FontWeight.w700, color: AppColors.kWhite),
),
],
Expand All @@ -202,7 +313,7 @@ class EventPassViewContent extends StatelessWidget {
SvgPicture.asset(kDiamondIcon),
SizedBox(width: 5.w),
Text(
'x ${events.listOfPerks?.length}',
'x ${widget.events.listOfPerks?.length}',
style: TextStyle(fontSize: 15.sp, color: AppColors.kWhite, fontWeight: FontWeight.bold),
),
SizedBox(width: 5.w),
Expand All @@ -224,7 +335,7 @@ class EventPassViewContent extends StatelessWidget {
child: CachedNetworkImage(
width: double.infinity,
fit: BoxFit.fill,
imageUrl: events.thumbnail,
imageUrl: widget.events.thumbnail,
errorWidget: (a, b, c) => const Center(
child: Icon(
Icons.error_outline,
Expand Down
13 changes: 0 additions & 13 deletions wallet/lib/pages/events/event_qr_code_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@ import 'package:pylons_wallet/pages/detailed_asset_view/widgets/nft_image_asset.
import 'package:pylons_wallet/utils/constants.dart';
import 'package:qr_flutter/qr_flutter.dart';

const jsonExecuteRecipe = '''
{
"creator": "",
"cookbook_id": "",
"recipe_id": "",
"eventName": "",
"eventPrice": "",
"eventCurrency": "",
"coinInputsIndex": 0
}
''';
final jsonMap = jsonDecode(jsonExecuteRecipe) as Map;

class EventQrCodeScreen extends StatefulWidget {
const EventQrCodeScreen({
super.key,
Expand Down
7 changes: 6 additions & 1 deletion wallet/lib/pages/events/events_owner_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class EventPassViewContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
final viewModel = context.watch<OwnerViewViewModel>();

final coinWithDenom = viewModel.events.denom.getAbbrev() == kPYLN_ABBREVATION
? "\$${viewModel.events.denom.pylnToCredit(viewModel.events.denom.getCoinWithProperDenomination(viewModel.events.price))} ${viewModel.events.denom.getAbbrev()}"
: "${viewModel.events.denom.getCoinWithProperDenomination(viewModel.events.price)} ${viewModel.events.denom.getAbbrev()}";

return ColoredBox(
color: AppColors.kBlack87,
child: SafeArea(
Expand Down Expand Up @@ -152,7 +157,7 @@ class EventPassViewContent extends StatelessWidget {
style: Theme.of(context).textTheme.displayLarge?.copyWith(fontSize: 11.sp, fontWeight: FontWeight.w400, color: AppColors.kWhite),
),
Text(
viewModel.events.price == "0" ? "Free" : '${viewModel.events.price} ${viewModel.events.denom.getName()}',
coinWithDenom,
style: Theme.of(context).textTheme.labelSmall?.copyWith(fontSize: 15.sp, fontWeight: FontWeight.w700, color: AppColors.kWhite),
),
],
Expand Down
Loading

0 comments on commit 93dc8a0

Please sign in to comment.