refactor: ♻️ Toast component
This commit is contained in:
@@ -4,7 +4,6 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Stack,
|
Stack,
|
||||||
HStack,
|
HStack,
|
||||||
useToast,
|
|
||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React, { ChangeEvent, FormEvent, useEffect } from 'react'
|
import React, { ChangeEvent, FormEvent, useEffect } from 'react'
|
||||||
@@ -21,6 +20,7 @@ import { SocialLoginButtons } from './SocialLoginButtons'
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||||
import { BuiltInProviderType } from 'next-auth/providers'
|
import { BuiltInProviderType } from 'next-auth/providers'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
defaultEmail?: string
|
defaultEmail?: string
|
||||||
@@ -34,9 +34,7 @@ export const SignInForm = ({
|
|||||||
const [isLoadingProviders, setIsLoadingProviders] = useState(true)
|
const [isLoadingProviders, setIsLoadingProviders] = useState(true)
|
||||||
|
|
||||||
const [emailValue, setEmailValue] = useState(defaultEmail ?? '')
|
const [emailValue, setEmailValue] = useState(defaultEmail ?? '')
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
})
|
|
||||||
const [providers, setProviders] =
|
const [providers, setProviders] =
|
||||||
useState<
|
useState<
|
||||||
Record<LiteralUnion<BuiltInProviderType, string>, ClientSafeProvider>
|
Record<LiteralUnion<BuiltInProviderType, string>, ClientSafeProvider>
|
||||||
@@ -65,7 +63,7 @@ export const SignInForm = ({
|
|||||||
email: emailValue,
|
email: emailValue,
|
||||||
redirect: false,
|
redirect: false,
|
||||||
})
|
})
|
||||||
toast({
|
showToast({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
title: 'Success!',
|
title: 'Success!',
|
||||||
description: 'Check your inbox to sign in',
|
description: 'Check your inbox to sign in',
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
useToast,
|
|
||||||
Wrap,
|
Wrap,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { useTypebotDnd } from 'contexts/TypebotDndContext'
|
import { useTypebotDnd } from 'contexts/TypebotDndContext'
|
||||||
@@ -27,6 +26,7 @@ import { TypebotButton } from './FolderContent/TypebotButton'
|
|||||||
import { TypebotCardOverlay } from './FolderContent/TypebotButtonOverlay'
|
import { TypebotCardOverlay } from './FolderContent/TypebotButtonOverlay'
|
||||||
import { OnboardingModal } from './OnboardingModal'
|
import { OnboardingModal } from './OnboardingModal'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = { folder: DashboardFolder | null }
|
type Props = { folder: DashboardFolder | null }
|
||||||
|
|
||||||
@@ -51,10 +51,7 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
const [typebotDragCandidate, setTypebotDragCandidate] =
|
const [typebotDragCandidate, setTypebotDragCandidate] =
|
||||||
useState<TypebotInDashboard>()
|
useState<TypebotInDashboard>()
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
folders,
|
folders,
|
||||||
@@ -64,7 +61,7 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
workspaceId: workspace?.id,
|
workspaceId: workspace?.id,
|
||||||
parentId: folder?.id,
|
parentId: folder?.id,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast({ title: "Couldn't fetch folders", description: error.message })
|
showToast({ title: "Couldn't fetch folders", description: error.message })
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -76,7 +73,10 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
workspaceId: workspace?.id,
|
workspaceId: workspace?.id,
|
||||||
folderId: folder?.id,
|
folderId: folder?.id,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast({ title: "Couldn't fetch typebots", description: error.message })
|
showToast({
|
||||||
|
title: "Couldn't fetch typebots",
|
||||||
|
description: error.message,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
const { error } = await patchTypebot(typebotId, {
|
const { error } = await patchTypebot(typebotId, {
|
||||||
folderId: folderId === 'root' ? null : folderId,
|
folderId: folderId === 'root' ? null : folderId,
|
||||||
})
|
})
|
||||||
if (error) toast({ description: error.message })
|
if (error) showToast({ description: error.message })
|
||||||
mutateTypebots({ typebots: typebots.filter((t) => t.id !== typebotId) })
|
mutateTypebots({ typebots: typebots.filter((t) => t.id !== typebotId) })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,10 @@ export const FolderContent = ({ folder }: Props) => {
|
|||||||
})
|
})
|
||||||
setIsCreatingFolder(false)
|
setIsCreatingFolder(false)
|
||||||
if (error)
|
if (error)
|
||||||
return toast({ title: 'An error occured', description: error.message })
|
return showToast({
|
||||||
|
title: 'An error occured',
|
||||||
|
description: error.message,
|
||||||
|
})
|
||||||
if (newFolder) mutateFolders({ folders: [...folders, newFolder] })
|
if (newFolder) mutateFolders({ folders: [...folders, newFolder] })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
Menu,
|
Menu,
|
||||||
MenuButton,
|
MenuButton,
|
||||||
MenuList,
|
MenuList,
|
||||||
useToast,
|
|
||||||
SkeletonText,
|
SkeletonText,
|
||||||
SkeletonCircle,
|
SkeletonCircle,
|
||||||
WrapItem,
|
WrapItem,
|
||||||
@@ -23,6 +22,7 @@ import { useTypebotDnd } from 'contexts/TypebotDndContext'
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import { deleteFolder, updateFolder } from 'services/folders'
|
import { deleteFolder, updateFolder } from 'services/folders'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
export const FolderButton = ({
|
export const FolderButton = ({
|
||||||
folder,
|
folder,
|
||||||
@@ -41,15 +41,12 @@ export const FolderButton = ({
|
|||||||
[draggedTypebot, folder.id, mouseOverFolderId]
|
[draggedTypebot, folder.id, mouseOverFolderId]
|
||||||
)
|
)
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const onDeleteClick = async () => {
|
const onDeleteClick = async () => {
|
||||||
const { error } = await deleteFolder(folder.id)
|
const { error } = await deleteFolder(folder.id)
|
||||||
return error
|
return error
|
||||||
? toast({
|
? showToast({
|
||||||
title: "Couldn't delete the folder",
|
title: "Couldn't delete the folder",
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
@@ -60,7 +57,7 @@ export const FolderButton = ({
|
|||||||
if (newName === '' || newName === folder.name) return
|
if (newName === '' || newName === folder.name) return
|
||||||
const { error } = await updateFolder(folder.id, { name: newName })
|
const { error } = await updateFolder(folder.id, { name: newName })
|
||||||
return error
|
return error
|
||||||
? toast({ title: 'An error occured', description: error.message })
|
? showToast({ title: 'An error occured', description: error.message })
|
||||||
: onFolderRenamed(newName)
|
: onFolderRenamed(newName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
Tag,
|
Tag,
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useToast,
|
|
||||||
VStack,
|
VStack,
|
||||||
WrapItem,
|
WrapItem,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
@@ -23,6 +22,7 @@ import { useDebounce } from 'use-debounce'
|
|||||||
import { EmojiOrImageIcon } from 'components/shared/EmojiOrImageIcon'
|
import { EmojiOrImageIcon } from 'components/shared/EmojiOrImageIcon'
|
||||||
import { Plan } from 'db'
|
import { Plan } from 'db'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type ChatbotCardProps = {
|
type ChatbotCardProps = {
|
||||||
typebot: Pick<Typebot, 'id' | 'publishedTypebotId' | 'name' | 'icon'>
|
typebot: Pick<Typebot, 'id' | 'publishedTypebotId' | 'name' | 'icon'>
|
||||||
@@ -47,10 +47,7 @@ export const TypebotButton = ({
|
|||||||
onClose: onDeleteClose,
|
onClose: onDeleteClose,
|
||||||
} = useDisclosure()
|
} = useDisclosure()
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleTypebotClick = () => {
|
const handleTypebotClick = () => {
|
||||||
if (draggedTypebotDebounced) return
|
if (draggedTypebotDebounced) return
|
||||||
@@ -65,7 +62,7 @@ export const TypebotButton = ({
|
|||||||
if (isReadOnly) return
|
if (isReadOnly) return
|
||||||
const { error } = await deleteTypebot(typebot.id)
|
const { error } = await deleteTypebot(typebot.id)
|
||||||
if (error)
|
if (error)
|
||||||
return toast({
|
return showToast({
|
||||||
title: "Couldn't delete typebot",
|
title: "Couldn't delete typebot",
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
@@ -82,7 +79,7 @@ export const TypebotButton = ({
|
|||||||
workspace?.plan ?? Plan.FREE
|
workspace?.plan ?? Plan.FREE
|
||||||
)
|
)
|
||||||
if (error)
|
if (error)
|
||||||
return toast({
|
return showToast({
|
||||||
title: "Couldn't duplicate typebot",
|
title: "Couldn't duplicate typebot",
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
ModalContent,
|
ModalContent,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { TypebotViewer } from 'bot-engine'
|
import { TypebotViewer } from 'bot-engine'
|
||||||
import { useUser } from 'contexts/UserContext'
|
import { useUser } from 'contexts/UserContext'
|
||||||
@@ -14,6 +13,7 @@ import React, { useEffect, useRef, useState } from 'react'
|
|||||||
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
|
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
|
||||||
import { sendRequest } from 'utils'
|
import { sendRequest } from 'utils'
|
||||||
import confetti from 'canvas-confetti'
|
import confetti from 'canvas-confetti'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = { totalTypebots: number }
|
type Props = { totalTypebots: number }
|
||||||
|
|
||||||
@@ -26,10 +26,7 @@ export const OnboardingModal = ({ totalTypebots }: Props) => {
|
|||||||
const [chosenCategories, setChosenCategories] = useState<string[]>([])
|
const [chosenCategories, setChosenCategories] = useState<string[]>([])
|
||||||
const [openedOnce, setOpenedOnce] = useState(false)
|
const [openedOnce, setOpenedOnce] = useState(false)
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTemplate()
|
fetchTemplate()
|
||||||
@@ -77,7 +74,8 @@ export const OnboardingModal = ({ totalTypebots }: Props) => {
|
|||||||
|
|
||||||
const fetchTemplate = async () => {
|
const fetchTemplate = async () => {
|
||||||
const { data, error } = await sendRequest(`/bots/onboarding.json`)
|
const { data, error } = await sendRequest(`/bots/onboarding.json`)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
setTypebot(data as Typebot)
|
setTypebot(data as Typebot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import {
|
|||||||
Flex,
|
Flex,
|
||||||
FlexProps,
|
FlexProps,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
useToast,
|
|
||||||
UseToastOptions,
|
UseToastOptions,
|
||||||
VStack,
|
VStack,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { TypebotViewer } from 'bot-engine'
|
import { TypebotViewer } from 'bot-engine'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { headerHeight } from 'components/shared/TypebotHeader'
|
import { headerHeight } from 'components/shared/TypebotHeader'
|
||||||
import { useEditor } from 'contexts/EditorContext'
|
import { useEditor } from 'contexts/EditorContext'
|
||||||
import { useGraph } from 'contexts/GraphContext'
|
import { useGraph } from 'contexts/GraphContext'
|
||||||
@@ -33,9 +33,7 @@ export const PreviewDrawer = () => {
|
|||||||
[typebot]
|
[typebot]
|
||||||
)
|
)
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleMouseDown = () => {
|
const handleMouseDown = () => {
|
||||||
setIsResizing(true)
|
setIsResizing(true)
|
||||||
@@ -60,7 +58,7 @@ export const PreviewDrawer = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleNewLog = (log: Omit<Log, 'id' | 'createdAt' | 'resultId'>) =>
|
const handleNewLog = (log: Omit<Log, 'id' | 'createdAt' | 'resultId'>) =>
|
||||||
toast(log as UseToastOptions)
|
showToast(log as UseToastOptions)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
Stack,
|
Stack,
|
||||||
Tag,
|
Tag,
|
||||||
useToast,
|
|
||||||
Wrap,
|
Wrap,
|
||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { TrashIcon } from 'assets/icons'
|
import { TrashIcon } from 'assets/icons'
|
||||||
import { UpgradeButton } from 'components/shared/buttons/UpgradeButton'
|
import { UpgradeButton } from 'components/shared/buttons/UpgradeButton'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@@ -24,15 +24,12 @@ import { integrationsList } from './integrations/EmbedButton'
|
|||||||
export const ShareContent = () => {
|
export const ShareContent = () => {
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const { typebot, updateOnBothTypebots } = useTypebot()
|
const { typebot, updateOnBothTypebots } = useTypebot()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handlePublicIdChange = (publicId: string) => {
|
const handlePublicIdChange = (publicId: string) => {
|
||||||
if (publicId === typebot?.publicId) return
|
if (publicId === typebot?.publicId) return
|
||||||
if (publicId.length < 4)
|
if (publicId.length < 4)
|
||||||
return toast({ description: 'ID must be longer than 4 characters' })
|
return showToast({ description: 'ID must be longer than 4 characters' })
|
||||||
updateOnBothTypebots({ publicId })
|
updateOnBothTypebots({ publicId })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import {
|
|||||||
Alert,
|
Alert,
|
||||||
ModalFooter,
|
ModalFooter,
|
||||||
Button,
|
Button,
|
||||||
useToast,
|
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { createCustomDomain } from 'services/user'
|
import { createCustomDomain } from 'services/user'
|
||||||
import { isEmpty } from 'utils'
|
import { isEmpty } from 'utils'
|
||||||
@@ -46,11 +46,7 @@ export const CustomDomainModal = ({
|
|||||||
subdomain: splitHostname(domain)?.subdomain ?? '',
|
subdomain: splitHostname(domain)?.subdomain ?? '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
description: 'An error occured',
|
|
||||||
})
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inputValue === '' || !isOpen) return
|
if (inputValue === '' || !isOpen) return
|
||||||
@@ -72,7 +68,8 @@ export const CustomDomainModal = ({
|
|||||||
name: inputValue,
|
name: inputValue,
|
||||||
})
|
})
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
onNewDomain(inputValue)
|
onNewDomain(inputValue)
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { ChevronLeftIcon, PlusIcon, TrashIcon } from 'assets/icons'
|
import { ChevronLeftIcon, PlusIcon, TrashIcon } from 'assets/icons'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { CustomDomainModal } from './CustomDomainModal'
|
import { CustomDomainModal } from './CustomDomainModal'
|
||||||
import { deleteCustomDomain, useCustomDomains } from 'services/user'
|
import { deleteCustomDomain, useCustomDomains } from 'services/user'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = Omit<MenuButtonProps, 'type'> & {
|
type Props = Omit<MenuButtonProps, 'type'> & {
|
||||||
currentCustomDomain?: string
|
currentCustomDomain?: string
|
||||||
@@ -30,14 +30,11 @@ export const CustomDomainsDropdown = ({
|
|||||||
const [isDeleting, setIsDeleting] = useState('')
|
const [isDeleting, setIsDeleting] = useState('')
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const { customDomains, mutate } = useCustomDomains({
|
const { customDomains, mutate } = useCustomDomains({
|
||||||
workspaceId: workspace?.id,
|
workspaceId: workspace?.id,
|
||||||
onError: (error) =>
|
onError: (error) =>
|
||||||
toast({ title: error.name, description: error.message }),
|
showToast({ title: error.name, description: error.message }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleMenuItemClick = (customDomain: string) => () =>
|
const handleMenuItemClick = (customDomain: string) => () =>
|
||||||
@@ -50,7 +47,8 @@ export const CustomDomainsDropdown = ({
|
|||||||
setIsDeleting(domainName)
|
setIsDeleting(domainName)
|
||||||
const { error } = await deleteCustomDomain(workspace.id, domainName)
|
const { error } = await deleteCustomDomain(workspace.id, domainName)
|
||||||
setIsDeleting('')
|
setIsDeleting('')
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutate({
|
mutate({
|
||||||
customDomains: (customDomains ?? []).filter(
|
customDomains: (customDomains ?? []).filter(
|
||||||
(cd) => cd.name !== domainName
|
(cd) => cd.name !== domainName
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
MenuList,
|
MenuList,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { ChevronLeftIcon, PlusIcon, TrashIcon } from 'assets/icons'
|
import { ChevronLeftIcon, PlusIcon, TrashIcon } from 'assets/icons'
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
import React, { useEffect, useMemo, useState } from 'react'
|
||||||
@@ -16,6 +15,7 @@ import { useRouter } from 'next/router'
|
|||||||
import { CredentialsType } from 'models'
|
import { CredentialsType } from 'models'
|
||||||
import { deleteCredentials, useCredentials } from 'services/user'
|
import { deleteCredentials, useCredentials } from 'services/user'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
|
import { useToast } from './hooks/useToast'
|
||||||
|
|
||||||
type Props = Omit<MenuButtonProps, 'type'> & {
|
type Props = Omit<MenuButtonProps, 'type'> & {
|
||||||
type: CredentialsType
|
type: CredentialsType
|
||||||
@@ -37,10 +37,7 @@ export const CredentialsDropdown = ({
|
|||||||
}: Props) => {
|
}: Props) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const { credentials, mutate } = useCredentials({
|
const { credentials, mutate } = useCredentials({
|
||||||
workspaceId: workspace?.id,
|
workspaceId: workspace?.id,
|
||||||
})
|
})
|
||||||
@@ -88,7 +85,8 @@ export const CredentialsDropdown = ({
|
|||||||
setIsDeleting(credentialsId)
|
setIsDeleting(credentialsId)
|
||||||
const { error } = await deleteCredentials(workspace.id, credentialsId)
|
const { error } = await deleteCredentials(workspace.id, credentialsId)
|
||||||
setIsDeleting(undefined)
|
setIsDeleting(undefined)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
onCredentialsSelect(undefined)
|
onCredentialsSelect(undefined)
|
||||||
mutate({ credentials: credentials.filter((c) => c.id !== credentialsId) })
|
mutate({ credentials: credentials.filter((c) => c.id !== credentialsId) })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
ModalBody,
|
ModalBody,
|
||||||
ModalFooter,
|
ModalFooter,
|
||||||
Button,
|
Button,
|
||||||
useToast,
|
|
||||||
FormControl,
|
FormControl,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -24,6 +23,7 @@ import { MoreInfoTooltip } from 'components/shared/MoreInfoTooltip'
|
|||||||
import { ExternalLinkIcon } from 'assets/icons'
|
import { ExternalLinkIcon } from 'assets/icons'
|
||||||
import { createCredentials } from 'services/credentials'
|
import { createCredentials } from 'services/credentials'
|
||||||
import { omit } from 'utils'
|
import { omit } from 'utils'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
@@ -39,10 +39,7 @@ export const StripeConfigModal = ({
|
|||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const [isCreating, setIsCreating] = useState(false)
|
const [isCreating, setIsCreating] = useState(false)
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const [stripeConfig, setStripeConfig] = useState<
|
const [stripeConfig, setStripeConfig] = useState<
|
||||||
StripeCredentialsData & { name: string }
|
StripeCredentialsData & { name: string }
|
||||||
>({
|
>({
|
||||||
@@ -91,9 +88,10 @@ export const StripeConfigModal = ({
|
|||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
})
|
})
|
||||||
setIsCreating(false)
|
setIsCreating(false)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
if (!data?.credentials)
|
if (!data?.credentials)
|
||||||
return toast({ description: "Credentials wasn't created" })
|
return showToast({ description: "Credentials wasn't created" })
|
||||||
onNewCredentials(data.credentials.id)
|
onNewCredentials(data.credentials.id)
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
ModalBody,
|
ModalBody,
|
||||||
ModalFooter,
|
ModalFooter,
|
||||||
Button,
|
Button,
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { useUser } from 'contexts/UserContext'
|
import { useUser } from 'contexts/UserContext'
|
||||||
import { CredentialsType, SmtpCredentialsData } from 'models'
|
import { CredentialsType, SmtpCredentialsData } from 'models'
|
||||||
@@ -17,6 +16,7 @@ import { testSmtpConfig } from 'services/integrations'
|
|||||||
import { isNotDefined } from 'utils'
|
import { isNotDefined } from 'utils'
|
||||||
import { SmtpConfigForm } from './SmtpConfigForm'
|
import { SmtpConfigForm } from './SmtpConfigForm'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
@@ -32,10 +32,7 @@ export const SmtpConfigModal = ({
|
|||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const [isCreating, setIsCreating] = useState(false)
|
const [isCreating, setIsCreating] = useState(false)
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const [smtpConfig, setSmtpConfig] = useState<SmtpCredentialsData>({
|
const [smtpConfig, setSmtpConfig] = useState<SmtpCredentialsData>({
|
||||||
from: {},
|
from: {},
|
||||||
port: 25,
|
port: 25,
|
||||||
@@ -50,7 +47,7 @@ export const SmtpConfigModal = ({
|
|||||||
)
|
)
|
||||||
if (testSmtpError) {
|
if (testSmtpError) {
|
||||||
setIsCreating(false)
|
setIsCreating(false)
|
||||||
return toast({
|
return showToast({
|
||||||
title: 'Invalid configuration',
|
title: 'Invalid configuration',
|
||||||
description: "We couldn't send the test email with your configuration",
|
description: "We couldn't send the test email with your configuration",
|
||||||
})
|
})
|
||||||
@@ -62,9 +59,10 @@ export const SmtpConfigModal = ({
|
|||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
})
|
})
|
||||||
setIsCreating(false)
|
setIsCreating(false)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
if (!data?.credentials)
|
if (!data?.credentials)
|
||||||
return toast({ description: "Credentials wasn't created" })
|
return showToast({ description: "Credentials wasn't created" })
|
||||||
onNewCredentials(data.credentials.id)
|
onNewCredentials(data.credentials.id)
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { HStack, IconButton, Input, useToast } from '@chakra-ui/react'
|
import { HStack, IconButton, Input } from '@chakra-ui/react'
|
||||||
import { ExternalLinkIcon } from 'assets/icons'
|
import { ExternalLinkIcon } from 'assets/icons'
|
||||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { SearchableDropdown } from 'components/shared/SearchableDropdown'
|
import { SearchableDropdown } from 'components/shared/SearchableDropdown'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
@@ -19,14 +20,11 @@ export const TypebotsDropdown = ({
|
|||||||
currentWorkspaceId,
|
currentWorkspaceId,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { query } = useRouter()
|
const { query } = useRouter()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const { typebots, isLoading } = useTypebots({
|
const { typebots, isLoading } = useTypebots({
|
||||||
workspaceId: currentWorkspaceId,
|
workspaceId: currentWorkspaceId,
|
||||||
allFolders: true,
|
allFolders: true,
|
||||||
onError: (e) => toast({ title: e.name, description: e.message }),
|
onError: (e) => showToast({ title: e.name, description: e.message }),
|
||||||
})
|
})
|
||||||
const currentTypebot = useMemo(
|
const currentTypebot = useMemo(
|
||||||
() => typebots?.find(byId(typebotId)),
|
() => typebots?.find(byId(typebotId)),
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
HStack,
|
HStack,
|
||||||
Spinner,
|
Spinner,
|
||||||
Stack,
|
Stack,
|
||||||
useToast,
|
|
||||||
Text,
|
Text,
|
||||||
Alert,
|
Alert,
|
||||||
AlertIcon,
|
AlertIcon,
|
||||||
@@ -43,6 +42,7 @@ import { DataVariableInputs } from './ResponseMappingInputs'
|
|||||||
import { byId } from 'utils'
|
import { byId } from 'utils'
|
||||||
import { SwitchWithLabel } from 'components/shared/SwitchWithLabel'
|
import { SwitchWithLabel } from 'components/shared/SwitchWithLabel'
|
||||||
import { ExternalLinkIcon } from 'assets/icons'
|
import { ExternalLinkIcon } from 'assets/icons'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Provider = {
|
type Provider = {
|
||||||
name: 'Make.com' | 'Pabbly Connect'
|
name: 'Make.com' | 'Pabbly Connect'
|
||||||
@@ -64,10 +64,7 @@ export const WebhookSettings = ({
|
|||||||
const [testResponse, setTestResponse] = useState<string>()
|
const [testResponse, setTestResponse] = useState<string>()
|
||||||
const [responseKeys, setResponseKeys] = useState<string[]>([])
|
const [responseKeys, setResponseKeys] = useState<string[]>([])
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const [localWebhook, setLocalWebhook] = useState(
|
const [localWebhook, setLocalWebhook] = useState(
|
||||||
webhooks.find(byId(webhookId))
|
webhooks.find(byId(webhookId))
|
||||||
)
|
)
|
||||||
@@ -140,7 +137,8 @@ export const WebhookSettings = ({
|
|||||||
),
|
),
|
||||||
{ blockId, stepId }
|
{ blockId, stepId }
|
||||||
)
|
)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
setTestResponse(JSON.stringify(data, undefined, 2))
|
setTestResponse(JSON.stringify(data, undefined, 2))
|
||||||
setResponseKeys(getDeepKeys(data))
|
setResponseKeys(getDeepKeys(data))
|
||||||
setIsTestResponseLoading(false)
|
setIsTestResponseLoading(false)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
HStack,
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
Button,
|
Button,
|
||||||
useToast,
|
|
||||||
Menu,
|
Menu,
|
||||||
MenuButton,
|
MenuButton,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
@@ -16,6 +15,7 @@ import {
|
|||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { ChevronLeftIcon } from 'assets/icons'
|
import { ChevronLeftIcon } from 'assets/icons'
|
||||||
import { EmojiOrImageIcon } from 'components/shared/EmojiOrImageIcon'
|
import { EmojiOrImageIcon } from 'components/shared/EmojiOrImageIcon'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { useTypebot } from 'contexts/TypebotContext'
|
import { useTypebot } from 'contexts/TypebotContext'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
import { CollaborationType, WorkspaceRole } from 'db'
|
import { CollaborationType, WorkspaceRole } from 'db'
|
||||||
@@ -45,10 +45,7 @@ export const CollaborationList = () => {
|
|||||||
const hasFullAccess =
|
const hasFullAccess =
|
||||||
(currentRole && currentRole !== WorkspaceRole.GUEST) || false
|
(currentRole && currentRole !== WorkspaceRole.GUEST) || false
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const {
|
const {
|
||||||
collaborators,
|
collaborators,
|
||||||
isLoading: isCollaboratorsLoading,
|
isLoading: isCollaboratorsLoading,
|
||||||
@@ -56,7 +53,7 @@ export const CollaborationList = () => {
|
|||||||
} = useCollaborators({
|
} = useCollaborators({
|
||||||
typebotId: typebot?.id,
|
typebotId: typebot?.id,
|
||||||
onError: (e) =>
|
onError: (e) =>
|
||||||
toast({
|
showToast({
|
||||||
title: "Couldn't fetch collaborators",
|
title: "Couldn't fetch collaborators",
|
||||||
description: e.message,
|
description: e.message,
|
||||||
}),
|
}),
|
||||||
@@ -68,7 +65,10 @@ export const CollaborationList = () => {
|
|||||||
} = useInvitations({
|
} = useInvitations({
|
||||||
typebotId: typebot?.id,
|
typebotId: typebot?.id,
|
||||||
onError: (e) =>
|
onError: (e) =>
|
||||||
toast({ title: "Couldn't fetch invitations", description: e.message }),
|
showToast({
|
||||||
|
title: "Couldn't fetch invitations",
|
||||||
|
description: e.message,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleChangeInvitationCollabType =
|
const handleChangeInvitationCollabType =
|
||||||
@@ -79,7 +79,8 @@ export const CollaborationList = () => {
|
|||||||
typebotId: typebot.id,
|
typebotId: typebot.id,
|
||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutateInvitations({
|
mutateInvitations({
|
||||||
invitations: (invitations ?? []).map((i) =>
|
invitations: (invitations ?? []).map((i) =>
|
||||||
i.email === email ? { ...i, type } : i
|
i.email === email ? { ...i, type } : i
|
||||||
@@ -89,7 +90,8 @@ export const CollaborationList = () => {
|
|||||||
const handleDeleteInvitation = (email: string) => async () => {
|
const handleDeleteInvitation = (email: string) => async () => {
|
||||||
if (!typebot || !hasFullAccess) return
|
if (!typebot || !hasFullAccess) return
|
||||||
const { error } = await deleteInvitation(typebot?.id, email)
|
const { error } = await deleteInvitation(typebot?.id, email)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutateInvitations({
|
mutateInvitations({
|
||||||
invitations: (invitations ?? []).filter((i) => i.email !== email),
|
invitations: (invitations ?? []).filter((i) => i.email !== email),
|
||||||
})
|
})
|
||||||
@@ -103,7 +105,8 @@ export const CollaborationList = () => {
|
|||||||
type,
|
type,
|
||||||
typebotId: typebot.id,
|
typebotId: typebot.id,
|
||||||
})
|
})
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutateCollaborators({
|
mutateCollaborators({
|
||||||
collaborators: (collaborators ?? []).map((c) =>
|
collaborators: (collaborators ?? []).map((c) =>
|
||||||
c.userId === userId ? { ...c, type } : c
|
c.userId === userId ? { ...c, type } : c
|
||||||
@@ -113,7 +116,8 @@ export const CollaborationList = () => {
|
|||||||
const handleDeleteCollaboration = (userId: string) => async () => {
|
const handleDeleteCollaboration = (userId: string) => async () => {
|
||||||
if (!typebot || !hasFullAccess) return
|
if (!typebot || !hasFullAccess) return
|
||||||
const { error } = await deleteCollaborator(typebot?.id, userId)
|
const { error } = await deleteCollaborator(typebot?.id, userId)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutateCollaborators({
|
mutateCollaborators({
|
||||||
collaborators: (collaborators ?? []).filter((c) => c.userId !== userId),
|
collaborators: (collaborators ?? []).filter((c) => c.userId !== userId),
|
||||||
})
|
})
|
||||||
@@ -130,8 +134,9 @@ export const CollaborationList = () => {
|
|||||||
setIsSendingInvitation(false)
|
setIsSendingInvitation(false)
|
||||||
mutateInvitations({ invitations: invitations ?? [] })
|
mutateInvitations({ invitations: invitations ?? [] })
|
||||||
mutateCollaborators({ collaborators: collaborators ?? [] })
|
mutateCollaborators({ collaborators: collaborators ?? [] })
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
toast({ status: 'success', title: 'Invitation sent! 📧' })
|
return showToast({ title: error.name, description: error.message })
|
||||||
|
showToast({ status: 'success', title: 'Invitation sent! 📧' })
|
||||||
setInvitationEmail('')
|
setInvitationEmail('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
apps/builder/components/shared/hooks/useToast.tsx
Normal file
20
apps/builder/components/shared/hooks/useToast.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { useToast as useChakraToast, UseToastOptions } from '@chakra-ui/toast'
|
||||||
|
|
||||||
|
export const useToast = () => {
|
||||||
|
const toast = useChakraToast()
|
||||||
|
|
||||||
|
const showToast = ({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
status = 'error',
|
||||||
|
}: UseToastOptions) => {
|
||||||
|
toast({
|
||||||
|
position: 'bottom-right',
|
||||||
|
description,
|
||||||
|
title,
|
||||||
|
status,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return { showToast }
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
ListProps,
|
ListProps,
|
||||||
Button,
|
Button,
|
||||||
HStack,
|
HStack,
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { pay } from 'services/stripe'
|
import { pay } from 'services/stripe'
|
||||||
import { useUser } from 'contexts/UserContext'
|
import { useUser } from 'contexts/UserContext'
|
||||||
@@ -25,6 +24,7 @@ import { useWorkspace } from 'contexts/WorkspaceContext'
|
|||||||
import { TypebotLogo } from 'assets/logos'
|
import { TypebotLogo } from 'assets/logos'
|
||||||
import { CheckIcon } from 'assets/icons'
|
import { CheckIcon } from 'assets/icons'
|
||||||
import { toTitleCase } from 'utils'
|
import { toTitleCase } from 'utils'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
export enum LimitReached {
|
export enum LimitReached {
|
||||||
BRAND = 'Remove branding',
|
BRAND = 'Remove branding',
|
||||||
@@ -48,7 +48,7 @@ export const UpgradeModal = ({
|
|||||||
const { workspace, refreshWorkspace } = useWorkspace()
|
const { workspace, refreshWorkspace } = useWorkspace()
|
||||||
const [payLoading, setPayLoading] = useState(false)
|
const [payLoading, setPayLoading] = useState(false)
|
||||||
const [currency, setCurrency] = useState<'usd' | 'eur'>('usd')
|
const [currency, setCurrency] = useState<'usd' | 'eur'>('usd')
|
||||||
const toast = useToast()
|
const { showToast } = useToast()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrency(
|
setCurrency(
|
||||||
@@ -69,7 +69,7 @@ export const UpgradeModal = ({
|
|||||||
setPayLoading(false)
|
setPayLoading(false)
|
||||||
if (response?.newPlan) {
|
if (response?.newPlan) {
|
||||||
refreshWorkspace({ plan: response.newPlan })
|
refreshWorkspace({ plan: response.newPlan })
|
||||||
toast({
|
showToast({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
title: 'Upgrade success!',
|
title: 'Upgrade success!',
|
||||||
description: `Workspace successfully upgraded to ${toTitleCase(
|
description: `Workspace successfully upgraded to ${toTitleCase(
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
import {
|
import { VStack, Heading, Stack, Button, useDisclosure } from '@chakra-ui/react'
|
||||||
VStack,
|
|
||||||
Heading,
|
|
||||||
Stack,
|
|
||||||
Button,
|
|
||||||
useDisclosure,
|
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
|
||||||
import { ToolIcon, TemplateIcon, DownloadIcon } from 'assets/icons'
|
import { ToolIcon, TemplateIcon, DownloadIcon } from 'assets/icons'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { useUser } from 'contexts/UserContext'
|
import { useUser } from 'contexts/UserContext'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
import { Typebot } from 'models'
|
import { Typebot } from 'models'
|
||||||
@@ -24,11 +18,7 @@ export const CreateNewTypebotButtons = () => {
|
|||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
title: 'An error occured',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleCreateSubmit = async (typebot?: Typebot) => {
|
const handleCreateSubmit = async (typebot?: Typebot) => {
|
||||||
if (!user || !workspace) return
|
if (!user || !workspace) return
|
||||||
@@ -54,7 +44,7 @@ export const CreateNewTypebotButtons = () => {
|
|||||||
folderId,
|
folderId,
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
})
|
})
|
||||||
if (error) toast({ description: error.message })
|
if (error) showToast({ description: error.message })
|
||||||
if (data)
|
if (data)
|
||||||
router.push({
|
router.push({
|
||||||
pathname: `/typebots/${data.id}/edit`,
|
pathname: `/typebots/${data.id}/edit`,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Button, ButtonProps, chakra, useToast } from '@chakra-ui/react'
|
import { Button, ButtonProps, chakra } from '@chakra-ui/react'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { Typebot } from 'models'
|
import { Typebot } from 'models'
|
||||||
import React, { ChangeEvent } from 'react'
|
import React, { ChangeEvent } from 'react'
|
||||||
import { readFile } from 'services/utils'
|
import { readFile } from 'services/utils'
|
||||||
@@ -11,10 +12,7 @@ export const ImportTypebotFromFileButton = ({
|
|||||||
onNewTypebot,
|
onNewTypebot,
|
||||||
...props
|
...props
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleInputChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
const handleInputChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
if (!e.target?.files) return
|
if (!e.target?.files) return
|
||||||
@@ -24,7 +22,7 @@ export const ImportTypebotFromFileButton = ({
|
|||||||
onNewTypebot(JSON.parse(fileContent))
|
onNewTypebot(JSON.parse(fileContent))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
toast({ description: 'Failed to parse the file' })
|
showToast({ description: 'Failed to parse the file' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import {
|
|||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
Stack,
|
Stack,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { ExternalLinkIcon } from 'assets/icons'
|
import { ExternalLinkIcon } from 'assets/icons'
|
||||||
import { TypebotViewer } from 'bot-engine'
|
import { TypebotViewer } from 'bot-engine'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { Typebot } from 'models'
|
import { Typebot } from 'models'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
|
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
|
||||||
@@ -33,10 +33,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
|||||||
)
|
)
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTemplate(templates[0])
|
fetchTemplate(templates[0])
|
||||||
@@ -46,7 +43,8 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
|||||||
const fetchTemplate = async (template: TemplateProps) => {
|
const fetchTemplate = async (template: TemplateProps) => {
|
||||||
setSelectedTemplate(template)
|
setSelectedTemplate(template)
|
||||||
const { data, error } = await sendRequest(`/templates/${template.fileName}`)
|
const { data, error } = await sendRequest(`/templates/${template.fileName}`)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
setTypebot(data as Typebot)
|
setTypebot(data as Typebot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useToast } from '@chakra-ui/react'
|
|
||||||
import {
|
import {
|
||||||
LogicStepType,
|
LogicStepType,
|
||||||
PublicTypebot,
|
PublicTypebot,
|
||||||
@@ -43,6 +42,7 @@ import { dequal } from 'dequal'
|
|||||||
import { saveWebhook } from 'services/webhook'
|
import { saveWebhook } from 'services/webhook'
|
||||||
import { stringify } from 'qs'
|
import { stringify } from 'qs'
|
||||||
import cuid from 'cuid'
|
import cuid from 'cuid'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
const autoSaveTimeout = 10000
|
const autoSaveTimeout = 10000
|
||||||
|
|
||||||
type UpdateTypebotPayload = Partial<{
|
type UpdateTypebotPayload = Partial<{
|
||||||
@@ -101,16 +101,13 @@ export const TypebotContext = ({
|
|||||||
typebotId: string
|
typebotId: string
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const { typebot, publishedTypebot, webhooks, isReadOnly, isLoading, mutate } =
|
const { typebot, publishedTypebot, webhooks, isReadOnly, isLoading, mutate } =
|
||||||
useFetchedTypebot({
|
useFetchedTypebot({
|
||||||
typebotId,
|
typebotId,
|
||||||
onError: (error) =>
|
onError: (error) =>
|
||||||
toast({
|
showToast({
|
||||||
title: 'Error while fetching typebot',
|
title: 'Error while fetching typebot',
|
||||||
description: error.message,
|
description: error.message,
|
||||||
}),
|
}),
|
||||||
@@ -145,7 +142,7 @@ export const TypebotContext = ({
|
|||||||
typebotId,
|
typebotId,
|
||||||
typebotIds: linkedTypebotIds,
|
typebotIds: linkedTypebotIds,
|
||||||
onError: (error) =>
|
onError: (error) =>
|
||||||
toast({
|
showToast({
|
||||||
title: 'Error while fetching linkedTypebots',
|
title: 'Error while fetching linkedTypebots',
|
||||||
description: error.message,
|
description: error.message,
|
||||||
}),
|
}),
|
||||||
@@ -181,7 +178,7 @@ export const TypebotContext = ({
|
|||||||
const { error } = await updateTypebot(typebotToSave.id, typebotToSave)
|
const { error } = await updateTypebot(typebotToSave.id, typebotToSave)
|
||||||
setIsSavingLoading(false)
|
setIsSavingLoading(false)
|
||||||
if (error) {
|
if (error) {
|
||||||
toast({ title: error.name, description: error.message })
|
showToast({ title: error.name, description: error.message })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!options?.disableMutation)
|
if (!options?.disableMutation)
|
||||||
@@ -200,7 +197,8 @@ export const TypebotContext = ({
|
|||||||
newPublishedTypebot
|
newPublishedTypebot
|
||||||
)
|
)
|
||||||
setIsPublishing(false)
|
setIsPublishing(false)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutate({
|
mutate({
|
||||||
typebot: currentTypebotRef.current as Typebot,
|
typebot: currentTypebotRef.current as Typebot,
|
||||||
publishedTypebot: newPublishedTypebot,
|
publishedTypebot: newPublishedTypebot,
|
||||||
@@ -252,7 +250,7 @@ export const TypebotContext = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoading) return
|
if (isLoading) return
|
||||||
if (!typebot) {
|
if (!typebot) {
|
||||||
toast({ status: 'info', description: "Couldn't find typebot" })
|
showToast({ status: 'info', description: "Couldn't find typebot" })
|
||||||
router.replace('/typebots')
|
router.replace('/typebots')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -314,7 +312,8 @@ export const TypebotContext = ({
|
|||||||
id: publishedTypebotId,
|
id: publishedTypebotId,
|
||||||
})
|
})
|
||||||
setIsPublishing(false)
|
setIsPublishing(false)
|
||||||
if (error) return toast({ title: error.name, description: error.message })
|
if (error)
|
||||||
|
return showToast({ title: error.name, description: error.message })
|
||||||
mutate({
|
mutate({
|
||||||
typebot: localTypebot,
|
typebot: localTypebot,
|
||||||
publishedTypebot: data,
|
publishedTypebot: data,
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { isDefined, isNotDefined } from 'utils'
|
import { isDefined, isNotDefined } from 'utils'
|
||||||
import { updateUser as updateUserInDb } from 'services/user/user'
|
import { updateUser as updateUserInDb } from 'services/user/user'
|
||||||
import { useToast } from '@chakra-ui/react'
|
|
||||||
import { dequal } from 'dequal'
|
import { dequal } from 'dequal'
|
||||||
import { User } from 'db'
|
import { User } from 'db'
|
||||||
import { setUser as setSentryUser } from '@sentry/nextjs'
|
import { setUser as setSentryUser } from '@sentry/nextjs'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
const userContext = createContext<{
|
const userContext = createContext<{
|
||||||
user?: User
|
user?: User
|
||||||
@@ -32,10 +32,7 @@ export const UserContext = ({ children }: { children: ReactNode }) => {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { data: session, status } = useSession()
|
const { data: session, status } = useSession()
|
||||||
const [user, setUser] = useState<User | undefined>()
|
const [user, setUser] = useState<User | undefined>()
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const [currentWorkspaceId, setCurrentWorkspaceId] = useState<string>()
|
const [currentWorkspaceId, setCurrentWorkspaceId] = useState<string>()
|
||||||
|
|
||||||
const [isSaving, setIsSaving] = useState(false)
|
const [isSaving, setIsSaving] = useState(false)
|
||||||
@@ -88,7 +85,7 @@ export const UserContext = ({ children }: { children: ReactNode }) => {
|
|||||||
setIsSaving(true)
|
setIsSaving(true)
|
||||||
if (newUser) updateUser(newUser)
|
if (newUser) updateUser(newUser)
|
||||||
const { error } = await updateUserInDb(user.id, { ...user, ...newUser })
|
const { error } = await updateUserInDb(user.id, { ...user, ...newUser })
|
||||||
if (error) toast({ title: error.name, description: error.message })
|
if (error) showToast({ title: error.name, description: error.message })
|
||||||
await refreshUser()
|
await refreshUser()
|
||||||
setIsSaving(false)
|
setIsSaving(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Flex, useDisclosure, useToast } from '@chakra-ui/react'
|
import { Flex, useDisclosure } from '@chakra-ui/react'
|
||||||
import { StatsCards } from 'components/analytics/StatsCards'
|
import { StatsCards } from 'components/analytics/StatsCards'
|
||||||
import { Graph } from 'components/shared/Graph'
|
import { Graph } from 'components/shared/Graph'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { UpgradeModal } from 'components/shared/modals/UpgradeModal'
|
import { UpgradeModal } from 'components/shared/modals/UpgradeModal'
|
||||||
import { GraphProvider } from 'contexts/GraphContext'
|
import { GraphProvider } from 'contexts/GraphContext'
|
||||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||||
@@ -11,14 +12,10 @@ import { useAnswersCount } from 'services/analytics'
|
|||||||
export const AnalyticsContent = ({ stats }: { stats?: Stats }) => {
|
export const AnalyticsContent = ({ stats }: { stats?: Stats }) => {
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
const { typebot, publishedTypebot } = useTypebot()
|
const { typebot, publishedTypebot } = useTypebot()
|
||||||
|
const { showToast } = useToast()
|
||||||
const toast = useToast({
|
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
const { answersCounts } = useAnswersCount({
|
const { answersCounts } = useAnswersCount({
|
||||||
typebotId: publishedTypebot && typebot?.id,
|
typebotId: publishedTypebot && typebot?.id,
|
||||||
onError: (err) => toast({ title: err.name, description: err.message }),
|
onError: (err) => showToast({ title: err.name, description: err.message }),
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Button, Flex, HStack, Tag, useToast, Text } from '@chakra-ui/react'
|
import { Button, Flex, HStack, Tag, Text } from '@chakra-ui/react'
|
||||||
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
import { NextChakraLink } from 'components/nextChakra/NextChakraLink'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||||
import { useWorkspace } from 'contexts/WorkspaceContext'
|
import { useWorkspace } from 'contexts/WorkspaceContext'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
@@ -17,14 +18,11 @@ export const ResultsContent = () => {
|
|||||||
() => router.pathname.endsWith('analytics'),
|
() => router.pathname.endsWith('analytics'),
|
||||||
[router.pathname]
|
[router.pathname]
|
||||||
)
|
)
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const { stats, mutate } = useStats({
|
const { stats, mutate } = useStats({
|
||||||
typebotId: publishedTypebot?.typebotId,
|
typebotId: publishedTypebot?.typebotId,
|
||||||
onError: (err) => toast({ title: err.name, description: err.message }),
|
onError: (err) => showToast({ title: err.name, description: err.message }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleDeletedResults = (total: number) => {
|
const handleDeletedResults = (total: number) => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Stack, useToast, Flex } from '@chakra-ui/react'
|
import { Stack, Flex } from '@chakra-ui/react'
|
||||||
import { ResultsActionButtons } from 'components/results/ResultsActionButtons'
|
import { ResultsActionButtons } from 'components/results/ResultsActionButtons'
|
||||||
import { SubmissionsTable } from 'components/results/SubmissionsTable'
|
import { SubmissionsTable } from 'components/results/SubmissionsTable'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
@@ -15,6 +15,7 @@ import { LogsModal } from './LogsModal'
|
|||||||
import { useTypebot } from 'contexts/TypebotContext'
|
import { useTypebot } from 'contexts/TypebotContext'
|
||||||
import { isDefined, parseResultHeader } from 'utils'
|
import { isDefined, parseResultHeader } from 'utils'
|
||||||
import { Plan } from 'db'
|
import { Plan } from 'db'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
typebotId: string
|
typebotId: string
|
||||||
@@ -34,10 +35,7 @@ export const SubmissionsContent = ({
|
|||||||
const [isExportLoading, setIsExportLoading] = useState(false)
|
const [isExportLoading, setIsExportLoading] = useState(false)
|
||||||
const [inspectingLogsResultId, setInspectingLogsResultId] = useState<string>()
|
const [inspectingLogsResultId, setInspectingLogsResultId] = useState<string>()
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const blocksAndVariables = {
|
const blocksAndVariables = {
|
||||||
blocks: [
|
blocks: [
|
||||||
@@ -54,7 +52,7 @@ export const SubmissionsContent = ({
|
|||||||
|
|
||||||
const { data, mutate, setSize, hasMore } = useResults({
|
const { data, mutate, setSize, hasMore } = useResults({
|
||||||
typebotId,
|
typebotId,
|
||||||
onError: (err) => toast({ title: err.name, description: err.message }),
|
onError: (err) => showToast({ title: err.name, description: err.message }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const results = useMemo(() => data?.flatMap((d) => d.results), [data])
|
const results = useMemo(() => data?.flatMap((d) => d.results), [data])
|
||||||
@@ -73,7 +71,7 @@ export const SubmissionsContent = ({
|
|||||||
totalSelected === totalResults
|
totalSelected === totalResults
|
||||||
? await deleteAllResults(typebotId)
|
? await deleteAllResults(typebotId)
|
||||||
: await deleteResults(typebotId, selectedIds)
|
: await deleteResults(typebotId, selectedIds)
|
||||||
if (error) toast({ description: error.message, title: error.name })
|
if (error) showToast({ description: error.message, title: error.name })
|
||||||
else {
|
else {
|
||||||
mutate(
|
mutate(
|
||||||
totalSelected === totalResults
|
totalSelected === totalResults
|
||||||
|
|||||||
@@ -5,21 +5,19 @@ import { Seo } from 'components/Seo'
|
|||||||
import { FolderContent } from 'components/dashboard/FolderContent'
|
import { FolderContent } from 'components/dashboard/FolderContent'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useFolderContent } from 'services/folders'
|
import { useFolderContent } from 'services/folders'
|
||||||
import { Spinner, useToast } from '@chakra-ui/react'
|
import { Spinner } from '@chakra-ui/react'
|
||||||
import { TypebotDndContext } from 'contexts/TypebotDndContext'
|
import { TypebotDndContext } from 'contexts/TypebotDndContext'
|
||||||
|
import { useToast } from 'components/shared/hooks/useToast'
|
||||||
|
|
||||||
const FolderPage = () => {
|
const FolderPage = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const toast = useToast({
|
const { showToast } = useToast()
|
||||||
position: 'top-right',
|
|
||||||
status: 'error',
|
|
||||||
})
|
|
||||||
|
|
||||||
const { folder } = useFolderContent({
|
const { folder } = useFolderContent({
|
||||||
folderId: router.query.id?.toString(),
|
folderId: router.query.id?.toString(),
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast({
|
showToast({
|
||||||
title: "Couldn't fetch folder content",
|
title: "Couldn't fetch folder content",
|
||||||
description: error.message,
|
description: error.message,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user