feat(bot): 💄 Responsive rating input
This commit is contained in:
@ -7,6 +7,7 @@ type Props = {
|
||||
|
||||
export const RatingInputContent = ({ block }: Props) => (
|
||||
<Text noOfLines={1} pr="6">
|
||||
Rate from 1 to {block.options.length}
|
||||
Rate from {block.options.buttonType === 'Icons' ? 1 : 0} to{' '}
|
||||
{block.options.length}
|
||||
</Text>
|
||||
)
|
||||
|
@ -33,9 +33,6 @@ export const RatingInputSettings = ({
|
||||
const handleLeftLabelChange = (left: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, left } })
|
||||
|
||||
const handleMiddleLabelChange = (middle: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, middle } })
|
||||
|
||||
const handleRightLabelChange = (right: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, right } })
|
||||
|
||||
@ -92,7 +89,7 @@ export const RatingInputSettings = ({
|
||||
)}
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
1 label:
|
||||
{options.buttonType === 'Icons' ? '1' : '0'} label:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="button"
|
||||
@ -101,19 +98,6 @@ export const RatingInputSettings = ({
|
||||
placeholder="Not likely at all"
|
||||
/>
|
||||
</Stack>
|
||||
{options.length >= 4 && (
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
{Math.floor(options.length / 2)} label:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="button"
|
||||
defaultValue={options.labels.middle}
|
||||
onChange={handleMiddleLabelChange}
|
||||
placeholder="Neutral"
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
{options.length} label:
|
||||
|
@ -39,15 +39,14 @@ test('options should work', async ({ page }) => {
|
||||
await typebotViewer(page).locator(`text=8`).click()
|
||||
await typebotViewer(page).locator(`text=Send`).click()
|
||||
await expect(typebotViewer(page).locator(`text=8`)).toBeVisible()
|
||||
await page.click('text=Rate from 1 to 10')
|
||||
await page.click('text=10')
|
||||
await page.click('text=5')
|
||||
await page.click('text=Rate from 0 to 10')
|
||||
await page.click('text="10"')
|
||||
await page.click('text="5"')
|
||||
await page.click('text=Numbers')
|
||||
await page.click('text=Icons')
|
||||
await page.click('text="Custom icon?"')
|
||||
await page.fill('[placeholder="<svg>...</svg>"]', boxSvg)
|
||||
await page.fill('[placeholder="Not likely at all"]', 'Not likely at all')
|
||||
await page.fill('[placeholder="Neutral"]', 'Neutral')
|
||||
await page.fill('[placeholder="Extremely likely"]', 'Extremely likely')
|
||||
await page.click('text="Restart"')
|
||||
await expect(typebotViewer(page).locator(`text=8`)).toBeHidden()
|
||||
@ -55,7 +54,6 @@ test('options should work', async ({ page }) => {
|
||||
await expect(
|
||||
typebotViewer(page).locator(`text=Not likely at all`)
|
||||
).toBeVisible()
|
||||
await expect(typebotViewer(page).locator(`text=Neutral`)).toBeVisible()
|
||||
await expect(
|
||||
typebotViewer(page).locator(`text=Extremely likely`)
|
||||
).toBeVisible()
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { RatingInputOptions, RatingInputBlock } from 'models'
|
||||
import React, { FormEvent, useRef, useState } from 'react'
|
||||
import React, { FormEvent, useState } from 'react'
|
||||
import { isDefined, isEmpty, isNotDefined } from 'utils'
|
||||
import { InputSubmitContent } from '../InputChatBlock'
|
||||
import { SendButton } from './SendButton'
|
||||
@ -11,7 +11,6 @@ type Props = {
|
||||
|
||||
export const RatingForm = ({ block, onSubmit }: Props) => {
|
||||
const [rating, setRating] = useState<number>()
|
||||
const scaleElement = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const handleSubmit = (e: FormEvent) => {
|
||||
e.preventDefault()
|
||||
@ -23,33 +22,32 @@ export const RatingForm = ({ block, onSubmit }: Props) => {
|
||||
|
||||
return (
|
||||
<form className="flex flex-col" onSubmit={handleSubmit}>
|
||||
<div className="flex flex-col" ref={scaleElement}>
|
||||
<div className="flex">
|
||||
{Array.from(Array(block.options.length)).map((_, idx) => (
|
||||
<RatingButton
|
||||
{...block.options}
|
||||
key={idx}
|
||||
rating={rating}
|
||||
idx={idx + 1}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between mr-2 mb-2">
|
||||
{<span className="text-sm w-full ">{block.options.labels.left}</span>}
|
||||
{!isEmpty(block.options.labels.middle) && (
|
||||
<span className="text-sm w-full text-center">
|
||||
{block.options.labels.middle}
|
||||
</span>
|
||||
)}
|
||||
{
|
||||
<span className="text-sm w-full text-right">
|
||||
{block.options.labels.right}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
{block.options.labels.left && (
|
||||
<span className="text-sm w-full mb-2 rating-label">
|
||||
{block.options.labels.left}
|
||||
</span>
|
||||
)}
|
||||
<div className="flex flex-wrap justify-center">
|
||||
{Array.from(
|
||||
Array(
|
||||
block.options.length +
|
||||
(block.options.buttonType === 'Numbers' ? 1 : 0)
|
||||
)
|
||||
).map((_, idx) => (
|
||||
<RatingButton
|
||||
{...block.options}
|
||||
key={idx}
|
||||
rating={rating}
|
||||
idx={idx + (block.options.buttonType === 'Numbers' ? 0 : 1)}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{block.options.labels.right && (
|
||||
<span className="text-sm w-full text-right mb-2 pr-2 rating-label">
|
||||
{block.options.labels.right}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end mr-2">
|
||||
{isDefined(rating) && (
|
||||
|
@ -20,7 +20,6 @@ export const ratingInputOptionsSchema = optionBaseSchema.and(
|
||||
labels: z.object({
|
||||
left: z.string().optional(),
|
||||
right: z.string().optional(),
|
||||
middle: z.string().optional(),
|
||||
button: z.string(),
|
||||
}),
|
||||
customIcon: z.object({
|
||||
|
Reference in New Issue
Block a user