chatbot-template/components/prompt-form.tsx

116 lines
3.3 KiB
TypeScript
Raw Normal View History

2024-03-14 20:00:52 +03:00
'use client'
2023-06-07 16:17:59 +04:00
import * as React from 'react'
2023-06-02 15:33:48 -04:00
import Textarea from 'react-textarea-autosize'
2024-03-14 20:00:52 +03:00
import { useActions, useUIState } from 'ai/rsc'
import { UserMessage } from './stocks/message'
import { type AI } from '@/lib/chat/actions'
import { Button } from '@/components/ui/button'
import { IconArrowElbow, IconPlus } from '@/components/ui/icons'
2023-06-07 16:17:59 +04:00
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip'
2024-03-14 20:00:52 +03:00
import { useEnterSubmit } from '@/lib/hooks/use-enter-submit'
import { nanoid } from 'nanoid'
import { useRouter } from 'next/navigation'
2023-05-19 12:33:56 -04:00
export function PromptForm({
input,
2024-03-14 20:00:52 +03:00
setInput
}: {
input: string
setInput: (value: string) => void
}) {
const router = useRouter()
const { formRef, onKeyDown } = useEnterSubmit()
2023-06-07 16:17:59 +04:00
const inputRef = React.useRef<HTMLTextAreaElement>(null)
2024-03-14 20:00:52 +03:00
const { submitUserMessage } = useActions()
const [_, setMessages] = useUIState<typeof AI>()
2023-06-07 16:17:59 +04:00
React.useEffect(() => {
if (inputRef.current) {
inputRef.current.focus()
}
}, [])
2023-05-19 12:33:56 -04:00
return (
<form
2024-03-14 20:00:52 +03:00
ref={formRef}
onSubmit={async (e: any) => {
2023-06-02 15:33:48 -04:00
e.preventDefault()
2024-03-14 20:00:52 +03:00
// Blur focus on mobile
if (window.innerWidth < 600) {
e.target['message']?.blur()
}
2024-03-14 20:00:52 +03:00
const value = input.trim()
2023-06-02 15:33:48 -04:00
setInput('')
2024-03-14 20:00:52 +03:00
if (!value) return
// Optimistically add user message UI
setMessages(currentMessages => [
...currentMessages,
{
id: nanoid(),
display: <UserMessage>{value}</UserMessage>
}
])
// Submit and get response message
const responseMessage = await submitUserMessage(value)
setMessages(currentMessages => [...currentMessages, responseMessage])
2023-05-19 12:33:56 -04:00
}}
>
2024-03-14 20:00:52 +03:00
<div className="relative flex max-h-60 w-full grow flex-col overflow-hidden bg-background px-8 sm:rounded-md sm:border sm:px-12">
<Tooltip>
<TooltipTrigger asChild>
2024-03-14 20:00:52 +03:00
<Button
variant="outline"
size="icon"
className="absolute left-0 top-[14px] size-8 rounded-full bg-background p-0 sm:left-4"
2024-03-14 20:00:52 +03:00
onClick={() => {
router.push('/new')
}}
>
<IconPlus />
<span className="sr-only">New Chat</span>
2024-03-14 20:00:52 +03:00
</Button>
</TooltipTrigger>
<TooltipContent>New Chat</TooltipContent>
</Tooltip>
<Textarea
ref={inputRef}
tabIndex={0}
onKeyDown={onKeyDown}
2024-03-14 20:00:52 +03:00
placeholder="Send a message."
className="min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.3rem] focus-within:outline-none sm:text-sm"
autoFocus
spellCheck={false}
autoComplete="off"
autoCorrect="off"
name="message"
rows={1}
value={input}
onChange={e => setInput(e.target.value)}
/>
<div className="absolute right-0 top-[13px] sm:right-4">
<Tooltip>
<TooltipTrigger asChild>
2024-03-14 20:00:52 +03:00
<Button type="submit" size="icon" disabled={input === ''}>
<IconArrowElbow />
<span className="sr-only">Send message</span>
</Button>
</TooltipTrigger>
<TooltipContent>Send message</TooltipContent>
</Tooltip>
</div>
</div>
2023-05-19 12:33:56 -04:00
</form>
2023-06-02 15:33:48 -04:00
)
2023-05-19 12:33:56 -04:00
}