Currently, all the billing types radios are being assigned the same "billingType" id, so clicking on any of the labels always selects the monthly one. If you inspect the HTML, all the billing type labels have 'for="billingType"' which is how the HTML knows which input to select. We have to keep the "name" attribute the same because that's how the input values are linked to the billingType form field. To fix, we explicitly assign the "id" prop for each radio so that the <label>'s "for" attribute is tied to the correct radio input.
220 lines
7.1 KiB
JavaScript
220 lines
7.1 KiB
JavaScript
import { Col, InputGroup, Row, Form as BootstrapForm, Badge } from 'react-bootstrap'
|
|
import { Checkbox, CheckboxGroup, Form, Input, MarkdownInput } from './form'
|
|
import FeeButton, { FeeButtonProvider } from './fee-button'
|
|
import { gql, useApolloClient, useMutation } from '@apollo/client'
|
|
import { useCallback, useState } from 'react'
|
|
import { useRouter } from 'next/router'
|
|
import { MAX_TERRITORY_DESC_LENGTH, POST_TYPES, TERRITORY_BILLING_OPTIONS } from '../lib/constants'
|
|
import { territorySchema } from '../lib/validate'
|
|
import { useMe } from './me'
|
|
import Info from './info'
|
|
|
|
export default function TerritoryForm ({ sub }) {
|
|
const router = useRouter()
|
|
const client = useApolloClient()
|
|
const me = useMe()
|
|
const [upsertSub] = useMutation(
|
|
gql`
|
|
mutation upsertSub($oldName: String, $name: String!, $desc: String, $baseCost: Int!,
|
|
$postTypes: [String!]!, $allowFreebies: Boolean!, $billingType: String!,
|
|
$billingAutoRenew: Boolean!, $moderated: Boolean!, $hash: String, $hmac: String) {
|
|
upsertSub(oldName: $oldName, name: $name, desc: $desc, baseCost: $baseCost,
|
|
postTypes: $postTypes, allowFreebies: $allowFreebies, billingType: $billingType,
|
|
billingAutoRenew: $billingAutoRenew, moderated: $moderated, hash: $hash, hmac: $hmac) {
|
|
name
|
|
}
|
|
}`
|
|
)
|
|
|
|
const onSubmit = useCallback(
|
|
async ({ ...variables }) => {
|
|
const { error } = await upsertSub({
|
|
variables: { oldName: sub?.name, ...variables }
|
|
})
|
|
|
|
if (error) {
|
|
throw new Error({ message: error.toString() })
|
|
}
|
|
|
|
// modify graphql cache to include new sub
|
|
client.cache.modify({
|
|
fields: {
|
|
subs (existing = []) {
|
|
const filtered = existing.filter(s => s.name !== variables.name && s.name !== sub?.name)
|
|
return [
|
|
...filtered,
|
|
{ __typename: 'Sub', name: variables.name }]
|
|
}
|
|
}
|
|
})
|
|
|
|
await router.push(`/~${variables.name}`)
|
|
}, [client, upsertSub, router]
|
|
)
|
|
|
|
const [billing, setBilling] = useState((sub?.billingType || 'MONTHLY').toLowerCase())
|
|
|
|
return (
|
|
<FeeButtonProvider baseLineItems={sub ? undefined : { territory: TERRITORY_BILLING_OPTIONS('first')[billing] }}>
|
|
<Form
|
|
initial={{
|
|
name: sub?.name || '',
|
|
desc: sub?.desc || '',
|
|
baseCost: sub?.baseCost || 10,
|
|
postTypes: sub?.postTypes || POST_TYPES,
|
|
allowFreebies: typeof sub?.allowFreebies === 'undefined' ? true : sub?.allowFreebies,
|
|
billingType: sub?.billingType || 'MONTHLY',
|
|
billingAutoRenew: sub?.billingAutoRenew || false,
|
|
moderated: sub?.moderated || false
|
|
}}
|
|
schema={territorySchema({ client, me })}
|
|
invoiceable
|
|
onSubmit={onSubmit}
|
|
className='mb-5'
|
|
storageKeyPrefix={sub ? undefined : 'territory'}
|
|
> <Input
|
|
label='name'
|
|
name='name'
|
|
required
|
|
autoFocus
|
|
clear
|
|
maxLength={32}
|
|
prepend={<InputGroup.Text className='text-monospace'>~</InputGroup.Text>}
|
|
/>
|
|
<MarkdownInput
|
|
label='description'
|
|
name='desc'
|
|
maxLength={MAX_TERRITORY_DESC_LENGTH}
|
|
required
|
|
minRows={3}
|
|
/>
|
|
<Input
|
|
label='post cost'
|
|
name='baseCost'
|
|
type='number'
|
|
groupClassName='mb-2'
|
|
required
|
|
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
|
/>
|
|
<Checkbox
|
|
label='allow free posts'
|
|
name='allowFreebies'
|
|
groupClassName='ms-1'
|
|
/>
|
|
<CheckboxGroup label='post types' name='postTypes'>
|
|
<Row>
|
|
<Col xs={4} sm='auto'>
|
|
<Checkbox
|
|
inline
|
|
label='links'
|
|
value='LINK'
|
|
name='postTypes'
|
|
id='links-checkbox'
|
|
groupClassName='ms-1 mb-0'
|
|
/>
|
|
</Col>
|
|
<Col xs={4} sm='auto'>
|
|
<Checkbox
|
|
inline
|
|
label='discussions'
|
|
value='DISCUSSION'
|
|
name='postTypes'
|
|
id='discussions-checkbox'
|
|
groupClassName='ms-1 mb-0'
|
|
/>
|
|
</Col>
|
|
<Col xs={4} sm='auto'>
|
|
<Checkbox
|
|
inline
|
|
label='bounties'
|
|
value='BOUNTY'
|
|
name='postTypes'
|
|
id='bounties-checkbox'
|
|
groupClassName='ms-1 mb-0'
|
|
/>
|
|
</Col>
|
|
<Col xs={4} sm='auto'>
|
|
<Checkbox
|
|
inline
|
|
label='polls'
|
|
value='POLL'
|
|
name='postTypes'
|
|
id='polls-checkbox'
|
|
groupClassName='ms-1 mb-0'
|
|
/>
|
|
</Col>
|
|
</Row>
|
|
</CheckboxGroup>
|
|
<BootstrapForm.Label>moderation</BootstrapForm.Label>
|
|
<Checkbox
|
|
inline
|
|
label={
|
|
<div className='d-flex align-items-center'>enable moderation
|
|
<Info>
|
|
<ol>
|
|
<li>Outlaw posts and comments with a click</li>
|
|
<li>Your territory will get a <Badge bg='secondary'>moderated</Badge> badge</li>
|
|
</ol>
|
|
</Info>
|
|
</div>
|
|
}
|
|
name='moderated'
|
|
groupClassName='ms-1'
|
|
/>
|
|
<CheckboxGroup
|
|
label='billing'
|
|
name='billing'
|
|
groupClassName='mb-0'
|
|
>
|
|
{(!sub?.billingType || sub.billingType === 'MONTHLY') &&
|
|
<Checkbox
|
|
type='radio'
|
|
label='100k sats/month'
|
|
value='MONTHLY'
|
|
name='billingType'
|
|
id='monthly-checkbox'
|
|
readOnly={!!sub}
|
|
handleChange={checked => checked && setBilling('monthly')}
|
|
groupClassName='ms-1 mb-0'
|
|
/>}
|
|
{(!sub?.billingType || sub.billingType === 'YEARLY') &&
|
|
<Checkbox
|
|
type='radio'
|
|
label='1m sats/year'
|
|
value='YEARLY'
|
|
name='billingType'
|
|
id='yearly-checkbox'
|
|
readOnly={!!sub}
|
|
handleChange={checked => checked && setBilling('yearly')}
|
|
groupClassName='ms-1 mb-0'
|
|
/>}
|
|
{(!sub?.billingType || sub.billingType === 'ONCE') &&
|
|
<Checkbox
|
|
type='radio'
|
|
label='3m sats once'
|
|
value='ONCE'
|
|
name='billingType'
|
|
id='once-checkbox'
|
|
readOnly={!!sub}
|
|
handleChange={checked => checked && setBilling('once')}
|
|
groupClassName='ms-1 mb-0'
|
|
/>}
|
|
</CheckboxGroup>
|
|
{billing !== 'once' &&
|
|
<Checkbox
|
|
label='auto renew'
|
|
name='billingAutoRenew'
|
|
groupClassName='ms-1 mt-2'
|
|
/>}
|
|
<div className='mt-3 d-flex justify-content-end'>
|
|
<FeeButton
|
|
text={sub ? 'save' : 'found it'}
|
|
variant='secondary'
|
|
disabled={sub?.status === 'STOPPED'}
|
|
/>
|
|
</div>
|
|
</Form>
|
|
</FeeButtonProvider>
|
|
)
|
|
}
|