2022-11-15 09:35:48 +01:00
|
|
|
import { TrashIcon } from '@/components/icons'
|
|
|
|
import { Seo } from '@/components/Seo'
|
|
|
|
import {
|
|
|
|
isProPlan,
|
|
|
|
LimitReached,
|
|
|
|
LockTag,
|
|
|
|
UpgradeButton,
|
|
|
|
} from '@/features/billing'
|
|
|
|
import { CustomDomainsDropdown } from '@/features/customDomains'
|
|
|
|
import { TypebotHeader, useTypebot } from '@/features/editor'
|
|
|
|
import { useWorkspace } from '@/features/workspace'
|
|
|
|
import { useToast } from '@/hooks/useToast'
|
2023-01-20 11:20:11 +01:00
|
|
|
import { isCloudProdInstance } from '@/utils/helpers'
|
2022-11-15 09:35:48 +01:00
|
|
|
import {
|
|
|
|
Flex,
|
|
|
|
Heading,
|
|
|
|
HStack,
|
|
|
|
IconButton,
|
|
|
|
Stack,
|
|
|
|
Wrap,
|
|
|
|
Text,
|
|
|
|
} from '@chakra-ui/react'
|
|
|
|
import { Plan } from 'db'
|
2023-01-21 18:20:10 +01:00
|
|
|
import { isDefined, getViewerUrl, isNotDefined, env } from 'utils'
|
2022-11-15 09:35:48 +01:00
|
|
|
import { isPublicDomainAvailableQuery } from '../queries/isPublicDomainAvailableQuery'
|
|
|
|
import { parseDefaultPublicId } from '../utils'
|
|
|
|
import { EditableUrl } from './EditableUrl'
|
|
|
|
import { integrationsList } from './embeds/EmbedButton'
|
|
|
|
|
|
|
|
export const SharePage = () => {
|
|
|
|
const { workspace } = useWorkspace()
|
2023-01-27 17:11:26 +01:00
|
|
|
const { typebot, updateTypebot, publishedTypebot } = useTypebot()
|
2022-11-15 09:35:48 +01:00
|
|
|
const { showToast } = useToast()
|
|
|
|
|
|
|
|
const handlePublicIdChange = async (publicId: string) => {
|
|
|
|
updateTypebot({ publicId })
|
|
|
|
}
|
|
|
|
|
|
|
|
const publicId = typebot
|
|
|
|
? typebot?.publicId ?? parseDefaultPublicId(typebot.name, typebot.id)
|
|
|
|
: ''
|
2023-01-27 17:11:26 +01:00
|
|
|
const isPublished = isDefined(publishedTypebot)
|
2022-11-15 09:35:48 +01:00
|
|
|
|
|
|
|
const handlePathnameChange = (pathname: string) => {
|
|
|
|
if (!typebot?.customDomain) return
|
|
|
|
const existingHost = typebot.customDomain?.split('/')[0]
|
|
|
|
const newDomain =
|
|
|
|
pathname === '' ? existingHost : existingHost + '/' + pathname
|
|
|
|
handleCustomDomainChange(newDomain)
|
|
|
|
}
|
|
|
|
|
2023-01-28 15:00:11 +01:00
|
|
|
const handleCustomDomainChange = (customDomain: string | null) =>
|
2022-11-15 09:35:48 +01:00
|
|
|
updateTypebot({ customDomain })
|
|
|
|
|
2023-01-20 11:20:11 +01:00
|
|
|
const checkIfPathnameIsValid = (pathname: string) => {
|
|
|
|
const isCorrectlyFormatted =
|
|
|
|
/^([a-z0-9]+-[a-z0-9]+)*$/.test(pathname) || /^[a-z0-9]*$/.test(pathname)
|
|
|
|
|
|
|
|
if (!isCorrectlyFormatted) {
|
|
|
|
showToast({
|
|
|
|
description:
|
|
|
|
'Should contain only contain letters, numbers. Words can be separated by dashes.',
|
|
|
|
})
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
const checkIfPublicIdIsValid = async (publicId: string) => {
|
|
|
|
const isLongerThanAllowed = publicId.length >= 4
|
|
|
|
if (!isLongerThanAllowed && isCloudProdInstance) {
|
|
|
|
showToast({
|
|
|
|
description: 'Should be longer than 4 characters',
|
|
|
|
})
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!checkIfPathnameIsValid(publicId)) return false
|
|
|
|
|
|
|
|
const { data } = await isPublicDomainAvailableQuery(publicId)
|
|
|
|
if (!data?.isAvailable) {
|
|
|
|
showToast({ description: 'ID is already taken' })
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-11-15 09:35:48 +01:00
|
|
|
return (
|
|
|
|
<Flex flexDir="column" pb="40">
|
2023-01-26 17:04:37 +01:00
|
|
|
<Seo title={typebot?.name ? `${typebot.name} | Share` : 'Share'} />
|
2022-11-15 09:35:48 +01:00
|
|
|
<TypebotHeader />
|
|
|
|
<Flex h="full" w="full" justifyContent="center" align="flex-start">
|
|
|
|
<Stack maxW="1000px" w="full" pt="10" spacing={10}>
|
|
|
|
<Stack spacing={4} align="flex-start">
|
|
|
|
<Heading fontSize="2xl" as="h1">
|
|
|
|
Your typebot link
|
|
|
|
</Heading>
|
|
|
|
{typebot && (
|
|
|
|
<EditableUrl
|
2023-01-25 11:27:47 +01:00
|
|
|
hostname={getViewerUrl() ?? 'https://typebot.io'}
|
2022-11-15 09:35:48 +01:00
|
|
|
pathname={publicId}
|
2023-01-20 11:20:11 +01:00
|
|
|
isValid={checkIfPublicIdIsValid}
|
2022-11-15 09:35:48 +01:00
|
|
|
onPathnameChange={handlePublicIdChange}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{typebot?.customDomain && (
|
|
|
|
<HStack>
|
|
|
|
<EditableUrl
|
|
|
|
hostname={'https://' + typebot.customDomain.split('/')[0]}
|
|
|
|
pathname={typebot.customDomain.split('/')[1]}
|
2023-01-20 11:20:11 +01:00
|
|
|
isValid={checkIfPathnameIsValid}
|
2022-11-15 09:35:48 +01:00
|
|
|
onPathnameChange={handlePathnameChange}
|
|
|
|
/>
|
|
|
|
<IconButton
|
|
|
|
icon={<TrashIcon />}
|
|
|
|
aria-label="Remove custom domain"
|
|
|
|
size="xs"
|
2023-01-28 15:00:11 +01:00
|
|
|
onClick={() => handleCustomDomainChange(null)}
|
2022-11-15 09:35:48 +01:00
|
|
|
/>
|
|
|
|
</HStack>
|
|
|
|
)}
|
2023-01-21 18:20:10 +01:00
|
|
|
{isNotDefined(typebot?.customDomain) &&
|
|
|
|
env('VERCEL_VIEWER_PROJECT_NAME') ? (
|
2022-11-15 09:35:48 +01:00
|
|
|
<>
|
|
|
|
{isProPlan(workspace) ? (
|
|
|
|
<CustomDomainsDropdown
|
|
|
|
onCustomDomainSelect={handleCustomDomainChange}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<UpgradeButton
|
|
|
|
colorScheme="gray"
|
|
|
|
limitReachedType={LimitReached.CUSTOM_DOMAIN}
|
|
|
|
>
|
|
|
|
<Text mr="2">Add my domain</Text>{' '}
|
|
|
|
<LockTag plan={Plan.PRO} />
|
|
|
|
</UpgradeButton>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
) : null}
|
|
|
|
</Stack>
|
|
|
|
|
|
|
|
<Stack spacing={4}>
|
|
|
|
<Heading fontSize="2xl" as="h1">
|
|
|
|
Embed your typebot
|
|
|
|
</Heading>
|
|
|
|
<Wrap spacing={7}>
|
|
|
|
{integrationsList.map((IntegrationButton, idx) => (
|
|
|
|
<IntegrationButton
|
|
|
|
key={idx}
|
|
|
|
publicId={publicId}
|
|
|
|
isPublished={isPublished}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</Wrap>
|
|
|
|
</Stack>
|
|
|
|
</Stack>
|
|
|
|
</Flex>
|
|
|
|
</Flex>
|
|
|
|
)
|
|
|
|
}
|