import { sortBy, sumBy, uniqBy } from 'lodash'
import clsx from 'clsx'
import React, { useEffect, useRef, useState } from 'react'
import Image from 'next/image'
import Confetti from 'react-confetti'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { Page } from 'web/components/page'
import { Title } from 'web/components/title'
import { BuyAmountInput } from 'web/components/amount-input'
import { Spacer } from 'web/components/layout/spacer'
import { User } from 'common/user'
import { useUser } from 'web/hooks/use-user'
import { Linkify } from 'web/components/linkify'
import { transact } from 'web/lib/firebase/api'
import { charities, Charity } from 'common/charity'
import { useRouter } from 'next/router'
import Custom404 from '../404'
import { useCharityTxns } from 'web/hooks/use-charity-txns'
import { useWindowSize } from 'web/hooks/use-window-size'
import { Donation } from 'web/components/charity/feed-items'
import { manaToUSD } from 'common/util/format'
import { track } from 'web/lib/service/analytics'
import { SEO } from 'web/components/SEO'
export default function CharityPageWrapper() {
const router = useRouter()
const { charitySlug } = router.query as { charitySlug: string }
const charity = charities.find((c) => c.slug === charitySlug?.toLowerCase())
if (!router.isReady) return <>>
if (!charity) {
return
}
return
}
function CharityPage(props: { charity: Charity }) {
const { charity } = props
const { name, photo, description } = charity
// TODO: why not just useUser inside Donation Box rather than passing in?
const user = useUser()
const txns = useCharityTxns(charity.id)
const newToOld = sortBy(txns, (txn) => -txn.createdTime)
const totalRaised = sumBy(txns, (txn) => txn.amount)
const fromYou = sumBy(
txns.filter((txn) => txn.fromId === user?.id),
(txn) => txn.amount
)
const numSupporters = uniqBy(txns, (txn) => txn.fromId).length
const { width, height } = useWindowSize()
const [showConfetti, setShowConfetti] = useState(false)
return (
}
>
{showConfetti && (
)}
{/* TODO: donations over time chart */}
{photo && (
)}
About
{newToOld.map((txn) => (
))}
)
}
function Blurb({ text }: { text: string }) {
const [open, setOpen] = useState(false)
// Calculate whether the full blurb is already shown
const ref = useRef(null)
const [hideExpander, setHideExpander] = useState(false)
useEffect(() => {
if (ref.current) {
setHideExpander(ref.current.scrollHeight <= ref.current.clientHeight)
}
}, [])
return (
<>
{text}
>
)
}
function Details(props: {
charity: Charity
totalRaised: number
userDonated: number
numSupporters: number
}) {
const { charity, userDonated, numSupporters, totalRaised } = props
const { website } = charity
return (
{manaToUSD(totalRaised ?? 0)} raised
{userDonated > 0 && (
{manaToUSD(userDonated)} from you!
)}
{numSupporters > 0 && (
{numSupporters} supporters
)}
)
}
function DonationBox(props: {
user?: User | null
charity: Charity
setShowConfetti: (show: boolean) => void
}) {
const { user, charity, setShowConfetti } = props
const [amount, setAmount] = useState()
const [isSubmitting, setIsSubmitting] = useState(false)
const [error, setError] = useState()
const donateDisabled = isSubmitting || !amount || error
const onSubmit: React.FormEventHandler = async (e) => {
if (!user || donateDisabled) return
e.preventDefault()
setIsSubmitting(true)
setError(undefined)
await transact({
amount,
fromId: user.id,
fromType: 'USER',
toId: charity.id,
toType: 'CHARITY',
token: 'M$',
category: 'CHARITY',
description: `${user.name} donated M$ ${amount} to ${charity.name}`,
}).catch((err) => console.log('Error', err))
setIsSubmitting(false)
setAmount(undefined)
setShowConfetti(true)
track('donation', { charityId: charity.id, amount })
}
return (
)
}