feat(bot): ⚡️ Add required option on file upload input
This commit is contained in:
@ -24,6 +24,7 @@ export const InputChatBlock = ({
|
||||
hasAvatar,
|
||||
hasGuestAvatar,
|
||||
onTransitionEnd,
|
||||
onSkip,
|
||||
}: {
|
||||
block: InputBlock
|
||||
hasGuestAvatar: boolean
|
||||
@ -32,6 +33,7 @@ export const InputChatBlock = ({
|
||||
answerContent?: InputSubmitContent,
|
||||
isRetry?: boolean
|
||||
) => void
|
||||
onSkip: () => void
|
||||
}) => {
|
||||
const { typebot } = useTypebot()
|
||||
const { addAnswer } = useAnswers()
|
||||
@ -84,6 +86,7 @@ export const InputChatBlock = ({
|
||||
<Input
|
||||
block={block}
|
||||
onSubmit={handleSubmit}
|
||||
onSkip={onSkip}
|
||||
defaultValue={defaultValue?.toString()}
|
||||
hasGuestAvatar={hasGuestAvatar}
|
||||
/>
|
||||
@ -94,11 +97,13 @@ export const InputChatBlock = ({
|
||||
const Input = ({
|
||||
block,
|
||||
onSubmit,
|
||||
onSkip,
|
||||
defaultValue,
|
||||
hasGuestAvatar,
|
||||
}: {
|
||||
block: InputBlock
|
||||
onSubmit: (value: InputSubmitContent) => void
|
||||
onSkip: () => void
|
||||
defaultValue?: string
|
||||
hasGuestAvatar: boolean
|
||||
}) => {
|
||||
@ -132,6 +137,8 @@ const Input = ({
|
||||
case InputBlockType.RATING:
|
||||
return <RatingForm block={block} onSubmit={onSubmit} />
|
||||
case InputBlockType.FILE:
|
||||
return <FileUploadForm block={block} onSubmit={onSubmit} />
|
||||
return (
|
||||
<FileUploadForm block={block} onSubmit={onSubmit} onSkip={onSkip} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -9,14 +9,16 @@ import { SendButton, Spinner } from './SendButton'
|
||||
type Props = {
|
||||
block: FileInputBlock
|
||||
onSubmit: (url: InputSubmitContent) => void
|
||||
onSkip: () => void
|
||||
}
|
||||
|
||||
export const FileUploadForm = ({
|
||||
block: {
|
||||
id,
|
||||
options: { isMultipleAllowed, labels, sizeLimit },
|
||||
options: { isMultipleAllowed, labels, sizeLimit, isRequired },
|
||||
},
|
||||
onSubmit,
|
||||
onSkip,
|
||||
}: Props) => {
|
||||
const {
|
||||
isPreview,
|
||||
@ -169,6 +171,18 @@ export const FileUploadForm = ({
|
||||
</>
|
||||
)}
|
||||
</label>
|
||||
{selectedFiles.length === 0 && isRequired === false && (
|
||||
<div className="flex justify-end">
|
||||
<button
|
||||
className={
|
||||
'py-2 px-4 justify-center font-semibold rounded-md text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button '
|
||||
}
|
||||
onClick={onSkip}
|
||||
>
|
||||
Skip
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{isMultipleAllowed && selectedFiles.length > 0 && !isUploading && (
|
||||
<div className="flex justify-end">
|
||||
<div className="flex">
|
||||
|
@ -243,6 +243,8 @@ const ChatChunks = ({
|
||||
keepShowingHostAvatar,
|
||||
onDisplayNextBlock,
|
||||
}: Props) => {
|
||||
const [isSkipped, setIsSkipped] = useState(false)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const avatarSideContainerRef = useRef<any>()
|
||||
|
||||
@ -250,6 +252,11 @@ const ChatChunks = ({
|
||||
refreshTopOffset()
|
||||
})
|
||||
|
||||
const skipInput = () => {
|
||||
onDisplayNextBlock()
|
||||
setIsSkipped(true)
|
||||
}
|
||||
|
||||
const refreshTopOffset = () =>
|
||||
avatarSideContainerRef.current?.refreshTopOffset()
|
||||
|
||||
@ -260,7 +267,9 @@ const ChatChunks = ({
|
||||
<AvatarSideContainer
|
||||
ref={avatarSideContainerRef}
|
||||
hostAvatarSrc={hostAvatar.src}
|
||||
keepShowing={keepShowingHostAvatar || isDefined(input)}
|
||||
keepShowing={
|
||||
(keepShowingHostAvatar || isDefined(input)) && !isSkipped
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
@ -287,21 +296,24 @@ const ChatChunks = ({
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</div>
|
||||
<CSSTransition
|
||||
classNames="bubble"
|
||||
timeout={500}
|
||||
unmountOnExit
|
||||
in={isDefined(input)}
|
||||
>
|
||||
{input && (
|
||||
<InputChatBlock
|
||||
block={input}
|
||||
onTransitionEnd={onDisplayNextBlock}
|
||||
hasAvatar={hostAvatar.isEnabled}
|
||||
hasGuestAvatar={hasGuestAvatar}
|
||||
/>
|
||||
)}
|
||||
</CSSTransition>
|
||||
{!isSkipped && (
|
||||
<CSSTransition
|
||||
classNames="bubble"
|
||||
timeout={500}
|
||||
unmountOnExit
|
||||
in={isDefined(input)}
|
||||
>
|
||||
{input && (
|
||||
<InputChatBlock
|
||||
block={input}
|
||||
onTransitionEnd={onDisplayNextBlock}
|
||||
onSkip={skipInput}
|
||||
hasAvatar={hostAvatar.isEnabled}
|
||||
hasGuestAvatar={hasGuestAvatar}
|
||||
/>
|
||||
)}
|
||||
</CSSTransition>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user