2022-04-19 07:40:12 +00:00
|
|
|
import clsx from 'clsx'
|
2022-04-25 20:51:01 +00:00
|
|
|
import { useEffect, useRef, useState } from 'react'
|
|
|
|
import { Col } from '../../components/layout/col'
|
|
|
|
import { Row } from '../../components/layout/row'
|
|
|
|
import { Page } from '../../components/page'
|
|
|
|
import { Title } from '../../components/title'
|
|
|
|
import { BuyAmountInput } from '../../components/amount-input'
|
|
|
|
import { Spacer } from '../../components/layout/spacer'
|
|
|
|
import { User } from '../../../common/user'
|
|
|
|
import { useUser } from '../../hooks/use-user'
|
|
|
|
import { Linkify } from '../../components/linkify'
|
|
|
|
import { transact } from '../../lib/firebase/api-call'
|
|
|
|
import { charities, Charity } from '../../../common/charity'
|
|
|
|
import { useRouter } from 'next/router'
|
|
|
|
import Custom404 from '../404'
|
2022-04-19 07:40:12 +00:00
|
|
|
|
2022-04-21 09:47:13 +00:00
|
|
|
const manaToUSD = (mana: number) =>
|
|
|
|
(mana / 100).toLocaleString('en-US', { style: 'currency', currency: 'USD' })
|
|
|
|
|
2022-04-25 20:51:01 +00:00
|
|
|
export default function CharityPageWrapper() {
|
|
|
|
const router = useRouter()
|
|
|
|
const { charitySlug } = router.query as { charitySlug: string }
|
|
|
|
|
|
|
|
const charity = charities.find(
|
|
|
|
(c) => c.slug.toLowerCase() === charitySlug?.toLowerCase()
|
|
|
|
)
|
|
|
|
if (!router.isReady) return <></>
|
|
|
|
if (!charity) {
|
|
|
|
return <Custom404 />
|
|
|
|
}
|
|
|
|
return <CharityPage charity={charity} />
|
2022-04-19 07:40:12 +00:00
|
|
|
}
|
|
|
|
|
2022-04-25 20:51:01 +00:00
|
|
|
function CharityPage(props: { charity: Charity }) {
|
|
|
|
const { charity } = props
|
|
|
|
const { name, photo, blurb } = charity
|
2022-04-19 07:40:12 +00:00
|
|
|
|
|
|
|
// TODO: why not just useUser inside Donation Box rather than passing in?
|
|
|
|
const user = useUser()
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Page rightSidebar={<DonationBox user={user} />}>
|
|
|
|
<Col className="mx-1 w-full items-center sm:px-0">
|
|
|
|
<Col className="max-w-2xl rounded bg-white px-8">
|
|
|
|
<Title text={name} />
|
|
|
|
{/* TODO: donations over time chart */}
|
|
|
|
<Row className="justify-between">
|
|
|
|
{photo && <img src={photo} alt="" className="w-40 rounded-2xl" />}
|
2022-04-25 20:51:01 +00:00
|
|
|
<Details charity={charity} userDonated={4} numSupporters={1} />
|
2022-04-19 07:40:12 +00:00
|
|
|
</Row>
|
|
|
|
<h2 className="mt-7 mb-2 text-xl text-indigo-700">About</h2>
|
|
|
|
<Blurb text={blurb} />
|
|
|
|
</Col>
|
|
|
|
</Col>
|
|
|
|
</Page>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
function Blurb({ text }: { text: string }) {
|
|
|
|
const [open, setOpen] = useState(false)
|
|
|
|
|
|
|
|
// Calculate whether the full blurb is already shown
|
|
|
|
const ref = useRef<HTMLDivElement>(null)
|
|
|
|
const [hideExpander, setHideExpander] = useState(false)
|
|
|
|
useEffect(() => {
|
|
|
|
if (ref.current) {
|
|
|
|
setHideExpander(ref.current.scrollHeight <= ref.current.clientHeight)
|
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div
|
|
|
|
className={clsx(' text-gray-500', !open && 'line-clamp-5')}
|
|
|
|
ref={ref}
|
|
|
|
>
|
|
|
|
{text}
|
|
|
|
</div>
|
|
|
|
<button
|
|
|
|
onClick={() => setOpen(!open)}
|
|
|
|
className={clsx(
|
|
|
|
'btn btn-link capitalize-none my-3 normal-case text-indigo-700',
|
|
|
|
hideExpander && 'hidden'
|
|
|
|
)}
|
|
|
|
>
|
|
|
|
{open ? 'Hide' : 'Read more'}
|
|
|
|
</button>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-04-25 20:51:01 +00:00
|
|
|
function Details(props: {
|
|
|
|
charity: Charity
|
|
|
|
userDonated?: number
|
|
|
|
numSupporters: number
|
|
|
|
}) {
|
|
|
|
const { charity, userDonated, numSupporters } = props
|
|
|
|
const { raised, website } = charity
|
2022-04-19 07:40:12 +00:00
|
|
|
return (
|
|
|
|
<Col className="gap-1 text-right">
|
2022-04-21 09:47:13 +00:00
|
|
|
<div className="text-primary mb-2 text-4xl">
|
2022-04-25 20:51:01 +00:00
|
|
|
{manaToUSD(raised ?? 0)} raised
|
2022-04-21 09:47:13 +00:00
|
|
|
</div>
|
2022-04-19 07:40:12 +00:00
|
|
|
{userDonated && (
|
|
|
|
<div className="text-primary text-xl">
|
2022-04-21 09:47:13 +00:00
|
|
|
{manaToUSD(userDonated)} from you!
|
2022-04-19 07:40:12 +00:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
{numSupporters > 0 && (
|
|
|
|
<div className="text-gray-500">{numSupporters} supporters</div>
|
|
|
|
)}
|
|
|
|
<Linkify text={website} />
|
|
|
|
</Col>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
function DonationBox(props: { user?: User | null }) {
|
|
|
|
const { user } = props
|
|
|
|
const [amount, setAmount] = useState<number | undefined>()
|
|
|
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
|
|
|
const [error, setError] = useState<string | undefined>()
|
|
|
|
|
|
|
|
const donateDisabled = isSubmitting || !amount || error
|
|
|
|
|
|
|
|
const onSubmit: React.FormEventHandler = async (e) => {
|
|
|
|
e.preventDefault()
|
|
|
|
setIsSubmitting(true)
|
|
|
|
setError(undefined)
|
2022-04-21 11:41:02 +00:00
|
|
|
await transact({
|
|
|
|
amount,
|
2022-04-21 17:47:13 +00:00
|
|
|
// TODO hardcode in Manifold Markets official account.
|
|
|
|
// Or should we just have it go into a void?
|
|
|
|
toId: 'igi2zGXsfxYPgB0DJTXVJVmwCOr2', // akrolsmir@gmail in Dev env
|
2022-04-21 11:41:02 +00:00
|
|
|
category: 'TO_CHARITY',
|
2022-04-21 17:47:13 +00:00
|
|
|
description: `${user?.name} donated M$ ${amount} to wellgive`,
|
|
|
|
txnData: {
|
|
|
|
charityId: 'wellgive', // TODO fill in
|
2022-04-21 11:41:02 +00:00
|
|
|
},
|
|
|
|
})
|
2022-04-19 07:40:12 +00:00
|
|
|
setIsSubmitting(false)
|
|
|
|
setAmount(undefined)
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="rounded-lg bg-white py-6 px-8 shadow-lg">
|
|
|
|
<div className="mb-6 text-2xl text-gray-700">Donate</div>
|
|
|
|
<form onSubmit={onSubmit}>
|
|
|
|
<label
|
|
|
|
className="mb-2 block text-sm text-gray-500"
|
|
|
|
htmlFor="donate-input"
|
|
|
|
>
|
|
|
|
Amount
|
|
|
|
</label>
|
|
|
|
<BuyAmountInput
|
|
|
|
inputClassName="w-full donate-input"
|
|
|
|
amount={amount}
|
|
|
|
onChange={setAmount}
|
|
|
|
error={error}
|
|
|
|
setError={setError}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Col className="mt-3 w-full gap-3">
|
|
|
|
<Row className="items-center justify-between text-sm">
|
|
|
|
<span className="text-gray-500">Conversion</span>
|
|
|
|
<span>
|
|
|
|
{amount || 0} Mana
|
|
|
|
<span className="mx-2">→</span>
|
2022-04-21 09:47:13 +00:00
|
|
|
{manaToUSD(amount || 0)}
|
2022-04-19 07:40:12 +00:00
|
|
|
</span>
|
|
|
|
</Row>
|
|
|
|
{/* TODO: matching pool */}
|
|
|
|
</Col>
|
|
|
|
|
|
|
|
<Spacer h={8} />
|
|
|
|
|
|
|
|
{user && (
|
|
|
|
<button
|
|
|
|
type="submit"
|
|
|
|
className={clsx(
|
|
|
|
'btn w-full',
|
|
|
|
donateDisabled ? 'btn-disabled' : 'btn-primary',
|
|
|
|
isSubmitting && 'loading'
|
|
|
|
)}
|
|
|
|
>
|
|
|
|
Donate
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|