CPM: sort charities by amount raised (#117)
* Sort charities by amount raised (after Featured) * Sort donations chronologically * refactor charities query to remove parens
This commit is contained in:
parent
beece64ae5
commit
db695875c4
|
@ -1,6 +1,9 @@
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Txn } from '../../common/txn'
|
import { Txn } from '../../common/txn'
|
||||||
import { listenForCharityTxns } from '../lib/firebase/txns'
|
import {
|
||||||
|
listenForAllCharityTxns,
|
||||||
|
listenForCharityTxns,
|
||||||
|
} from '../lib/firebase/txns'
|
||||||
|
|
||||||
export const useCharityTxns = (charityId: string) => {
|
export const useCharityTxns = (charityId: string) => {
|
||||||
const [txns, setTxns] = useState<Txn[]>([])
|
const [txns, setTxns] = useState<Txn[]>([])
|
||||||
|
@ -11,3 +14,13 @@ export const useCharityTxns = (charityId: string) => {
|
||||||
|
|
||||||
return txns
|
return txns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useAllCharityTxns = () => {
|
||||||
|
const [txns, setTxns] = useState<Txn[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return listenForAllCharityTxns(setTxns)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return txns
|
||||||
|
}
|
||||||
|
|
|
@ -21,3 +21,9 @@ export function listenForCharityTxns(
|
||||||
) {
|
) {
|
||||||
return listenForValues<Txn>(getCharityQuery(charityId), setTxns)
|
return listenForValues<Txn>(getCharityQuery(charityId), setTxns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const charitiesQuery = query(txnCollection, where('toType', '==', 'CHARITY'))
|
||||||
|
|
||||||
|
export function listenForAllCharityTxns(setTxns: (txns: Txn[]) => void) {
|
||||||
|
return listenForValues<Txn>(charitiesQuery, setTxns)
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ function CharityPage(props: { charity: Charity }) {
|
||||||
const user = useUser()
|
const user = useUser()
|
||||||
|
|
||||||
const txns = useCharityTxns(charity.id)
|
const txns = useCharityTxns(charity.id)
|
||||||
|
const newToOld = _.sortBy(txns, (txn) => -txn.createdTime)
|
||||||
const totalRaised = _.sumBy(txns, (txn) => txn.amount)
|
const totalRaised = _.sumBy(txns, (txn) => txn.amount)
|
||||||
const fromYou = _.sumBy(
|
const fromYou = _.sumBy(
|
||||||
txns.filter((txn) => txn.fromId === user?.id),
|
txns.filter((txn) => txn.fromId === user?.id),
|
||||||
|
@ -92,7 +93,7 @@ function CharityPage(props: { charity: Charity }) {
|
||||||
</Row>
|
</Row>
|
||||||
<h2 className="mt-7 mb-2 text-xl text-indigo-700">About</h2>
|
<h2 className="mt-7 mb-2 text-xl text-indigo-700">About</h2>
|
||||||
<Blurb text={description} />
|
<Blurb text={description} />
|
||||||
{txns.map((txn) => (
|
{newToOld.map((txn) => (
|
||||||
<Donation key={txn.id} txn={txn} />
|
<Donation key={txn.id} txn={txn} />
|
||||||
))}
|
))}
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -1,26 +1,36 @@
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { useState, useMemo } from 'react'
|
import { useState, useMemo } from 'react'
|
||||||
import { charities as charityList } from '../../../common/charity'
|
import { charities } from '../../../common/charity'
|
||||||
import { CharityCard } from '../../components/charity/charity-card'
|
import { CharityCard } from '../../components/charity/charity-card'
|
||||||
import { Col } from '../../components/layout/col'
|
import { Col } from '../../components/layout/col'
|
||||||
|
import { Spacer } from '../../components/layout/spacer'
|
||||||
import { Page } from '../../components/page'
|
import { Page } from '../../components/page'
|
||||||
import { Title } from '../../components/title'
|
import { Title } from '../../components/title'
|
||||||
|
import { useAllCharityTxns } from '../../hooks/use-charity-txns'
|
||||||
const charities = charityList.map((charity) => ({
|
|
||||||
...charity,
|
|
||||||
raised: 4001,
|
|
||||||
}))
|
|
||||||
|
|
||||||
export default function Charity() {
|
export default function Charity() {
|
||||||
|
const allCharityTxn = useAllCharityTxns()
|
||||||
|
const totals = _.mapValues(_.groupBy(allCharityTxn, 'toId'), (txns) =>
|
||||||
|
_.sumBy(txns, (txn) => txn.amount)
|
||||||
|
)
|
||||||
|
const totalRaised = _.sum(Object.values(totals))
|
||||||
|
|
||||||
|
// TODO: show loading state while totals are calculating
|
||||||
|
|
||||||
|
const sortedCharities = _.sortBy(charities, [
|
||||||
|
(charity) => (charity.tags?.includes('Featured') ? 0 : 1),
|
||||||
|
(charity) => -totals[charity.id],
|
||||||
|
])
|
||||||
|
|
||||||
const [query, setQuery] = useState('')
|
const [query, setQuery] = useState('')
|
||||||
const debouncedQuery = _.debounce(setQuery, 50)
|
const debouncedQuery = _.debounce(setQuery, 50)
|
||||||
|
|
||||||
const filterCharities = useMemo(
|
const filterCharities = useMemo(
|
||||||
() =>
|
() =>
|
||||||
charities.filter((charity) =>
|
sortedCharities.filter((charity) =>
|
||||||
charity.name.toLowerCase().includes(query.toLowerCase())
|
charity.name.toLowerCase().includes(query.toLowerCase())
|
||||||
),
|
),
|
||||||
[query]
|
[query, sortedCharities]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -31,6 +41,9 @@ export default function Charity() {
|
||||||
<div className="mb-6 text-gray-500">
|
<div className="mb-6 text-gray-500">
|
||||||
Donate your winnings to charity! Through the month of May, every M$
|
Donate your winnings to charity! Through the month of May, every M$
|
||||||
100 you contribute turns into $1 USD sent to your chosen charity.
|
100 you contribute turns into $1 USD sent to your chosen charity.
|
||||||
|
<Spacer h={5} />
|
||||||
|
Together we've donated over ${Math.floor(totalRaised / 100)} USD so
|
||||||
|
far!
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
|
Loading…
Reference in New Issue
Block a user