Skip to content

Commit

Permalink
⚡ Auto continue bot on whatsApp if starting block is input (#849)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
### Summary by CodeRabbit

**New Features:**
- Added WhatsApp integration feature to the Pro plan.

**Refactor:**
- Introduced the ability to exclude specific plans from being displayed
in the Change Plan Modal.
- Renamed the function `isProPlan` to `hasProPerks`, enhancing code
readability and maintainability.
- Updated the `EmbedButton` component to handle a new `lockTagPlan`
property and use the `modal` function instead of the `Modal` component.

**Chore:**
- Removed the `whatsAppPhoneNumberId` field from the `Typebot` model
across various files, simplifying the data structure of the model.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
baptisteArno authored Sep 25, 2023
1 parent 459fc4d commit b81fcf0
Show file tree
Hide file tree
Showing 30 changed files with 224 additions and 140 deletions.
17 changes: 13 additions & 4 deletions apps/builder/src/components/UnlockPlanAlertInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,23 @@ import {
useDisclosure,
} from '@chakra-ui/react'
import React from 'react'
import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
import {
ChangePlanModal,
ChangePlanModalProps,
} from '@/features/billing/components/ChangePlanModal'
import { useI18n } from '@/locales'

type Props = {
contentLabel: React.ReactNode
buttonLabel?: string
type?: string
} & AlertProps
} & AlertProps &
Pick<ChangePlanModalProps, 'type' | 'excludedPlans'>

