2
0

(date) Add min and max options to date input block

Closes #792
This commit is contained in:
Baptiste Arnaud
2023-09-08 11:38:23 +02:00
parent bea3332c32
commit a2e24d08a0
12 changed files with 163 additions and 14 deletions

View File

@ -28,6 +28,14 @@ export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
if (format === '') return onOptionsChange({ ...options, format: undefined })
onOptionsChange({ ...options, format })
}
const updateMin = (min: string) => {
if (min === '') return onOptionsChange({ ...options, min: undefined })
onOptionsChange({ ...options, min })
}
const updateMax = (max: string) => {
if (max === '') return onOptionsChange({ ...options, max: undefined })
onOptionsChange({ ...options, max })
}
return (
<Stack spacing={4}>
@ -57,6 +65,18 @@ export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
defaultValue={options.labels.button}
onChange={updateButtonLabel}
/>
<TextInput
label="Min:"
defaultValue={options.min}
placeholder={options.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
onChange={updateMin}
/>
<TextInput
label="Max:"
defaultValue={options.max}
placeholder={options.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
onChange={updateMax}
/>
<TextInput
label="Format:"
defaultValue={options.format}

View File

@ -1275,6 +1275,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -5574,6 +5580,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -9508,6 +9520,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -13582,6 +13600,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -17536,6 +17560,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -21545,6 +21575,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -25617,6 +25653,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [

View File

@ -858,6 +858,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [
@ -4697,6 +4703,12 @@
},
"format": {
"type": "string"
},
"min": {
"type": "string"
},
"max": {
"type": "string"
}
},
"required": [

View File

@ -0,0 +1,48 @@
import { getPrefilledInputValue } from '@/features/chat/helpers/getPrefilledValue'
import { deepParseVariables } from '@/features/variables/deepParseVariable'
import { parseVariables } from '@/features/variables/parseVariables'
import {
DateInputBlock,
DateInputOptions,
SessionState,
Variable,
} from '@typebot.io/schemas'
export const parseDateInput =
(state: SessionState) => (block: DateInputBlock) => {
return {
...block,
options: {
...deepParseVariables(state.typebotsQueue[0].typebot.variables)(
block.options
),
min: parseDateLimit(
block.options.min,
block.options.hasTime,
state.typebotsQueue[0].typebot.variables
),
max: parseDateLimit(
block.options.max,
block.options.hasTime,
state.typebotsQueue[0].typebot.variables
),
},
prefilledValue: getPrefilledInputValue(
state.typebotsQueue[0].typebot.variables
)(block),
}
}
const parseDateLimit = (
limit: DateInputOptions['min'] | DateInputOptions['max'],
hasTime: DateInputOptions['hasTime'],
variables: Variable[]
) => {
if (!limit) return
const parsedLimit = parseVariables(variables)(limit)
const dateIsoNoSecondsRegex = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d/
const matchDateTime = parsedLimit.match(dateIsoNoSecondsRegex)
if (matchDateTime)
return hasTime ? matchDateTime[0] : matchDateTime[0].slice(0, 10)
return parsedLimit
}

View File

@ -27,6 +27,20 @@ export const parseDateReply = (
if (block.options.isRange && !endDate) return { status: 'fail' }
if (
block.options.max &&
(detectedStartDate > new Date(block.options.max) ||
(detectedEndDate && detectedEndDate > new Date(block.options.max)))
)
return { status: 'fail' }
if (
block.options.min &&
(detectedStartDate < new Date(block.options.min) ||
(detectedEndDate && detectedEndDate < new Date(block.options.min)))
)
return { status: 'fail' }
return {
status: 'success',
reply: block.options.isRange ? `${startDate} to ${endDate}` : startDate,

View File

@ -11,7 +11,6 @@ import {
} from '@typebot.io/schemas'
import {
isBubbleBlock,
isDefined,
isInputBlock,
isIntegrationBlock,
isLogicBlock,
@ -24,6 +23,8 @@ import { injectVariableValuesInButtonsInputBlock } from '@/features/blocks/input
import { deepParseVariables } from '@/features/variables/deepParseVariable'
import { computePaymentInputRuntimeOptions } from '@/features/blocks/inputs/payment/computePaymentInputRuntimeOptions'
import { injectVariableValuesInPictureChoiceBlock } from '@/features/blocks/inputs/pictureChoice/injectVariableValuesInPictureChoiceBlock'
import { parseDateInput } from '@/features/blocks/inputs/date/parseDateInput'
import { getPrefilledInputValue } from './getPrefilledValue'
export const executeGroup =
(
@ -152,16 +153,6 @@ const computeRuntimeOptions =
}
}
const getPrefilledInputValue =
(variables: Variable[]) => (block: InputBlock) => {
const variableValue = variables.find(
(variable) =>
variable.id === block.options.variableId && isDefined(variable.value)
)?.value
if (!variableValue || Array.isArray(variableValue)) return
return variableValue
}
const parseBubbleBlock =
(variables: Variable[]) =>
(block: BubbleBlock): ChatReply['messages'][0] => {
@ -227,6 +218,9 @@ export const parseInput =
},
}
}
case InputBlockType.DATE: {
return parseDateInput(state)(block)
}
default: {
return deepParseVariables(state.typebotsQueue[0].typebot.variables)({
...block,

View File

@ -0,0 +1,13 @@
import { isDefined } from '@typebot.io/lib/utils'
import { InputBlock } from '@typebot.io/schemas/features/blocks/schemas'
import { Variable } from '@typebot.io/schemas/features/typebot/variable'
export const getPrefilledInputValue =
(variables: Variable[]) => (block: InputBlock) => {
const variableValue = variables.find(
(variable) =>
variable.id === block.options.variableId && isDefined(variable.value)
)?.value
if (!variableValue || Array.isArray(variableValue)) return
return variableValue
}

View File

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

View File

@ -56,6 +56,8 @@ export const DateForm = (props: Props) => {
from: e.currentTarget.value,
})
}
min={props.options?.min}
max={props.options?.max}
data-testid="from-date"
/>
</div>
@ -81,6 +83,8 @@ export const DateForm = (props: Props) => {
to: e.currentTarget.value,
})
}
min={props.options?.min}
max={props.options?.max}
data-testid="to-date"
/>
</div>

View File

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

View File

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

View File

@ -13,6 +13,8 @@ export const dateInputOptionsSchema = optionBaseSchema.merge(
hasTime: z.boolean(),
isRange: z.boolean(),
format: z.string().optional(),
min: z.string().optional(),
max: z.string().optional(),
})
)