Files
omnivore/packages/web/components/templates/integrations/Readwise.tsx
2023-04-12 16:50:10 +08:00

205 lines
5.2 KiB
TypeScript

import { useCallback, useMemo, useState } from 'react'
import { styled } from '@stitches/react'
import Image from 'next/image'
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
import { Button } from '../../elements/Button'
import { StyledText } from '../../elements/StyledText'
import { FormInput } from '../../elements/FormElements'
import { setIntegrationMutation } from '../../../lib/networking/mutations/setIntegrationMutation'
import {
Integration,
useGetIntegrationsQuery,
} from '../../../lib/networking/queries/useGetIntegrationsQuery'
import { useRouter } from 'next/router'
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
import { deleteIntegrationMutation } from '../../../lib/networking/mutations/deleteIntegrationMutation'
// Styles
const Header = styled(Box, {
color: '$utilityTextDefault',
fontSize: 'x-large',
margin: '20px',
})
export function Readwise(): JSX.Element {
const { integrations, revalidate } = useGetIntegrationsQuery()
const readwiseIntegration = useMemo(() => {
return integrations.find((i) => i.name == 'READWISE' && i.type == 'EXPORT')
}, [integrations])
return (
<VStack
distribution={'start'}
alignment={'start'}
css={{
margin: '0 auto',
width: '80%',
height: '500px',
}}
>
<HStack
alignment={'start'}
distribution={'start'}
css={{
width: '100%',
pb: '$2',
borderBottom: '1px solid $utilityTextDefault',
pr: '$1',
}}
>
<Image
src="/static/icons/readwise.svg"
alt="integration Image"
width={75}
height={75}
/>
<Header>Readwise</Header>
</HStack>
{readwiseIntegration && (
<RemoveReadwiseForm
integration={readwiseIntegration}
revalidate={revalidate}
/>
)}
{!readwiseIntegration && <AddReadwiseForm />}
</VStack>
)
}
function AddReadwiseForm(): JSX.Element {
const router = useRouter()
const [errorMessage, setErrorMessage] = useState<string | undefined>(
undefined
)
const [token, setToken] = useState<string>('')
const setReadwiseToken = useCallback(async () => {
try {
const result = await setIntegrationMutation({
token,
name: 'READWISE',
type: 'EXPORT',
enabled: true,
})
if (result) {
router.push(`/settings/integrations`)
showSuccessToast('Your Readwise API token has been set.')
} else {
setErrorMessage('There was an error connecting to Readwise.')
}
} catch (err) {
setErrorMessage('Error: ' + err)
}
}, [token, router])
return (
<>
<HStack
css={{
fontSize: '18px',
color: '$utilityTextDefault',
my: '20px',
whiteSpace: 'pre-wrap',
}}
>
<SpanBox>
Enter your API key from Readwise below. You can get your token{' '}
<a
target="_blank"
rel="noreferrer"
referrerPolicy="no-referrer"
style={{ color: '$utilityTextDefault' }}
href="https://readwise.io/access_token"
>
here
</a>
.
</SpanBox>
</HStack>
<FormInput
type="token"
key="token"
value={token}
placeholder={'Readwise Token'}
onChange={(e) => {
e.preventDefault()
setToken(e.target.value)
}}
disabled={false}
hidden={false}
required={true}
css={{
border: '1px solid $textNonessential',
borderRadius: '8px',
width: '80%',
bg: 'transparent',
fontSize: '16px',
textIndent: '8px',
my: '20px',
height: '38px',
color: '$grayTextContrast',
'&:focus': {
outline: 'none',
boxShadow: '0px 0px 2px 2px rgba(255, 234, 159, 0.56)',
},
}}
min={200}
/>
{errorMessage && <StyledText style="error">{errorMessage}</StyledText>}
<Button style="ctaDarkYellow" css={{}} onClick={setReadwiseToken}>
Set Token
</Button>
</>
)
}
type RemoveReadwiseFormProps = {
integration: Integration
revalidate: () => void
}
function RemoveReadwiseForm(props: RemoveReadwiseFormProps): JSX.Element {
const deleteIntegration = useCallback(async () => {
try {
if (props.integration.id) {
const result = await deleteIntegrationMutation(props.integration.id)
if (result) {
props.revalidate()
showSuccessToast('Integration Removed')
} else {
showErrorToast('Error removing Readwise integration.')
}
}
} catch (err) {
showErrorToast('Error: ' + err)
}
}, [props])
return (
<>
<HStack
css={{
fontSize: '18px',
color: '$utilityTextDefault',
my: '20px',
whiteSpace: 'pre-wrap',
}}
>
<SpanBox>
Omnivore is configured to send all your highlights to Readwise.
</SpanBox>
</HStack>
<Button style="ctaDarkYellow" onClick={deleteIntegration}>
Remove Readwise Integration
</Button>
</>
)
}