Create common card component (#1012)

* Create common card component

* lint
This commit is contained in:
Sinclair Chen 2022-10-05 18:02:24 -07:00 committed by GitHub
parent 7ce09ae39d
commit 94624c5387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 86 deletions

16
web/components/card.tsx Normal file
View File

@ -0,0 +1,16 @@
import clsx from 'clsx'
export function Card(props: JSX.IntrinsicElements['div']) {
const { children, className, ...rest } = props
return (
<div
className={clsx(
'cursor-pointer rounded-lg border-2 bg-white transition-shadow hover:shadow-md focus:shadow-md',
className
)}
{...rest}
>
{children}
</div>
)
}

View File

@ -6,6 +6,8 @@ import { Charity } from 'common/charity'
import { useCharityTxns } from 'web/hooks/use-charity-txns' import { useCharityTxns } from 'web/hooks/use-charity-txns'
import { manaToUSD } from '../../../common/util/format' import { manaToUSD } from '../../../common/util/format'
import { Row } from '../layout/row' import { Row } from '../layout/row'
import { Col } from '../layout/col'
import { Card } from '../card'
export function CharityCard(props: { charity: Charity; match?: number }) { export function CharityCard(props: { charity: Charity; match?: number }) {
const { charity } = props const { charity } = props
@ -15,43 +17,44 @@ export function CharityCard(props: { charity: Charity; match?: number }) {
const raised = sumBy(txns, (txn) => txn.amount) const raised = sumBy(txns, (txn) => txn.amount)
return ( return (
<Link href={`/charity/${slug}`} passHref> <Link href={`/charity/${slug}`}>
<div className="card card-compact transition:shadow flex-1 cursor-pointer border-2 bg-white hover:shadow-md"> <a className="flex-1">
<Row className="mt-6 mb-2"> <Card className="!rounded-2xl">
{tags?.includes('Featured') && <FeaturedBadge />} <Row className="mt-6 mb-2">
</Row> {tags?.includes('Featured') && <FeaturedBadge />}
<div className="px-8"> </Row>
<figure className="relative h-32"> <div className="px-8">
{photo ? ( <figure className="relative h-32">
<Image src={photo} alt="" layout="fill" objectFit="contain" /> {photo ? (
) : ( <Image src={photo} alt="" layout="fill" objectFit="contain" />
<div className="h-full w-full bg-gradient-to-r from-slate-300 to-indigo-200" /> ) : (
)} <div className="h-full w-full bg-gradient-to-r from-slate-300 to-indigo-200" />
</figure> )}
</div> </figure>
<div className="card-body"> </div>
{/* <h3 className="card-title line-clamp-3">{name}</h3> */} <Col className="p-8">
<div className="line-clamp-4 text-sm">{preview}</div> <div className="line-clamp-4 text-sm">{preview}</div>
{raised > 0 && ( {raised > 0 && (
<> <>
<Row className="mt-4 flex-1 items-end justify-center gap-6 text-gray-900"> <Row className="mt-4 flex-1 items-end justify-center gap-6 text-gray-900">
<Row className="items-baseline gap-1"> <Row className="items-baseline gap-1">
<span className="text-3xl font-semibold"> <span className="text-3xl font-semibold">
{formatUsd(raised)} {formatUsd(raised)}
</span> </span>
raised raised
</Row> </Row>
{/* {match && ( {/* {match && (
<Col className="text-gray-500"> <Col className="text-gray-500">
<span className="text-xl">+{formatUsd(match)}</span> <span className="text-xl">+{formatUsd(match)}</span>
<span className="">match</span> <span className="">match</span>
</Col> </Col>
)} */} )} */}
</Row> </Row>
</> </>
)} )}
</div> </Col>
</div> </Card>
</a>
</Link> </Link>
) )
} }

View File

