2022-07-28 04:03:08 +00:00
|
|
|
import { searchInAny } from 'common/util/parse'
|
2022-07-29 23:08:43 +00:00
|
|
|
import { debounce, sortBy } from 'lodash'
|
2022-07-28 04:03:08 +00:00
|
|
|
import { useMemo, useState } from 'react'
|
2022-07-28 01:17:30 +00:00
|
|
|
import { Col } from 'web/components/layout/col'
|
|
|
|
import { Page } from 'web/components/page'
|
|
|
|
import { Title } from 'web/components/title'
|
2022-07-28 03:58:30 +00:00
|
|
|
import { ftxGrants } from './ftxGrants'
|
2022-07-28 01:17:30 +00:00
|
|
|
import GranteeCard from './GranteeCard'
|
|
|
|
|
|
|
|
export type Grantee = {
|
|
|
|
name: string // Better be unique lol
|
|
|
|
// slug = name.toLowerCase().replace(/\s/g, '-')
|
|
|
|
slug: string
|
|
|
|
website?: string
|
|
|
|
photo?: string
|
|
|
|
preview: string
|
|
|
|
description: string
|
|
|
|
grantsReceived: Grant[]
|
2022-07-29 23:08:43 +00:00
|
|
|
totalReceived: number
|
2022-07-28 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export type Grant = {
|
|
|
|
date: string // in YYYY-MM-DD format
|
|
|
|
amount: number // in USD
|
|
|
|
from: 'FTX FF' | 'SFF' | 'OP'
|
|
|
|
to: string // The name of the receiving charity
|
|
|
|
description: string // Why the grant was given; if stated
|
|
|
|
}
|
|
|
|
|
2022-07-28 03:58:30 +00:00
|
|
|
// const grantees: Grantee[] = [
|
|
|
|
// {
|
|
|
|
// name: 'Manifold Markets',
|
|
|
|
// slug: 'manifold-markets',
|
|
|
|
// website: 'https://manifold.markets',
|
|
|
|
// preview: '',
|
|
|
|
// description: '',
|
|
|
|
// grantsReceived: [
|
|
|
|
// {
|
|
|
|
// date: '2022-03-01',
|
|
|
|
// amount: 500000,
|
|
|
|
// from: 'FTX FF',
|
|
|
|
// to: 'Manifold Markets',
|
|
|
|
// description: 'Because you guys are awesome!',
|
|
|
|
// },
|
|
|
|
// ],
|
|
|
|
// },
|
|
|
|
// ]
|
|
|
|
|
|
|
|
const grantees = grantsToGrantees(ftxGrants)
|
|
|
|
|
|
|
|
function grantsToGrantees(grantsList: Grant[]) {
|
|
|
|
const grantees = [] as Grantee[]
|
|
|
|
for (const grant of grantsList) {
|
|
|
|
const name = grant.to
|
|
|
|
let grantee: Grantee | undefined = grantees.find((g) => g.name === name)
|
|
|
|
if (!grantee) {
|
|
|
|
grantee = {
|
|
|
|
name,
|
|
|
|
slug: name.toLowerCase().replace(/\s/g, '-'),
|
|
|
|
preview: grant.description,
|
|
|
|
description: grant.description,
|
|
|
|
grantsReceived: [],
|
2022-07-29 23:08:43 +00:00
|
|
|
totalReceived: 0,
|
2022-07-28 03:58:30 +00:00
|
|
|
}
|
|
|
|
grantees.push(grantee)
|
|
|
|
}
|
|
|
|
grantee.grantsReceived.push(grant)
|
2022-07-29 23:08:43 +00:00
|
|
|
grantee.totalReceived += grant.amount
|
2022-07-28 03:58:30 +00:00
|
|
|
}
|
|
|
|
console.log(grantees)
|
|
|
|
return grantees
|
|
|
|
}
|
2022-07-28 01:17:30 +00:00
|
|
|
|
|
|
|
export default function Grants() {
|
2022-07-28 04:03:08 +00:00
|
|
|
const [query, setQuery] = useState('')
|
|
|
|
const debouncedQuery = debounce(setQuery, 50)
|
|
|
|
|
2022-07-29 23:08:43 +00:00
|
|
|
const filteredGrantees = useMemo(() => {
|
|
|
|
const g = grantees.filter((grantee) =>
|
|
|
|
searchInAny(query, grantee.name, grantee.description)
|
|
|
|
)
|
|
|
|
return sortBy(g, 'totalReceived').reverse()
|
|
|
|
}, [query])
|
2022-07-28 04:03:08 +00:00
|
|
|
|
2022-07-28 01:17:30 +00:00
|
|
|
return (
|
|
|
|
<Page>
|
|
|
|
<Col className="w-full rounded px-4 py-6 sm:px-8 xl:w-[125%]">
|
|
|
|
<Col className="">
|
2022-07-28 04:03:08 +00:00
|
|
|
<Title className="!mt-0" text="EA Grants Database" />
|
|
|
|
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
onChange={(e) => debouncedQuery(e.target.value)}
|
|
|
|
placeholder="Find a charity"
|
|
|
|
className="input input-bordered mb-6 w-full"
|
|
|
|
/>
|
2022-07-28 01:17:30 +00:00
|
|
|
|
|
|
|
<div className="grid max-w-xl grid-flow-row grid-cols-1 gap-4 lg:max-w-full lg:grid-cols-2 xl:grid-cols-3">
|
2022-07-28 04:03:08 +00:00
|
|
|
{filteredGrantees.map((grantee) => (
|
2022-07-28 01:17:30 +00:00
|
|
|
<GranteeCard grantee={grantee} key={grantee.name} />
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</Col>
|
|
|
|
</Col>
|
|
|
|
</Page>
|
|
|
|
)
|
|
|
|
}
|