♻️ (builder) Remove barrel export and flatten folder arch
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { compressFile } from '@/utils/helpers'
|
|
||||||
import { Button, ButtonProps, chakra } from '@chakra-ui/react'
|
import { Button, ButtonProps, chakra } from '@chakra-ui/react'
|
||||||
import { ChangeEvent, useState } from 'react'
|
import { ChangeEvent, useState } from 'react'
|
||||||
import { uploadFiles } from '@typebot.io/lib'
|
import { uploadFiles } from '@typebot.io/lib'
|
||||||
|
import { compressFile } from '@/helpers/compressFile'
|
||||||
|
|
||||||
type UploadButtonProps = {
|
type UploadButtonProps = {
|
||||||
fileType: 'image' | 'audio'
|
fileType: 'image' | 'audio'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useTypebot } from '@/features/editor'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useTypebot } from '@/features/editor'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { useUser } from '@/features/account'
|
import { useUser } from '@/features/account/hooks/useUser'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Bubble } from '@typebot.io/react'
|
import { Bubble } from '@typebot.io/react'
|
||||||
import { planToReadable } from '@/features/billing'
|
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
|
||||||
import { isCloudProdInstance } from '@/utils/helpers'
|
import { planToReadable } from '@/features/billing/helpers/planToReadable'
|
||||||
|
|
||||||
export const SupportBubble = () => {
|
export const SupportBubble = () => {
|
||||||
const { typebot } = useTypebot()
|
const { typebot } = useTypebot()
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ChangePlanModal, LimitReached } from '@/features/billing'
|
import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||||
|
import { LimitReached } from '@/features/billing/types'
|
||||||
|
|
||||||
export const UnlockPlanAlertInfo = ({
|
export const UnlockPlanAlertInfo = ({
|
||||||
contentLabel,
|
contentLabel,
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ import { useDebouncedCallback } from 'use-debounce'
|
|||||||
import { env, isDefined } from '@typebot.io/lib'
|
import { env, isDefined } from '@typebot.io/lib'
|
||||||
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
||||||
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
|
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
|
||||||
import { VariablesButton } from '@/features/variables'
|
import { VariablesButton } from '@/features/variables/components/VariablesButton'
|
||||||
import { Variable } from '@typebot.io/schemas'
|
import { Variable } from '@typebot.io/schemas'
|
||||||
import { injectVariableInText } from '@/features/variables/utils/injectVariableInTextInput'
|
import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput'
|
||||||
import { focusInput } from '@/utils/focusInput'
|
import { focusInput } from '@/helpers/focusInput'
|
||||||
import { MoreInfoTooltip } from '../MoreInfoTooltip'
|
import { MoreInfoTooltip } from '../MoreInfoTooltip'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useDebouncedCallback } from 'use-debounce'
|
import { useDebouncedCallback } from 'use-debounce'
|
||||||
import { VariablesButton } from '@/features/variables'
|
import { VariablesButton } from '@/features/variables/components/VariablesButton'
|
||||||
import { Variable } from '@typebot.io/schemas'
|
import { Variable } from '@typebot.io/schemas'
|
||||||
import { env } from '@typebot.io/lib'
|
import { env } from '@typebot.io/lib'
|
||||||
import CodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror'
|
import CodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { VariablesButton } from '@/features/variables'
|
import { VariablesButton } from '@/features/variables/components/VariablesButton'
|
||||||
import {
|
import {
|
||||||
NumberInputProps,
|
NumberInputProps,
|
||||||
NumberInput as ChakraNumberInput,
|
NumberInput as ChakraNumberInput,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { VariablesButton } from '@/features/variables'
|
import { VariablesButton } from '@/features/variables/components/VariablesButton'
|
||||||
import { injectVariableInText } from '@/features/variables/utils/injectVariableInTextInput'
|
import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput'
|
||||||
import { focusInput } from '@/utils/focusInput'
|
import { focusInput } from '@/helpers/focusInput'
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormHelperText,
|
FormHelperText,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { VariablesButton } from '@/features/variables'
|
import { VariablesButton } from '@/features/variables/components/VariablesButton'
|
||||||
import { injectVariableInText } from '@/features/variables/utils/injectVariableInTextInput'
|
import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput'
|
||||||
import { focusInput } from '@/utils/focusInput'
|
import { focusInput } from '@/helpers/focusInput'
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { EditIcon, PlusIcon, TrashIcon } from '@/components/icons'
|
import { EditIcon, PlusIcon, TrashIcon } from '@/components/icons'
|
||||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider/TypebotProvider'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { createId } from '@paralleldrive/cuid2'
|
import { createId } from '@paralleldrive/cuid2'
|
||||||
import { Variable } from '@typebot.io/schemas'
|
import { Variable } from '@typebot.io/schemas'
|
||||||
import React, { useState, useRef, ChangeEvent, useEffect } from 'react'
|
import React, { useState, useRef, ChangeEvent, useEffect } from 'react'
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
import { useSession } from 'next-auth/react'
|
import { useSession } from 'next-auth/react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import {
|
import { createContext, ReactNode, useEffect, useState } from 'react'
|
||||||
createContext,
|
|
||||||
ReactNode,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
} from 'react'
|
|
||||||
import { env, isDefined, isNotDefined } from '@typebot.io/lib'
|
import { env, isDefined, isNotDefined } from '@typebot.io/lib'
|
||||||
import { User } from '@typebot.io/prisma'
|
import { User } from '@typebot.io/prisma'
|
||||||
import { setUser as setSentryUser } from '@sentry/nextjs'
|
import { setUser as setSentryUser } from '@sentry/nextjs'
|
||||||
@@ -14,7 +8,7 @@ import { useToast } from '@/hooks/useToast'
|
|||||||
import { updateUserQuery } from './queries/updateUserQuery'
|
import { updateUserQuery } from './queries/updateUserQuery'
|
||||||
import { useDebouncedCallback } from 'use-debounce'
|
import { useDebouncedCallback } from 'use-debounce'
|
||||||
|
|
||||||
const userContext = createContext<{
|
export const userContext = createContext<{
|
||||||
user?: User
|
user?: User
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
currentWorkspaceId?: string
|
currentWorkspaceId?: string
|
||||||
@@ -110,5 +104,3 @@ const reloadSession = () => {
|
|||||||
const event = new Event('visibilitychange')
|
const event = new Event('visibilitychange')
|
||||||
document.dispatchEvent(event)
|
document.dispatchEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useUser = () => useContext(userContext)
|
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import { User } from '@typebot.io/prisma'
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { byId, isDefined } from '@typebot.io/lib'
|
import { byId, isDefined } from '@typebot.io/lib'
|
||||||
import { CreateTokenModal } from './CreateTokenModal'
|
import { CreateTokenModal } from './CreateTokenModal'
|
||||||
import { useApiTokens } from '../../../hooks/useApiTokens'
|
import { useApiTokens } from '../hooks/useApiTokens'
|
||||||
import { ApiTokenFromServer } from '../../../types'
|
import { ApiTokenFromServer } from '../types'
|
||||||
import { timeSince } from '@/utils/helpers'
|
import { parseTimeSince } from '@/helpers/parseTimeSince'
|
||||||
import { deleteApiTokenQuery } from '../../../queries/deleteApiTokenQuery'
|
import { deleteApiTokenQuery } from '../queries/deleteApiTokenQuery'
|
||||||
|
|
||||||
type Props = { user: User }
|
type Props = { user: User }
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ export const ApiTokensList = ({ user }: Props) => {
|
|||||||
{apiTokens?.map((token) => (
|
{apiTokens?.map((token) => (
|
||||||
<Tr key={token.id}>
|
<Tr key={token.id}>
|
||||||
<Td>{token.name}</Td>
|
<Td>{token.name}</Td>
|
||||||
<Td>{timeSince(token.createdAt)} ago</Td>
|
<Td>{parseTimeSince(token.createdAt)} ago</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Button
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import { CopyButton } from '@/components/CopyButton'
|
import { CopyButton } from '@/components/CopyButton'
|
||||||
import { createApiTokenQuery } from '../../../queries/createApiTokenQuery'
|
|
||||||
import { ApiTokenFromServer } from '../../../types'
|
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
@@ -17,6 +15,8 @@ import {
|
|||||||
InputRightElement,
|
InputRightElement,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React, { FormEvent, useState } from 'react'
|
import React, { FormEvent, useState } from 'react'
|
||||||
|
import { createApiTokenQuery } from '../queries/createApiTokenQuery'
|
||||||
|
import { ApiTokenFromServer } from '../types'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
userId: string
|
userId: string
|
||||||
@@ -3,7 +3,7 @@ import { UploadIcon } from '@/components/icons'
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { ApiTokensList } from './ApiTokensList'
|
import { ApiTokensList } from './ApiTokensList'
|
||||||
import { UploadButton } from '@/components/ImageUploadContent/UploadButton'
|
import { UploadButton } from '@/components/ImageUploadContent/UploadButton'
|
||||||
import { useUser } from '@/features/account'
|
import { useUser } from '../hooks/useUser'
|
||||||
import { TextInput } from '@/components/inputs/TextInput'
|
import { TextInput } from '@/components/inputs/TextInput'
|
||||||
|
|
||||||
export const MyAccountForm = () => {
|
export const MyAccountForm = () => {
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { ApiTokensList } from './ApiTokensList'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { MyAccountForm } from './MyAccountForm'
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Stack, Heading, useColorMode } from '@chakra-ui/react'
|
import { Stack, Heading, useColorMode } from '@chakra-ui/react'
|
||||||
import { useUser } from '@/features/account'
|
|
||||||
import { GraphNavigation } from '@typebot.io/prisma'
|
import { GraphNavigation } from '@typebot.io/prisma'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { GraphNavigationRadioGroup } from './GraphNavigationRadioGroup'
|
import { GraphNavigationRadioGroup } from './GraphNavigationRadioGroup'
|
||||||
import { AppearanceRadioGroup } from './AppearanceRadioGroup'
|
import { AppearanceRadioGroup } from './AppearanceRadioGroup'
|
||||||
|
import { useUser } from '../hooks/useUser'
|
||||||
|
|
||||||
export const UserPreferencesForm = () => {
|
export const UserPreferencesForm = () => {
|
||||||
const { colorMode, setColorMode } = useColorMode()
|
const { colorMode, setColorMode } = useColorMode()
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './MyAccountForm'
|
|
||||||
export * from './UserPreferenceForm/UserPreferencesForm'
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { fetcher } from '@/utils/helpers'
|
import { fetcher } from '@/helpers/fetcher'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { env } from '@typebot.io/lib'
|
import { env } from '@typebot.io/lib'
|
||||||
import { ApiTokenFromServer } from '../types'
|
import { ApiTokenFromServer } from '../types'
|
||||||
|
|||||||
4
apps/builder/src/features/account/hooks/useUser.ts
Normal file
4
apps/builder/src/features/account/hooks/useUser.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { useContext } from 'react'
|
||||||
|
import { userContext } from '../UserProvider'
|
||||||
|
|
||||||
|
export const useUser = () => useContext(userContext)
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { UserProvider, useUser } from './UserProvider'
|
|
||||||
export type { ApiTokenFromServer } from './types'
|
|
||||||
export * from './components'
|
|
||||||
@@ -5,17 +5,16 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { useTypebot } from '@/features/editor'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { Stats } from '@typebot.io/schemas'
|
import { Stats } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useAnswersCount } from '../hooks/useAnswersCount'
|
import { useAnswersCount } from '../hooks/useAnswersCount'
|
||||||
import {
|
|
||||||
Graph,
|
|
||||||
GraphProvider,
|
|
||||||
GroupsCoordinatesProvider,
|
|
||||||
} from '@/features/graph'
|
|
||||||
import { ChangePlanModal, LimitReached } from '@/features/billing'
|
|
||||||
import { StatsCards } from './StatsCards'
|
import { StatsCards } from './StatsCards'
|
||||||
|
import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||||
|
import { LimitReached } from '@/features/billing/types'
|
||||||
|
import { Graph } from '@/features/graph/components/Graph'
|
||||||
|
import { GraphProvider } from '@/features/graph/providers/GraphProvider'
|
||||||
|
import { GroupsCoordinatesProvider } from '@/features/graph/providers/GroupsCoordinateProvider'
|
||||||
|
|
||||||
export const AnalyticsGraphContainer = ({ stats }: { stats?: Stats }) => {
|
export const AnalyticsGraphContainer = ({ stats }: { stats?: Stats }) => {
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { fetcher } from '@/utils/helpers'
|
import { fetcher } from '@/helpers/fetcher'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { AnswersCount } from '../types'
|
import { AnswersCount } from '../types'
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
export { AnalyticsGraphContainer } from './components/AnalyticsGraphContainer'
|
|
||||||
export type { AnswersCount } from './types'
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export * from './convertInvitationsToCollaborations'
|
|
||||||
export * from './getAuthenticatedUser'
|
|
||||||
export * from './getNewUserInvitations'
|
|
||||||
export * from './joinWorkspaces'
|
|
||||||
@@ -11,8 +11,10 @@ import React, { useState } from 'react'
|
|||||||
import { stringify } from 'qs'
|
import { stringify } from 'qs'
|
||||||
import { BuiltInProviderType } from 'next-auth/providers'
|
import { BuiltInProviderType } from 'next-auth/providers'
|
||||||
import { GoogleLogo } from '@/components/GoogleLogo'
|
import { GoogleLogo } from '@/components/GoogleLogo'
|
||||||
import { AzureAdLogo, FacebookLogo, GitlabLogo } from './logos'
|
|
||||||
import { omit } from '@typebot.io/lib'
|
import { omit } from '@typebot.io/lib'
|
||||||
|
import { AzureAdLogo } from '@/components/logos/AzureAdLogo'
|
||||||
|
import { FacebookLogo } from '@/components/logos/FacebookLogo'
|
||||||
|
import { GitlabLogo } from '@/components/logos/GitlabLogo'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
providers:
|
providers:
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export { AzureAdLogo } from './AzureAdLogo'
|
|
||||||
export { GitlabLogo } from './GitlabLogo'
|
|
||||||
export { FacebookLogo } from './FacebookLogo'
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { SignInPage } from './components/SignInPage'
|
|
||||||
export { mockedUser } from './constants'
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Plan, WorkspaceRole } from '@typebot.io/prisma'
|
import { Plan, WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Plan, WorkspaceRole } from '@typebot.io/prisma'
|
import { Plan, WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { parseSubscriptionItems } from '../utils/parseSubscriptionItems'
|
import { parseSubscriptionItems } from '../helpers/parseSubscriptionItems'
|
||||||
|
|
||||||
export const createCheckoutSession = authenticatedProcedure
|
export const createCheckoutSession = authenticatedProcedure
|
||||||
.meta({
|
.meta({
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { WorkspaceRole } from '@typebot.io/prisma'
|
import { WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { WorkspaceRole } from '@typebot.io/prisma'
|
import { WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { WorkspaceRole } from '@typebot.io/prisma'
|
import { WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { router } from '@/utils/server/trpc'
|
import { router } from '@/helpers/server/trpc'
|
||||||
import { getBillingPortalUrl } from './procedures/getBillingPortalUrl'
|
import { cancelSubscription } from './cancelSubscription'
|
||||||
import { listInvoices } from './procedures/listInvoices'
|
import { createCheckoutSession } from './createCheckoutSession'
|
||||||
import { cancelSubscription } from './procedures/cancelSubscription'
|
import { getBillingPortalUrl } from './getBillingPortalUrl'
|
||||||
import { createCheckoutSession } from './procedures/createCheckoutSession'
|
import { getSubscription } from './getSubscription'
|
||||||
import { updateSubscription } from './procedures/updateSubscription'
|
import { getUsage } from './getUsage'
|
||||||
import { getSubscription } from './procedures/getSubscription'
|
import { listInvoices } from './listInvoices'
|
||||||
import { getUsage } from './procedures/getUsage'
|
import { updateSubscription } from './updateSubscription'
|
||||||
|
|
||||||
export const billingRouter = router({
|
export const billingRouter = router({
|
||||||
getBillingPortalUrl,
|
getBillingPortalUrl,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent'
|
import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent'
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { authenticatedProcedure } from '@/utils/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Plan, WorkspaceRole } from '@typebot.io/prisma'
|
import { Plan, WorkspaceRole } from '@typebot.io/prisma'
|
||||||
import { workspaceSchema } from '@typebot.io/schemas'
|
import { workspaceSchema } from '@typebot.io/schemas'
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { UsageContent } from './UsageContent'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { BillingContent } from './BillingContent'
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { sendRequest } from '@typebot.io/lib'
|
|
||||||
|
|
||||||
export const cancelSubscriptionQuery = (stripeId: string) =>
|
|
||||||
sendRequest({
|
|
||||||
url: `api/stripe/subscription?stripeId=${stripeId}`,
|
|
||||||
method: 'DELETE',
|
|
||||||
})
|
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
import { HStack, Stack, Text } from '@chakra-ui/react'
|
import { HStack, Stack, Text } from '@chakra-ui/react'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import { Plan } from '@typebot.io/prisma'
|
import { Plan } from '@typebot.io/prisma'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { CurrentSubscriptionContent } from './CurrentSubscriptionContent'
|
|
||||||
import { InvoicesList } from './InvoicesList'
|
import { InvoicesList } from './InvoicesList'
|
||||||
import { UsageContent } from './UsageContent/UsageContent'
|
import { StripeClimateLogo } from './StripeClimateLogo'
|
||||||
import { StripeClimateLogo } from '../StripeClimateLogo'
|
|
||||||
import { TextLink } from '@/components/TextLink'
|
import { TextLink } from '@/components/TextLink'
|
||||||
import { ChangePlanForm } from '../ChangePlanForm'
|
import { ChangePlanForm } from './ChangePlanForm'
|
||||||
|
import { UsageProgressBars } from './UsageProgressBars'
|
||||||
|
import { CurrentSubscriptionSummary } from './CurrentSubscriptionSummary'
|
||||||
|
|
||||||
export const BillingContent = () => {
|
export const BillingSettingsLayout = () => {
|
||||||
const { workspace, refreshWorkspace } = useWorkspace()
|
const { workspace, refreshWorkspace } = useWorkspace()
|
||||||
|
|
||||||
if (!workspace) return null
|
if (!workspace) return null
|
||||||
return (
|
return (
|
||||||
<Stack spacing="10" w="full">
|
<Stack spacing="10" w="full">
|
||||||
<UsageContent workspace={workspace} />
|
<UsageProgressBars workspace={workspace} />
|
||||||
<Stack spacing="4">
|
<Stack spacing="4">
|
||||||
<CurrentSubscriptionContent
|
<CurrentSubscriptionSummary
|
||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
onCancelSuccess={refreshWorkspace}
|
onCancelSuccess={refreshWorkspace}
|
||||||
/>
|
/>
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { Stack, HStack, Text } from '@chakra-ui/react'
|
import { Stack, HStack, Text } from '@chakra-ui/react'
|
||||||
import { useUser } from '@/features/account'
|
|
||||||
import { Plan } from '@typebot.io/prisma'
|
import { Plan } from '@typebot.io/prisma'
|
||||||
import { ProPlanContent } from './ProPlanContent'
|
|
||||||
import { StarterPlanContent } from './StarterPlanContent'
|
|
||||||
import { TextLink } from '@/components/TextLink'
|
import { TextLink } from '@/components/TextLink'
|
||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import { guessIfUserIsEuropean } from '@typebot.io/lib/pricing'
|
import { guessIfUserIsEuropean } from '@typebot.io/lib/pricing'
|
||||||
import { Workspace } from '@typebot.io/schemas'
|
import { Workspace } from '@typebot.io/schemas'
|
||||||
import { PreCheckoutModal, PreCheckoutModalProps } from '../PreCheckoutModal'
|
import { PreCheckoutModal, PreCheckoutModalProps } from './PreCheckoutModal'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { ParentModalProvider } from '@/features/graph/providers/ParentModalProvider'
|
import { ParentModalProvider } from '@/features/graph/providers/ParentModalProvider'
|
||||||
|
import { useUser } from '@/features/account/hooks/useUser'
|
||||||
|
import { StarterPlanPricingCard } from './StarterPlanPricingCard'
|
||||||
|
import { ProPlanPricingCard } from './ProPlanPricingCard'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workspace: Pick<Workspace, 'id' | 'stripeId' | 'plan'>
|
workspace: Pick<Workspace, 'id' | 'stripeId' | 'plan'>
|
||||||
@@ -88,7 +88,7 @@ export const ChangePlanForm = ({ workspace, onUpgradeSuccess }: Props) => {
|
|||||||
</ParentModalProvider>
|
</ParentModalProvider>
|
||||||
)}
|
)}
|
||||||
<HStack alignItems="stretch" spacing="4" w="full">
|
<HStack alignItems="stretch" spacing="4" w="full">
|
||||||
<StarterPlanContent
|
<StarterPlanPricingCard
|
||||||
initialChatsLimitIndex={
|
initialChatsLimitIndex={
|
||||||
workspace?.plan === Plan.STARTER
|
workspace?.plan === Plan.STARTER
|
||||||
? data?.subscription.additionalChatsIndex
|
? data?.subscription.additionalChatsIndex
|
||||||
@@ -106,7 +106,7 @@ export const ChangePlanForm = ({ workspace, onUpgradeSuccess }: Props) => {
|
|||||||
currency={data?.subscription.currency}
|
currency={data?.subscription.currency}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ProPlanContent
|
<ProPlanPricingCard
|
||||||
initialChatsLimitIndex={
|
initialChatsLimitIndex={
|
||||||
workspace?.plan === Plan.PRO
|
workspace?.plan === Plan.PRO
|
||||||
? data?.subscription.additionalChatsIndex
|
? data?.subscription.additionalChatsIndex
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { ChangePlanForm } from './ChangePlanForm'
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AlertInfo } from '@/components/AlertInfo'
|
import { AlertInfo } from '@/components/AlertInfo'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
@@ -10,16 +10,9 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
HStack,
|
HStack,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
|
import { LimitReached } from '../types'
|
||||||
import { ChangePlanForm } from './ChangePlanForm'
|
import { ChangePlanForm } from './ChangePlanForm'
|
||||||
|
|
||||||
export enum LimitReached {
|
|
||||||
BRAND = 'remove branding',
|
|
||||||
CUSTOM_DOMAIN = 'add custom domains',
|
|
||||||
FOLDER = 'create folders',
|
|
||||||
FILE_INPUT = 'use file input blocks',
|
|
||||||
ANALYTICS = 'unlock in-depth analytics',
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChangePlanModalProps = {
|
type ChangePlanModalProps = {
|
||||||
type?: LimitReached
|
type?: LimitReached
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ import { Text, HStack, Link, Spinner, Stack, Heading } from '@chakra-ui/react'
|
|||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { Plan } from '@typebot.io/prisma'
|
import { Plan } from '@typebot.io/prisma'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { PlanTag } from '../PlanTag'
|
import { PlanTag } from './PlanTag'
|
||||||
import { BillingPortalButton } from './BillingPortalButton'
|
import { BillingPortalButton } from './BillingPortalButton'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import { Workspace } from '@typebot.io/schemas'
|
import { Workspace } from '@typebot.io/schemas'
|
||||||
|
|
||||||
type CurrentSubscriptionContentProps = {
|
type Props = {
|
||||||
workspace: Pick<Workspace, 'id' | 'plan' | 'stripeId'>
|
workspace: Pick<Workspace, 'id' | 'plan' | 'stripeId'>
|
||||||
onCancelSuccess: () => void
|
onCancelSuccess: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CurrentSubscriptionContent = ({
|
export const CurrentSubscriptionSummary = ({
|
||||||
workspace,
|
workspace,
|
||||||
onCancelSuccess,
|
onCancelSuccess,
|
||||||
}: CurrentSubscriptionContentProps) => {
|
}: Props) => {
|
||||||
const { showToast } = useToast()
|
const { showToast } = useToast()
|
||||||
|
|
||||||
const { mutate: cancelSubscription, isLoading: isCancelling } =
|
const { mutate: cancelSubscription, isLoading: isCancelling } =
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { Select } from '@/components/inputs/Select'
|
import { Select } from '@/components/inputs/Select'
|
||||||
import { useParentModal } from '@/features/graph'
|
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
|
||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
useColorModeValue,
|
useColorModeValue,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { ChevronLeftIcon } from '@/components/icons'
|
import { ChevronLeftIcon } from '@/components/icons'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import { Plan } from '@typebot.io/prisma'
|
import { Plan } from '@typebot.io/prisma'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { parseNumberWithCommas } from '@typebot.io/lib'
|
import { parseNumberWithCommas } from '@typebot.io/lib'
|
||||||
@@ -27,10 +27,10 @@ import {
|
|||||||
getStorageLimit,
|
getStorageLimit,
|
||||||
storageLimit,
|
storageLimit,
|
||||||
} from '@typebot.io/lib/pricing'
|
} from '@typebot.io/lib/pricing'
|
||||||
import { FeaturesList } from './components/FeaturesList'
|
import { FeaturesList } from './FeaturesList'
|
||||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||||
|
|
||||||
type ProPlanContentProps = {
|
type Props = {
|
||||||
initialChatsLimitIndex?: number
|
initialChatsLimitIndex?: number
|
||||||
initialStorageLimitIndex?: number
|
initialStorageLimitIndex?: number
|
||||||
currency?: 'usd' | 'eur'
|
currency?: 'usd' | 'eur'
|
||||||
@@ -41,13 +41,13 @@ type ProPlanContentProps = {
|
|||||||
}) => void
|
}) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProPlanContent = ({
|
export const ProPlanPricingCard = ({
|
||||||
initialChatsLimitIndex,
|
initialChatsLimitIndex,
|
||||||
initialStorageLimitIndex,
|
initialStorageLimitIndex,
|
||||||
currency,
|
currency,
|
||||||
isLoading,
|
isLoading,
|
||||||
onPayClick,
|
onPayClick,
|
||||||
}: ProPlanContentProps) => {
|
}: Props) => {
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
||||||
useState<number>()
|
useState<number>()
|
||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { ChevronLeftIcon } from '@/components/icons'
|
import { ChevronLeftIcon } from '@/components/icons'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import { Plan } from '@typebot.io/prisma'
|
import { Plan } from '@typebot.io/prisma'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { parseNumberWithCommas } from '@typebot.io/lib'
|
import { parseNumberWithCommas } from '@typebot.io/lib'
|
||||||
@@ -23,10 +23,10 @@ import {
|
|||||||
getStorageLimit,
|
getStorageLimit,
|
||||||
storageLimit,
|
storageLimit,
|
||||||
} from '@typebot.io/lib/pricing'
|
} from '@typebot.io/lib/pricing'
|
||||||
import { FeaturesList } from './components/FeaturesList'
|
import { FeaturesList } from './FeaturesList'
|
||||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||||
|
|
||||||
type StarterPlanContentProps = {
|
type Props = {
|
||||||
initialChatsLimitIndex?: number
|
initialChatsLimitIndex?: number
|
||||||
initialStorageLimitIndex?: number
|
initialStorageLimitIndex?: number
|
||||||
currency?: 'eur' | 'usd'
|
currency?: 'eur' | 'usd'
|
||||||
@@ -37,13 +37,13 @@ type StarterPlanContentProps = {
|
|||||||
}) => void
|
}) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const StarterPlanContent = ({
|
export const StarterPlanPricingCard = ({
|
||||||
initialChatsLimitIndex,
|
initialChatsLimitIndex,
|
||||||
initialStorageLimitIndex,
|
initialStorageLimitIndex,
|
||||||
isLoading,
|
isLoading,
|
||||||
currency,
|
currency,
|
||||||
onPayClick,
|
onPayClick,
|
||||||
}: StarterPlanContentProps) => {
|
}: Props) => {
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
|
||||||
useState<number>()
|
useState<number>()
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Button, ButtonProps, useDisclosure } from '@chakra-ui/react'
|
import { Button, ButtonProps, useDisclosure } from '@chakra-ui/react'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { isNotDefined } from '@typebot.io/lib'
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
import { ChangePlanModal } from './ChangePlanModal'
|
import { ChangePlanModal } from './ChangePlanModal'
|
||||||
import { LimitReached } from './ChangePlanModal'
|
import { LimitReached } from '../types'
|
||||||
|
|
||||||
type Props = { limitReachedType?: LimitReached } & ButtonProps
|
type Props = { limitReachedType?: LimitReached } & ButtonProps
|
||||||
|
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ import { Plan, Workspace } from '@typebot.io/prisma'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { parseNumberWithCommas } from '@typebot.io/lib'
|
import { parseNumberWithCommas } from '@typebot.io/lib'
|
||||||
import { getChatsLimit, getStorageLimit } from '@typebot.io/lib/pricing'
|
import { getChatsLimit, getStorageLimit } from '@typebot.io/lib/pricing'
|
||||||
import { storageToReadable } from './helpers'
|
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
|
import { storageToReadable } from '../helpers/storageToReadable'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workspace: Workspace
|
workspace: Workspace
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UsageContent = ({ workspace }: Props) => {
|
export const UsageProgressBars = ({ workspace }: Props) => {
|
||||||
const { data, isLoading } = trpc.billing.getUsage.useQuery({
|
const { data, isLoading } = trpc.billing.getUsage.useQuery({
|
||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
})
|
})
|
||||||
5
apps/builder/src/features/billing/helpers/isFreePlan.ts
Normal file
5
apps/builder/src/features/billing/helpers/isFreePlan.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
|
import { Workspace, Plan } from '@typebot.io/prisma'
|
||||||
|
|
||||||
|
export const isFreePlan = (workspace?: Pick<Workspace, 'plan'>) =>
|
||||||
|
isNotDefined(workspace) || workspace?.plan === Plan.FREE
|
||||||
9
apps/builder/src/features/billing/helpers/isProPlan.ts
Normal file
9
apps/builder/src/features/billing/helpers/isProPlan.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { isDefined } from '@typebot.io/lib'
|
||||||
|
import { Workspace, Plan } from '@typebot.io/prisma'
|
||||||
|
|
||||||
|
export const isProPlan = (workspace?: Pick<Workspace, 'plan'>) =>
|
||||||
|
isDefined(workspace) &&
|
||||||
|
(workspace.plan === Plan.PRO ||
|
||||||
|
workspace.plan === Plan.LIFETIME ||
|
||||||
|
workspace.plan === Plan.CUSTOM ||
|
||||||
|
workspace.plan === Plan.UNLIMITED)
|
||||||
17
apps/builder/src/features/billing/helpers/planToReadable.ts
Normal file
17
apps/builder/src/features/billing/helpers/planToReadable.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Plan } from '@typebot.io/prisma'
|
||||||
|
|
||||||
|
export const planToReadable = (plan?: Plan) => {
|
||||||
|
if (!plan) return
|
||||||
|
switch (plan) {
|
||||||
|
case Plan.FREE:
|
||||||
|
return 'Free'
|
||||||
|
case Plan.LIFETIME:
|
||||||
|
return 'Lifetime'
|
||||||
|
case Plan.OFFERED:
|
||||||
|
return 'Offered'
|
||||||
|
case Plan.PRO:
|
||||||
|
return 'Pro'
|
||||||
|
case Plan.UNLIMITED:
|
||||||
|
return 'Unlimited'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
export { ChangePlanModal, LimitReached } from './components/ChangePlanModal'
|
|
||||||
export { planToReadable, isFreePlan, isProPlan } from './utils'
|
|
||||||
export { BillingContent } from './components/BillingContent'
|
|
||||||
export { LockTag } from './components/LockTag'
|
|
||||||
export { UpgradeButton } from './components/UpgradeButton'
|
|
||||||
export { PlanTag } from './components/PlanTag'
|
|
||||||
7
apps/builder/src/features/billing/types.ts
Normal file
7
apps/builder/src/features/billing/types.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export enum LimitReached {
|
||||||
|
BRAND = 'remove branding',
|
||||||
|
CUSTOM_DOMAIN = 'add custom domains',
|
||||||
|
FOLDER = 'create folders',
|
||||||
|
FILE_INPUT = 'use file input blocks',
|
||||||
|
ANALYTICS = 'unlock in-depth analytics',
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { Plan, Workspace } from '@typebot.io/prisma'
|
|
||||||
import { isDefined, isNotDefined } from '@typebot.io/lib'
|
|
||||||
|
|
||||||
export const planToReadable = (plan?: Plan) => {
|
|
||||||
if (!plan) return
|
|
||||||
switch (plan) {
|
|
||||||
case Plan.FREE:
|
|
||||||
return 'Free'
|
|
||||||
case Plan.LIFETIME:
|
|
||||||
return 'Lifetime'
|
|
||||||
case Plan.OFFERED:
|
|
||||||
return 'Offered'
|
|
||||||
case Plan.PRO:
|
|
||||||
return 'Pro'
|
|
||||||
case Plan.UNLIMITED:
|
|
||||||
return 'Unlimited'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isFreePlan = (workspace?: Pick<Workspace, 'plan'>) =>
|
|
||||||
isNotDefined(workspace) || workspace?.plan === Plan.FREE
|
|
||||||
|
|
||||||
export const isProPlan = (workspace?: Pick<Workspace, 'plan'>) =>
|
|
||||||
isDefined(workspace) &&
|
|
||||||
(workspace.plan === Plan.PRO ||
|
|
||||||
workspace.plan === Plan.LIFETIME ||
|
|
||||||
workspace.plan === Plan.CUSTOM ||
|
|
||||||
workspace.plan === Plan.UNLIMITED)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './AudioBubbleNode'
|
|
||||||
export * from './AudioBubbleIcon'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from './components'
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { EmbedBubbleContent } from './components/EmbedBubbleContent'
|
|
||||||
export { EmbedUploadContent } from './components/EmbedUploadContent'
|
|
||||||
export { EmbedBubbleIcon } from './components/EmbedBubbleIcon'
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { ImageBubbleContent } from './components/ImageBubbleContent'
|
|
||||||
export { ImageBubbleIcon } from './components/ImageBubbleIcon'
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Flex } from '@chakra-ui/react'
|
import { Flex } from '@chakra-ui/react'
|
||||||
import { useTypebot } from '@/features/editor'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { TextBubbleBlock } from '@typebot.io/schemas'
|
import { TextBubbleBlock } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { parseVariableHighlight } from '@/utils/helpers'
|
|
||||||
import { isEmpty } from '@typebot.io/lib'
|
import { isEmpty } from '@typebot.io/lib'
|
||||||
|
import { parseVariableHtmlTags } from '@/features/variables/helpers/parseVariableHtmlTags'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: TextBubbleBlock
|
block: TextBubbleBlock
|
||||||
@@ -11,7 +11,6 @@ type Props = {
|
|||||||
|
|
||||||
export const TextBubbleContent = ({ block }: Props) => {
|
export const TextBubbleContent = ({ block }: Props) => {
|
||||||
const { typebot } = useTypebot()
|
const { typebot } = useTypebot()
|
||||||
if (!typebot) return <></>
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
w="90%"
|
w="90%"
|
||||||
@@ -22,7 +21,7 @@ export const TextBubbleContent = ({ block }: Props) => {
|
|||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: isEmpty(block.content.plainText)
|
__html: isEmpty(block.content.plainText)
|
||||||
? `<p>Click to edit...</p>`
|
? `<p>Click to edit...</p>`
|
||||||
: parseVariableHighlight(block.content.html, typebot),
|
: parseVariableHtmlTags(block.content.html, typebot?.variables ?? []),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import React, { useEffect, useRef, useState } from 'react'
|
|||||||
import { Plate, PlateProvider, usePlateEditorRef } from '@udecode/plate-core'
|
import { Plate, PlateProvider, usePlateEditorRef } from '@udecode/plate-core'
|
||||||
import { editorStyle, platePlugins } from '@/lib/plate'
|
import { editorStyle, platePlugins } from '@/lib/plate'
|
||||||
import { BaseEditor, BaseSelection, Transforms } from 'slate'
|
import { BaseEditor, BaseSelection, Transforms } from 'slate'
|
||||||
import { ToolBar } from './ToolBar'
|
|
||||||
import {
|
import {
|
||||||
defaultTextBubbleContent,
|
defaultTextBubbleContent,
|
||||||
TextBubbleContent,
|
TextBubbleContent,
|
||||||
@@ -16,11 +15,12 @@ import {
|
|||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { ReactEditor } from 'slate-react'
|
import { ReactEditor } from 'slate-react'
|
||||||
import { serializeHtml } from '@udecode/plate-serializer-html'
|
import { serializeHtml } from '@udecode/plate-serializer-html'
|
||||||
import { parseHtmlStringToPlainText } from '../../utils'
|
import { parseHtmlStringToPlainText } from '../utils'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { colors } from '@/lib/theme'
|
import { colors } from '@/lib/theme'
|
||||||
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
||||||
import { selectEditor, TElement } from '@udecode/plate-common'
|
import { selectEditor, TElement } from '@udecode/plate-common'
|
||||||
|
import { TextEditorToolBar } from './TextEditorToolBar'
|
||||||
|
|
||||||
type TextBubbleEditorContentProps = {
|
type TextBubbleEditorContentProps = {
|
||||||
id: string
|
id: string
|
||||||
@@ -130,7 +130,9 @@ const TextBubbleEditorContent = ({
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToolBar onVariablesButtonClick={() => setIsVariableDropdownOpen(true)} />
|
<TextEditorToolBar
|
||||||
|
onVariablesButtonClick={() => setIsVariableDropdownOpen(true)}
|
||||||
|
/>
|
||||||
<Plate
|
<Plate
|
||||||
id={id}
|
id={id}
|
||||||
editableProps={{
|
editableProps={{
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { TextBubbleEditor } from './TextBubbleEditor'
|
|
||||||
@@ -24,7 +24,10 @@ type Props = {
|
|||||||
onVariablesButtonClick: () => void
|
onVariablesButtonClick: () => void
|
||||||
} & StackProps
|
} & StackProps
|
||||||
|
|
||||||
export const ToolBar = ({ onVariablesButtonClick, ...props }: Props) => {
|
export const TextEditorToolBar = ({
|
||||||
|
onVariablesButtonClick,
|
||||||
|
...props
|
||||||
|
}: Props) => {
|
||||||
const editor = usePlateEditorRef()
|
const editor = usePlateEditorRef()
|
||||||
const handleVariablesButtonMouseDown = (e: React.MouseEvent) => {
|
const handleVariablesButtonMouseDown = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { TextBubbleEditor } from './components/TextBubbleEditor'
|
|
||||||
export { TextBubbleContent } from './components/TextBubbleContent'
|
|
||||||
export { TextBubbleIcon } from './components/TextBubbleIcon'
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { VideoUploadContent } from './components/VideoUploadContent'
|
|
||||||
export { VideoBubbleContent } from './components/VideoBubbleContent'
|
|
||||||
export { VideoBubbleIcon } from './components/VideoBubbleIcon'
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { BlockIndices, ChoiceInputBlock } from '@typebot.io/schemas'
|
import { BlockIndices, ChoiceInputBlock } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ItemNodesList } from '@/features/graph/components/Nodes/ItemNode'
|
|
||||||
import { Stack, Tag, Text, Wrap } from '@chakra-ui/react'
|
import { Stack, Tag, Text, Wrap } from '@chakra-ui/react'
|
||||||
import { useTypebot } from '@/features/editor'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
||||||
|
import { ItemNodesList } from '@/features/graph/components/nodes/item/ItemNodesList'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: ChoiceInputBlock
|
block: ChoiceInputBlock
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
Flex,
|
Flex,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { PlusIcon } from '@/components/icons'
|
import { PlusIcon } from '@/components/icons'
|
||||||
import { useTypebot } from '@/features/editor'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { ButtonItem, ItemIndices, ItemType } from '@typebot.io/schemas'
|
import { ButtonItem, ItemIndices, ItemType } from '@typebot.io/schemas'
|
||||||
import React, { useRef, useState } from 'react'
|
import React, { useRef, useState } from 'react'
|
||||||
import { isNotDefined } from '@typebot.io/lib'
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export * from './ButtonsItemNode'
|
|
||||||
export * from './ButtonsIcon'
|
|
||||||
export * from './ButtonsBlockSettings'
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from './components'
|
|
||||||
@@ -5,15 +5,12 @@ import { FormLabel, Stack } from '@chakra-ui/react'
|
|||||||
import { DateInputOptions, Variable } from '@typebot.io/schemas'
|
import { DateInputOptions, Variable } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
type DateInputSettingsBodyProps = {
|
type Props = {
|
||||||
options: DateInputOptions
|
options: DateInputOptions
|
||||||
onOptionsChange: (options: DateInputOptions) => void
|
onOptionsChange: (options: DateInputOptions) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DateInputSettingsBody = ({
|
export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
options,
|
|
||||||
onOptionsChange,
|
|
||||||
}: DateInputSettingsBodyProps) => {
|
|
||||||
const handleFromChange = (from: string) =>
|
const handleFromChange = (from: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, from } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, from } })
|
||||||
const handleToChange = (to: string) =>
|
const handleToChange = (to: string) =>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
import { WithVariableContent } from '@/features/graph/components/Nodes/BlockNode/BlockNodeContent/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variableId?: string
|
variableId?: string
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export { DateInputSettingsBody } from './components/DateInputSettingsBody'
|
|
||||||
export { DateNodeContent } from './components/DateNodeContent'
|
|
||||||
export { DateInputIcon } from './components/DateInputIcon'
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
import { EmailInputBlock } from '@typebot.io/schemas'
|
import { EmailInputBlock } from '@typebot.io/schemas'
|
||||||
import { WithVariableContent } from '@/features/graph/components/Nodes/BlockNode/BlockNodeContent/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variableId?: string
|
variableId?: string
|
||||||
|
|||||||
@@ -4,15 +4,12 @@ import { FormLabel, Stack } from '@chakra-ui/react'
|
|||||||
import { EmailInputOptions, Variable } from '@typebot.io/schemas'
|
import { EmailInputOptions, Variable } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
type EmailInputSettingsBodyProps = {
|
type Props = {
|
||||||
options: EmailInputOptions
|
options: EmailInputOptions
|
||||||
onOptionsChange: (options: EmailInputOptions) => void
|
onOptionsChange: (options: EmailInputOptions) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EmailInputSettingsBody = ({
|
export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
options,
|
|
||||||
onOptionsChange,
|
|
||||||
}: EmailInputSettingsBodyProps) => {
|
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export { EmailInputSettingsBody } from './components/EmailInputSettingsBody'
|
|
||||||
export { EmailInputNodeContent } from './components/EmailInputNodeContent'
|
|
||||||
export { EmailInputIcon } from './components/EmailInputIcon'
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WithVariableContent } from '@/features/graph/components/Nodes/BlockNode/BlockNodeContent/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
import { FileInputOptions } from '@typebot.io/schemas'
|
import { FileInputOptions } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export { FileInputSettings } from './components/FileInputSettings'
|
|
||||||
export { FileInputContent } from './components/FileInputContent'
|
|
||||||
export { FileInputIcon } from './components/FileInputIcon'
|
|
||||||
@@ -1,29 +1,23 @@
|
|||||||
import { TextInput, NumberInput } from '@/components/inputs'
|
import { TextInput, NumberInput } from '@/components/inputs'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { removeUndefinedFields } from '@/utils/helpers'
|
|
||||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||||
import { NumberInputOptions, Variable } from '@typebot.io/schemas'
|
import { NumberInputOptions, Variable } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
type NumberInputSettingsBodyProps = {
|
type Props = {
|
||||||
options: NumberInputOptions
|
options: NumberInputOptions
|
||||||
onOptionsChange: (options: NumberInputOptions) => void
|
onOptionsChange: (options: NumberInputOptions) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NumberInputSettingsBody = ({
|
export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
options,
|
|
||||||
onOptionsChange,
|
|
||||||
}: NumberInputSettingsBodyProps) => {
|
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||||
const handleMinChange = (min?: number) =>
|
const handleMinChange = (min?: number) => onOptionsChange({ ...options, min })
|
||||||
onOptionsChange(removeUndefinedFields({ ...options, min }))
|
const handleMaxChange = (max?: number) => onOptionsChange({ ...options, max })
|
||||||
const handleMaxChange = (max?: number) =>
|
const handleStepChange = (step?: number) =>
|
||||||
onOptionsChange(removeUndefinedFields({ ...options, max }))
|
onOptionsChange({ ...options, step })
|
||||||
const handleBlockChange = (block?: number) =>
|
|
||||||
onOptionsChange(removeUndefinedFields({ ...options, block }))
|
|
||||||
const handleVariableChange = (variable?: Variable) => {
|
const handleVariableChange = (variable?: Variable) => {
|
||||||
onOptionsChange({ ...options, variableId: variable?.id })
|
onOptionsChange({ ...options, variableId: variable?.id })
|
||||||
}
|
}
|
||||||
@@ -55,7 +49,7 @@ export const NumberInputSettingsBody = ({
|
|||||||
<NumberInput
|
<NumberInput
|
||||||
label="Step:"
|
label="Step:"
|
||||||
defaultValue={options.step}
|
defaultValue={options.step}
|
||||||
onValueChange={handleBlockChange}
|
onValueChange={handleStepChange}
|
||||||
withVariableButton={false}
|
withVariableButton={false}
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
import { NumberInputBlock } from '@typebot.io/schemas'
|
import { NumberInputBlock } from '@typebot.io/schemas'
|
||||||
import { WithVariableContent } from '@/features/graph/components/Nodes/BlockNode/BlockNodeContent/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variableId?: string
|
variableId?: string
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export { NumberInputSettingsBody } from './components/NumberInputSettingsBody'
|
|
||||||
export { NumberNodeContent } from './components/NumberNodeContent'
|
|
||||||
export { NumberInputIcon } from './components/NumberInputIcon'
|
|
||||||
@@ -13,9 +13,9 @@ import {
|
|||||||
import { DropdownList } from '@/components/DropdownList'
|
import { DropdownList } from '@/components/DropdownList'
|
||||||
import { PaymentInputOptions, PaymentProvider } from '@typebot.io/schemas'
|
import { PaymentInputOptions, PaymentProvider } from '@typebot.io/schemas'
|
||||||
import React, { ChangeEvent } from 'react'
|
import React, { ChangeEvent } from 'react'
|
||||||
import { currencies } from './currencies'
|
import { currencies } from '../currencies'
|
||||||
import { StripeConfigModal } from './StripeConfigModal'
|
import { StripeConfigModal } from './StripeConfigModal'
|
||||||
import { CredentialsDropdown } from '@/features/credentials'
|
import { CredentialsDropdown } from '@/features/credentials/components/CredentialsDropdown'
|
||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { PaymentSettings } from './PaymentSettings'
|
|
||||||
@@ -13,9 +13,8 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
HStack,
|
HStack,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import { useUser } from '@/features/account'
|
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useWorkspace } from '@/features/workspace'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
import { useToast } from '@/hooks/useToast'
|
import { useToast } from '@/hooks/useToast'
|
||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||||
@@ -23,6 +22,7 @@ import { TextLink } from '@/components/TextLink'
|
|||||||
import { StripeCredentials } from '@typebot.io/schemas'
|
import { StripeCredentials } from '@typebot.io/schemas'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import { isNotEmpty } from '@typebot.io/lib'
|
import { isNotEmpty } from '@typebot.io/lib'
|
||||||
|
import { useUser } from '@/features/account/hooks/useUser'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user