Skip to content

Commit

Permalink
🚸 (phone) Improve phone input behavior and validation
Browse files Browse the repository at this point in the history
Now accepting landline phone numbers. Consistent select UI on every browser. Auto focus on country select.
  • Loading branch information
baptisteArno committed Mar 9, 2023
1 parent bf1fbf2 commit 6b08df7
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test.describe('Phone input block', () => {

await page.click('text=Restart')
await page.locator(`input[placeholder="+33 XX XX XX XX"]`).type('+33 6 73')
await expect(page.getByRole('combobox')).toHaveText(/🇫🇷.+/)
await expect(page.getByText('🇫🇷')).toBeVisible()
await page.locator('button >> text="Go"').click()
await expect(page.locator('text=Try again bro')).toBeVisible()
await page
Expand Down
2 changes: 1 addition & 1 deletion apps/viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
"db": "workspace:*",
"google-spreadsheet": "3.3.0",
"got": "12.5.3",
"libphonenumber-js": "^1.10.21",
"next": "13.1.6",
"nextjs-cors": "^2.1.2",
"nodemailer": "6.9.1",
"openai": "^3.2.1",
"phone": "^3.1.34",
"qs": "6.11.0",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import phone from 'phone'
import { parsePhoneNumber } from 'libphonenumber-js'

export const formatPhoneNumber = (phoneNumber: string) =>
phone(phoneNumber).phoneNumber
parsePhoneNumber(phoneNumber).formatInternational()
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { phone } from 'phone'
import { isValidPhoneNumber } from 'libphonenumber-js'

export const validatePhoneNumber = (phoneNumber: string) =>
phone(phoneNumber).isValid
isValidPhoneNumber(phoneNumber)
4 changes: 2 additions & 2 deletions apps/viewer/src/features/chat/api/utils/continueBotFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ export const continueBotFlow =
message: 'Current block is not an input block',
})

if (reply && !isReplyValid(reply, block)) return parseRetryMessage(block)

const formattedReply = formatReply(reply, block.type)

if (!formattedReply && !canSkip(block.type)) {
return parseRetryMessage(block)
}
if (formattedReply && !isReplyValid(formattedReply, block))
return parseRetryMessage(block)

