stacker.news/components/territory-header.js

173 lines
5.0 KiB
JavaScript
Raw Normal View History

2023-12-31 01:41:16 +00:00
import { Badge, Button, CardFooter, Dropdown } from 'react-bootstrap'
2023-12-15 18:10:29 +00:00
import { AccordianCard } from './accordian-item'
import TerritoryPaymentDue, { TerritoryBillingLine } from './territory-payment-due'
import Link from 'next/link'
import Text from './text'
import { numWithUnits } from '../lib/format'
import styles from './item.module.css'
import Hat from './hat'
import { useMe } from './me'
import Share from './share'
import { gql, useMutation } from '@apollo/client'
import { useToast } from './toast'
export function TerritoryDetails ({ sub }) {
return (
<AccordianCard
header={
<small className='text-muted fw-bold align-items-center d-flex'>
territory details
{sub.status === 'STOPPED' && <Badge className='ms-2' bg='danger'>archived</Badge>}
{(sub.moderated || sub.moderatedCount > 0) && <Badge className='ms-2' bg='secondary'>moderated{sub.moderatedCount > 0 && ` ${sub.moderatedCount}`}</Badge>}
</small>
}
>
2024-01-09 01:02:00 +00:00
<TerritoryInfo sub={sub} />
</AccordianCard>
)
}
export function TerritoryInfo ({ sub }) {
return (
<>
<div className='py-2'>
<Text>{sub.desc}</Text>
</div>
<CardFooter className={`py-1 ${styles.other}`}>
<div className='text-muted'>
<span>founded by </span>
<Link href={`/${sub.user.name}`}>
@{sub.user.name}<span> </span><Hat className='fill-grey' user={sub.user} height={12} width={12} />
</Link>
</div>
<div className='text-muted'>
<span>post cost </span>
<span className='fw-bold'>{numWithUnits(sub.baseCost)}</span>
</div>
<TerritoryBillingLine sub={sub} />
</CardFooter>
2024-01-09 01:02:00 +00:00
</>
)
}
2023-12-15 18:10:29 +00:00
export default function TerritoryHeader ({ sub }) {
const me = useMe()
const toaster = useToast()
const [toggleMuteSub] = useMutation(
gql`
mutation toggleMuteSub($name: String!) {
toggleMuteSub(name: $name)
}`, {
update (cache, { data: { toggleMuteSub } }) {
cache.modify({
id: `Sub:{"name":"${sub.name}"}`,
fields: {
2023-12-31 01:41:16 +00:00
meMuteSub: () => toggleMuteSub
2023-12-15 18:10:29 +00:00
}
})
}
}
)
return (
<>
<TerritoryPaymentDue sub={sub} />
<div className='mb-3'>
<div>
<TerritoryDetails sub={sub} />
2023-12-15 18:10:29 +00:00
</div>
<div className='d-flex my-2 justify-content-end'>
<Share path={`/~${sub.name}`} title={`~${sub.name} stacker news territory`} className='mx-3' />
2023-12-31 01:45:41 +00:00
{me &&
(Number(sub.userId) === Number(me?.id)
? (
<Link href={`/~${sub.name}/edit`} className='d-flex align-items-center'>
<Button variant='outline-grey border-2 rounded py-0' size='sm'>edit territory</Button>
</Link>)
: (
<Button
variant='outline-grey border-2 py-0 rounded'
size='sm'
onClick={async () => {
try {
await toggleMuteSub({ variables: { name: sub.name } })
} catch {
toaster.danger(`failed to ${sub.meMuteSub ? 'join' : 'mute'} territory`)
return
}
toaster.success(`${sub.meMuteSub ? 'joined' : 'muted'} territory`)
}}
>{sub.meMuteSub ? 'join' : 'mute'} territory
</Button>))}
2023-12-15 18:10:29 +00:00
</div>
</div>
</>
)
}
2023-12-31 01:41:16 +00:00
export function MuteSubDropdownItem ({ item, sub }) {
const toaster = useToast()
const [toggleMuteSub] = useMutation(
gql`
mutation toggleMuteSub($name: String!) {
toggleMuteSub(name: $name)
}`, {
update (cache, { data: { toggleMuteSub } }) {
console.log(sub, toggleMuteSub)
cache.modify({
id: `Sub:{"name":"${sub.name}"}`,
fields: {
meMuteSub: () => toggleMuteSub
}
})
}
}
)
return (
<Dropdown.Item
onClick={async () => {
try {
await toggleMuteSub({ variables: { name: sub.name } })
} catch {
toaster.danger(`failed to ${sub.meMuteSub ? 'join' : 'mute'} territory`)
return
}
toaster.success(`${sub.meMuteSub ? 'joined' : 'muted'} territory`)
}}
>{sub.meMuteSub ? 'unmute' : 'mute'} ~{sub.name}
</Dropdown.Item>
)
}
export function PinSubDropdownItem ({ item: { id, position } }) {
const toaster = useToast()
const [pinItem] = useMutation(
gql`
mutation pinItem($id: ID!) {
pinItem(id: $id) {
position
}
}`, {
// refetch since position of other items might also have changed to fill gaps
refetchQueries: ['SubItems', 'Item']
}
)
return (
<Dropdown.Item
onClick={async () => {
try {
await pinItem({ variables: { id } })
toaster.success(position ? 'pin removed' : 'pin added')
} catch (err) {
toaster.danger(err.message)
}
}}
>
{position ? 'unpin item' : 'pin item'}
</Dropdown.Item>
)
}