♻️ (builder) Change to features-centric folder structure
This commit is contained in:
committed by
Baptiste Arnaud
parent
3686465a85
commit
643571fe7d
@@ -0,0 +1,13 @@
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { RatingInputBlock } from 'models'
|
||||
|
||||
type Props = {
|
||||
block: RatingInputBlock
|
||||
}
|
||||
|
||||
export const RatingInputContent = ({ block }: Props) => (
|
||||
<Text noOfLines={1} pr="6">
|
||||
Rate from {block.options.buttonType === 'Icons' ? 1 : 0} to{' '}
|
||||
{block.options.length}
|
||||
</Text>
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
import { StarIcon } from '@/components/icons'
|
||||
import { IconProps } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
|
||||
export const RatingInputIcon = (props: IconProps) => (
|
||||
<StarIcon color="orange.500" {...props} />
|
||||
)
|
||||
@@ -0,0 +1,132 @@
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { DropdownList } from '@/components/DropdownList'
|
||||
import { RatingInputOptions, Variable } from 'models'
|
||||
import React from 'react'
|
||||
import { SwitchWithLabel } from '@/components/SwitchWithLabel'
|
||||
import { Input } from '@/components/inputs'
|
||||
import { VariableSearchInput } from '@/components/VariableSearchInput'
|
||||
|
||||
type RatingInputSettingsProps = {
|
||||
options: RatingInputOptions
|
||||
onOptionsChange: (options: RatingInputOptions) => void
|
||||
}
|
||||
|
||||
export const RatingInputSettings = ({
|
||||
options,
|
||||
onOptionsChange,
|
||||
}: RatingInputSettingsProps) => {
|
||||
const handleLengthChange = (length: number) =>
|
||||
onOptionsChange({ ...options, length })
|
||||
|
||||
const handleTypeChange = (buttonType: 'Icons' | 'Numbers') =>
|
||||
onOptionsChange({ ...options, buttonType })
|
||||
|
||||
const handleCustomIconCheck = (isEnabled: boolean) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
customIcon: { ...options.customIcon, isEnabled },
|
||||
})
|
||||
|
||||
const handleIconSvgChange = (svg: string) =>
|
||||
onOptionsChange({ ...options, customIcon: { ...options.customIcon, svg } })
|
||||
|
||||
const handleLeftLabelChange = (left: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, left } })
|
||||
|
||||
const handleRightLabelChange = (right: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, right } })
|
||||
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
Maximum:
|
||||
</FormLabel>
|
||||
<DropdownList
|
||||
onItemSelect={handleLengthChange}
|
||||
items={[3, 4, 5, 6, 7, 8, 9, 10]}
|
||||
currentItem={options.length}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
Type:
|
||||
</FormLabel>
|
||||
<DropdownList
|
||||
onItemSelect={handleTypeChange}
|
||||
items={['Icons', 'Numbers']}
|
||||
currentItem={options.buttonType}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
{options.buttonType === 'Icons' && (
|
||||
<SwitchWithLabel
|
||||
label="Custom icon?"
|
||||
initialValue={options.customIcon.isEnabled}
|
||||
onCheckChange={handleCustomIconCheck}
|
||||
/>
|
||||
)}
|
||||
{options.buttonType === 'Icons' && options.customIcon.isEnabled && (
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="svg">
|
||||
Icon SVG:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="svg"
|
||||
defaultValue={options.customIcon.svg}
|
||||
onChange={handleIconSvgChange}
|
||||
placeholder="<svg>...</svg>"
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
{options.buttonType === 'Icons' ? '1' : '0'} label:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="button"
|
||||
defaultValue={options.labels.left}
|
||||
onChange={handleLeftLabelChange}
|
||||
placeholder="Not likely at all"
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
{options.length} label:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="button"
|
||||
defaultValue={options.labels.right}
|
||||
onChange={handleRightLabelChange}
|
||||
placeholder="Extremely likely"
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="button">
|
||||
Button label:
|
||||
</FormLabel>
|
||||
<Input
|
||||
id="button"
|
||||
defaultValue={options.labels.button}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="variable">
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
3
apps/builder/src/features/blocks/inputs/rating/index.ts
Normal file
3
apps/builder/src/features/blocks/inputs/rating/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { RatingInputSettings } from './components/RatingInputSettingsBody'
|
||||
export { RatingInputContent } from './components/RatingInputContent'
|
||||
export { RatingInputIcon } from './components/RatingInputIcon'
|
||||
@@ -0,0 +1,61 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from 'utils/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from 'utils/playwright/databaseHelpers'
|
||||
import { defaultRatingInputOptions, InputBlockType } from 'models'
|
||||
import { typebotViewer } from 'utils/playwright/testHelpers'
|
||||
import cuid from 'cuid'
|
||||
|
||||
const boxSvg = `<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
|
||||
<line x1="12" y1="22.08" x2="12" y2="12"></line>
|
||||
</svg>`
|
||||
|
||||
test('options should work', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.RATING,
|
||||
options: defaultRatingInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
await page.goto(`/typebots/${typebotId}/edit`)
|
||||
|
||||
await page.click('text=Preview')
|
||||
await expect(typebotViewer(page).locator(`text=Send`)).toBeHidden()
|
||||
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 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="Extremely likely"]', 'Extremely likely')
|
||||
await page.click('text="Restart"')
|
||||
await expect(typebotViewer(page).locator(`text=8`)).toBeHidden()
|
||||
await expect(typebotViewer(page).locator(`text=4`)).toBeHidden()
|
||||
await expect(
|
||||
typebotViewer(page).locator(`text=Not likely at all`)
|
||||
).toBeVisible()
|
||||
await expect(
|
||||
typebotViewer(page).locator(`text=Extremely likely`)
|
||||
).toBeVisible()
|
||||
await typebotViewer(page).locator(`svg >> nth=4`).click()
|
||||
await typebotViewer(page).locator(`text=Send`).click()
|
||||
await expect(typebotViewer(page).locator(`text=5`)).toBeVisible()
|
||||
})
|
||||
Reference in New Issue
Block a user