export const UnlockPlanAlertInfo = ({
contentLabel,
buttonLabel,
type,
excludedPlans,
...props
}: Props) => {
const t = useI18n()
Expand All @@ -45,7 +49,12 @@ export const UnlockPlanAlertInfo = ({
>
{buttonLabel ?? t('billing.upgradeAlert.buttonDefaultLabel')}
</Button>
<ChangePlanModal isOpen={isOpen} onClose={onClose} type={type} />
<ChangePlanModal
isOpen={isOpen}
onClose={onClose}
type={type}
excludedPlans={excludedPlans}
/>
</Alert>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const AnalyticsGraphContainer = ({ stats }: { stats?: Stats }) => {
onClose={onClose}
isOpen={isOpen}
type={t('billing.limitMessage.analytics')}
excludedPlans={['STARTER']}
/>
<StatsCards stats={stats} pos="absolute" />
</Flex>
Expand Down
47 changes: 26 additions & 21 deletions apps/builder/src/features/billing/components/ChangePlanForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import { StripeClimateLogo } from './StripeClimateLogo'

type Props = {
workspace: Workspace
excludedPlans?: ('STARTER' | 'PRO')[]
}

export const ChangePlanForm = ({ workspace }: Props) => {
export const ChangePlanForm = ({ workspace, excludedPlans }: Props) => {
const scopedT = useScopedI18n('billing')

const { user } = useUser()
Expand Down Expand Up @@ -133,27 +134,31 @@ export const ChangePlanForm = ({ workspace }: Props) => {
</HStack>
</HStack>
<HStack alignItems="stretch" spacing="4" w="full">
<StarterPlanPricingCard
workspace={workspace}
currentSubscription={{ isYearly: data.subscription?.isYearly }}
onPayClick={(props) =>
handlePayClick({ ...props, plan: Plan.STARTER })
}
isYearly={isYearly}
isLoading={isUpdatingSubscription}
currency={data.subscription?.currency}
/>
{excludedPlans?.includes('STARTER') ? null : (
<StarterPlanPricingCard
workspace={workspace}
currentSubscription={{ isYearly: data.subscription?.isYearly }}
onPayClick={(props) =>
handlePayClick({ ...props, plan: Plan.STARTER })
}
isYearly={isYearly}
isLoading={isUpdatingSubscription}
currency={data.subscription?.currency}
/>
)}

<ProPlanPricingCard
workspace={workspace}
currentSubscription={{ isYearly: data.subscription?.isYearly }}
onPayClick={(props) =>
handlePayClick({ ...props, plan: Plan.PRO })
}
isYearly={isYearly}
isLoading={isUpdatingSubscription}
currency={data.subscription?.currency}
/>
{excludedPlans?.includes('PRO') ? null : (
<ProPlanPricingCard
workspace={workspace}
currentSubscription={{ isYearly: data.subscription?.isYearly }}
onPayClick={(props) =>
handlePayClick({ ...props, plan: Plan.PRO })
}
isYearly={isYearly}
isLoading={isUpdatingSubscription}
currency={data.subscription?.currency}
/>
)}
</HStack>
</Stack>
)}
Expand Down
17 changes: 14 additions & 3 deletions apps/builder/src/features/billing/components/ChangePlanModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,27 @@ import {
} from '@chakra-ui/react'
import { ChangePlanForm } from './ChangePlanForm'

type ChangePlanModalProps = {
export type ChangePlanModalProps = {
type?: string
isOpen: boolean
excludedPlans?: ('STARTER' | 'PRO')[]
onClose: () => void
}

export const ChangePlanModal = ({
onClose,
isOpen,
type,
excludedPlans,
}: ChangePlanModalProps) => {
const t = useI18n()
const { workspace } = useWorkspace()
return (
<Modal isOpen={isOpen} onClose={onClose} size="2xl">
<Modal
isOpen={isOpen}
onClose={onClose}
size={excludedPlans ? 'lg' : '2xl'}
>
<ModalOverlay />
<ModalContent>
<ModalBody as={Stack} spacing="6" pt="10">
Expand All @@ -36,7 +42,12 @@ export const ChangePlanModal = ({
{t('billing.upgradeLimitLabel', { type: type })}
</AlertInfo>
)}
{workspace && <ChangePlanForm workspace={workspace} />}
{workspace && (
<ChangePlanForm
workspace={workspace}
excludedPlans={excludedPlans}
/>
)}
</ModalBody>

<ModalFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export const ProPlanPricingCard = ({
</Text>
<MoreInfoTooltip>{scopedT('chatsTooltip')}</MoreInfoTooltip>
</HStack>,
scopedT('pro.whatsAppIntegration'),
scopedT('pro.customDomains'),
scopedT('pro.analytics'),
]}
Expand Down
12 changes: 10 additions & 2 deletions apps/builder/src/features/billing/components/UpgradeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import { isNotDefined } from '@typebot.io/lib'
import { ChangePlanModal } from './ChangePlanModal'
import { useI18n } from '@/locales'

type Props = { limitReachedType?: string } & ButtonProps
type Props = {
limitReachedType?: string
excludedPlans?: ('STARTER' | 'PRO')[]
} & ButtonProps

export const UpgradeButton = ({ limitReachedType, ...props }: Props) => {
export const UpgradeButton = ({
limitReachedType,
excludedPlans,
...props
}: Props) => {
const t = useI18n()
const { isOpen, onOpen, onClose } = useDisclosure()
const { workspace } = useWorkspace()
Expand All @@ -23,6 +30,7 @@ export const UpgradeButton = ({ limitReachedType, ...props }: Props) => {
isOpen={isOpen}
onClose={onClose}
type={limitReachedType}
excludedPlans={excludedPlans}
/>
</Button>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isDefined } from '@typebot.io/lib'
import { Workspace, Plan } from '@typebot.io/prisma'

export const isProPlan = (workspace?: Pick<Workspace, 'plan'>) =>
export const hasProPerks = (workspace?: Pick<Workspace, 'plan'>) =>
isDefined(workspace) &&
(workspace.plan === Plan.PRO ||
workspace.plan === Plan.LIFETIME ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
import React, { useMemo } from 'react'
import { useEndpoints } from '../../providers/EndpointsProvider'
import { useGroupsCoordinates } from '../../providers/GroupsCoordinateProvider'
import { isProPlan } from '@/features/billing/helpers/isProPlan'
import { hasProPerks } from '@/features/billing/helpers/hasProPerks'
import { computeDropOffPath } from '../../helpers/computeDropOffPath'
import { computeSourceCoordinates } from '../../helpers/computeSourceCoordinates'
import { TotalAnswersInBlock } from '@typebot.io/schemas/features/analytics'
Expand Down Expand Up @@ -64,7 +64,7 @@ export const DropOffEdge = ({
[blockId, totalAnswersInBlocks]
)

const isWorkspaceProPlan = isProPlan(workspace)
const isWorkspaceProPlan = hasProPerks(workspace)

const { totalDroppedUser, dropOffRate } = useMemo(() => {
if (!publishedTypebot || currentBlock?.total === undefined)
Expand Down
5 changes: 3 additions & 2 deletions apps/builder/src/features/publish/components/SharePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { integrationsList } from './embeds/EmbedButton'
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
import { LockTag } from '@/features/billing/components/LockTag'
import { UpgradeButton } from '@/features/billing/components/UpgradeButton'
import { isProPlan } from '@/features/billing/helpers/isProPlan'
import { hasProPerks } from '@/features/billing/helpers/hasProPerks'
import { CustomDomainsDropdown } from '@/features/customDomains/components/CustomDomainsDropdown'
import { TypebotHeader } from '@/features/editor/components/TypebotHeader'
import { parseDefaultPublicId } from '../helpers/parseDefaultPublicId'
Expand Down Expand Up @@ -130,14 +130,15 @@ export const SharePage = () => {
{isNotDefined(typebot?.customDomain) &&
env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME ? (
<>
{isProPlan(workspace) ? (
{hasProPerks(workspace) ? (
<CustomDomainsDropdown
onCustomDomainSelect={handleCustomDomainChange}
/>
) : (
<UpgradeButton
colorScheme="gray"
limitReachedType={t('billing.limitMessage.customDomain')}
excludedPlans={[Plan.STARTER]}
>
<Text mr="2">Add my domain</Text>{' '}
<LockTag plan={Plan.PRO} />
Expand Down
Loading

4 comments on commit b81fcf0

@vercel
Copy link

@vercel vercel bot commented on b81fcf0 Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs.typebot.io
docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on b81fcf0 Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b81fcf0 Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-typebot-io.vercel.app
builder-v2-git-main-typebot-io.vercel.app
app.typebot.io

@vercel
Copy link

@vercel vercel bot commented on b81fcf0 Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

bii.bj
1stop.au
houss.io
wasap.nl
x.cr8.ai
yobot.me
klujo.com
me.cr8.ai
p1314.fun
sifuim.co
wachat.io
wassep.io
247987.com
8jours.top
aginap.com
ai.mprs.in
andreimayer.com.br
bebesemcolicas.com
bot.innovacion.fun
bot.jogodospix.com
bot.jogomilion.com
bot.lucide.contact
bot.neferlopez.com
bot.photonative.de
bot.rajatanjak.com
bot.samplehunt.com
bot.sinalcerto.com
bot.wphelpchat.com
bots.robomotion.io
brandingmkt.com.br
cadu.uninta.edu.br
chat.daftarjer.com
chat.foxbot.online
chat.hand-made.one
chat.tuanpakya.com
chat.webisharp.com
chatbotforthat.com
descobrindotudo.me
dicanatural.online
digitalhelp.com.au
draraquelnutri.com
drcarlosyoshi.site
goalsettingbot.com
leads.gecoelho.com
noticiasnet.online
novoappespiao.site
omarcodosanjos.com
pant.maxbot.com.br
pantherview.cr8.ai
positivobra.com.br
recruit-magnet.com
rollingball.cr8.ai
speciallife.com.br
sub.yolozeeeer.com
survey.digienge.io
tribe.ezbooking.ai
w.onewebcenter.com
zap.techadviser.in
ai.digitaldaftar.in
al.onewebcenter.com
app.danielnalex.com
ask.realversity.org
blazecontrol.com.br
bot.boston-voip.com
bot.cabinpromos.com
viewer-v2-typebot-io.vercel.app
form.shopmercedesbenzsouthorlando.com
mdb.evento.equipeinterna.progenbr.com
bot.studiotecnicoimmobiliaremerelli.it
mdb.assessoria.boaventura.progenbr.com
mdb.assessoria.jtrebesqui.progenbr.com
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
mdb.assessoria.carreirinha.progenbr.com
chrome-os-inquiry-system.itschromeos.com
mdb.assessoria.paulomarques.progenbr.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com
mdb.assessoria.qrcode.ademir.progenbr.com
mdb.assessoria.qrcode.arthur.progenbr.com
mdb.assessoria.qrcode.danilo.progenbr.com
mdb.assessoria.qrcode.marcao.progenbr.com
mdb.assessoria.qrcode.marcio.progenbr.com
mdb.assessoria.qrcode.aloisio.progenbr.com
mdb.assessoria.qrcode.girotto.progenbr.com
mdb.assessoria.qrcode.marinho.progenbr.com
mdb.assessoria.qrcode.rodrigo.progenbr.com
mdb.assessoria.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.desideri.progenbr.com
mdb.assessoria.qrcode.fernanda.progenbr.com
mdb.assessoria.qrcode.jbatista.progenbr.com
mdb.assessoria.qrcode.mauricio.progenbr.com
mdb.assessoria.fernanda.regional.progenbr.com
mdb.assessoria.qrcode.boaventura.progenbr.com
mdb.assessoria.qrcode.jtrebesqui.progenbr.com
mdb.assessoria.qrcode.carreirinha.progenbr.com
mdb.assessoria.qrcode.paulomarques.progenbr.com
mdb.assessoria.qrcode.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.fernanda.regional.progenbr.com

Please sign in to comment.