mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-18 12:11:35 +00:00
Implement backend handle range amounts, order take amount input and order book ranges
This commit is contained in:
parent
bf80986005
commit
8ae2406275
10
api/admin.py
10
api/admin.py
@ -46,7 +46,7 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
|
||||
"maker_link",
|
||||
"taker_link",
|
||||
"status",
|
||||
"amount",
|
||||
"amt",
|
||||
"currency_link",
|
||||
"t0_satoshis",
|
||||
"is_disputed",
|
||||
@ -69,7 +69,13 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
|
||||
"trade_escrow",
|
||||
)
|
||||
list_filter = ("is_disputed", "is_fiat_sent", "type", "currency", "status")
|
||||
search_fields = ["id","amount"]
|
||||
search_fields = ["id","amount","min_amount","max_amount"]
|
||||
|
||||
def amt(self, obj):
|
||||
if obj.has_range and obj.amount == None:
|
||||
return str(float(obj.min_amount))+"-"+ str(float(obj.max_amount))
|
||||
else:
|
||||
return float(obj.amount)
|
||||
|
||||
@admin.register(LNPayment)
|
||||
class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
|
||||
|
@ -118,16 +118,16 @@ class Logics:
|
||||
elif max_sats > MAX_TRADE:
|
||||
return False, {
|
||||
"bad_request":
|
||||
"Your order upper range value (max_amount) is too big. It is worth " +
|
||||
"{:,}".format(max_sats) +
|
||||
"Your order maximum amount is too big. It is worth " +
|
||||
"{:,}".format(int(max_sats)) +
|
||||
" Sats now, but the limit is " + "{:,}".format(MAX_TRADE) +
|
||||
" Sats"
|
||||
}
|
||||
elif min_sats < MIN_TRADE:
|
||||
return False, {
|
||||
"bad_request":
|
||||
"Your order lower range value (min_mount) is too small. It is worth " +
|
||||
"{:,}".format(min_sats) +
|
||||
"Your order minimum amount is too small. It is worth " +
|
||||
"{:,}".format(int(min_sats)) +
|
||||
" Sats now, but the limit is " + "{:,}".format(MAX_TRADE) +
|
||||
" Sats"
|
||||
}
|
||||
@ -139,6 +139,15 @@ class Logics:
|
||||
|
||||
return True, None
|
||||
|
||||
def validate_amount_within_range(order, amount):
|
||||
if amount > float(order.max_amount) or amount < float(order.min_amount):
|
||||
return False, {
|
||||
"bad_request":
|
||||
"The amount specified is outside the range specified by the maker"
|
||||
}
|
||||
|
||||
return True, None
|
||||
|
||||
def user_activity_status(last_seen):
|
||||
if last_seen > (timezone.now() - timedelta(minutes=2)):
|
||||
return "Active"
|
||||
@ -148,7 +157,7 @@ class Logics:
|
||||
return "Inactive"
|
||||
|
||||
@classmethod
|
||||
def take(cls, order, user):
|
||||
def take(cls, order, user, amount=None):
|
||||
is_penalized, time_out = cls.is_penalized(user)
|
||||
if is_penalized:
|
||||
return False, {
|
||||
@ -156,6 +165,8 @@ class Logics:
|
||||
f"You need to wait {time_out} seconds to take an order",
|
||||
}
|
||||
else:
|
||||
if order.has_range:
|
||||
order.amount= amount
|
||||
order.taker = user
|
||||
order.status = Order.Status.TAK
|
||||
order.expires_at = timezone.now() + timedelta(
|
||||
@ -702,6 +713,8 @@ class Logics:
|
||||
order.status = Order.Status.PUB
|
||||
order.expires_at = order.created_at + timedelta(
|
||||
seconds=order.t_to_expire(Order.Status.PUB))
|
||||
if order.has_range:
|
||||
order.amount = None
|
||||
order.save()
|
||||
# send_message.delay(order.id,'order_published') # too spammy
|
||||
return
|
||||
|
@ -339,7 +339,11 @@ class Order(models.Model):
|
||||
taker_platform_rated = models.BooleanField(default=False, null=False)
|
||||
|
||||
def __str__(self):
|
||||
return f"Order {self.id}: {self.Types(self.type).label} BTC for {float(self.amount)} {self.currency}"
|
||||
if self.has_range and self.amount == None:
|
||||
amt = str(float(self.min_amount))+"-"+ str(float(self.max_amount))
|
||||
else:
|
||||
amt = float(self.amount)
|
||||
return f"Order {self.id}: {self.Types(self.type).label} BTC for {amt} {self.currency}"
|
||||
|
||||
def t_to_expire(self, status):
|
||||
|
||||
|
@ -21,7 +21,7 @@ class ListOrderSerializer(serializers.ModelSerializer):
|
||||
"is_explicit",
|
||||
"premium",
|
||||
"satoshis",
|
||||
"bondless_taker"
|
||||
"bondless_taker",
|
||||
"maker",
|
||||
"taker",
|
||||
)
|
||||
@ -75,6 +75,7 @@ class UpdateOrderSerializer(serializers.Serializer):
|
||||
allow_blank=True,
|
||||
default=None,
|
||||
)
|
||||
amount = serializers.DecimalField(max_digits=18, decimal_places=8, allow_null=True, required=False, default=None)
|
||||
|
||||
class ClaimRewardSerializer(serializers.Serializer):
|
||||
invoice = serializers.CharField(max_length=2000,
|
||||
|
16
api/views.py
16
api/views.py
@ -390,6 +390,10 @@ class OrderView(viewsets.ViewSet):
|
||||
"""
|
||||
order_id = request.GET.get(self.lookup_url_kwarg)
|
||||
|
||||
import sys
|
||||
sys.stdout.write('AAAAAA')
|
||||
print('BBBBB1')
|
||||
|
||||
serializer = UpdateOrderSerializer(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST)
|
||||
@ -410,7 +414,17 @@ class OrderView(viewsets.ViewSet):
|
||||
request.user)
|
||||
if not valid:
|
||||
return Response(context, status=status.HTTP_409_CONFLICT)
|
||||
valid, context = Logics.take(order, request.user)
|
||||
|
||||
# For order with amount range, set the amount now.
|
||||
if order.has_range:
|
||||
amount = float(serializer.data.get("amount"))
|
||||
valid, context = Logics.validate_amount_within_range(order, amount)
|
||||
if not valid:
|
||||
return Response(context, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
valid, context = Logics.take(order, request.user, amount)
|
||||
else:
|
||||
valid, context = Logics.take(order, request.user)
|
||||
if not valid:
|
||||
return Response(context, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
|
@ -78,6 +78,15 @@ export default class BookPage extends Component {
|
||||
if(status=='Seen recently'){return("warning")}
|
||||
if(status=='Inactive'){return('error')}
|
||||
}
|
||||
amountToString = (amount,has_range,min_amount,max_amount) => {
|
||||
if (has_range){
|
||||
console.log(this.pn(parseFloat(Number(min_amount).toPrecision(2))))
|
||||
console.log(this.pn(parseFloat(Number(min_amount).toPrecision(2)))+'-'+this.pn(parseFloat(Number(max_amount).toPrecision(2))))
|
||||
return this.pn(parseFloat(Number(min_amount).toPrecision(2)))+'-'+this.pn(parseFloat(Number(max_amount).toPrecision(2)))
|
||||
}else{
|
||||
return this.pn(parseFloat(Number(amount).toPrecision(3)))
|
||||
}
|
||||
}
|
||||
|
||||
bookListTableDesktop=()=>{
|
||||
return (
|
||||
@ -90,7 +99,10 @@ export default class BookPage extends Component {
|
||||
robot: order.maker_nick,
|
||||
robot_status: order.maker_status,
|
||||
type: order.type ? "Seller": "Buyer",
|
||||
amount: parseFloat(parseFloat(order.amount).toFixed(5)),
|
||||
amount: order.amount,
|
||||
has_range: order.has_range,
|
||||
min_amount: order.min_amount,
|
||||
max_amount: order.max_amount,
|
||||
currency: this.getCurrencyCode(order.currency),
|
||||
payment_method: order.payment_method,
|
||||
price: order.price,
|
||||
@ -123,9 +135,9 @@ export default class BookPage extends Component {
|
||||
);
|
||||
} },
|
||||
{ field: 'type', headerName: 'Is', width: 60 },
|
||||
{ field: 'amount', headerName: 'Amount', type: 'number', width: 80,
|
||||
{ field: 'amount', headerName: 'Amount', type: 'number', width: 90,
|
||||
renderCell: (params) => {return (
|
||||
<div style={{ cursor: "pointer" }}>{this.pn(params.row.amount)}</div>
|
||||
<div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div>
|
||||
)}},
|
||||
{ field: 'currency', headerName: 'Currency', width: 100,
|
||||
renderCell: (params) => {return (
|
||||
@ -163,7 +175,10 @@ export default class BookPage extends Component {
|
||||
robot: order.maker_nick,
|
||||
robot_status: order.maker_status,
|
||||
type: order.type ? "Seller": "Buyer",
|
||||
amount: parseFloat(parseFloat(order.amount).toFixed(4)),
|
||||
amount: order.amount,
|
||||
has_range: order.has_range,
|
||||
min_amount: order.min_amount,
|
||||
max_amount: order.max_amount,
|
||||
currency: this.getCurrencyCode(order.currency),
|
||||
payment_method: order.payment_method,
|
||||
price: order.price,
|
||||
@ -191,10 +206,10 @@ export default class BookPage extends Component {
|
||||
);
|
||||
} },
|
||||
{ field: 'type', headerName: 'Is', width: 60, hide:'true'},
|
||||
{ field: 'amount', headerName: 'Amount', type: 'number', width: 80,
|
||||
{ field: 'amount', headerName: 'Amount', type: 'number', width: 90,
|
||||
renderCell: (params) => {return (
|
||||
<Tooltip placement="right" enterTouchDelay="0" title={params.row.type}>
|
||||
<div style={{ cursor: "pointer" }}>{this.pn(params.row.amount)}</div>
|
||||
<div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div>
|
||||
</Tooltip>
|
||||
)} },
|
||||
{ field: 'currency', headerName: 'Currency', width: 100,
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React, { Component } from 'react';
|
||||
import { LinearProgress, Checkbox, Slider, Switch, Tooltip, Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material"
|
||||
import { LinearProgress, Checkbox, Slider, SliderThumb, Switch, Tooltip, Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material"
|
||||
import { LocalizationProvider, TimePicker} from '@mui/lab';
|
||||
import DateFnsUtils from "@date-io/date-fns";
|
||||
import { Link } from 'react-router-dom'
|
||||
import { styled } from '@mui/material/styles';
|
||||
import getFlags from './getFlags'
|
||||
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import SelfImprovementIcon from '@mui/icons-material/SelfImprovement';
|
||||
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
@ -43,8 +43,8 @@ export default class MakerPage extends Component {
|
||||
minTradeSats = 20000;
|
||||
maxTradeSats = 800000;
|
||||
maxBondlessSats = 50000;
|
||||
maxRangeAmountMultiple = 5;
|
||||
minRangeAmountMultiple = 1.5;
|
||||
maxRangeAmountMultiple = 4.9;
|
||||
minRangeAmountMultiple = 1.6;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -79,9 +79,8 @@ export default class MakerPage extends Component {
|
||||
limits:data,
|
||||
loadingLimits:false,
|
||||
minAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.25).toPrecision(2)),
|
||||
maxAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.75).toPrecision(2))
|
||||
})
|
||||
& console.log(this.state.limits));
|
||||
maxAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.75).toPrecision(2)),
|
||||
}));
|
||||
}
|
||||
|
||||
handleTypeChange=(e)=>{
|
||||
@ -94,6 +93,12 @@ export default class MakerPage extends Component {
|
||||
currency: e.target.value,
|
||||
currencyCode: this.getCurrencyCode(e.target.value),
|
||||
});
|
||||
if(this.state.enableAmountRange){
|
||||
this.setState({
|
||||
minAmount: parseFloat(Number(this.state.limits[e.target.value]['max_amount']*0.25).toPrecision(2)),
|
||||
maxAmount: parseFloat(Number(this.state.limits[e.target.value]['max_amount']*0.75).toPrecision(2)),
|
||||
})
|
||||
}
|
||||
}
|
||||
handleAmountChange=(e)=>{
|
||||
this.setState({
|
||||
@ -101,7 +106,7 @@ export default class MakerPage extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
handleRangeAmountChange = (e, activeThumb) => {
|
||||
handleRangeAmountChange = (e, newValue, activeThumb) => {
|
||||
var maxAmount = this.getMaxAmount();
|
||||
var minAmount = this.getMinAmount();
|
||||
var lowerValue = e.target.value[0];
|
||||
@ -379,7 +384,6 @@ export default class MakerPage extends Component {
|
||||
}
|
||||
|
||||
handleChangePublicDuration = (date) => {
|
||||
console.log(date)
|
||||
let d = new Date(date),
|
||||
hours = d.getHours(),
|
||||
minutes = d.getMinutes();
|
||||
@ -401,7 +405,8 @@ export default class MakerPage extends Component {
|
||||
}else{
|
||||
var max_amount = this.state.limits[this.state.currency]['max_amount']
|
||||
}
|
||||
return parseFloat(Number(max_amount).toPrecision(2))
|
||||
// times 0.98 to allow a bit of margin with respect to the backend minimum
|
||||
return parseFloat(Number(max_amount*0.98).toPrecision(2))
|
||||
}
|
||||
|
||||
getMinAmount = () => {
|
||||
@ -410,10 +415,52 @@ export default class MakerPage extends Component {
|
||||
}else{
|
||||
var min_amount = this.state.limits[this.state.currency]['min_amount']
|
||||
}
|
||||
return parseFloat(Number(min_amount).toPrecision(2))
|
||||
// times 1.1 to allow a bit of margin with respect to the backend minimum
|
||||
return parseFloat(Number(min_amount*1.1).toPrecision(2))
|
||||
}
|
||||
|
||||
RangeSlider = styled(Slider)(({ theme }) => ({
|
||||
color: 'primary',
|
||||
height: 3,
|
||||
padding: '13px 0',
|
||||
'& .MuiSlider-thumb': {
|
||||
height: 27,
|
||||
width: 27,
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid currentColor',
|
||||
'&:hover': {
|
||||
boxShadow: '0 0 0 8px rgba(58, 133, 137, 0.16)',
|
||||
},
|
||||
'& .range-bar': {
|
||||
height: 9,
|
||||
width: 1,
|
||||
backgroundColor: 'currentColor',
|
||||
marginLeft: 1,
|
||||
marginRight: 1,
|
||||
},
|
||||
},
|
||||
'& .MuiSlider-track': {
|
||||
height: 3,
|
||||
},
|
||||
'& .MuiSlider-rail': {
|
||||
color: theme.palette.mode === 'dark' ? '#bfbfbf' : '#d8d8d8',
|
||||
opacity: theme.palette.mode === 'dark' ? undefined : 1,
|
||||
height: 3,
|
||||
},
|
||||
}));
|
||||
|
||||
RangeThumbComponent(props) {
|
||||
const { children, ...other } = props;
|
||||
return (
|
||||
<SliderThumb {...other}>
|
||||
{children}
|
||||
<span className="range-bar" />
|
||||
<span className="range-bar" />
|
||||
<span className="range-bar" />
|
||||
</SliderThumb>
|
||||
);
|
||||
}
|
||||
|
||||
AdvancedMakerOptions = () => {
|
||||
return(
|
||||
<Paper elevation={12} style={{ padding: 8, width:250, align:'center'}}>
|
||||
@ -421,6 +468,61 @@ export default class MakerPage extends Component {
|
||||
<Grid container xs={12} spacing={1}>
|
||||
|
||||
<Grid item xs={12} align="center" spacing={1}>
|
||||
<FormControl align="center">
|
||||
<FormHelperText>
|
||||
<Tooltip enterTouchDelay="0" placement="top" align="center"title={"Let the taker chose an amount within the range"}>
|
||||
<div align="center" style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
|
||||
<Checkbox onChange={(e)=>this.setState({enableAmountRange:e.target.checked}) & (e.target.checked ? this.getLimits() : null)}/>
|
||||
{this.state.enableAmountRange & this.state.minAmount != null?
|
||||
"From "+this.state.minAmount+" to "+this.state.maxAmount +" "+this.state.currencyCode: "Enable Amount Range"}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</FormHelperText>
|
||||
<div style={{ display: this.state.loadingLimits == true ? '':'none'}}>
|
||||
<LinearProgress />
|
||||
</div>
|
||||
<div style={{ display: this.state.loadingLimits == false ? '':'none'}}>
|
||||
<this.RangeSlider
|
||||
disableSwap={true}
|
||||
sx={{width:200, align:"center"}}
|
||||
disabled={!this.state.enableAmountRange || this.state.loadingLimits}
|
||||
value={[this.state.minAmount, this.state.maxAmount]}
|
||||
step={(this.getMaxAmount()-this.getMinAmount())/100}
|
||||
valueLabelDisplay="auto"
|
||||
components={{ Thumb: this.RangeThumbComponent }}
|
||||
valueLabelFormat={(x) => (parseFloat(Number(x).toPrecision(2))+" "+this.state.currencyCode)}
|
||||
marks={this.state.limits == null?
|
||||
null
|
||||
:
|
||||
[{value: this.getMinAmount(),label: this.getMinAmount()+" "+ this.state.currencyCode},
|
||||
{value: this.getMaxAmount(),label: this.getMaxAmount()+" "+this.state.currencyCode}]}
|
||||
min={this.getMinAmount()}
|
||||
max={this.getMaxAmount()}
|
||||
onChange={this.handleRangeAmountChange}
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} align="center" spacing={1}>
|
||||
<LocalizationProvider dateAdapter={DateFnsUtils}>
|
||||
<TimePicker
|
||||
ampm={false}
|
||||
openTo="hours"
|
||||
views={['hours', 'minutes']}
|
||||
inputFormat="HH:mm"
|
||||
mask="__:__"
|
||||
renderInput={(props) => <TextField {...props} />}
|
||||
label="Public Duration (HH:mm)"
|
||||
value={this.state.publicExpiryTime}
|
||||
onChange={this.handleChangePublicDuration}
|
||||
minTime={new Date(0, 0, 0, 0, 10)}
|
||||
maxTime={new Date(0, 0, 0, 23, 59)}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} align="center" spacing={1}>
|
||||
<FormControl align="center">
|
||||
<Tooltip enterDelay="800" enterTouchDelay="0" placement="top" title={"Set the skin-in-the-game, increase for higher safety assurance"}>
|
||||
<FormHelperText>
|
||||
@ -445,59 +547,6 @@ export default class MakerPage extends Component {
|
||||
</FormControl>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} align="center" spacing={1}>
|
||||
<LocalizationProvider dateAdapter={DateFnsUtils}>
|
||||
<TimePicker
|
||||
ampm={false}
|
||||
openTo="hours"
|
||||
views={['hours', 'minutes']}
|
||||
inputFormat="HH:mm"
|
||||
mask="__:__"
|
||||
renderInput={(props) => <TextField {...props} />}
|
||||
label="Public Duration (HH:mm)"
|
||||
value={this.state.publicExpiryTime}
|
||||
onChange={this.handleChangePublicDuration}
|
||||
minTime={new Date(0, 0, 0, 0, 10)}
|
||||
maxTime={new Date(0, 0, 0, 23, 59)}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} align="center" spacing={1}>
|
||||
<FormControl align="center">
|
||||
<FormHelperText>
|
||||
<Tooltip enterTouchDelay="0" placement="top" align="center"title={"Let the taker chose an amount within the range"}>
|
||||
<div align="center" style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
|
||||
<Checkbox onChange={(e)=>this.setState({enableAmountRange:e.target.checked}) & (e.target.checked ? this.getLimits() : null)}/>
|
||||
Amount Range
|
||||
</div>
|
||||
</Tooltip>
|
||||
</FormHelperText>
|
||||
<div style={{ display: this.state.loadingLimits == true ? '':'none'}}>
|
||||
<LinearProgress />
|
||||
</div>
|
||||
<div style={{ display: this.state.loadingLimits == false ? '':'none'}}>
|
||||
<Slider
|
||||
disableSwap={true}
|
||||
sx={{width:190, align:"center"}}
|
||||
disabled={!this.state.enableAmountRange || this.state.loadingLimits}
|
||||
value={[this.state.minAmount, this.state.maxAmount]}
|
||||
step={(this.getMaxAmount()-this.getMinAmount())/100}
|
||||
valueLabelDisplay="auto"
|
||||
valueLabelFormat={(x) => (parseFloat(Number(x).toPrecision(2))+" "+this.state.currencyCode)}
|
||||
marks={this.state.limits == null?
|
||||
null
|
||||
:
|
||||
[{value: this.getMinAmount(),label: this.getMinAmount()+" "+ this.state.currencyCode},
|
||||
{value: this.getMaxAmount(),label: this.getMaxAmount()+" "+this.state.currencyCode}]}
|
||||
min={this.getMinAmount()}
|
||||
max={this.getMaxAmount()}
|
||||
onChange={this.handleRangeAmountChange}
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} align="center" spacing={1}>
|
||||
<Tooltip enterTouchDelay="0" title={"COMING SOON - High risk! Limited to "+ this.maxBondlessSats/1000 +"K Sats"}>
|
||||
<FormControlLabel
|
||||
@ -554,8 +603,8 @@ export default class MakerPage extends Component {
|
||||
|
||||
<Grid item xs={12} align="center">
|
||||
{/* conditions to disable the make button */}
|
||||
{(this.state.amount == null ||
|
||||
this.state.amount <= 0 ||
|
||||
{(this.state.amount == null & (this.state.enableAmountRange == false & this.state.minAmount != null) ||
|
||||
this.state.amount <= 0 & !this.state.enableAmountRange ||
|
||||
(this.state.is_explicit & (this.state.badSatoshis != null || this.state.satoshis == null)) ||
|
||||
(!this.state.is_explicit & this.state.badPremium != null))
|
||||
?
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Component } from "react";
|
||||
import { Chip, Tooltip, Badge, Tab, Tabs, Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
|
||||
import {TextField,Chip, Tooltip, Badge, Tab, Tabs, Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
|
||||
import Countdown, { zeroPad, calcTimeDelta } from 'react-countdown';
|
||||
import MediaQuery from 'react-responsive'
|
||||
|
||||
@ -89,6 +89,7 @@ export default class OrderPage extends Component {
|
||||
}
|
||||
|
||||
var otherStateVars = {
|
||||
amount: newStateVars.amount ? newStateVars.amount : null,
|
||||
loading: false,
|
||||
delay: this.setDelay(newStateVars.status),
|
||||
currencyCode: this.getCurrencyCode(newStateVars.currency),
|
||||
@ -157,32 +158,81 @@ export default class OrderPage extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
countdownTakeOrderRenderer = ({ seconds, completed }) => {
|
||||
if(isNaN(seconds)){
|
||||
return (
|
||||
<>
|
||||
handleTakeAmountChange = (e) => {
|
||||
if (e.target.value != "" & e.target.value != null){
|
||||
this.setState({takeAmount: parseFloat(e.target.value)})
|
||||
}else{
|
||||
this.setState({takeAmount: e.target.value})
|
||||
}
|
||||
}
|
||||
|
||||
amountHelperText=()=>{
|
||||
if(this.state.takeAmount < this.state.min_amount & this.state.takeAmount != ""){
|
||||
return "Too low"
|
||||
}else if (this.state.takeAmount > this.state.max_amount & this.state.takeAmount != ""){
|
||||
return "Too high"
|
||||
}else{
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
takeOrderButton = () => {
|
||||
if(this.state.has_range){
|
||||
return(
|
||||
<Grid containter xs={12} align="center" alignItems="stretch" justifyContent="center" style={{ display: "flex"}}>
|
||||
<this.InactiveMakerDialog/>
|
||||
<div style={{maxWidth:120}}>
|
||||
<Tooltip placement="top" enterTouchDelay="500" enterDelay="700" enterNextDelay="2000" title="Amount of fiat to exchange for bitcoin">
|
||||
<Paper sx={{maxHeight:40}}>
|
||||
<TextField
|
||||
error={(this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount) & this.state.takeAmount != "" }
|
||||
helperText={this.amountHelperText()}
|
||||
label={"Amount "+this.state.currencyCode}
|
||||
size="small"
|
||||
type="number"
|
||||
required="true"
|
||||
value={this.state.takeAmount}
|
||||
inputProps={{
|
||||
min:this.state.min_amount ,
|
||||
max:this.state.max_amount ,
|
||||
style: {textAlign:"center"}
|
||||
}}
|
||||
onChange={this.handleTakeAmountChange}
|
||||
/>
|
||||
</Paper>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div style={{height:38, top:'1px', position:'relative'}}>
|
||||
<Button sx={{height:38}} variant='contained' color='primary'
|
||||
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}
|
||||
disabled={this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount || this.state.takeAmount == "" || this.state.takeAmount == null } >
|
||||
Take Order
|
||||
</Button>
|
||||
</div>
|
||||
</Grid>
|
||||
)
|
||||
}else{
|
||||
return(
|
||||
<>
|
||||
<this.InactiveMakerDialog/>
|
||||
<Button variant='contained' color='primary'
|
||||
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
|
||||
Take Order
|
||||
</Button>
|
||||
</>)
|
||||
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
|
||||
Take Order
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
countdownTakeOrderRenderer = ({ seconds, completed }) => {
|
||||
if(isNaN(seconds)){return (<this.takeOrderButton/>)}
|
||||
if (completed) {
|
||||
// Render a completed state
|
||||
return (
|
||||
<>
|
||||
<this.InactiveMakerDialog/>
|
||||
<Button variant='contained' color='primary'
|
||||
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
|
||||
Take Order
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
return ( <this.takeOrderButton/>);
|
||||
} else{
|
||||
return(
|
||||
<Tooltip enterTouchDelay="0" title="Wait until you can take an order"><div>
|
||||
<Button disabled={true} variant='contained' color='primary' onClick={this.takeOrder}>Take Order</Button>
|
||||
<Button disabled={true} variant='contained' color='primary'>Take Order</Button>
|
||||
</div></Tooltip>)
|
||||
}
|
||||
};
|
||||
@ -212,12 +262,13 @@ export default class OrderPage extends Component {
|
||||
|
||||
takeOrder=()=>{
|
||||
this.setState({loading:true})
|
||||
|
||||
console.log(this.state.takeAmount)
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
|
||||
body: JSON.stringify({
|
||||
'action':'take',
|
||||
'amount':this.state.takeAmount,
|
||||
}),
|
||||
};
|
||||
fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions)
|
||||
@ -483,10 +534,17 @@ export default class OrderPage extends Component {
|
||||
<ListItemIcon>
|
||||
{getFlags(this.state.currencyCode)}
|
||||
</ListItemIcon>
|
||||
{this.state.has_range & this.state.amount == null ?
|
||||
<ListItemText primary={parseFloat(Number(this.state.min_amount).toPrecision(2))
|
||||
+"-" + parseFloat(Number(this.state.max_amount).toPrecision(2)) +" "+this.state.currencyCode} secondary="Amount range"/>
|
||||
:
|
||||
<ListItemText primary={parseFloat(parseFloat(this.state.amount).toFixed(4))
|
||||
+" "+this.state.currencyCode} secondary="Amount"/>
|
||||
}
|
||||
|
||||
</ListItem>
|
||||
<Divider />
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PaymentsIcon/>
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user