Create common card component (#1012)
* Create common card component * lint
This commit is contained in:
parent
7ce09ae39d
commit
94624c5387
16
web/components/card.tsx
Normal file
16
web/components/card.tsx
Normal 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>
|
||||
)
|
||||
}
|
|
@ -6,6 +6,8 @@ import { Charity } from 'common/charity'
|
|||
import { useCharityTxns } from 'web/hooks/use-charity-txns'
|
||||
import { manaToUSD } from '../../../common/util/format'
|
||||
import { Row } from '../layout/row'
|
||||
import { Col } from '../layout/col'
|
||||
import { Card } from '../card'
|
||||
|
||||
export function CharityCard(props: { charity: Charity; match?: number }) {
|
||||
const { charity } = props
|
||||
|
@ -15,43 +17,44 @@ export function CharityCard(props: { charity: Charity; match?: number }) {
|
|||
const raised = sumBy(txns, (txn) => txn.amount)
|
||||
|
||||
return (
|
||||
<Link href={`/charity/${slug}`} passHref>
|
||||
<div className="card card-compact transition:shadow flex-1 cursor-pointer border-2 bg-white hover:shadow-md">
|
||||
<Row className="mt-6 mb-2">
|
||||
{tags?.includes('Featured') && <FeaturedBadge />}
|
||||
</Row>
|
||||
<div className="px-8">
|
||||
<figure className="relative h-32">
|
||||
{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" />
|
||||
)}
|
||||
</figure>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
{/* <h3 className="card-title line-clamp-3">{name}</h3> */}
|
||||
<div className="line-clamp-4 text-sm">{preview}</div>
|
||||
{raised > 0 && (
|
||||
<>
|
||||
<Row className="mt-4 flex-1 items-end justify-center gap-6 text-gray-900">
|
||||
<Row className="items-baseline gap-1">
|
||||
<span className="text-3xl font-semibold">
|
||||
{formatUsd(raised)}
|
||||
</span>
|
||||
raised
|
||||
</Row>
|
||||
{/* {match && (
|
||||
<Link href={`/charity/${slug}`}>
|
||||
<a className="flex-1">
|
||||
<Card className="!rounded-2xl">
|
||||
<Row className="mt-6 mb-2">
|
||||
{tags?.includes('Featured') && <FeaturedBadge />}
|
||||
</Row>
|
||||
<div className="px-8">
|
||||
<figure className="relative h-32">
|
||||
{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" />
|
||||
)}
|
||||
</figure>
|
||||
</div>
|
||||
<Col className="p-8">
|
||||
<div className="line-clamp-4 text-sm">{preview}</div>
|
||||
{raised > 0 && (
|
||||
<>
|
||||
<Row className="mt-4 flex-1 items-end justify-center gap-6 text-gray-900">
|
||||
<Row className="items-baseline gap-1">
|
||||
<span className="text-3xl font-semibold">
|
||||
{formatUsd(raised)}
|
||||
</span>
|
||||
raised
|
||||
</Row>
|
||||
{/* {match && (
|
||||
<Col className="text-gray-500">
|
||||
<span className="text-xl">+{formatUsd(match)}</span>
|
||||
<span className="">match</span>
|
||||
</Col>
|
||||
)} */}
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
</Col>
|
||||
</Card>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
BinaryContract,
|
||||
Contract,
|
||||
CPMMBinaryContract,
|
||||
CPMMContract,
|
||||
FreeResponseContract,
|
||||
MultipleChoiceContract,
|
||||
NumericContract,
|
||||
|
@ -35,6 +36,7 @@ import { getMappedValue } from 'common/pseudo-numeric'
|
|||
import { Tooltip } from '../tooltip'
|
||||
import { SiteLink } from '../site-link'
|
||||
import { ProbChange } from './prob-change-table'
|
||||
import { Card } from '../card'
|
||||
|
||||
export function ContractCard(props: {
|
||||
contract: Contract
|
||||
|
@ -75,12 +77,7 @@ export function ContractCard(props: {
|
|||
!hideQuickBet
|
||||
|
||||
return (
|
||||
<Row
|
||||
className={clsx(
|
||||
'group relative gap-3 rounded-lg bg-white shadow-md hover:cursor-pointer hover:bg-gray-100',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<Card className={clsx('group relative flex gap-3', className)}>
|
||||
<Col className="relative flex-1 gap-3 py-4 pb-12 pl-6">
|
||||
<AvatarDetails
|
||||
contract={contract}
|
||||
|
@ -195,7 +192,7 @@ export function ContractCard(props: {
|
|||
/>
|
||||
</Link>
|
||||
)}
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -391,7 +388,7 @@ export function PseudoNumericResolutionOrExpectation(props: {
|
|||
}
|
||||
|
||||
export function ContractCardProbChange(props: {
|
||||
contract: CPMMBinaryContract
|
||||
contract: CPMMContract
|
||||
noLinkAvatar?: boolean
|
||||
className?: string
|
||||
}) {
|
||||
|
@ -399,12 +396,7 @@ export function ContractCardProbChange(props: {
|
|||
const contract = useContractWithPreload(props.contract) as CPMMBinaryContract
|
||||
|
||||
return (
|
||||
<Col
|
||||
className={clsx(
|
||||
className,
|
||||
'mb-4 rounded-lg bg-white shadow hover:bg-gray-100 hover:shadow-lg'
|
||||
)}
|
||||
>
|
||||
<Card className={clsx(className, 'mb-4')}>
|
||||
<AvatarDetails
|
||||
contract={contract}
|
||||
className={'px-6 pt-4'}
|
||||
|
@ -419,6 +411,6 @@ export function ContractCardProbChange(props: {
|
|||
</SiteLink>
|
||||
<ProbChange className="py-2 pr-4" contract={contract} />
|
||||
</Row>
|
||||
</Col>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import { sortBy } from 'lodash'
|
||||
import clsx from 'clsx'
|
||||
import { contractPath } from 'web/lib/firebase/contracts'
|
||||
import { CPMMContract } from 'common/contract'
|
||||
import { formatPercent } from 'common/util/format'
|
||||
import { SiteLink } from '../site-link'
|
||||
import { sortBy } from 'lodash'
|
||||
import { Col } from '../layout/col'
|
||||
import { Row } from '../layout/row'
|
||||
import { LoadingIndicator } from '../loading-indicator'
|
||||
import { useContractWithPreload } from 'web/hooks/use-contract'
|
||||
import { ContractCardProbChange } from './contract-card'
|
||||
|
||||
export function ProbChangeTable(props: {
|
||||
changes: CPMMContract[] | undefined
|
||||
|
@ -39,46 +36,21 @@ export function ProbChangeTable(props: {
|
|||
if (rows === 0) return <div className="px-4 text-gray-500">None</div>
|
||||
|
||||
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="flex-1 divide-y">
|
||||
<Col className="mb-4 w-full gap-4 rounded-lg md:flex-row">
|
||||
<Col className="flex-1 gap-4">
|
||||
{filteredPositiveChanges.map((contract) => (
|
||||
<ProbChangeRow key={contract.id} contract={contract} />
|
||||
<ContractCardProbChange key={contract.id} contract={contract} />
|
||||
))}
|
||||
</Col>
|
||||
<Col className="flex-1 divide-y">
|
||||
<Col className="flex-1 gap-4">
|
||||
{filteredNegativeChanges.map((contract) => (
|
||||
<ProbChangeRow key={contract.id} contract={contract} />
|
||||
<ContractCardProbChange key={contract.id} contract={contract} />
|
||||
))}
|
||||
</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: {
|
||||
contract: CPMMContract
|
||||
className?: string
|
||||
|
|
|
@ -7,8 +7,8 @@ import { useUserById } from 'web/hooks/use-user'
|
|||
import { postPath } from 'web/lib/firebase/posts'
|
||||
import { fromNow } from 'web/lib/util/time'
|
||||
import { Avatar } from './avatar'
|
||||
import { Card } from './card'
|
||||
import { CardHighlightOptions } from './contract/contracts-grid'
|
||||
import { Row } from './layout/row'
|
||||
import { UserLink } from './user-link'
|
||||
|
||||
export function PostCard(props: {
|
||||
|
@ -26,9 +26,9 @@ export function PostCard(props: {
|
|||
|
||||
return (
|
||||
<div className="relative py-1">
|
||||
<Row
|
||||
<Card
|
||||
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
|
||||
)}
|
||||
>
|
||||
|
@ -58,7 +58,7 @@ export function PostCard(props: {
|
|||
Post
|
||||
</span>
|
||||
</div>
|
||||
</Row>
|
||||
</Card>
|
||||
{onPostClick ? (
|
||||
<a
|
||||
className="absolute top-0 left-0 right-0 bottom-0"
|
||||
|
|
Loading…
Reference in New Issue
Block a user