diff --git a/src/components/projects/BackProject.jsx b/src/components/projects/BackProject.jsx index 6957f91..09ac195 100644 --- a/src/components/projects/BackProject.jsx +++ b/src/components/projects/BackProject.jsx @@ -172,9 +172,9 @@ const SubmissionSection = ({ classes, profiles, delegatePledges, projectId, open ) } -function BackProject({classes, match, profile, delegates: _delegates, projectAddedEvents, delegateAddedEvents: _delegateAddedEvents}) { +function BackProject({classes, match, delegates: _delegates, projectAddedEvents, delegateAddedEvents: _delegateAddedEvents}) { const projectId = match.params.id - const { manifest, delegateProfiles, openSnackBar } = useProjectData(projectId, profile, projectAddedEvents) + const { manifest, delegateProfiles, openSnackBar } = useProjectData(projectId, projectAddedEvents) const delegatePledges = useProfileData(delegateProfiles) return (
diff --git a/src/components/projects/Project.jsx b/src/components/projects/Project.jsx index 938d58a..a5c480b 100644 --- a/src/components/projects/Project.jsx +++ b/src/components/projects/Project.jsx @@ -15,8 +15,8 @@ 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' +import { getAmountsPledged } from '../../utils/pledges' import { getFiles } from '../../utils/ipfs' import { getImageType } from '../../utils/images' import { useProjectData } from './hooks' @@ -111,18 +111,6 @@ function _getWithdrawnAmount(id, transfers){ }, 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)) } @@ -195,7 +183,7 @@ const getAvatarSrc = assets => { function Project({ classes, match, profile, transfers, pledges, projectAddedEvents }) { const projectId = match.params.id - const { projectAge, projectAssets, manifest } = useProjectData(projectId, profile, projectAddedEvents) + const { projectAge, projectAssets, manifest } = useProjectData(projectId, projectAddedEvents) const amountsPledged = useMemo(() => getAmountsPledged(pledges), [pledges, projectId]) const numberOfBackers = useMemo(() => getNumberOfBackers(pledges), [pledges, projectId]) diff --git a/src/components/projects/Projects.jsx b/src/components/projects/Projects.jsx index 26a3e58..ced7e86 100644 --- a/src/components/projects/Projects.jsx +++ b/src/components/projects/Projects.jsx @@ -1,4 +1,4 @@ -import React, {Fragment, useState} from 'react' +import React, {Fragment, useState, useMemo} from 'react' import {withStyles} from '@material-ui/core/styles' import {withDatabase} from "@nozbe/watermelondb/DatabaseProvider"; import withObservables from "@nozbe/with-observables"; @@ -28,6 +28,7 @@ import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; import classnames from 'classnames'; +import { getAmountsPledged } from '../../utils/pledges' import defaultProjectImage from '../../images/default-project-img.png'; import newProjectImage from '../../images/new-project.png'; @@ -138,43 +139,61 @@ function sortByDate(a, b) { } function Favorite({classes, setFavorites, favorites, projectId, className}) { - return ( setFavorites({...favorites, [projectId]: !favorites[projectId]})}/>); + return ( + setFavorites({...favorites, [projectId]: !favorites[projectId]})} /> + ); } -function ProjectCard({classes, project, favorites, setFavorites}) { - return ( - { if (e.target.className.indexOf(classes.favorite) > -1) { e.preventDefault() } }}> - - {/*TODO get actual percentage*/} - - 75% of 2.055 ETH {/*TODO get actual percentage*/} - 3 funders {/*TODO get actual funders*/} - - {project.manifest.title} - - - {project.manifest.description}  - - - Delegate: {project.manifest.creator} {/*TODO check if that really is the delegate*/} - - {project.manifest.avatar && avatar} - - - - - - - ) +function RawProjectCard({classes, project, pledges, favorites, setFavorites}) { + const { manifest } = project + const amountsPledged = useMemo(() => getAmountsPledged(pledges), [pledges]) + const totalPledged = amountsPledged[0] ? amountsPledged[0][1] : 0 + const pledgeCurrency = amountsPledged[0] ? amountsPledged[0][0] : 'ETH' + const percentToGoal = manifest ? Math.min( + (Number(totalPledged) / Number(manifest.goal)) * 100, + 100 + ) : 0 + return ( + + { if (e.target.className.indexOf(classes.favorite) > -1) { e.preventDefault() } }}> + + + + {Math.round(totalPledged)} pledged of {manifest.goal} {pledgeCurrency} + 3 funders {/*TODO get actual funders*/} + + {project.manifest.title} + + + {project.manifest.description}  + + + Delegate: {project.manifest.creator} {/*TODO check if that really is the delegate*/} + + {project.manifest.avatar && avatar} + + + + + + + ) } +const ProjectCard = withDatabase(withObservables(['project'], ({ database, project }) => ({ + pledges: database.collections.get('pledges').query( + Q.where('intended_project', project.projectId) + ).observe() +}))(RawProjectCard)) + function GridView({classes, projects, favorites, setFavorites}) { return ( {projects.map((project, index) => { @@ -233,7 +252,7 @@ function ListView({classes, projects, history, favorites, setFavorites}) { {project.manifest.avatar && - avatar} + avatar} {project.manifest.title} {project.manifest.description} @@ -269,7 +288,7 @@ function Projects({projectAddedEvents, classes, history}) { const [isGridView, setIsGridView] = useState(true); const projects = projectAddedEvents.map(event => { - return Object.assign({projectId: event.returnValues.idProject}, useProjectData(event.returnValues.idProject, '', projectAddedEvents)); + return Object.assign({projectId: event.returnValues.idProject}, useProjectData(event.returnValues.idProject, projectAddedEvents)); }) let sortFunction = (sortType === SORT_TYPES.name) ? sortByTitle : sortByDate; @@ -281,26 +300,26 @@ function Projects({projectAddedEvents, classes, history}) { {projects.length === 0 && } {projects.length > 0 && - -
- - , - }} - /> - + +
+ + , + }} + /> + - setIsGridView(true)}/> - setIsGridView(false)}/> -
+ setIsGridView(true)}/> + setIsGridView(false)}/> +
- {!isGridView && ListView({classes, projects, history, favorites, setFavorites})} - {isGridView && GridView({classes, projects, favorites, setFavorites})} -
+ {!isGridView && ListView({classes, projects, history, favorites, setFavorites})} + {isGridView && GridView({classes, projects, favorites, setFavorites})} + }
) } diff --git a/src/components/projects/hooks.js b/src/components/projects/hooks.js index 7bdc407..7e0d2d9 100644 --- a/src/components/projects/hooks.js +++ b/src/components/projects/hooks.js @@ -20,16 +20,16 @@ async function getProjectAge(id, events, setState){ } } -async function getProjectAssets(projectId, setState){ +async function getProjectAssets(projectId, setState, debug=false){ EmbarkJS.onReady(async (_err) => { const projectInfo = await LiquidPledging.methods.getPledgeAdmin(projectId).call() const CID = projectInfo.url.split('/').slice(-1)[0] - console.log({CID, projectInfo, ipfs}) + if (debug) console.log({CID, projectInfo, ipfs}) getFiles(CID) .then((files) => { setState(files) const manifest = files[2] - console.log({files}, JSON.parse(manifest.content)) + if (debug) console.log({files}, JSON.parse(manifest.content)) }) .catch(async (err) => { console.log('IPFS getFiles error: ', err) @@ -40,7 +40,7 @@ async function getProjectAssets(projectId, setState){ .then((files) => { setState(files) const manifest = files[2] - console.log({files}, JSON.parse(manifest.content)) + if (debug) console.log({files}, JSON.parse(manifest.content)) }) .catch((err) => { console.log('IPFS FAILED ON READY', err) @@ -99,7 +99,7 @@ const getProjectManifest = assets => { } } -export function useProjectData(projectId, profile, projectAddedEvents) { +export function useProjectData(projectId, projectAddedEvents) { const [projectAge, setAge] = useState(null) const [projectAssets, setAssets] = useState(null) const [ipfsReady, setIpfsState] = useState(null) diff --git a/src/utils/pledges.js b/src/utils/pledges.js index 89c750f..0112c74 100644 --- a/src/utils/pledges.js +++ b/src/utils/pledges.js @@ -1,5 +1,7 @@ /*global web3, BigInt*/ import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging' +import { getTokenLabel } from './currencies' +import { toEther } from './conversions' const { getPledgeDelegate, numberOfPledges, getPledge } = LiquidPledging.methods const getPledgeDelegates = (idPledge, numDelegates) => { @@ -78,3 +80,15 @@ export const transferBetweenPledges = (setState, tx) => { } }) } + +export 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]])) +}