Consistent tips (#984)
* consistent tip button * hide tips for self * prettier
This commit is contained in:
parent
aeeb47bdbe
commit
cb613705e9
|
@ -46,7 +46,6 @@ export function Button(props: {
|
|||
<button
|
||||
type={type}
|
||||
className={clsx(
|
||||
className,
|
||||
'font-md items-center justify-center rounded-md border border-transparent shadow-sm transition-colors disabled:cursor-not-allowed',
|
||||
sizeClasses,
|
||||
color === 'green' &&
|
||||
|
@ -66,7 +65,8 @@ export function Button(props: {
|
|||
color === 'gray-white' &&
|
||||
'text-greyscale-6 hover:bg-greyscale-2 border-none shadow-none disabled:opacity-50',
|
||||
color === 'highlight-blue' &&
|
||||
'text-highlight-blue disabled:bg-greyscale-2 border-none shadow-none'
|
||||
'text-highlight-blue disabled:bg-greyscale-2 border-none shadow-none',
|
||||
className
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { HeartIcon } from '@heroicons/react/outline'
|
||||
import { Button } from 'web/components/button'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
|
@ -8,12 +6,10 @@ import toast from 'react-hot-toast'
|
|||
import { formatMoney } from 'common/util/format'
|
||||
import { likeContract } from 'web/lib/firebase/likes'
|
||||
import { LIKE_TIP_AMOUNT } from 'common/like'
|
||||
import clsx from 'clsx'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { firebaseLogin } from 'web/lib/firebase/users'
|
||||
import { useMarketTipTxns } from 'web/hooks/use-tip-txns'
|
||||
import { sum } from 'lodash'
|
||||
import { Tooltip } from '../tooltip'
|
||||
import { TipButton } from './tip-button'
|
||||
|
||||
export function LikeMarketButton(props: {
|
||||
contract: Contract
|
||||
|
@ -45,45 +41,16 @@ export function LikeMarketButton(props: {
|
|||
}
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
text={`Tip ${formatMoney(LIKE_TIP_AMOUNT)}`}
|
||||
placement="bottom"
|
||||
noTap
|
||||
noFade
|
||||
>
|
||||
<Button
|
||||
size={'sm'}
|
||||
className={'max-w-xs self-center'}
|
||||
color={'gray-white'}
|
||||
onClick={onLike}
|
||||
>
|
||||
<Col className={'relative items-center sm:flex-row'}>
|
||||
<HeartIcon
|
||||
className={clsx(
|
||||
'h-5 w-5 sm:h-6 sm:w-6',
|
||||
totalTipped > 0 ? 'mr-2' : '',
|
||||
user &&
|
||||
(isLiking ||
|
||||
userLikedContractIds?.includes(contract.id) ||
|
||||
(!likes && contract.likedByUserIds?.includes(user.id)))
|
||||
? 'fill-red-500 text-red-500'
|
||||
: ''
|
||||
)}
|
||||
/>
|
||||
{totalTipped > 0 && (
|
||||
<div
|
||||
className={clsx(
|
||||
'bg-greyscale-6 absolute ml-3.5 mt-2 h-4 w-4 rounded-full align-middle text-white sm:mt-3 sm:h-5 sm:w-5 sm:px-1',
|
||||
totalTipped > 99
|
||||
? 'text-[0.4rem] sm:text-[0.5rem]'
|
||||
: 'sm:text-2xs text-[0.5rem]'
|
||||
)}
|
||||
>
|
||||
{totalTipped}
|
||||
</div>
|
||||
)}
|
||||
</Col>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<TipButton
|
||||
onClick={onLike}
|
||||
tipAmount={LIKE_TIP_AMOUNT}
|
||||
totalTipped={totalTipped}
|
||||
userTipped={
|
||||
!!user &&
|
||||
(isLiking ||
|
||||
userLikedContractIds?.includes(contract.id) ||
|
||||
(!likes && !!contract.likedByUserIds?.includes(user.id)))
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
57
web/components/contract/tip-button.tsx
Normal file
57
web/components/contract/tip-button.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import { HeartIcon } from '@heroicons/react/outline'
|
||||
import { Button } from 'web/components/button'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import clsx from 'clsx'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { Tooltip } from '../tooltip'
|
||||
|
||||
export function TipButton(props: {
|
||||
tipAmount: number
|
||||
totalTipped: number
|
||||
onClick: () => void
|
||||
userTipped: boolean
|
||||
isCompact?: boolean
|
||||
disabled?: boolean
|
||||
}) {
|
||||
const { tipAmount, totalTipped, userTipped, isCompact, onClick, disabled } =
|
||||
props
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
text={`Tip ${formatMoney(tipAmount)}`}
|
||||
placement="bottom"
|
||||
noTap
|
||||
noFade
|
||||
>
|
||||
<Button
|
||||
size={'sm'}
|
||||
className={clsx('max-w-xs self-center', isCompact && 'px-0 py-0')}
|
||||
color={'gray-white'}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Col className={'relative items-center sm:flex-row'}>
|
||||
<HeartIcon
|
||||
className={clsx(
|
||||
'h-5 w-5 sm:h-6 sm:w-6',
|
||||
totalTipped > 0 ? 'mr-2' : '',
|
||||
userTipped ? 'fill-red-500 text-red-500' : ''
|
||||
)}
|
||||
/>
|
||||
{totalTipped > 0 && (
|
||||
<div
|
||||
className={clsx(
|
||||
'bg-greyscale-6 absolute ml-3.5 mt-2 h-4 w-4 rounded-full align-middle text-white sm:mt-3 sm:h-5 sm:w-5 sm:px-1',
|
||||
totalTipped > 99
|
||||
? 'text-[0.4rem] sm:text-[0.5rem]'
|
||||
: 'sm:text-2xs text-[0.5rem]'
|
||||
)}
|
||||
>
|
||||
{totalTipped}
|
||||
</div>
|
||||
)}
|
||||
</Col>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
|
@ -177,10 +177,6 @@ export function FeedComment(props: {
|
|||
smallImage
|
||||
/>
|
||||
<Row className="mt-2 items-center gap-6 text-xs text-gray-500">
|
||||
{tips && <Tipper comment={comment} tips={tips} />}
|
||||
{(contract.openCommentBounties ?? 0) > 0 && (
|
||||
<AwardBountyButton comment={comment} contract={contract} />
|
||||
)}
|
||||
{onReplyClick && (
|
||||
<button
|
||||
className="font-bold hover:underline"
|
||||
|
@ -189,6 +185,10 @@ export function FeedComment(props: {
|
|||
Reply
|
||||
</button>
|
||||
)}
|
||||
{tips && <Tipper comment={comment} tips={tips} />}
|
||||
{(contract.openCommentBounties ?? 0) > 0 && (
|
||||
<AwardBountyButton comment={comment} contract={contract} />
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
</Row>
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
import {
|
||||
ChevronDoubleRightIcon,
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
} from '@heroicons/react/solid'
|
||||
import clsx from 'clsx'
|
||||
import { debounce } from 'lodash'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
import { Comment } from 'common/comment'
|
||||
import { User } from 'common/user'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { debounce, sum } from 'lodash'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { CommentTips } from 'web/hooks/use-tip-txns'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { transact } from 'web/lib/firebase/api'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
import { TipButton } from './contract/tip-button'
|
||||
import { Row } from './layout/row'
|
||||
import { Tooltip } from './tooltip'
|
||||
|
||||
const TIP_SIZE = 10
|
||||
|
||||
|
@ -26,6 +20,7 @@ export function Tipper(prop: { comment: Comment; tips: CommentTips }) {
|
|||
const savedTip = tips[myId] ?? 0
|
||||
|
||||
const [localTip, setLocalTip] = useState(savedTip)
|
||||
|
||||
// listen for user being set
|
||||
const initialized = useRef(false)
|
||||
useEffect(() => {
|
||||
|
@ -35,8 +30,6 @@ export function Tipper(prop: { comment: Comment; tips: CommentTips }) {
|
|||
}
|
||||
}, [tips, myId])
|
||||
|
||||
const total = sum(Object.values(tips)) - savedTip + localTip
|
||||
|
||||
// declare debounced function only on first render
|
||||
const [saveTip] = useState(() =>
|
||||
debounce(async (user: User, comment: Comment, change: number) => {
|
||||
|
@ -80,69 +73,22 @@ export function Tipper(prop: { comment: Comment; tips: CommentTips }) {
|
|||
me && saveTip(me, comment, localTip - savedTip + delta)
|
||||
}
|
||||
|
||||
const canDown = me && localTip > savedTip
|
||||
const canUp = me && me.id !== comment.userId && me.balance >= localTip + 5
|
||||
if (me && comment.userId === me.id) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
const canUp = me && me.balance >= localTip + TIP_SIZE
|
||||
|
||||
return (
|
||||
<Row className="items-center gap-0.5">
|
||||
<DownTip onClick={canDown ? () => addTip(-TIP_SIZE) : undefined} />
|
||||
<span className="font-bold">{Math.floor(total)}</span>
|
||||
<UpTip
|
||||
onClick={canUp ? () => addTip(+TIP_SIZE) : undefined}
|
||||
value={localTip}
|
||||
<TipButton
|
||||
tipAmount={TIP_SIZE}
|
||||
totalTipped={localTip}
|
||||
onClick={() => addTip(+TIP_SIZE)}
|
||||
userTipped={localTip > 0}
|
||||
disabled={!canUp}
|
||||
isCompact
|
||||
/>
|
||||
{localTip === 0 ? (
|
||||
''
|
||||
) : (
|
||||
<span
|
||||
className={clsx(
|
||||
'ml-1 font-semibold',
|
||||
localTip > 0 ? 'text-primary' : 'text-red-400'
|
||||
)}
|
||||
>
|
||||
({formatMoney(localTip)} tip)
|
||||
</span>
|
||||
)}
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
||||
function DownTip(props: { onClick?: () => void }) {
|
||||
const { onClick } = props
|
||||
return (
|
||||
<Tooltip
|
||||
className="h-6 w-6"
|
||||
placement="bottom"
|
||||
text={onClick && `-${formatMoney(TIP_SIZE)}`}
|
||||
noTap
|
||||
>
|
||||
<button
|
||||
className="hover:text-red-600 disabled:text-gray-100"
|
||||
disabled={!onClick}
|
||||
onClick={onClick}
|
||||
>
|
||||
<ChevronLeftIcon className="h-6 w-6" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
function UpTip(props: { onClick?: () => void; value: number }) {
|
||||
const { onClick, value } = props
|
||||
const IconKind = value > TIP_SIZE ? ChevronDoubleRightIcon : ChevronRightIcon
|
||||
return (
|
||||
<Tooltip
|
||||
className="h-6 w-6"
|
||||
placement="bottom"
|
||||
text={onClick && `Tip ${formatMoney(TIP_SIZE)}`}
|
||||
noTap
|
||||
>
|
||||
<button
|
||||
className="hover:text-primary disabled:text-gray-100"
|
||||
disabled={!onClick}
|
||||
onClick={onClick}
|
||||
>
|
||||
<IconKind className={clsx('h-6 w-6', value ? 'text-primary' : '')} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -154,7 +154,6 @@ export function PostComment(props: {
|
|||
smallImage
|
||||
/>
|
||||
<Row className="mt-2 items-center gap-6 text-xs text-gray-500">
|
||||
<Tipper comment={comment} tips={tips ?? {}} />
|
||||
{onReplyClick && (
|
||||
<button
|
||||
className="font-bold hover:underline"
|
||||
|
@ -163,6 +162,7 @@ export function PostComment(props: {
|
|||
Reply
|
||||
</button>
|
||||
)}
|
||||
<Tipper comment={comment} tips={tips ?? {}} />
|
||||
</Row>
|
||||
</div>
|
||||
</Row>
|
||||
|
|
Loading…
Reference in New Issue
Block a user