const newSessionState = await processAndSaveAnswer(
state,
Expand Down
2 changes: 1 addition & 1 deletion packages/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
"version": "0.0.21",
"version": "0.0.22",
"description": "Javascript library to display typebots on your website",
"type": "module",
"main": "dist/index.js",
Expand Down
16 changes: 16 additions & 0 deletions packages/js/src/components/icons/ChevronDownIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { JSX } from 'solid-js/jsx-runtime'

export const ChevronDownIcon = (props: JSX.SvgSVGAttributes<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2px"
stroke-linecap="round"
stroke-linejoin="round"
{...props}
>
<polyline points="6 9 12 15 18 9" />
</svg>
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ShortTextInput } from '@/components'
import { ChevronDownIcon } from '@/components/icons/ChevronDownIcon'
import { SendButton } from '@/components/SendButton'
import { InputSubmitContent } from '@/types'
import { isMobile } from '@/utils/isMobileSignal'
Expand Down Expand Up @@ -75,7 +76,13 @@ export const PhoneInput = (props: PhoneInputProps) => {
const selectNewCountryCode = (
event: Event & { currentTarget: { value: string } }
) => {
setSelectedCountryCode(event.currentTarget.value)
const code = event.currentTarget.value
setSelectedCountryCode(code)
const dial_code = phoneCountries.find(
(country) => country.code === code
)?.dial_code
if (inputValue() === '' && dial_code) setInputValue(dial_code)
inputRef?.focus()
}

onMount(() => {
Expand All @@ -91,30 +98,37 @@ export const PhoneInput = (props: PhoneInputProps) => {
}}
onKeyDown={submitWhenEnter}
>
<div class="flex flex-1">
<select
onChange={selectNewCountryCode}
class="w-12 pl-2 focus:outline-none rounded-lg typebot-country-select"
>
<option selected>
{
phoneCountries.find(
(country) => selectedCountryCode() === country.code
)?.flag
}
</option>
<For
each={phoneCountries.filter(
(country) => country.code !== selectedCountryCode()
)}
<div class="flex">
<div class="relative typebot-country-select flex justify-center items-center rounded-md">
<div class="pl-2 pr-1 flex items-center gap-2">
<span>
{
phoneCountries.find(
(country) => selectedCountryCode() === country.code
)?.flag
}
</span>
<ChevronDownIcon class="w-3" />
</div>

<select
onChange={selectNewCountryCode}
class="absolute top-0 left-0 w-full h-full cursor-pointer opacity-0"
>
{(country) => (
<option value={country.code}>
{country.name} ({country.dial_code})
</option>
)}
</For>
</select>
<For each={phoneCountries}>
{(country) => (
<option
value={country.code}
selected={country.code === selectedCountryCode()}
>
{country.name}{' '}
{country.dial_code ? `(${country.dial_code})` : ''}
</option>
)}
</For>
</select>
</div>

<ShortTextInput
type="tel"
ref={inputRef}
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
"version": "0.0.21",
"version": "0.0.22",
"description": "React library to display typebots on your website",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
13 changes: 6 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 comments on commit 6b08df7

@vercel
Copy link

@vercel vercel bot commented on 6b08df7 Mar 9, 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 6b08df7 Mar 9, 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 6b08df7 Mar 9, 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 6b08df7 Mar 9, 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

ns8.vn
1stop.au
yobot.me
klujo.com
me.cr8.ai
247987.com
voicehelp.cr8.ai
zap.fundviser.in
app.bouclidom.com
app.chatforms.net
bot.hostnation.de
bot.maitempah.com
bot.phuonghub.com
bot.reviewzer.com
bot.rihabilita.it
cares.urlabout.me
chat.gaswadern.de
fmm.wpwakanda.com
gentleman-shop.fr
k1.kandabrand.com
kp.pedroknoll.com
lb.ticketfute.com
ov1.wpwakanda.com
ov2.wpwakanda.com
ov3.wpwakanda.com
support.triplo.ai
viewer.typebot.io
welcome.triplo.ai
1988.bouclidom.com
andreimayer.com.br
bot.danyservice.it
bot.iconicbrows.it
bot.megafox.com.br
bot.neferlopez.com
bots.robomotion.io
cadu.uninta.edu.br
dicanatural.online
digitalhelp.com.au
goalsettingbot.com
pant.maxbot.com.br
positivobra.com.br
survey.digienge.io
this-is-a-test.com
zap.techadviser.in
ai.digitaldaftar.in
bot.boston-voip.com
bot.cabinpromos.com
bot.digitalbled.com
bot.dsignagency.com
bot.eventhub.com.au
bot.jepierre.com.br
bot.leadgenpod.site
bot.ltmidias.com.br
bot.viralsangat.com
bot.winglabs.com.br
carsalesenquiry.com
type.dericsoncalari.com.br
bot.pinpointinteractive.com
bot.polychromes-project.com
bot.seidinembroseanchetu.it
chat.semanalimpanome.com.br
chatbot.berbelanjabiz.trade
designguide.techyscouts.com
jcapp.virtuesocialmedia.com
liveconvert2.kandalearn.com
presente.empresarias.com.mx
sell.sellthemotorhome.co.uk
anamnese.odontopavani.com.br
austin.channelautomation.com
bot.marketingplusmindset.com
bot.seidibergamoseanchetu.it
desabafe.sergiolimajr.com.br
download.venturemarketing.in
jc-app.virtuesocialmedia.com
piazzatorre.barrettamario.it
type.cookieacademyonline.com
upload.atlasoutfittersk9.com
bot.brigadeirosemdrama.com.br
forms.escoladeautomacao.com.br
onboarding.libertydreamcare.ie
type.talitasouzamarques.com.br
agendamento.sergiolimajr.com.br
anamnese.clinicamegasjdr.com.br
bookings.littlepartymonkeys.com
bot.comercializadoraomicron.com
elevateyourmind.groovepages.com
viewer-v2-typebot-io.vercel.app
yourfeedback.comebackreward.com
gerador.verificadordehospedes.com
personal-trainer.barrettamario.it
preagendamento.sergiolimajr.com.br
studiotecnicoimmobiliaremerelli.it
download.thailandmicespecialist.com
register.thailandmicespecialist.com
bot.studiotecnicoimmobiliaremerelli.it
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
chrome-os-inquiry-system.itschromeos.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com

Please sign in to comment.