@@ -1,3 +1,8 @@ | |||||
# Breakups-Webapp | # Breakups-Webapp | ||||
https://breakups-webapp.herokuapp.com/ | |||||
[![Build Status](https://travis-ci.org/binhonglee/breakups-webapp.svg?branch=master)](https://travis-ci.org/binhonglee/breakups-webapp) | |||||
[![Dependency Status](https://gemnasium.com/badges/github.com/binhonglee/Breakups.svg)](https://gemnasium.com/github.com/binhonglee/Breakups) | |||||
Basic webapp that implements the [Breakups API](https://github.com/binhonglee/Breakups) functionality. | Basic webapp that implements the [Breakups API](https://github.com/binhonglee/Breakups) functionality. |
@@ -13,15 +13,5 @@ | |||||
You need to enable JavaScript to run this app. | You need to enable JavaScript to run this app. | ||||
</noscript> | </noscript> | ||||
<div id="root"></div> | <div id="root"></div> | ||||
<!-- | |||||
This HTML file is a template. | |||||
If you open it directly in the browser, you will see an empty page. | |||||
You can add webfonts, meta tags, or analytics to this file. | |||||
The build step will place the bundled scripts into the <body> tag. | |||||
To begin the development, run `npm start` or `yarn start`. | |||||
To create a production bundle, use `npm run build` or `yarn build`. | |||||
--> | |||||
</body> | </body> | ||||
</html> | </html> |
@@ -1,34 +0,0 @@ | |||||
.App { | |||||
text-align: center; | |||||
} | |||||
.App-logo { | |||||
animation: App-logo-spin infinite 20s linear; | |||||
height: 80px; | |||||
} | |||||
.App-header { | |||||
background-color: #222; | |||||
height: 150px; | |||||
padding: 20px; | |||||
color: white; | |||||
} | |||||
.App-title { | |||||
font-size: 1.5em; | |||||
} | |||||
.App-intro { | |||||
font-size: large; | |||||
} | |||||
@keyframes App-logo-spin { | |||||
from { transform: rotate(0deg); } | |||||
to { transform: rotate(360deg); } | |||||
} | |||||
.form { | |||||
/*text-align: left;*/ | |||||
align-items: left; | |||||
align-self:left; | |||||
} |
@@ -1,47 +1,109 @@ | |||||
import React, { Component } from 'react'; | import React, { Component } from 'react'; | ||||
import People from './Components/People'; | import People from './Components/People'; | ||||
import PaymentChain from './Components/PaymentChain'; | |||||
import './App.css'; | import './App.css'; | ||||
var https = require('https'); | |||||
class App extends Component { | class App extends Component { | ||||
constructor() { | constructor() { | ||||
super(); | super(); | ||||
this.state = { | this.state = { | ||||
peoples: [] | |||||
peoples: [], | |||||
info: [], | |||||
paymentChain: [] | |||||
} | } | ||||
} | } | ||||
render() { | render() { | ||||
return ( | return ( | ||||
<div className="App"> | <div className="App"> | ||||
Breakups | |||||
<br/> | |||||
<br/> | |||||
<h1>Breakups</h1> | |||||
<h3>Easy way to split bills among multiple people.</h3> | |||||
<form onSubmit={this.populatePeople.bind(this)}> | <form onSubmit={this.populatePeople.bind(this)}> | ||||
Number of people: <input type="text" ref="noOfPeople"/> <input type="submit" value="Submit" /> | Number of people: <input type="text" ref="noOfPeople"/> <input type="submit" value="Submit" /> | ||||
</form> | </form> | ||||
<br/> | <br/> | ||||
<br/> | |||||
{this.state.peoples} | {this.state.peoples} | ||||
<input type="submit" value="Get Payment Chain"/> | |||||
<input type="submit" value="Send email reminder"/> | |||||
<br/> | |||||
<PaymentChain paymentChain={this.state.paymentChain} /> | |||||
<br/> | |||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
getPaymentChain() { | |||||
let request = {}; | |||||
let users = []; | |||||
for (var key in this.state.info) { | |||||
if (isNaN(this.state.info[key].amount)) { | |||||
alert('Amount must be number!'); | |||||
return; | |||||
} | |||||
let user = {}; | |||||
user.name = this.state.info[key].name; | |||||
user.email = this.state.info[key].email; | |||||
user.amount = parseInt(this.state.info[key].amount, 10); | |||||
users.push(user); | |||||
} | |||||
request.users = users; | |||||
this.httpsPost(request, result => { | |||||
let existingState = this.state; | |||||
existingState.paymentChain = JSON.parse("[" + result + "]")[0]; | |||||
this.setState(existingState); | |||||
}) | |||||
} | |||||
populatePeople(e) { | populatePeople(e) { | ||||
let peoples = [] | let peoples = [] | ||||
let info = [] | |||||
if (isNaN(this.refs.noOfPeople.value)) { | |||||
alert('Please input number!'); | |||||
if (isNaN(this.refs.noOfPeople.value) || this.refs.noOfPeople.value <= 2) { | |||||
alert('Please input number larger than 2!'); | |||||
} else { | } else { | ||||
for (var i = 0; i < this.refs.noOfPeople.value; i++) { | for (var i = 0; i < this.refs.noOfPeople.value; i++) { | ||||
peoples.push (<People key={i} people={(i+1)} />); | |||||
this.setState({peoples:peoples}); | |||||
} | |||||
info.push({}); | |||||
peoples.push(<People key={i} id={i} people={(i+1)} info={this.updateInfo.bind(this)} />); | |||||
} | |||||
peoples.push(<input key="paymentChain" type="submit" value="Get Payment Chain" onClick={this.getPaymentChain.bind(this)}/>); | |||||
peoples.push(<input key="email" type="submit" value="Send email reminder (non-functional yet)"/>); | |||||
this.setState({peoples:peoples, info:info}); | |||||
} | } | ||||
e.preventDefault(); | e.preventDefault(); | ||||
} | } | ||||
updateInfo(e) { | |||||
let existingState = this.state; | |||||
existingState.info[e.id] = e.info; | |||||
this.setState(existingState); | |||||
} | |||||
httpsPost(data, callback) { | |||||
var post_options = { | |||||
host: 'breakups.herokuapp.com', | |||||
path: '/paymentChain', | |||||
method: 'POST', | |||||
headers: { | |||||
'Content-Type': 'application/json', | |||||
'Content-Length': Buffer.byteLength(JSON.stringify(data)) | |||||
} | |||||
}; | |||||
var post_req = https.request(post_options, res => { | |||||
res.setEncoding('utf8'); | |||||
var returnData = ""; | |||||
res.on('data', chunk => { | |||||
returnData += chunk; | |||||
}); | |||||
res.on('end', () => { | |||||
console.log(returnData) | |||||
callback(returnData); | |||||
}); | |||||
}); | |||||
post_req.write(JSON.stringify(data)); | |||||
post_req.end(); | |||||
} | |||||
} | } | ||||
export default App; | export default App; |
@@ -0,0 +1,14 @@ | |||||
import React, { Component } from 'react'; | |||||
class Payment extends Component { | |||||
render() { | |||||
return ( | |||||
<div className="Payment"> | |||||
<br/> | |||||
{this.props.payment.from} ----{this.props.payment.amount}----> {this.props.payment.to} | |||||
</div> | |||||
) | |||||
} | |||||
} | |||||
export default Payment; |
@@ -0,0 +1,23 @@ | |||||
import React, { Component } from 'react'; | |||||
import Payment from './Payment'; | |||||
class PaymentChain extends Component { | |||||
render() { | |||||
let payments; | |||||
if (this.props.paymentChain) { | |||||
payments = this.props.paymentChain.map(payment => { | |||||
return ( | |||||
<Payment key={payment.from} payment={payment} /> | |||||
); | |||||
}); | |||||
} | |||||
return ( | |||||
<div className="PaymentChain"> | |||||
{payments} | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
export default PaymentChain; |
@@ -6,14 +6,27 @@ class People extends Component { | |||||
<div className="People"> | <div className="People"> | ||||
<form className="form"> | <form className="form"> | ||||
Person {this.props.people}<br/> | Person {this.props.people}<br/> | ||||
Name: <input type = "text" ref="name"/><br/> | |||||
Email: <input type = "text" ref="email"/><br/> | |||||
Amount: <input type = "text" ref="amount"/><br/> | |||||
Name: <input type = "text" ref="name" onBlur={this.updateProps.bind(this)}/><br/> | |||||
Email: <input type = "text" ref="email" onBlur={this.updateProps.bind(this)}/><br/> | |||||
Amount: <input type = "text" ref="amount" onBlur={this.updateProps.bind(this)}/><br/> | |||||
</form> | </form> | ||||
<br/> | <br/> | ||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
updateProps() { | |||||
let req = { | |||||
name: this.refs.name.value, | |||||
email: this.refs.email.value, | |||||
amount: this.refs.amount.value | |||||
}; | |||||
let infoToSend = { | |||||
id: this.props.id, | |||||
info: req | |||||
} | |||||
this.props.info(infoToSend); | |||||
} | |||||
} | } | ||||
export default People; | export default People; |