2
0

(rating) Add start number option in Rating block

This commit is contained in:
Baptiste Arnaud
2024-02-06 17:01:53 +01:00
parent 5a7ec5c921
commit 3e2533b934
11 changed files with 71 additions and 13 deletions

View File

@ -17,7 +17,9 @@ export const RatingInputContent = ({ variableId, block }: Props) => {
) : ( ) : (
<Text noOfLines={1} pr="6"> <Text noOfLines={1} pr="6">
{t('blocks.inputs.rating.from.label')}{' '} {t('blocks.inputs.rating.from.label')}{' '}
{block.options?.buttonType === 'Icons' ? 1 : 0}{' '} {block.options?.buttonType === 'Icons'
? 1
: block.options?.startsAt ?? defaultRatingInputOptions.startsAt}{' '}
{t('blocks.inputs.rating.to.label')}{' '} {t('blocks.inputs.rating.to.label')}{' '}
{block.options?.length ?? defaultRatingInputOptions.length} {block.options?.length ?? defaultRatingInputOptions.length}
</Text> </Text>

View File

@ -3,7 +3,7 @@ import { DropdownList } from '@/components/DropdownList'
import { RatingInputBlock, Variable } from '@typebot.io/schemas' import { RatingInputBlock, Variable } from '@typebot.io/schemas'
import React from 'react' import React from 'react'
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel' import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
import { TextInput } from '@/components/inputs' import { NumberInput, TextInput } from '@/components/inputs'
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput' import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants' import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
import { useTranslate } from '@tolgee/react' import { useTranslate } from '@tolgee/react'
@ -46,11 +46,15 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
const handleOneClickSubmitChange = (isOneClickSubmitEnabled: boolean) => const handleOneClickSubmitChange = (isOneClickSubmitEnabled: boolean) =>
onOptionsChange({ ...options, isOneClickSubmitEnabled }) onOptionsChange({ ...options, isOneClickSubmitEnabled })
const updateStartsAt = (startsAt: number | `{{${string}}}` | undefined) =>
onOptionsChange({ ...options, startsAt })
const length = options?.length ?? defaultRatingInputOptions.length const length = options?.length ?? defaultRatingInputOptions.length
const isOneClickSubmitEnabled = const isOneClickSubmitEnabled =
options?.isOneClickSubmitEnabled ?? options?.isOneClickSubmitEnabled ??
defaultRatingInputOptions.isOneClickSubmitEnabled defaultRatingInputOptions.isOneClickSubmitEnabled
const buttonType = options?.buttonType ?? defaultRatingInputOptions.buttonType
return ( return (
<Stack spacing={4}> <Stack spacing={4}>
<Stack> <Stack>
@ -71,13 +75,20 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
<DropdownList <DropdownList
onItemSelect={handleTypeChange} onItemSelect={handleTypeChange}
items={['Icons', 'Numbers'] as const} items={['Icons', 'Numbers'] as const}
currentItem={ currentItem={buttonType}
options?.buttonType ?? defaultRatingInputOptions.buttonType
}
/> />
</Stack> </Stack>
{options?.buttonType === 'Icons' && ( {buttonType === 'Numbers' && (
<NumberInput
defaultValue={options?.startsAt ?? defaultRatingInputOptions.startsAt}
onValueChange={updateStartsAt}
label="Starts at"
direction="row"
/>
)}
{buttonType === 'Icons' && (
<SwitchWithLabel <SwitchWithLabel
label={t('blocks.inputs.rating.settings.customIcon.label')} label={t('blocks.inputs.rating.settings.customIcon.label')}
initialValue={ initialValue={
@ -87,7 +98,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
onCheckChange={handleCustomIconCheck} onCheckChange={handleCustomIconCheck}
/> />
)} )}
{options?.buttonType === 'Icons' && options.customIcon?.isEnabled && ( {buttonType === 'Icons' && options?.customIcon?.isEnabled && (
<TextInput <TextInput
label={t('blocks.inputs.rating.settings.iconSVG.label')} label={t('blocks.inputs.rating.settings.iconSVG.label')}
defaultValue={options.customIcon.svg} defaultValue={options.customIcon.svg}
@ -97,7 +108,10 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
)} )}
<TextInput <TextInput
label={t('blocks.inputs.rating.settings.rateLabel.label', { label={t('blocks.inputs.rating.settings.rateLabel.label', {
rate: options?.buttonType === 'Icons' ? '1' : '0', rate:
buttonType === 'Icons'
? '1'
: options?.startsAt ?? defaultRatingInputOptions.startsAt,
})} })}
defaultValue={options?.labels?.left} defaultValue={options?.labels?.left}
onChange={handleLeftLabelChange} onChange={handleLeftLabelChange}

View File

@ -15946,6 +15946,14 @@
"length": { "length": {
"type": "number" "type": "number"
}, },
"startsAt": {
"anyOf": [
{
"type": "number"
},
{}
]
},
"labels": { "labels": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -6231,6 +6231,14 @@
"length": { "length": {
"type": "number" "type": "number"
}, },
"startsAt": {
"anyOf": [
{
"type": "number"
},
{}
]
},
"labels": { "labels": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -252,6 +252,25 @@ export const parseInput =
case InputBlockType.DATE: { case InputBlockType.DATE: {
return parseDateInput(state)(block) return parseDateInput(state)(block)
} }
case InputBlockType.RATING: {
const parsedBlock = deepParseVariables(
state.typebotsQueue[0].typebot.variables
)({
...block,
prefilledValue: getPrefilledInputValue(
state.typebotsQueue[0].typebot.variables
)(block),
})
return {
...parsedBlock,
options: {
...parsedBlock.options,
startsAt: isNotEmpty(parsedBlock.options?.startsAt as string)
? Number(parsedBlock.options?.startsAt)
: undefined,
},
}
}
default: { default: {
return deepParseVariables(state.typebotsQueue[0].typebot.variables)({ return deepParseVariables(state.typebotsQueue[0].typebot.variables)({
...block, ...block,

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.2.40", "version": "0.2.41",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -45,7 +45,10 @@ export const RatingForm = (props: Props) => {
defaultRatingInputOptions.length) + defaultRatingInputOptions.length) +
((props.block.options?.buttonType ?? ((props.block.options?.buttonType ??
defaultRatingInputOptions.buttonType) === 'Numbers' defaultRatingInputOptions.buttonType) === 'Numbers'
? 1 ? -(
((props.block.options?.startsAt as number | undefined) ??
defaultRatingInputOptions.startsAt) - 1
)
: 0) : 0)
) )
)} )}
@ -58,7 +61,8 @@ export const RatingForm = (props: Props) => {
idx() + idx() +
((props.block.options?.buttonType ?? ((props.block.options?.buttonType ??
defaultRatingInputOptions.buttonType) === 'Numbers' defaultRatingInputOptions.buttonType) === 'Numbers'
? 0 ? (props.block.options?.startsAt as number | undefined) ??
defaultRatingInputOptions.startsAt
: 1) : 1)
} }
onClick={handleClick} onClick={handleClick}

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/nextjs", "name": "@typebot.io/nextjs",
"version": "0.2.40", "version": "0.2.41",
"description": "Convenient library to display typebots on your Next.js website", "description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.2.40", "version": "0.2.41",
"description": "Convenient library to display typebots on your React app", "description": "Convenient library to display typebots on your React app",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -7,6 +7,7 @@ export const defaultRatingInputOptions = {
labels: { labels: {
button: defaultButtonLabel, button: defaultButtonLabel,
}, },
startsAt: 0,
customIcon: { isEnabled: false }, customIcon: { isEnabled: false },
isOneClickSubmitEnabled: false, isOneClickSubmitEnabled: false,
} as const satisfies RatingInputBlock['options'] } as const satisfies RatingInputBlock['options']

View File

@ -1,4 +1,5 @@
import { z } from '../../../../zod' import { z } from '../../../../zod'
import { variableStringSchema } from '../../../utils'
import { optionBaseSchema, blockBaseSchema } from '../../shared' import { optionBaseSchema, blockBaseSchema } from '../../shared'
import { InputBlockType } from '../constants' import { InputBlockType } from '../constants'
@ -6,6 +7,7 @@ export const ratingInputOptionsSchema = optionBaseSchema.merge(
z.object({ z.object({
buttonType: z.literal('Icons').or(z.literal('Numbers')).optional(), buttonType: z.literal('Icons').or(z.literal('Numbers')).optional(),
length: z.number().optional(), length: z.number().optional(),
startsAt: z.number().or(variableStringSchema).optional(),
labels: z labels: z
.object({ .object({
left: z.string().optional(), left: z.string().optional(),