diff --git a/app/components/projects/Project.jsx b/app/components/projects/Project.jsx index 665d9b7..ff61d51 100644 --- a/app/components/projects/Project.jsx +++ b/app/components/projects/Project.jsx @@ -1,6 +1,10 @@ -import React from 'react' +import web3 from 'Embark/web3' +import React, { useMemo, useState, useEffect } from 'react' import Typography from '@material-ui/core/Typography' import Button from '@material-ui/core/Button' +import withObservables from '@nozbe/with-observables' +import { Q } from '@nozbe/watermelondb' +import { withDatabase } from '@nozbe/watermelondb/DatabaseProvider' import Card from '@material-ui/core/Card' import CardHeader from '@material-ui/core/CardHeader' import CardMedia from '@material-ui/core/CardMedia' @@ -9,8 +13,12 @@ import CardActions from '@material-ui/core/CardActions' import CardActionArea from '@material-ui/core/CardActionArea' import LinearProgress from '@material-ui/core/LinearProgress' import Avatar from '@material-ui/core/Avatar' +import { uniqBy, length } from 'ramda' import { withStyles } from '@material-ui/core/styles' import PropTypes from 'prop-types' +import { toEther } from '../../utils/conversions' +import { getTokenLabel } from '../../utils/currencies' +import { timeSinceBlock } from '../../utils/dates' const styles = theme => ({ root: { @@ -81,8 +89,57 @@ const styles = theme => ({ } }) -function Project({ classes, match }) { +function getReceivedAmount(id, transfers){ + return transfers + .filter(t => t.returnValues.to === id) + .reduce((pv, cv) => { + const amount = Number(toEther(cv.returnValues.amount)) + return pv + amount + }, 0) +} + +function getWithdrawnAmount(id, transfers){ + return transfers + .filter(t => t.returnValues.from === id) + .reduce((pv, cv) => { + const amount = Number(toEther(cv.returnValues.amount)) + return pv + amount + }, 0) +} + +function getAmountsPledged(pledges){ + const amounts = {} + pledges.forEach(pledge => { + const { token, amount } = pledge + if (amounts[token]) amounts[token] += Number(toEther(amount)) + else amounts[token] = Number(toEther(amount)) + }) + return Object + .entries(amounts) + .map(entry => ([getTokenLabel(entry[0]), entry[1]])) +} + +function getNumberOfBackers(pledges){ + return length(uniqBy(p => p.owner, pledges)) +} + +async function getProjectAge(id, events, setState){ + const event = events.find(e => e.returnValues.idProject === id) + const { timestamp } = await web3.eth.getBlock(event.blockNumber) + setState(timeSinceBlock(timestamp, 'days')) +} + +function Project({ classes, match, profile, transfers, pledges, projectAddedEvents }) { const projectId = match.params.id + const [projectAge, setAge] = useState(null) + + useEffect(() => { + getProjectAge(projectId, projectAddedEvents, setAge) + }) + const received = useMemo(() => getReceivedAmount(projectId, transfers), [projectId, transfers]) + const withdrawn = useMemo(() => getWithdrawnAmount(projectId, transfers), [projectId, transfers]) + const amountsPledged = useMemo(() => getAmountsPledged(pledges), [pledges]) + const numberOfBackers = useMemo(() => getNumberOfBackers(pledges), [pledges]) return (
@@ -117,16 +174,16 @@ function Project({ classes, match }) { />
- $13,412 + {`${amountsPledged[0][1]} ${amountsPledged[0][0]}`} pledged of $48,894 goal
- 475 + {numberOfBackers} backers
- 19 + {projectAge} days active
@@ -138,7 +195,23 @@ function Project({ classes, match }) { Project.propTypes = { classes: PropTypes.object.isRequired, - match: PropTypes.object + match: PropTypes.object, + profile: PropTypes.array.isRequired, } -export default withStyles(styles)(Project) +const StyledProject = withStyles(styles)(Project) +export default withDatabase(withObservables([], ({ database, match }) => ({ + profile: database.collections.get('profiles').query( + Q.where('id_profile', match.params.id) + ).observe(), + transfers: database.collections.get('lp_events').query( + Q.where('event', 'Transfer') + ).observe(), + projectAddedEvents: database.collections.get('lp_events').query( + Q.where('event', 'ProjectAdded') + ).observe(), + pledges: database.collections.get('pledges').query( + Q.where('intended_project', match.params.id) + ).observe() +}))(StyledProject)) + diff --git a/app/utils/dates.js b/app/utils/dates.js new file mode 100644 index 0000000..cdd4769 --- /dev/null +++ b/app/utils/dates.js @@ -0,0 +1,21 @@ +export function timeSinceBlock(date, interval) { + var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7; + let date1 = new Date(date*1000); + let date2 = new Date(); + var timediff = date2 - date1; + if (isNaN(timediff)) return NaN; + switch (interval) { + case "years": return date2.getFullYear() - date1.getFullYear(); + case "months": return ( + ( date2.getFullYear() * 12 + date2.getMonth() ) + - + ( date1.getFullYear() * 12 + date1.getMonth() ) + ); + case "weeks" : return Math.floor(timediff / week) + case "days" : return Math.floor(timediff / day) + case "hours" : return Math.floor(timediff / hour) + case "minutes": return Math.floor(timediff / minute) + case "seconds": return Math.floor(timediff / second) + default: return undefined + } +}