@ -8,6 +8,7 @@ import {
BinaryContract, BinaryContract,
Contract, Contract,
CPMMBinaryContract, CPMMBinaryContract,
CPMMContract,
FreeResponseContract, FreeResponseContract,
MultipleChoiceContract, MultipleChoiceContract,
NumericContract, NumericContract,
@ -35,6 +36,7 @@ import { getMappedValue } from 'common/pseudo-numeric'
import { Tooltip } from '../tooltip' import { Tooltip } from '../tooltip'
import { SiteLink } from '../site-link' import { SiteLink } from '../site-link'
import { ProbChange } from './prob-change-table' import { ProbChange } from './prob-change-table'
import { Card } from '../card'
export function ContractCard(props: { export function ContractCard(props: {
contract: Contract contract: Contract
@ -75,12 +77,7 @@ export function ContractCard(props: {
!hideQuickBet !hideQuickBet
return ( return (
<Row <Card className={clsx('group relative flex gap-3', className)}>
className={clsx(
'group relative gap-3 rounded-lg bg-white shadow-md hover:cursor-pointer hover:bg-gray-100',
className
)}
>
<Col className="relative flex-1 gap-3 py-4 pb-12 pl-6"> <Col className="relative flex-1 gap-3 py-4 pb-12 pl-6">
<AvatarDetails <AvatarDetails
contract={contract} contract={contract}
@ -195,7 +192,7 @@ export function ContractCard(props: {
/> />
</Link> </Link>
)} )}
</Row> </Card>
) )
} }
@ -391,7 +388,7 @@ export function PseudoNumericResolutionOrExpectation(props: {
} }
export function ContractCardProbChange(props: { export function ContractCardProbChange(props: {
contract: CPMMBinaryContract contract: CPMMContract
noLinkAvatar?: boolean noLinkAvatar?: boolean
className?: string className?: string
}) { }) {
@ -399,12 +396,7 @@ export function ContractCardProbChange(props: {
const contract = useContractWithPreload(props.contract) as CPMMBinaryContract const contract = useContractWithPreload(props.contract) as CPMMBinaryContract
return ( return (
<Col <Card className={clsx(className, 'mb-4')}>
className={clsx(
className,
'mb-4 rounded-lg bg-white shadow hover:bg-gray-100 hover:shadow-lg'
)}
>
<AvatarDetails <AvatarDetails
contract={contract} contract={contract}
className={'px-6 pt-4'} className={'px-6 pt-4'}
@ -419,6 +411,6 @@ export function ContractCardProbChange(props: {
</SiteLink> </SiteLink>
<ProbChange className="py-2 pr-4" contract={contract} /> <ProbChange className="py-2 pr-4" contract={contract} />
</Row> </Row>
</Col> </Card>
) )
} }

View File

@ -1,13 +1,10 @@
import { sortBy } from 'lodash'
import clsx from 'clsx' import clsx from 'clsx'
import { contractPath } from 'web/lib/firebase/contracts'
import { CPMMContract } from 'common/contract' import { CPMMContract } from 'common/contract'
import { formatPercent } from 'common/util/format' import { formatPercent } from 'common/util/format'
import { SiteLink } from '../site-link' import { sortBy } from 'lodash'
import { Col } from '../layout/col' import { Col } from '../layout/col'
import { Row } from '../layout/row'
import { LoadingIndicator } from '../loading-indicator' import { LoadingIndicator } from '../loading-indicator'
import { useContractWithPreload } from 'web/hooks/use-contract' import { ContractCardProbChange } from './contract-card'
export function ProbChangeTable(props: { export function ProbChangeTable(props: {
changes: CPMMContract[] | undefined changes: CPMMContract[] | undefined
@ -39,46 +36,21 @@ export function ProbChangeTable(props: {
if (rows === 0) return <div className="px-4 text-gray-500">None</div> if (rows === 0) return <div className="px-4 text-gray-500">None</div>
return ( return (
<Col className="mb-4 w-full divide-x-2 divide-y rounded-lg bg-white shadow-md md:flex-row md:divide-y-0"> <Col className="mb-4 w-full gap-4 rounded-lg md:flex-row">
<Col className="flex-1 divide-y"> <Col className="flex-1 gap-4">
{filteredPositiveChanges.map((contract) => ( {filteredPositiveChanges.map((contract) => (
<ProbChangeRow key={contract.id} contract={contract} /> <ContractCardProbChange key={contract.id} contract={contract} />
))} ))}
</Col> </Col>
<Col className="flex-1 divide-y"> <Col className="flex-1 gap-4">
{filteredNegativeChanges.map((contract) => ( {filteredNegativeChanges.map((contract) => (
<ProbChangeRow key={contract.id} contract={contract} /> <ContractCardProbChange key={contract.id} contract={contract} />
))} ))}
</Col> </Col>
</Col> </Col>
) )
} }
export function ProbChangeRow(props: {
contract: CPMMContract
className?: string
}) {
const { className } = props
const contract =
(useContractWithPreload(props.contract) as CPMMContract) ?? props.contract
return (
<Row
className={clsx(
'items-center justify-between gap-4 hover:bg-gray-100',
className
)}
>
<SiteLink
className="p-4 pr-0 font-semibold text-indigo-700"
href={contractPath(contract)}
>
<span className="line-clamp-2">{contract.question}</span>
</SiteLink>
<ProbChange className="py-2 pr-4 text-xl" contract={contract} />
</Row>
)
}
export function ProbChange(props: { export function ProbChange(props: {
contract: CPMMContract contract: CPMMContract
className?: string className?: string

View File

@ -7,8 +7,8 @@ import { useUserById } from 'web/hooks/use-user'
import { postPath } from 'web/lib/firebase/posts' import { postPath } from 'web/lib/firebase/posts'
import { fromNow } from 'web/lib/util/time' import { fromNow } from 'web/lib/util/time'
import { Avatar } from './avatar' import { Avatar } from './avatar'
import { Card } from './card'
import { CardHighlightOptions } from './contract/contracts-grid' import { CardHighlightOptions } from './contract/contracts-grid'
import { Row } from './layout/row'
import { UserLink } from './user-link' import { UserLink } from './user-link'
export function PostCard(props: { export function PostCard(props: {
@ -26,9 +26,9 @@ export function PostCard(props: {
return ( return (
<div className="relative py-1"> <div className="relative py-1">
<Row <Card
className={clsx( className={clsx(
'relative gap-3 rounded-lg bg-white py-2 px-3 shadow-md hover:cursor-pointer hover:bg-gray-100', 'relative flex gap-3 py-2 px-3',
itemIds?.includes(post.id) && highlightClassName itemIds?.includes(post.id) && highlightClassName
)} )}
> >
@ -58,7 +58,7 @@ export function PostCard(props: {
Post Post
</span> </span>
</div> </div>
</Row> </Card>
{onPostClick ? ( {onPostClick ? (
<a <a
className="absolute top-0 left-0 right-0 bottom-0" className="absolute top-0 left-0 right-0 bottom-0"