@ -7,6 +7,10 @@ const withTM = require('next-transpile-modules')(['utils', 'models', 'emails'])
|
|||||||
const nextConfig = withTM({
|
const nextConfig = withTM({
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
|
i18n: {
|
||||||
|
defaultLocale: 'en',
|
||||||
|
locales: ['en', 'fr', 'pr'],
|
||||||
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
outputFileTracingRoot: path.join(__dirname, '../../'),
|
outputFileTracingRoot: path.join(__dirname, '../../'),
|
||||||
},
|
},
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"@giphy/react-components": "6.5.2",
|
"@giphy/react-components": "6.5.2",
|
||||||
"@googleapis/drive": "4.0.2",
|
"@googleapis/drive": "4.0.2",
|
||||||
"@lezer/css": "^1.1.1",
|
"@lezer/css": "^1.1.1",
|
||||||
|
"@paralleldrive/cuid2": "2.2.0",
|
||||||
"@sentry/nextjs": "7.38.0",
|
"@sentry/nextjs": "7.38.0",
|
||||||
"@stripe/stripe-js": "1.47.0",
|
"@stripe/stripe-js": "1.47.0",
|
||||||
"@tanstack/react-query": "^4.24.10",
|
"@tanstack/react-query": "^4.24.10",
|
||||||
@ -36,6 +37,8 @@
|
|||||||
"@trpc/next": "10.12.0",
|
"@trpc/next": "10.12.0",
|
||||||
"@trpc/react-query": "10.12.0",
|
"@trpc/react-query": "10.12.0",
|
||||||
"@trpc/server": "10.12.0",
|
"@trpc/server": "10.12.0",
|
||||||
|
"@typebot.io/js": "workspace:*",
|
||||||
|
"@typebot.io/react": "workspace:*",
|
||||||
"@udecode/plate-basic-marks": "19.2.0",
|
"@udecode/plate-basic-marks": "19.2.0",
|
||||||
"@udecode/plate-common": "^7.0.2",
|
"@udecode/plate-common": "^7.0.2",
|
||||||
"@udecode/plate-core": "19.2.0",
|
"@udecode/plate-core": "19.2.0",
|
||||||
@ -43,18 +46,15 @@
|
|||||||
"@udecode/plate-serializer-html": "19.2.0",
|
"@udecode/plate-serializer-html": "19.2.0",
|
||||||
"@udecode/plate-ui-link": "19.2.0",
|
"@udecode/plate-ui-link": "19.2.0",
|
||||||
"@udecode/plate-ui-toolbar": "19.2.0",
|
"@udecode/plate-ui-toolbar": "19.2.0",
|
||||||
|
"@uiw/codemirror-extensions-langs": "^4.19.9",
|
||||||
|
"@uiw/codemirror-theme-github": "^4.19.9",
|
||||||
|
"@uiw/codemirror-theme-tokyo-night": "^4.19.9",
|
||||||
|
"@uiw/react-codemirror": "^4.19.9",
|
||||||
"@use-gesture/react": "^10.2.24",
|
"@use-gesture/react": "^10.2.24",
|
||||||
"aws-sdk": "2.1321.0",
|
"aws-sdk": "2.1321.0",
|
||||||
"browser-image-compression": "2.0.0",
|
"browser-image-compression": "2.0.0",
|
||||||
"canvas-confetti": "1.6.0",
|
"canvas-confetti": "1.6.0",
|
||||||
"codemirror": "6.0.1",
|
"codemirror": "6.0.1",
|
||||||
"@paralleldrive/cuid2": "2.2.0",
|
|
||||||
"@typebot.io/js": "workspace:*",
|
|
||||||
"@typebot.io/react": "workspace:*",
|
|
||||||
"@uiw/codemirror-extensions-langs": "^4.19.9",
|
|
||||||
"@uiw/codemirror-theme-github": "^4.19.9",
|
|
||||||
"@uiw/codemirror-theme-tokyo-night": "^4.19.9",
|
|
||||||
"@uiw/react-codemirror": "^4.19.9",
|
|
||||||
"deep-object-diff": "1.1.9",
|
"deep-object-diff": "1.1.9",
|
||||||
"dequal": "2.0.3",
|
"dequal": "2.0.3",
|
||||||
"emails": "workspace:*",
|
"emails": "workspace:*",
|
||||||
@ -73,6 +73,7 @@
|
|||||||
"minio": "7.0.32",
|
"minio": "7.0.32",
|
||||||
"next": "13.1.6",
|
"next": "13.1.6",
|
||||||
"next-auth": "4.19.2",
|
"next-auth": "4.19.2",
|
||||||
|
"@typebot.io/next-international": "^0.3.8",
|
||||||
"nextjs-cors": "^2.1.2",
|
"nextjs-cors": "^2.1.2",
|
||||||
"nodemailer": "6.9.1",
|
"nodemailer": "6.9.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
AlertDialogOverlay,
|
AlertDialogOverlay,
|
||||||
Button,
|
Button,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
|
import { useScopedI18n } from '@/locales'
|
||||||
|
|
||||||
type ConfirmDeleteModalProps = {
|
type ConfirmDeleteModalProps = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
@ -28,6 +29,7 @@ export const ConfirmModal = ({
|
|||||||
onConfirm,
|
onConfirm,
|
||||||
confirmButtonColor = 'red',
|
confirmButtonColor = 'red',
|
||||||
}: ConfirmDeleteModalProps) => {
|
}: ConfirmDeleteModalProps) => {
|
||||||
|
const scopedT = useScopedI18n('confirmModal')
|
||||||
const [confirmLoading, setConfirmLoading] = useState(false)
|
const [confirmLoading, setConfirmLoading] = useState(false)
|
||||||
const cancelRef = useRef(null)
|
const cancelRef = useRef(null)
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ export const ConfirmModal = ({
|
|||||||
<AlertDialogOverlay>
|
<AlertDialogOverlay>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader fontSize="lg" fontWeight="bold">
|
<AlertDialogHeader fontSize="lg" fontWeight="bold">
|
||||||
{title ?? 'Are you sure?'}
|
{title ?? scopedT('defaultTitle')}
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
|
|
||||||
<AlertDialogBody>{message}</AlertDialogBody>
|
<AlertDialogBody>{message}</AlertDialogBody>
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
import { CloseButton, Flex, HStack, StackProps } from '@chakra-ui/react'
|
|
||||||
import React, { useEffect, useState } from 'react'
|
|
||||||
|
|
||||||
type VerifyEmailBannerProps = { id: string } & StackProps
|
|
||||||
|
|
||||||
export const Banner = ({ id, ...props }: VerifyEmailBannerProps) => {
|
|
||||||
const [show, setShow] = useState(false)
|
|
||||||
const localStorageKey = `banner-${id}`
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!localStorage.getItem(localStorageKey)) setShow(true)
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const handleCloseClick = () => {
|
|
||||||
localStorage.setItem(localStorageKey, 'hide')
|
|
||||||
setShow(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!show) return <></>
|
|
||||||
return (
|
|
||||||
<HStack
|
|
||||||
h="50px"
|
|
||||||
bgColor="blue.400"
|
|
||||||
color="white"
|
|
||||||
justifyContent="center"
|
|
||||||
align="center"
|
|
||||||
w="full"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<Flex maxW="1000px" justifyContent="space-between" w="full">
|
|
||||||
<HStack>{props.children}</HStack>
|
|
||||||
<CloseButton rounded="full" onClick={handleCloseClick} />
|
|
||||||
</Flex>
|
|
||||||
</HStack>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
import {
|
|
||||||
Modal,
|
|
||||||
ModalOverlay,
|
|
||||||
ModalContent,
|
|
||||||
ModalHeader,
|
|
||||||
ModalCloseButton,
|
|
||||||
ModalBody,
|
|
||||||
Text,
|
|
||||||
Stack,
|
|
||||||
Link,
|
|
||||||
} from '@chakra-ui/react'
|
|
||||||
import React, { useEffect, useState } from 'react'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
isOpen: boolean
|
|
||||||
onClose: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const localStorageKey = 'typebot-20-modal'
|
|
||||||
export const AnnoucementModal = ({ isOpen, onClose }: Props) => {
|
|
||||||
const [show, setShow] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!localStorage.getItem(localStorageKey)) setShow(true)
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const handleCloseClick = () => {
|
|
||||||
localStorage.setItem(localStorageKey, 'hide')
|
|
||||||
setShow(false)
|
|
||||||
onClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!show) return <></>
|
|
||||||
return (
|
|
||||||
<Modal isOpen={isOpen} onClose={handleCloseClick} size="2xl">
|
|
||||||
<ModalOverlay />
|
|
||||||
<ModalContent>
|
|
||||||
<ModalHeader>What's new in Typebot 2.0?</ModalHeader>
|
|
||||||
<ModalCloseButton />
|
|
||||||
<ModalBody as={Stack} spacing="6" pb="10">
|
|
||||||
<Text>Typebo 2.0 has been launched February the 15th 🎉.</Text>
|
|
||||||
<iframe
|
|
||||||
width="620"
|
|
||||||
height="315"
|
|
||||||
src="https://www.youtube.com/embed/u8FZHvlYviw"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameBorder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
||||||
allowFullScreen
|
|
||||||
style={{ borderRadius: '5px' }}
|
|
||||||
/>
|
|
||||||
<Text>
|
|
||||||
Most questions are answered in this{' '}
|
|
||||||
<Link
|
|
||||||
href="https://docs.typebot.io"
|
|
||||||
color="blue.500"
|
|
||||||
textDecor="underline"
|
|
||||||
>
|
|
||||||
FAQ
|
|
||||||
</Link>
|
|
||||||
. If you have other questions, open up the bot on the bottom right
|
|
||||||
corner. 😃
|
|
||||||
</Text>
|
|
||||||
<Text>Baptiste.</Text>
|
|
||||||
</ModalBody>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
@ -8,8 +8,10 @@ import { isNotDefined } from 'utils'
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { WorkspaceSettingsModal } from '@/features/workspace'
|
import { WorkspaceSettingsModal } from '@/features/workspace'
|
||||||
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
||||||
|
import { useScopedI18n } from '@/locales'
|
||||||
|
|
||||||
export const DashboardHeader = () => {
|
export const DashboardHeader = () => {
|
||||||
|
const scopedT = useScopedI18n('dashboard.header')
|
||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
const { workspace, switchWorkspace, createWorkspace } = useWorkspace()
|
const { workspace, switchWorkspace, createWorkspace } = useWorkspace()
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ export const DashboardHeader = () => {
|
|||||||
onClick={onOpen}
|
onClick={onOpen}
|
||||||
isLoading={isNotDefined(workspace)}
|
isLoading={isNotDefined(workspace)}
|
||||||
>
|
>
|
||||||
Settings & Members
|
{scopedT('settingsButton.label')}
|
||||||
</Button>
|
</Button>
|
||||||
<WorkspaceDropdown
|
<WorkspaceDropdown
|
||||||
currentWorkspace={workspace}
|
currentWorkspace={workspace}
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
import { TypebotDndProvider, FolderContent } from '@/features/folders'
|
import { TypebotDndProvider, FolderContent } from '@/features/folders'
|
||||||
import { ParentModalProvider } from '@/features/graph'
|
import { ParentModalProvider } from '@/features/graph'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace'
|
||||||
|
import { useScopedI18n } from '@/locales'
|
||||||
import { Stack, VStack, Spinner, Text } from '@chakra-ui/react'
|
import { Stack, VStack, Spinner, Text } from '@chakra-ui/react'
|
||||||
import { Plan } from 'db'
|
import { Plan } from 'db'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
@ -15,6 +16,7 @@ import { guessIfUserIsEuropean } from 'utils/pricing'
|
|||||||
import { DashboardHeader } from './DashboardHeader'
|
import { DashboardHeader } from './DashboardHeader'
|
||||||
|
|
||||||
export const DashboardPage = () => {
|
export const DashboardPage = () => {
|
||||||
|
const scopedT = useScopedI18n('dashboard')
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const { query } = useRouter()
|
const { query } = useRouter()
|
||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
@ -42,7 +44,7 @@ export const DashboardPage = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack minH="100vh">
|
<Stack minH="100vh">
|
||||||
<Seo title={workspace?.name ?? 'My typebots'} />
|
<Seo title={workspace?.name ?? scopedT('title')} />
|
||||||
<DashboardHeader />
|
<DashboardHeader />
|
||||||
{!workspace?.stripeId && (
|
{!workspace?.stripeId && (
|
||||||
<ParentModalProvider>
|
<ParentModalProvider>
|
||||||
@ -57,7 +59,7 @@ export const DashboardPage = () => {
|
|||||||
<TypebotDndProvider>
|
<TypebotDndProvider>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<VStack w="full" justifyContent="center" pt="10" spacing={6}>
|
<VStack w="full" justifyContent="center" pt="10" spacing={6}>
|
||||||
<Text>You are being redirected...</Text>
|
<Text>{scopedT('redirectionMessage')}</Text>
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</VStack>
|
</VStack>
|
||||||
) : (
|
) : (
|
||||||
|
@ -40,7 +40,7 @@ test('folders and typebots should be deletable', async ({ page }) => {
|
|||||||
await page.click('li:has-text("Folder #1") >> button:has-text("Delete")')
|
await page.click('li:has-text("Folder #1") >> button:has-text("Delete")')
|
||||||
await deleteButtonInConfirmDialog(page).click()
|
await deleteButtonInConfirmDialog(page).click()
|
||||||
await expect(page.locator('span >> text="Folder #1"')).not.toBeVisible()
|
await expect(page.locator('span >> text="Folder #1"')).not.toBeVisible()
|
||||||
await page.click('button[aria-label="Show Typebot #1 menu"]')
|
await page.click('button[aria-label="Show more options"]')
|
||||||
await page.click('li:has-text("Typebot #1") >> button:has-text("Delete")')
|
await page.click('li:has-text("Typebot #1") >> button:has-text("Delete")')
|
||||||
await deleteButtonInConfirmDialog(page).click()
|
await deleteButtonInConfirmDialog(page).click()
|
||||||
await expect(page.locator('span >> text="Typebot #1"')).not.toBeVisible()
|
await expect(page.locator('span >> text="Typebot #1"')).not.toBeVisible()
|
||||||
|
@ -3,8 +3,10 @@ import { ChevronLeftIcon } from '@/components/icons'
|
|||||||
import { useTypebotDnd } from '../TypebotDndProvider'
|
import { useTypebotDnd } from '../TypebotDndProvider'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
|
import { useI18n } from '@/locales'
|
||||||
|
|
||||||
export const BackButton = ({ id }: { id: string | null }) => {
|
export const BackButton = ({ id }: { id: string | null }) => {
|
||||||
|
const t = useI18n()
|
||||||
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
||||||
useTypebotDnd()
|
useTypebotDnd()
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ export const BackButton = ({ id }: { id: string | null }) => {
|
|||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
>
|
>
|
||||||
Back
|
{t('back')}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,14 @@ import { PlusIcon } from '@/components/icons'
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { stringify } from 'qs'
|
import { stringify } from 'qs'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useScopedI18n } from '@/locales'
|
||||||
|
|
||||||
export const CreateBotButton = ({
|
export const CreateBotButton = ({
|
||||||
folderId,
|
folderId,
|
||||||
isFirstBot,
|
isFirstBot,
|
||||||
...props
|
...props
|
||||||
}: { folderId?: string; isFirstBot: boolean } & ButtonProps) => {
|
}: { folderId?: string; isFirstBot: boolean } & ButtonProps) => {
|
||||||
|
const scopedT = useScopedI18n('folders.createTypebotButton')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const handleClick = () =>
|
const handleClick = () =>
|
||||||
@ -39,7 +41,7 @@ export const CreateBotButton = ({
|
|||||||
textAlign="center"
|
textAlign="center"
|
||||||
mt="6"
|
mt="6"
|
||||||
>
|
>
|
||||||
Create a typebot
|
{scopedT('label')}
|
||||||
</Text>
|
</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -9,10 +9,12 @@ import {
|
|||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace'
|
||||||
import { Plan } from 'db'
|
import { Plan } from 'db'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useScopedI18n } from '@/locales'
|
||||||
|
|
||||||
type Props = { isLoading: boolean; onClick: () => void }
|
type Props = { isLoading: boolean; onClick: () => void }
|
||||||
|
|
||||||
export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
||||||
|
const scopedT = useScopedI18n('folders.createFolderButton')
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
<HStack>
|
<HStack>
|
||||||
<Text>Create a folder</Text>
|
<Text>{scopedT('label')}</Text>
|
||||||
{isFreePlan(workspace) && <LockTag plan={Plan.STARTER} />}
|
{isFreePlan(workspace) && <LockTag plan={Plan.STARTER} />}
|
||||||
</HStack>
|
</HStack>
|
||||||
<ChangePlanModal
|
<ChangePlanModal
|
||||||
|
@ -25,6 +25,7 @@ import React, { useMemo } from 'react'
|
|||||||
import { deleteFolderQuery } from '../queries/deleteFolderQuery'
|
import { deleteFolderQuery } from '../queries/deleteFolderQuery'
|
||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { updateFolderQuery } from '../queries/updateFolderQuery'
|
import { updateFolderQuery } from '../queries/updateFolderQuery'
|
||||||
|
import { useI18n, useScopedI18n } from '@/locales'
|
||||||
|
|
||||||
export const FolderButton = ({
|
export const FolderButton = ({
|
||||||
folder,
|
folder,
|
||||||
@ -35,6 +36,8 @@ export const FolderButton = ({
|
|||||||
onFolderDeleted: () => void
|
onFolderDeleted: () => void
|
||||||
onFolderRenamed: (newName: string) => void
|
onFolderRenamed: (newName: string) => void
|
||||||
}) => {
|
}) => {
|
||||||
|
const t = useI18n()
|
||||||
|
const scopedT = useScopedI18n('folders.folderButton')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
||||||
useTypebotDnd()
|
useTypebotDnd()
|
||||||
@ -49,7 +52,6 @@ export const FolderButton = ({
|
|||||||
const { error } = await deleteFolderQuery(folder.id)
|
const { error } = await deleteFolderQuery(folder.id)
|
||||||
return error
|
return error
|
||||||
? showToast({
|
? showToast({
|
||||||
title: "Couldn't delete the folder",
|
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
: onFolderDeleted()
|
: onFolderDeleted()
|
||||||
@ -59,7 +61,7 @@ export const FolderButton = ({
|
|||||||
if (newName === '' || newName === folder.name) return
|
if (newName === '' || newName === folder.name) return
|
||||||
const { error } = await updateFolderQuery(folder.id, { name: newName })
|
const { error } = await updateFolderQuery(folder.id, { name: newName })
|
||||||
return error
|
return error
|
||||||
? showToast({ title: 'An error occured', description: error.message })
|
? showToast({ title: t('errorMessage'), description: error.message })
|
||||||
: onFolderRenamed(newName)
|
: onFolderRenamed(newName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ export const FolderButton = ({
|
|||||||
onOpen()
|
onOpen()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Delete
|
{t('delete')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
@ -138,8 +140,9 @@ export const FolderButton = ({
|
|||||||
confirmButtonLabel={'Delete'}
|
confirmButtonLabel={'Delete'}
|
||||||
message={
|
message={
|
||||||
<Text>
|
<Text>
|
||||||
Are you sure you want to delete <strong>{folder.name}</strong>{' '}
|
{scopedT('deleteConfirmationMessage', {
|
||||||
folder? (Everything inside will be move to your dashboard)
|
folderName: <strong>{folder.name}</strong>,
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
}
|
}
|
||||||
title={`Delete ${folder.name}?`}
|
title={`Delete ${folder.name}?`}
|
||||||
|
@ -24,12 +24,14 @@ import { CreateFolderButton } from './CreateFolderButton'
|
|||||||
import { ButtonSkeleton, FolderButton } from './FolderButton'
|
import { ButtonSkeleton, FolderButton } from './FolderButton'
|
||||||
import { TypebotButton } from './TypebotButton'
|
import { TypebotButton } from './TypebotButton'
|
||||||
import { TypebotCardOverlay } from './TypebotButtonOverlay'
|
import { TypebotCardOverlay } from './TypebotButtonOverlay'
|
||||||
|
import { useI18n } from '@/locales'
|
||||||
|
|
||||||
type Props = { folder: DashboardFolder | null }
|
type Props = { folder: DashboardFolder | null }
|
||||||
|
|
||||||
const dragDistanceTolerance = 20
|
const dragDistanceTolerance = 20
|
||||||
|
|
||||||
export const FolderContent = ({ folder }: Props) => {
|
export const FolderContent = ({ folder }: Props) => {
|
||||||
|
const t = useI18n()
|
||||||
const { workspace, currentRole } = useWorkspace()
|
const { workspace, currentRole } = useWorkspace()
|
||||||
const [isCreatingFolder, setIsCreatingFolder] = useState(false)
|
const [isCreatingFolder, setIsCreatingFolder] = useState(false)
|
||||||
const {
|
const {
|
||||||
@ -57,7 +59,9 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
workspaceId: workspace?.id,
|
workspaceId: workspace?.id,
|
||||||
parentId: folder?.id,
|
parentId: folder?.id,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast({ title: "Couldn't fetch folders", description: error.message })
|
showToast({
|
||||||
|
description: error.message,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -70,7 +74,6 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
folderId: folder === null ? 'root' : folder.id,
|
folderId: folder === null ? 'root' : folder.id,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast({
|
showToast({
|
||||||
title: "Couldn't fetch typebots",
|
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -94,7 +97,7 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
setIsCreatingFolder(false)
|
setIsCreatingFolder(false)
|
||||||
if (error)
|
if (error)
|
||||||
return showToast({
|
return showToast({
|
||||||
title: 'An error occured',
|
title: t('errorMessage'),
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
if (newFolder) mutateFolders({ folders: [...folders, newFolder] })
|
if (newFolder) mutateFolders({ folders: [...folders, newFolder] })
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Seo } from '@/components/Seo'
|
import { Seo } from '@/components/Seo'
|
||||||
import { DashboardHeader } from '@/features/dashboard'
|
import { DashboardHeader } from '@/features/dashboard'
|
||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
|
import { useI18n } from '@/locales'
|
||||||
import { Stack, Flex, Spinner } from '@chakra-ui/react'
|
import { Stack, Flex, Spinner } from '@chakra-ui/react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useFolder } from '../hooks/useFolder'
|
import { useFolder } from '../hooks/useFolder'
|
||||||
@ -8,6 +9,7 @@ import { TypebotDndProvider } from '../TypebotDndProvider'
|
|||||||
import { FolderContent } from './FolderContent'
|
import { FolderContent } from './FolderContent'
|
||||||
|
|
||||||
export const FolderPage = () => {
|
export const FolderPage = () => {
|
||||||
|
const t = useI18n()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const { showToast } = useToast()
|
const { showToast } = useToast()
|
||||||
@ -16,7 +18,6 @@ export const FolderPage = () => {
|
|||||||
folderId: router.query.id?.toString(),
|
folderId: router.query.id?.toString(),
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
showToast({
|
showToast({
|
||||||
title: "Couldn't fetch folder content",
|
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -24,7 +25,7 @@ export const FolderPage = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack minH="100vh">
|
<Stack minH="100vh">
|
||||||
<Seo title="My typebots" />
|
<Seo title={t('dashboard.title')} />
|
||||||
<DashboardHeader />
|
<DashboardHeader />
|
||||||
<TypebotDndProvider>
|
<TypebotDndProvider>
|
||||||
{!folder ? (
|
{!folder ? (
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
|
Alert,
|
||||||
|
AlertIcon,
|
||||||
Button,
|
Button,
|
||||||
Flex,
|
Flex,
|
||||||
IconButton,
|
IconButton,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
|
Stack,
|
||||||
Tag,
|
Tag,
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
@ -28,6 +31,7 @@ import {
|
|||||||
import { MoreButton } from './MoreButton'
|
import { MoreButton } from './MoreButton'
|
||||||
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
||||||
import { deletePublishedTypebotQuery } from '@/features/publish/queries/deletePublishedTypebotQuery'
|
import { deletePublishedTypebotQuery } from '@/features/publish/queries/deletePublishedTypebotQuery'
|
||||||
|
import { useScopedI18n } from '@/locales'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
typebot: TypebotInDashboard
|
typebot: TypebotInDashboard
|
||||||
@ -42,6 +46,7 @@ export const TypebotButton = ({
|
|||||||
onTypebotUpdated,
|
onTypebotUpdated,
|
||||||
onMouseDown,
|
onMouseDown,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const scopedT = useScopedI18n('folders.typebotButton')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const { draggedTypebot } = useTypebotDnd()
|
const { draggedTypebot } = useTypebotDnd()
|
||||||
@ -68,7 +73,6 @@ export const TypebotButton = ({
|
|||||||
const { error } = await deleteTypebotQuery(typebot.id)
|
const { error } = await deleteTypebotQuery(typebot.id)
|
||||||
if (error)
|
if (error)
|
||||||
return showToast({
|
return showToast({
|
||||||
title: "Couldn't delete typebot",
|
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
onTypebotUpdated()
|
onTypebotUpdated()
|
||||||
@ -78,14 +82,13 @@ export const TypebotButton = ({
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const { data } = await getTypebotQuery(typebot.id)
|
const { data } = await getTypebotQuery(typebot.id)
|
||||||
const typebotToDuplicate = data?.typebot
|
const typebotToDuplicate = data?.typebot
|
||||||
if (!typebotToDuplicate) return { error: new Error('Typebot not found') }
|
if (!typebotToDuplicate) return
|
||||||
const { data: createdTypebot, error } = await importTypebotQuery(
|
const { data: createdTypebot, error } = await importTypebotQuery(
|
||||||
data.typebot,
|
data.typebot,
|
||||||
workspace?.plan ?? Plan.FREE
|
workspace?.plan ?? Plan.FREE
|
||||||
)
|
)
|
||||||
if (error)
|
if (error)
|
||||||
return showToast({
|
return showToast({
|
||||||
title: "Couldn't duplicate typebot",
|
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
if (createdTypebot) router.push(`/typebots/${createdTypebot?.id}/edit`)
|
if (createdTypebot) router.push(`/typebots/${createdTypebot?.id}/edit`)
|
||||||
@ -153,14 +156,18 @@ export const TypebotButton = ({
|
|||||||
pos="absolute"
|
pos="absolute"
|
||||||
top="20px"
|
top="20px"
|
||||||
right="20px"
|
right="20px"
|
||||||
aria-label={`Show ${typebot.name} menu`}
|
aria-label={scopedT('showMoreOptions')}
|
||||||
>
|
>
|
||||||
{typebot.publishedTypebotId && (
|
{typebot.publishedTypebotId && (
|
||||||
<MenuItem onClick={handleUnpublishClick}>Unpublish</MenuItem>
|
<MenuItem onClick={handleUnpublishClick}>
|
||||||
|
{scopedT('unpublish')}
|
||||||
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MenuItem onClick={handleDuplicateClick}>Duplicate</MenuItem>
|
<MenuItem onClick={handleDuplicateClick}>
|
||||||
|
{scopedT('duplicate')}
|
||||||
|
</MenuItem>
|
||||||
<MenuItem color="red.400" onClick={handleDeleteClick}>
|
<MenuItem color="red.400" onClick={handleDeleteClick}>
|
||||||
Delete
|
{scopedT('delete')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MoreButton>
|
</MoreButton>
|
||||||
</>
|
</>
|
||||||
@ -181,12 +188,17 @@ export const TypebotButton = ({
|
|||||||
{!isReadOnly && (
|
{!isReadOnly && (
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
message={
|
message={
|
||||||
<Text>
|
<Stack spacing="4">
|
||||||
Are you sure you want to delete your Typebot "{typebot.name}
|
<Text>
|
||||||
".
|
{scopedT('deleteConfirmationMessage', {
|
||||||
<br />
|
typebotName: <strong>{typebot.name}</strong>,
|
||||||
All associated data will be lost.
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
|
<Alert status="warning">
|
||||||
|
<AlertIcon />
|
||||||
|
{scopedT('deleteConfirmationMessageWarning')}
|
||||||
|
</Alert>
|
||||||
|
</Stack>
|
||||||
}
|
}
|
||||||
confirmButtonLabel="Delete"
|
confirmButtonLabel="Delete"
|
||||||
onConfirm={handleDeleteTypebotClick}
|
onConfirm={handleDeleteTypebotClick}
|
||||||
|
@ -169,6 +169,11 @@ const Alert = createMultiStyleConfigHelpers(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
baseStyle: {
|
||||||
|
container: {
|
||||||
|
borderRadius: 'md',
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const Switch = createMultiStyleConfigHelpers(
|
const Switch = createMultiStyleConfigHelpers(
|
||||||
|
22
apps/builder/src/locales/en.ts
Normal file
22
apps/builder/src/locales/en.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
export default {
|
||||||
|
back: 'Back',
|
||||||
|
'confirmModal.defaultTitle': 'Are you sure?',
|
||||||
|
'dashboard.header.settingsButton.label': 'Settings & Members',
|
||||||
|
'dashboard.redirectionMessage': 'You are being redirected...',
|
||||||
|
'dashboard.title': 'My typebots',
|
||||||
|
delete: 'Delete',
|
||||||
|
errorMessage: 'An error occured',
|
||||||
|
'folders.createFolderButton.label': 'Create a folder',
|
||||||
|
'folders.createTypebotButton.label': 'Create a typebot',
|
||||||
|
'folders.folderButton.deleteConfirmationMessage':
|
||||||
|
'Are you sure you want to delete {folderName} folder? (Everything inside will be move to your dashboard)',
|
||||||
|
'folders.typebotButton.live': 'Live',
|
||||||
|
'folders.typebotButton.showMoreOptions': 'Show more options',
|
||||||
|
'folders.typebotButton.unpublish': 'Unpublish',
|
||||||
|
'folders.typebotButton.duplicate': 'Duplicate',
|
||||||
|
'folders.typebotButton.delete': 'Delete',
|
||||||
|
'folders.typebotButton.deleteConfirmationMessage':
|
||||||
|
'Are you sure you want to delete your typebot {typebotName}?',
|
||||||
|
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||||
|
"All its associated data will be deleted and won't be recoverable.",
|
||||||
|
} as const
|
24
apps/builder/src/locales/fr.ts
Normal file
24
apps/builder/src/locales/fr.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { defineLocale } from './index'
|
||||||
|
|
||||||
|
export default defineLocale({
|
||||||
|
back: 'Retour',
|
||||||
|
'confirmModal.defaultTitle': 'Êtes-vous sûr ?',
|
||||||
|
'dashboard.header.settingsButton.label': 'Paramètres & Membres',
|
||||||
|
'dashboard.redirectionMessage': "Vous êtes en train d'être redirigé...",
|
||||||
|
'dashboard.title': 'Mes typebots',
|
||||||
|
delete: 'Supprimer',
|
||||||
|
errorMessage: "Une erreur s'est produite",
|
||||||
|
'folders.createFolderButton.label': 'Créer un dossier',
|
||||||
|
'folders.createTypebotButton.label': 'Créer un typebot',
|
||||||
|
'folders.folderButton.deleteConfirmationMessage':
|
||||||
|
"Êtes-vous sûr de vouloir supprimer le dossier {folderName} ? (Tout ce qui est à l'intérieur sera déplacé dans le dossier parent ou sur votre tableau de bord)",
|
||||||
|
'folders.typebotButton.live': 'Live',
|
||||||
|
'folders.typebotButton.showMoreOptions': "Afficher plus d'options",
|
||||||
|
'folders.typebotButton.unpublish': 'Dépublier',
|
||||||
|
'folders.typebotButton.duplicate': 'Dupliquer',
|
||||||
|
'folders.typebotButton.delete': 'Supprimer',
|
||||||
|
'folders.typebotButton.deleteConfirmationMessage':
|
||||||
|
'Êtes-vous sûr de vouloir supprimer votre typebot {typebotName} ?',
|
||||||
|
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||||
|
'Toutes les données associées seront supprimées et ne pourront pas être récupérées.',
|
||||||
|
})
|
14
apps/builder/src/locales/index.ts
Normal file
14
apps/builder/src/locales/index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { createI18n } from '@typebot.io/next-international'
|
||||||
|
import type Locale from './en'
|
||||||
|
|
||||||
|
export const {
|
||||||
|
defineLocale,
|
||||||
|
useI18n,
|
||||||
|
useScopedI18n,
|
||||||
|
I18nProvider,
|
||||||
|
getLocaleProps,
|
||||||
|
} = createI18n<typeof Locale>({
|
||||||
|
en: () => import('./en'),
|
||||||
|
fr: () => import('./fr'),
|
||||||
|
pt: () => import('./pt'),
|
||||||
|
})
|
24
apps/builder/src/locales/pt.ts
Normal file
24
apps/builder/src/locales/pt.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { defineLocale } from './index'
|
||||||
|
|
||||||
|
export default defineLocale({
|
||||||
|
back: 'Voltar',
|
||||||
|
'confirmModal.defaultTitle': 'Tem certeza?',
|
||||||
|
'dashboard.header.settingsButton.label': 'Configurações & Membros',
|
||||||
|
'dashboard.redirectionMessage': 'Você está sendo redirecionado...',
|
||||||
|
'dashboard.title': 'Meus typebots',
|
||||||
|
delete: 'Deletar',
|
||||||
|
errorMessage: 'Ocorreu um erro',
|
||||||
|
'folders.createFolderButton.label': 'Criar uma pasta',
|
||||||
|
'folders.createTypebotButton.label': 'Criar um typebot',
|
||||||
|
'folders.folderButton.deleteConfirmationMessage':
|
||||||
|
'Tem certeza de que deseja excluir a pasta {folderName}? (Tudo o que estiver dentro será movido para o seu painel)',
|
||||||
|
'folders.typebotButton.live': 'Live',
|
||||||
|
'folders.typebotButton.showMoreOptions': 'Mostrar mais opções',
|
||||||
|
'folders.typebotButton.unpublish': 'Despublicar',
|
||||||
|
'folders.typebotButton.duplicate': 'Duplicar',
|
||||||
|
'folders.typebotButton.delete': 'Deletar',
|
||||||
|
'folders.typebotButton.deleteConfirmationMessage':
|
||||||
|
'Tem certeza de que deseja excluir seu typebot {typebotName}?',
|
||||||
|
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||||
|
'Todos os dados associados serão excluídos e não poderão ser recuperados.',
|
||||||
|
})
|
@ -14,17 +14,14 @@ import { useRouter } from 'next/router'
|
|||||||
import { SupportBubble } from '@/components/SupportBubble'
|
import { SupportBubble } from '@/components/SupportBubble'
|
||||||
import { WorkspaceProvider } from '@/features/workspace'
|
import { WorkspaceProvider } from '@/features/workspace'
|
||||||
import { toTitleCase } from 'utils'
|
import { toTitleCase } from 'utils'
|
||||||
import { Session } from 'next-auth'
|
|
||||||
import { Plan } from 'db'
|
import { Plan } from 'db'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import { NewVersionPopup } from '@/components/NewVersionPopup'
|
import { NewVersionPopup } from '@/components/NewVersionPopup'
|
||||||
|
import { I18nProvider } from '@/locales'
|
||||||
|
|
||||||
const { ToastContainer, toast } = createStandaloneToast(customTheme)
|
const { ToastContainer, toast } = createStandaloneToast(customTheme)
|
||||||
|
|
||||||
const App = ({
|
const App = ({ Component, pageProps }: AppProps) => {
|
||||||
Component,
|
|
||||||
pageProps: { session, ...pageProps },
|
|
||||||
}: AppProps<{ session?: Session }>) => {
|
|
||||||
useRouterProgressBar()
|
useRouterProgressBar()
|
||||||
const { query, pathname } = useRouter()
|
const { query, pathname } = useRouter()
|
||||||
|
|
||||||
@ -50,19 +47,21 @@ const App = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
<ChakraProvider theme={customTheme}>
|
<I18nProvider locale={pageProps.locale}>
|
||||||
<SessionProvider session={session}>
|
<ChakraProvider theme={customTheme}>
|
||||||
<UserProvider>
|
<SessionProvider session={pageProps.session}>
|
||||||
<TypebotProvider typebotId={typebotId}>
|
<UserProvider>
|
||||||
<WorkspaceProvider typebotId={typebotId}>
|
<TypebotProvider typebotId={typebotId}>
|
||||||
<Component {...pageProps} />
|
<WorkspaceProvider typebotId={typebotId}>
|
||||||
<SupportBubble />
|
<Component {...pageProps} />
|
||||||
<NewVersionPopup />
|
<SupportBubble />
|
||||||
</WorkspaceProvider>
|
<NewVersionPopup />
|
||||||
</TypebotProvider>
|
</WorkspaceProvider>
|
||||||
</UserProvider>
|
</TypebotProvider>
|
||||||
</SessionProvider>
|
</UserProvider>
|
||||||
</ChakraProvider>
|
</SessionProvider>
|
||||||
|
</ChakraProvider>
|
||||||
|
</I18nProvider>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { getLocaleProps } from '@/locales'
|
||||||
import { GetServerSidePropsContext } from 'next'
|
import { GetServerSidePropsContext } from 'next'
|
||||||
import { getSession } from 'next-auth/react'
|
import { getSession } from 'next-auth/react'
|
||||||
|
|
||||||
@ -5,12 +6,28 @@ export default function Page() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getServerSideProps = async (
|
export const getServerSideProps = getLocaleProps(
|
||||||
context: GetServerSidePropsContext
|
async (context: GetServerSidePropsContext) => {
|
||||||
) => {
|
const session = await getSession(context)
|
||||||
const session = await getSession(context)
|
if (!session?.user) {
|
||||||
if (!session?.user) {
|
return {
|
||||||
return { redirect: { permanent: false, destination: '/signin' } }
|
redirect: {
|
||||||
|
permanent: false,
|
||||||
|
destination:
|
||||||
|
context.locale !== context.defaultLocale
|
||||||
|
? `/${context.locale}/signin`
|
||||||
|
: '/signin',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
permanent: false,
|
||||||
|
destination:
|
||||||
|
context.locale !== context.defaultLocale
|
||||||
|
? `/${context.locale}/typebots`
|
||||||
|
: '/typebots',
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return { redirect: { permanent: false, destination: '/typebots' } }
|
)
|
||||||
}
|
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
import { NextPageContext } from 'next/types'
|
|
||||||
import { DashboardPage } from '@/features/dashboard'
|
import { DashboardPage } from '@/features/dashboard'
|
||||||
|
import { getLocaleProps } from '@/locales'
|
||||||
|
import { GetServerSidePropsContext } from 'next'
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return <DashboardPage />
|
return <DashboardPage />
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getServerSideProps(context: NextPageContext) {
|
export const getServerSideProps = getLocaleProps(
|
||||||
const redirectPath = context.query.redirectPath?.toString()
|
async (context: GetServerSidePropsContext) => {
|
||||||
return redirectPath
|
const redirectPath = context.query.redirectPath?.toString()
|
||||||
? {
|
return redirectPath
|
||||||
redirect: {
|
? {
|
||||||
permanent: false,
|
redirect: {
|
||||||
destination: redirectPath,
|
permanent: false,
|
||||||
},
|
destination: redirectPath,
|
||||||
}
|
},
|
||||||
: { props: {} }
|
}
|
||||||
}
|
: { props: {} }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
17
pnpm-lock.yaml
generated
17
pnpm-lock.yaml
generated
@ -44,6 +44,7 @@ importers:
|
|||||||
'@trpc/react-query': 10.12.0
|
'@trpc/react-query': 10.12.0
|
||||||
'@trpc/server': 10.12.0
|
'@trpc/server': 10.12.0
|
||||||
'@typebot.io/js': workspace:*
|
'@typebot.io/js': workspace:*
|
||||||
|
'@typebot.io/next-international': ^0.3.8
|
||||||
'@typebot.io/react': workspace:*
|
'@typebot.io/react': workspace:*
|
||||||
'@types/canvas-confetti': 1.6.0
|
'@types/canvas-confetti': 1.6.0
|
||||||
'@types/google-spreadsheet': 3.3.1
|
'@types/google-spreadsheet': 3.3.1
|
||||||
@ -148,6 +149,7 @@ importers:
|
|||||||
'@trpc/react-query': 10.12.0_tij422wpfxfl3iixjhzsgwgs2e
|
'@trpc/react-query': 10.12.0_tij422wpfxfl3iixjhzsgwgs2e
|
||||||
'@trpc/server': 10.12.0
|
'@trpc/server': 10.12.0
|
||||||
'@typebot.io/js': link:../../packages/js
|
'@typebot.io/js': link:../../packages/js
|
||||||
|
'@typebot.io/next-international': 0.3.8_next@13.1.6+react@18.2.0
|
||||||
'@typebot.io/react': link:../../packages/react
|
'@typebot.io/react': link:../../packages/react
|
||||||
'@udecode/plate-basic-marks': 19.2.0_opnyntabsv5vdkt3p6hmagoxbq
|
'@udecode/plate-basic-marks': 19.2.0_opnyntabsv5vdkt3p6hmagoxbq
|
||||||
'@udecode/plate-common': 7.0.2_rjhyybmi5zd2n2kz5mt3q7icvy
|
'@udecode/plate-common': 7.0.2_rjhyybmi5zd2n2kz5mt3q7icvy
|
||||||
@ -6669,6 +6671,17 @@ packages:
|
|||||||
- webpack-cli
|
- webpack-cli
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@typebot.io/next-international/0.3.8_next@13.1.6+react@18.2.0:
|
||||||
|
resolution: {integrity: sha512-X5Q/r7iNhCBlWGeQho2PESDFjYk5NUW72dUEI/ghG6kE1jactXJRC0yuPRef/eILwlbwF5k+YXSo5ueiJZ4H1Q==}
|
||||||
|
peerDependencies:
|
||||||
|
next: ^12.0.0 || ^11.0.0
|
||||||
|
react: ^18.0.0 || ^17.0.0
|
||||||
|
dependencies:
|
||||||
|
international-types: 0.3.8
|
||||||
|
next: 13.1.6_6m24vuloj5ihw4zc5lbsktc4fu
|
||||||
|
react: 18.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/aos/3.0.4:
|
/@types/aos/3.0.4:
|
||||||
resolution: {integrity: sha512-mna6Jd6bdK1NpwarLopGvXOgUoCfj0470IwLxuVOFDElTGI0JTd7xSGQ0AjbAEnHErC/b3fA9t2uB3IXVKmckA==}
|
resolution: {integrity: sha512-mna6Jd6bdK1NpwarLopGvXOgUoCfj0470IwLxuVOFDElTGI0JTd7xSGQ0AjbAEnHErC/b3fA9t2uB3IXVKmckA==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -13026,6 +13039,10 @@ packages:
|
|||||||
has: 1.0.3
|
has: 1.0.3
|
||||||
side-channel: 1.0.4
|
side-channel: 1.0.4
|
||||||
|
|
||||||
|
/international-types/0.3.8:
|
||||||
|
resolution: {integrity: sha512-DeAFYOSA2wuUiSkFnAqrIM1UNVSAa8aP6hbXQOK4n74VuP/bCZPlZ7SEnCZ6+JBID/ekH1Ir5xTwsKA2Q++mKw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/interpret/1.4.0:
|
/interpret/1.4.0:
|
||||||
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
|
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
Reference in New Issue
Block a user