robosats/frontend/src/components/TradeBox.js

638 lines
23 KiB
JavaScript
Raw Normal View History

import React, { Component } from "react";
import { Link, Paper, Rating, Button, Grid, Typography, TextField, List, ListItem, ListItemText, Divider, ListItemIcon, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
2022-01-09 01:23:13 +00:00
import QRCode from "react-qr-code";
import Chat from "./Chat"
2022-01-14 13:31:54 +00:00
// Icons
import SmartToyIcon from '@mui/icons-material/SmartToy';
import PercentIcon from '@mui/icons-material/Percent';
import BookIcon from '@mui/icons-material/Book';
2022-01-09 14:07:05 +00:00
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
2022-01-09 01:23:13 +00:00
}
2022-01-09 14:07:05 +00:00
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
2022-01-09 01:23:13 +00:00
2022-01-09 14:07:05 +00:00
// pretty numbers
function pn(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
2022-01-09 01:23:13 +00:00
2022-01-09 14:07:05 +00:00
export default class TradeBox extends Component {
constructor(props) {
super(props);
this.state = {
openConfirmFiatReceived: false,
openConfirmDispute: false,
badInvoice: false,
badStatement: false,
}
2022-01-09 01:23:13 +00:00
}
handleClickOpenConfirmDispute = () => {
this.setState({openConfirmDispute: true});
};
handleClickCloseConfirmDispute = () => {
this.setState({openConfirmDispute: false});
};
handleClickAgreeDisputeButton=()=>{
const requestOptions = {
method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({
'action': "dispute",
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => (this.props.data = data));
this.handleClickCloseConfirmDispute();
}
ConfirmDisputeDialog =() =>{
return(
<Dialog
open={this.state.openConfirmDispute}
onClose={this.handleClickCloseConfirmDispute}
aria-labelledby="open-dispute-dialog-title"
aria-describedby="open-dispute-dialog-description"
>
<DialogTitle id="open-dispute-dialog-title">
{"Do you want to open a dispute?"}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
The RoboSats staff will examine the statements and evidence provided by the participants.
It is best if you provide a burner contact method on your statement for the staff to contact you.
The satoshis in the trade escrow will be sent to the dispute winner, while the dispute
loser will lose the bond.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClickCloseConfirmDispute} autoFocus>Disagree</Button>
<Button onClick={this.handleClickAgreeDisputeButton}> Agree </Button>
</DialogActions>
</Dialog>
)
}
handleClickOpenConfirmFiatReceived = () => {
this.setState({openConfirmFiatReceived: true});
};
handleClickCloseConfirmFiatReceived = () => {
this.setState({openConfirmFiatReceived: false});
};
handleClickTotallyConfirmFiatReceived = () =>{
this.handleClickConfirmButton();
this.handleClickCloseConfirmFiatReceived();
};
ConfirmFiatReceivedDialog =() =>{
return(
<Dialog
open={this.state.openConfirmFiatReceived}
onClose={this.handleClickCloseConfirmFiatReceived}
aria-labelledby="fiat-received-dialog-title"
aria-describedby="fiat-received-dialog-description"
>
<DialogTitle id="open-dispute-dialog-title">
{"Confirm you received " +this.props.data.currencyCode+ "?"}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Confirming that you received the fiat will finalize the trade. The satoshis
in the escrow will be released to the buyer. Only confirm after the {this.props.data.currencyCode+ " "}
has arrived to your account. In addition, if you have received {this.props.data.currencyCode+ " "}
and do not confirm the receipt, you risk losing your bond.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClickCloseConfirmFiatReceived} autoFocus>Go back</Button>
<Button onClick={this.handleClickTotallyConfirmFiatReceived}> Confirm </Button>
</DialogActions>
</Dialog>
)
}
2022-01-09 12:14:11 +00:00
showQRInvoice=()=>{
return (
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="body2" variant="body2">
2022-01-10 18:47:16 +00:00
Robosats show commitment to their peers
</Typography>
</Grid>
<Grid item xs={12} align="center">
2022-01-09 14:07:05 +00:00
{this.props.data.isMaker ?
2022-01-10 18:47:16 +00:00
<Typography color="primary" component="subtitle1" variant="subtitle1">
2022-01-09 14:07:05 +00:00
<b>Lock {pn(this.props.data.bondSatoshis)} Sats to PUBLISH order </b>
</Typography>
:
2022-01-10 18:47:16 +00:00
<Typography color="primary" component="subtitle1" variant="subtitle1">
2022-01-09 14:07:05 +00:00
<b>Lock {pn(this.props.data.bondSatoshis)} Sats to TAKE the order </b>
</Typography>
}
</Grid>
<Grid item xs={12} align="center">
2022-01-09 14:07:05 +00:00
<QRCode value={this.props.data.bondInvoice} size={305}/>
<Button size="small" color="inherit" onClick={() => {navigator.clipboard.writeText(this.props.data.bondInvoice)}} align="center"> 📋Copy to clipboard</Button>
</Grid>
<Grid item xs={12} align="center">
<TextField
hiddenLabel
2022-01-14 14:19:25 +00:00
variant="standard"
size="small"
2022-01-09 14:07:05 +00:00
defaultValue={this.props.data.bondInvoice}
disabled="true"
2022-01-14 14:19:25 +00:00
helperText="This is a hold invoice. It will be charged only if you cancel or lose a dispute."
color = "secondary"
/>
</Grid>
</Grid>
);
}
2022-01-09 20:05:19 +00:00
showBondIsLocked=()=>{
return (
<Grid item xs={12} align="center">
2022-01-14 14:19:25 +00:00
<Typography color="primary" component="subtitle1" variant="subtitle1" align="center">
🔒 Your {this.props.data.isMaker ? 'maker' : 'taker'} bond is locked
</Typography>
</Grid>
);
}
2022-01-09 12:14:11 +00:00
showEscrowQRInvoice=()=>{
2022-01-08 17:19:30 +00:00
return (
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography color="green" component="subtitle1" variant="subtitle1">
2022-01-09 14:07:05 +00:00
<b>Deposit {pn(this.props.data.escrowSatoshis)} Sats as trade collateral </b>
2022-01-08 17:19:30 +00:00
</Typography>
</Grid>
<Grid item xs={12} align="center">
2022-01-09 14:07:05 +00:00
<QRCode value={this.props.data.escrowInvoice} size={305}/>
<Button size="small" color="inherit" onClick={() => {navigator.clipboard.writeText(this.props.data.escrowInvoice)}} align="center"> 📋Copy to clipboard</Button>
2022-01-08 17:19:30 +00:00
</Grid>
<Grid item xs={12} align="center">
<TextField
hiddenLabel
variant="filled"
size="small"
2022-01-09 14:07:05 +00:00
defaultValue={this.props.data.escrowInvoice}
2022-01-08 17:19:30 +00:00
disabled="true"
2022-01-14 14:19:25 +00:00
helperText="This is a hold invoice. It will be charged once the buyer confirms he sent the fiat."
2022-01-08 17:19:30 +00:00
color = "secondary"
/>
</Grid>
{this.showBondIsLocked()}
2022-01-08 17:19:30 +00:00
</Grid>
);
}
2022-01-09 01:23:13 +00:00
showTakerFound=()=>{
2022-01-09 14:07:05 +00:00
// TODO Make some sound here! The maker might have been waiting for long
2022-01-09 01:23:13 +00:00
return (
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1">
<b>A taker has been found! </b>
</Typography>
</Grid>
<Divider/>
<Grid item xs={12} align="center">
2022-01-09 15:28:12 +00:00
<Typography component="body2" variant="body2">
2022-01-09 01:23:13 +00:00
Please wait for the taker to confirm his commitment by locking a bond.
</Typography>
</Grid>
{this.showBondIsLocked()}
2022-01-09 01:23:13 +00:00
</Grid>
);
}
2022-01-08 15:34:09 +00:00
showMakerWait=()=>{
return (
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1">
2022-01-10 18:47:16 +00:00
<b> Your order is public. Wait for a taker. </b>
2022-01-08 15:34:09 +00:00
</Typography>
</Grid>
<Grid item xs={12} align="center">
<List dense="true">
<Divider/>
<ListItem>
<Typography component="body2" variant="body2" align="left">
<p>Be patient while robots check the book.
It might take some time. This box will ring 🔊 once a robot takes your order. </p>
<p>Please note that if your premium is too high, or if your currency or payment
methods are not popular, your order might expire untaken. Your bond will
return to you (no action needed).</p>
</Typography>
</ListItem>
{/* TODO API sends data for a more confortable wait */}
<Divider/>
<ListItem>
2022-01-14 13:31:54 +00:00
<ListItemIcon>
<SmartToyIcon/>
</ListItemIcon>
2022-01-18 18:24:45 +00:00
<ListItemText primary={'000 coming soon'} secondary="Robots looking at the book"/>
2022-01-08 15:34:09 +00:00
</ListItem>
<Divider/>
<ListItem>
2022-01-14 13:31:54 +00:00
<ListItemIcon>
<BookIcon/>
</ListItemIcon>
2022-01-14 12:00:53 +00:00
<ListItemText primary={this.props.data.numSimilarOrders} secondary={"Public orders for " + this.props.data.currencyCode}/>
2022-01-08 15:34:09 +00:00
</ListItem>
<Divider/>
<ListItem>
2022-01-14 13:31:54 +00:00
<ListItemIcon>
<PercentIcon/>
</ListItemIcon>
2022-01-18 18:24:45 +00:00
<ListItemText primary={"Premium rank " + this.props.data.premiumPercentile*100+"%"}
secondary={"Among public " + this.props.data.currencyCode + " orders (higher is cheaper)"} />
2022-01-08 15:34:09 +00:00
</ListItem>
<Divider/>
2022-01-08 15:34:09 +00:00
</List>
</Grid>
{this.showBondIsLocked()}
2022-01-08 15:34:09 +00:00
</Grid>
)
}
2022-01-09 14:07:05 +00:00
handleInputInvoiceChanged=(e)=>{
this.setState({
invoice: e.target.value,
badInvoice: false,
2022-01-09 14:07:05 +00:00
});
}
2022-01-09 12:14:11 +00:00
2022-01-09 14:07:05 +00:00
handleClickSubmitInvoiceButton=()=>{
this.setState({badInvoice:false});
2022-01-09 14:07:05 +00:00
const requestOptions = {
method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({
'action':'update_invoice',
'invoice': this.state.invoice,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.setState({badInvoice:data.bad_invoice})
& console.log(data));
2022-01-09 14:07:05 +00:00
}
2022-01-09 12:14:11 +00:00
handleInputDisputeChanged=(e)=>{
this.setState({
statement: e.target.value,
badStatement: false,
});
}
handleClickSubmitStatementButton=()=>{
this.setState({badInvoice:false});
const requestOptions = {
method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({
'action':'submit_statement',
'statement': this.state.statement,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.setState({badStatement:data.bad_statement})
& console.log(data));
}
2022-01-09 14:07:05 +00:00
showInputInvoice(){
return (
2022-01-09 12:14:11 +00:00
// TODO Option to upload files and images
2022-01-09 14:07:05 +00:00
<Grid container spacing={1}>
<Grid item xs={12} align="center">
2022-01-10 18:47:16 +00:00
<Typography color="primary" component="subtitle1" variant="subtitle1">
2022-01-09 14:07:05 +00:00
<b> Submit a LN invoice for {pn(this.props.data.invoiceAmount)} Sats </b>
</Typography>
</Grid>
<Grid item xs={12} align="left">
<Typography component="body2" variant="body2">
The taker is committed! Before letting you send {" "+ parseFloat(parseFloat(this.props.data.amount).toFixed(4))+
" "+ this.props.data.currencyCode}, we want to make sure you are able to receive the BTC. Please provide a
valid invoice for {pn(this.props.data.invoiceAmount)} Satoshis.
</Typography>
</Grid>
<Grid item xs={12} align="center">
<TextField
error={this.state.badInvoice}
helperText={this.state.badInvoice ? this.state.badInvoice : "" }
label={"Payout Lightning Invoice"}
required
inputProps={{
style: {textAlign:"center"}
}}
multiline
onChange={this.handleInputInvoiceChanged}
/>
</Grid>
<Grid item xs={12} align="center">
<Button onClick={this.handleClickSubmitInvoiceButton} variant='contained' color='primary'>Submit</Button>
</Grid>
{this.showBondIsLocked()}
</Grid>
)
}
// Asks the user for a dispute statement.
showInDisputeStatement(){
return (
// TODO Option to upload files
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1">
<b> A dispute has been opened </b>
</Typography>
</Grid>
<Grid item xs={12} align="left">
<Typography component="body2" variant="body2">
Please, submit your statement. Be clear and specific about what happened and provide the necessary
evidence. It is best to provide a burner email, XMPP or telegram username to follow up with the staff.
Disputes are solved at the discretion of real robots <i>(aka humans)</i>, so be as helpful
as possible to ensure a fair outcome. Max 5000 chars.
</Typography>
</Grid>
<Grid item xs={12} align="center">
<TextField
error={this.state.badStatement}
helperText={this.state.badStatement ? this.state.badStatement : "" }
label={"Submit dispute statement"}
required
inputProps={{
style: {textAlign:"center"}
}}
multiline
rows={4}
onChange={this.handleInputDisputeChanged}
/>
</Grid>
<Grid item xs={12} align="center">
<Button onClick={this.handleClickSubmitStatementButton} variant='contained' color='primary'>Submit</Button>
</Grid>
{this.showBondIsLocked()}
2022-01-09 14:07:05 +00:00
</Grid>
)
}
showWaitingForEscrow(){
2022-01-09 15:28:12 +00:00
return(
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1">
2022-01-19 13:32:54 +00:00
<b>Your invoice looks good!🎉</b>
2022-01-09 15:28:12 +00:00
</Typography>
</Grid>
<Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="left">
<p>We are waiting for the seller to deposit the full trade BTC amount
into the escrow.</p>
<p> Just hang on for a moment. If the seller does not deposit,
you will get your bond back automatically.</p>
</Typography>
</Grid>
{this.showBondIsLocked()}
2022-01-09 15:28:12 +00:00
</Grid>
)
}
showWaitingForBuyerInvoice(){
return(
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1">
2022-01-19 13:32:54 +00:00
<b>The trade collateral is locked! 🎉 </b>
2022-01-09 15:28:12 +00:00
</Typography>
</Grid>
<Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="left">
<p> We are waiting for the buyer to post a lightning invoice. Once
he does, you will be able to directly communicate the fiat payment
details. </p>
<p> Just hang on for a moment. If the buyer does not cooperate,
you will get back the trade collateral and your bond automatically.</p>
</Typography>
</Grid>
{this.showBondIsLocked()}
2022-01-09 15:28:12 +00:00
</Grid>
)
2022-01-09 14:07:05 +00:00
}
2022-01-09 12:14:11 +00:00
2022-01-09 20:05:19 +00:00
handleClickConfirmButton=()=>{
2022-01-09 15:28:12 +00:00
const requestOptions = {
method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({
2022-01-09 20:05:19 +00:00
'action': "confirm",
2022-01-09 15:28:12 +00:00
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => (this.props.data = data));
}
handleRatingChange=(e)=>{
const requestOptions = {
method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({
'action': "rate",
'rating': e.target.value,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => (this.props.data = data));
}
2022-01-09 12:14:11 +00:00
2022-01-09 15:28:12 +00:00
showFiatSentButton(){
return(
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Button defaultValue="confirm" variant='contained' color='secondary' onClick={this.handleClickConfirmButton}>Confirm {this.props.data.currencyCode} sent</Button>
2022-01-09 20:05:19 +00:00
</Grid>
</Grid>
)
}
showFiatReceivedButton(){
return(
<Grid item xs={12} align="center">
<Button defaultValue="confirm" variant='contained' color='secondary' onClick={this.handleClickOpenConfirmFiatReceived}>Confirm {this.props.data.currencyCode} received</Button>
2022-01-09 20:05:19 +00:00
</Grid>
)
}
showOpenDisputeButton(){
// TODO, show alert about how opening a dispute might involve giving away personal data and might mean losing the bond. Ask for double confirmation.
return(
<Grid item xs={12} align="center">
<Button color="inherit" onClick={this.handleClickOpenConfirmDispute}>Open Dispute</Button>
2022-01-09 20:05:19 +00:00
</Grid>
)
}
2022-01-18 15:45:04 +00:00
showOrderExpired(){
return(
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1">
<b>The order has expired</b>
</Typography>
</Grid>
</Grid>
)
}
2022-01-09 20:05:19 +00:00
showChat(sendFiatButton, receivedFiatButton, openDisputeButton){
return(
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1">
<b>Chatting with {this.props.data.isMaker ? this.props.data.takerNick : this.props.data.makerNick}</b>
</Typography>
</Grid>
<Grid item xs={12} align="center">
2022-01-09 20:05:19 +00:00
{this.props.data.isSeller ?
<Typography component="body2" variant="body2" align="center">
2022-01-19 13:32:54 +00:00
Say hi! Be helpful and concise. Let them know how to send you {this.props.data.currencyCode}.
2022-01-09 20:05:19 +00:00
</Typography>
:
<Typography component="body2" variant="body2" align="center">
Say hi! Ask for payment details and click "Confirm Sent" as soon as the payment is sent.
2022-01-09 20:05:19 +00:00
</Typography>
}
<Divider/>
2022-01-09 20:05:19 +00:00
</Grid>
<Chat orderId={this.props.data.id} urNick={this.props.data.urNick}/>
2022-01-09 20:05:19 +00:00
<Grid item xs={12} align="center">
{openDisputeButton ? this.showOpenDisputeButton() : ""}
{sendFiatButton ? this.showFiatSentButton() : ""}
{receivedFiatButton ? this.showFiatReceivedButton() : ""}
2022-01-09 15:28:12 +00:00
</Grid>
{this.showBondIsLocked()}
2022-01-09 15:28:12 +00:00
</Grid>
)
}
showRateSelect(){
return(
<Grid container spacing={1}>
<Grid item xs={12} align="center">
<Typography component="h6" variant="h6">
🎉Trade finished!🥳
</Typography>
</Grid>
<Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center">
What do you think of <b>{this.props.data.isMaker ? this.props.data.takerNick : this.props.data.makerNick}</b>?
</Typography>
</Grid>
<Grid item xs={12} align="center">
<Rating name="size-large" defaultValue={2} size="large" onChange={this.handleRatingChange} />
</Grid>
<Grid item xs={12} align="center">
<Button color='primary' href='/' component="a">Start Again</Button>
</Grid>
</Grid>
)
}
2022-01-09 12:14:11 +00:00
render() {
return (
2022-01-08 15:34:09 +00:00
<Grid container spacing={1} style={{ width:330}}>
<this.ConfirmDisputeDialog/>
<this.ConfirmFiatReceivedDialog/>
<Grid item xs={12} align="center">
<Typography component="h5" variant="h5">
Contract Box
</Typography>
<Paper elevation={12} style={{ padding: 8,}}>
2022-01-09 12:14:11 +00:00
{/* Maker and taker Bond request */}
2022-01-09 14:07:05 +00:00
{this.props.data.bondInvoice ? this.showQRInvoice() : ""}
2022-01-09 12:14:11 +00:00
{/* Waiting for taker and taker bond request */}
2022-01-09 14:07:05 +00:00
{this.props.data.isMaker & this.props.data.statusCode == 1 ? this.showMakerWait() : ""}
{this.props.data.isMaker & this.props.data.statusCode == 3 ? this.showTakerFound() : ""}
2022-01-09 12:14:11 +00:00
{/* Send Invoice (buyer) and deposit collateral (seller) */}
2022-01-09 14:07:05 +00:00
{this.props.data.isSeller & this.props.data.escrowInvoice != null ? this.showEscrowQRInvoice() : ""}
{this.props.data.isBuyer & this.props.data.invoiceAmount != null ? this.showInputInvoice() : ""}
{this.props.data.isBuyer & this.props.data.statusCode == 7 ? this.showWaitingForEscrow() : ""}
{this.props.data.isSeller & this.props.data.statusCode == 8 ? this.showWaitingForBuyerInvoice() : ""}
2022-01-09 12:14:11 +00:00
{/* In Chatroom - No fiat sent - showChat(showSendButton, showReveiceButton, showDisputeButton) */}
2022-01-09 20:05:19 +00:00
{this.props.data.isBuyer & this.props.data.statusCode == 9 ? this.showChat(true,false,true) : ""}
{this.props.data.isSeller & this.props.data.statusCode == 9 ? this.showChat(false,false,true) : ""}
{/* In Chatroom - Fiat sent - showChat(showSendButton, showReveiceButton, showDisputeButton) */}
2022-01-09 20:05:19 +00:00
{this.props.data.isBuyer & this.props.data.statusCode == 10 ? this.showChat(false,false,true) : ""}
{this.props.data.isSeller & this.props.data.statusCode == 10 ? this.showChat(false,true,true) : ""}
2022-01-09 12:14:11 +00:00
{/* Trade Finished */}
2022-01-12 14:26:26 +00:00
{(this.props.data.isSeller & this.props.data.statusCode > 12 & this.props.data.statusCode < 15) ? this.showRateSelect() : ""}
{(this.props.data.isBuyer & this.props.data.statusCode == 14) ? this.showRateSelect() : ""}
{/* Trade Finished - Payment Routing Failed */}
{this.props.data.isBuyer & this.props.data.statusCode == 15 ? this.showUpdateInvoice() : ""}
{/* Trade Finished - TODO Needs more planning */}
{this.props.data.statusCode == 11 ? this.showInDisputeStatement() : ""}
2022-01-18 15:45:04 +00:00
{/* Order has expired */}
{this.props.data.statusCode == 5 ? this.showOrderExpired() : ""}
2022-01-09 12:14:11 +00:00
{/* TODO */}
{/* */}
{/* */}
2022-01-09 12:35:19 +00:00
</Paper>
</Grid>
</Grid>
);
}
}