Files
Compass/web/components/widgets/like-button.tsx
Martin Braquet ba9b3cfb06 Add pretty formatting (#29)
* Test

* Add pretty formatting

* Fix Tests

* Fix Tests

* Fix Tests

* Fix

* Add pretty formatting fix

* Fix

* Test

* Fix tests

* Clean typeckech

* Add prettier check

* Fix api tsconfig

* Fix api tsconfig

* Fix tsconfig

* Fix

* Fix

* Prettier
2026-02-20 17:32:27 +01:00

158 lines
4.8 KiB
TypeScript

import {HeartIcon} from '@heroicons/react/outline'
import clsx from 'clsx'
import {Profile} from 'common/profiles/profile'
import {useState} from 'react'
import {Button, buttonClass} from 'web/components/buttons/button'
import {Col} from 'web/components/layout/col'
import {Modal, MODAL_CLASS} from 'web/components/layout/modal'
import {Row} from 'web/components/layout/row'
import {Tooltip} from 'web/components/widgets/tooltip'
import {useAPIGetter} from 'web/hooks/use-api-getter'
import {useProfile} from 'web/hooks/use-profile'
import {useUserById} from 'web/hooks/use-user-supabase'
import {api} from 'web/lib/api'
import {track} from 'web/lib/service/analytics'
import {MatchAvatars} from '../matches/match-avatars'
export const LikeButton = (props: {
targetProfile: Profile
liked: boolean
refresh: () => Promise<void>
className?: string
}) => {
const {targetProfile, liked, refresh, className} = props
const targetId = targetProfile.user_id
const [isLoading, setIsLoading] = useState(false)
const {data, refresh: refreshHasFreeLike} = useAPIGetter('has-free-like', {})
const hasFreeLike = data?.hasFreeLike ?? false
const [showConfirmation, setShowConfirmation] = useState(false)
const like = async () => {
setShowConfirmation(false)
setIsLoading(true)
await api('like-profile', {targetUserId: targetId, remove: liked})
track('like profile', {
targetId,
remove: liked,
})
await refresh()
setIsLoading(false)
await refreshHasFreeLike()
}
return (
<Tooltip text={liked ? 'Unlike' : 'Send like'} noTap>
<button
disabled={isLoading}
className={clsx(
buttonClass('md', 'none'),
'text-ink-500 disabled:text-ink-500 bg-canvas-0 active:bg-canvas-100 disabled:bg-canvas-100 border-ink-100 dark:border-ink-300 !rounded-full border shadow',
isLoading && 'animate-pulse',
className,
)}
onClick={() => setShowConfirmation(true)}
>
<Col className="items-center">
<HeartIcon
className={clsx(
'h-8 w-8',
liked && 'fill-primary-400 stroke-primary-500 dark:stroke-primary-600',
)}
/>
<div className="p-2 pb-0 pt-0">{liked ? <>Liked!</> : <>Like</>}</div>
</Col>
</button>
<LikeConfirmationDialog
targetProfile={targetProfile}
hasFreeLike={hasFreeLike}
submit={like}
open={!liked && showConfirmation}
setOpen={setShowConfirmation}
/>
<CancelLikeConfimationDialog
targetProfile={targetProfile}
submit={like}
open={liked && showConfirmation}
setOpen={setShowConfirmation}
/>
</Tooltip>
)
}
const LikeConfirmationDialog = (props: {
targetProfile: Profile
hasFreeLike: boolean
open: boolean
setOpen: (open: boolean) => void
submit: () => void
}) => {
const {open, setOpen, targetProfile, hasFreeLike, submit} = props
const youProfile = useProfile()
const user = useUserById(targetProfile.user_id)
return (
<Modal
open={open}
className={clsx(MODAL_CLASS, 'pointer-events-auto max-h-[32rem] overflow-auto')}
>
<Col className="gap-4">
<div className="text-xl">Like {user ? user.name : ''}?</div>
<Col className="gap-2">
<div className="text-ink-500">They will get a notification. Unlocks messaging them.</div>
<div className="text-ink-500">You get one like per day</div>
</Col>
{youProfile && user && (
<MatchAvatars
profileProfile={youProfile}
matchedProfile={{...targetProfile, user: user as any}}
/>
)}
<Row className="mt-2 items-center justify-between">
<Button color="gray-outline" onClick={() => setOpen(false)}>
Cancel
</Button>
{
<Button onClick={() => submit()} disabled={!hasFreeLike}>
{hasFreeLike ? 'Use like for today' : 'Come back tomorrow!'}
</Button>
}
</Row>
</Col>
</Modal>
)
}
const CancelLikeConfimationDialog = (props: {
targetProfile: Profile
open: boolean
setOpen: (open: boolean) => void
submit: () => void
}) => {
const {open, setOpen, targetProfile, submit} = props
const user = useUserById(targetProfile.user_id)
return (
<Modal
open={open}
setOpen={setOpen}
className={clsx(MODAL_CLASS, 'pointer-events-auto max-h-[32rem] overflow-auto')}
>
<Col className="gap-4">
<div className="text-xl">Remove like of {user ? user.name : ''}</div>
<Row className="mt-2 items-center justify-between">
<Button color="gray-outline" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button onClick={() => submit()}>Remove like</Button>
</Row>
</Col>
</Modal>
)
}