// Haveno App extends the features of Haveno, supporting mobile devices and more. // Copyright (C) 2024 Kewbit (https://kewbit.org) // Source Code: https://git.haveno.com/haveno/haveno-app.git // // Author: Kewbit // Website: https://kewbit.org // Contact Email: me@kewbit.org // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import 'package:flutter/material.dart'; import 'package:haveno/grpc_models.dart'; import 'package:haveno_app/utils/payment_utils.dart'; import 'package:provider/provider.dart'; import 'package:haveno_app/providers/haveno_client_providers/offers_provider.dart'; class EditTradeOfferForm extends StatefulWidget { final OfferInfo offer; const EditTradeOfferForm({super.key, required this.offer}); @override _EditTradeOfferFormState createState() => _EditTradeOfferFormState(); } class _EditTradeOfferFormState extends State { final TextEditingController _deviationController = TextEditingController(); final TextEditingController _triggerPriceController = TextEditingController(); @override void initState() { super.initState(); // Initialize with current offer data _deviationController.text = widget.offer.marketPriceMarginPct.toString(); _triggerPriceController.text = autoFormatCurrency(widget.offer.triggerPrice.toString(), widget.offer.counterCurrencyCode, includeCurrencyCode: false); } @override Widget build(BuildContext context) { final isBuy = widget.offer.direction == 'BUY'; final useMarketBasedPrice = widget.offer.useMarketBasedPrice; return Padding( padding: MediaQuery.of(context).viewInsets, child: Container( padding: const EdgeInsets.all(16.0), child: Form( child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'Edit ${isBuy ? 'Buy' : 'Sell'} Offer', style: const TextStyle(fontSize: 18), ), const SizedBox(height: 16.0), if (useMarketBasedPrice) TextFormField( controller: _deviationController, decoration: const InputDecoration( labelText: 'Maximum Deviation from Market Price', border: OutlineInputBorder(), suffixText: '%', // Suffix text to indicate percentage ), keyboardType: TextInputType.number, validator: (value) { if (value == null || value.isEmpty) { return 'Please enter the maximum deviation percentage'; } return null; }, ), const SizedBox(height: 16.0), TextFormField( controller: _triggerPriceController, decoration: InputDecoration( labelText: isBuy ? 'Delist if Market Price goes above' : 'Delist if Market Price goes below', border: const OutlineInputBorder(), suffixText: widget.offer.counterCurrencyCode, // Suffix is the currency code ), keyboardType: TextInputType.number, validator: (value) { if (value == null || value.isEmpty) { return 'Please enter a trigger price'; } return null; }, ), const SizedBox(height: 16.0), Row( children: [ Expanded( child: ElevatedButton( onPressed: () async { // Validate and update offer details if (Form.of(context).validate()) { final offersProvider = Provider.of(context, listen: false); await offersProvider.editOffer( offerId: widget.offer.id, marketPriceMarginPct: double.tryParse(_deviationController.text), triggerPrice: _triggerPriceController.text, ); Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Offer updated successfully!')), ); } }, child: const Text('Save Changes'), ), ), ], ), const SizedBox(height: 16.0), Row( children: [ Expanded( child: ElevatedButton( onPressed: () async { // Cancel offer action final offersProvider = Provider.of(context, listen: false); await offersProvider.cancelOffer(widget.offer.id); Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Offer canceled')), ); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.red.withOpacity(0.8), // Red color with opacity ), child: const Text('Cancel Offer'), ), ), ], ), ], ), ), ), ), ); } }