diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts
index 515d947..7fc3ec8 100644
--- a/app/api/chat/route.ts
+++ b/app/api/chat/route.ts
@@ -42,7 +42,7 @@ export const POST = auth(async function POST(req: Request) {
if (req.auth?.user?.email == null) {
return
}
- const title = json.messages[0].content.substring(0, 20)
+ const title = json.messages[0].content.substring(0, 100)
const userId = (req as any).auth?.user?.email
const id = json.id ?? nanoid()
const createdAt = Date.now()
diff --git a/components/chat-list.tsx b/components/chat-list.tsx
index 808fd90..cf6b830 100644
--- a/components/chat-list.tsx
+++ b/components/chat-list.tsx
@@ -4,25 +4,24 @@ import { type Message } from 'ai-connector'
import { Separator } from '@/components/ui/separator'
import { ChatMessage } from '@/components/chat-message'
-import { EmptyScreen } from '@/components/empty-screen'
export interface ChatList {
messages: Message[]
}
export function ChatList({ messages }: ChatList) {
+ if (!messages.length) {
+ return null
+ }
+
return (
- {messages.length > 0 ? (
- messages.map((message, index) => (
-
-
- {index < messages.length - 1 && }
-
- ))
- ) : (
-
- )}
+ {messages.map((message, index) => (
+
+
+ {index < messages.length - 1 && }
+
+ ))}
)
}
diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx
index c3c0f6b..6bd0a40 100644
--- a/components/chat-panel.tsx
+++ b/components/chat-panel.tsx
@@ -1,6 +1,4 @@
-'use client'
-
-import { UseChatHelpers } from 'ai-connector'
+import { type UseChatHelpers } from 'ai-connector'
import { Button } from '@/components/ui/button'
import { ExternalLink } from '@/components/external-link'
@@ -11,7 +9,13 @@ import { IconRefresh, IconStop } from '@/components/ui/icons'
export interface ChatPanelProps
extends Pick<
UseChatHelpers,
- 'append' | 'isLoading' | 'reload' | 'messages' | 'stop'
+ | 'append'
+ | 'isLoading'
+ | 'reload'
+ | 'messages'
+ | 'stop'
+ | 'input'
+ | 'setInput'
> {
id?: string
}
@@ -21,6 +25,8 @@ export function ChatPanel({
stop,
append,
reload,
+ input,
+ setInput,
messages
}: ChatPanelProps) {
return (
@@ -58,6 +64,8 @@ export function ChatPanel({
role: 'user'
})
}}
+ input={input}
+ setInput={setInput}
isLoading={isLoading}
/>
diff --git a/components/chat.tsx b/components/chat.tsx
index c7fff5d..4352cc6 100644
--- a/components/chat.tsx
+++ b/components/chat.tsx
@@ -2,24 +2,32 @@
import { useChat, type Message } from 'ai-connector'
+import { cn } from '@/lib/utils'
import { ChatList } from '@/components/chat-list'
import { ChatPanel } from '@/components/chat-panel'
+import { EmptyScreen } from '@/components/empty-screen'
-export interface ChatProps {
- // create?: (input: string) => Chat | undefined;
+export interface ChatProps extends React.ComponentProps<'div'> {
initialMessages?: Message[]
id?: string
}
-export function Chat({ id, initialMessages }: ChatProps) {
- const { messages, append, reload, stop, isLoading } = useChat({
- initialMessages,
- id
- })
+export function Chat({ id, initialMessages, className }: ChatProps) {
+ const { messages, append, reload, stop, isLoading, input, setInput } =
+ useChat({
+ initialMessages,
+ id
+ })
return (
-
-
+ <>
+
+ {messages.length ? (
+
+ ) : (
+
+ )}
+
-
+ >
)
}
diff --git a/components/empty-screen.tsx b/components/empty-screen.tsx
index b2804c4..e739b31 100644
--- a/components/empty-screen.tsx
+++ b/components/empty-screen.tsx
@@ -1,8 +1,8 @@
-import { useChatStore } from '@/lib/hooks/use-chat-store'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { ExternalLink } from '@/components/external-link'
import { IconArrowRight } from '@/components/ui/icons'
+import { UseChatHelpers } from 'ai-connector'
const exampleMessages = [
{
@@ -19,37 +19,37 @@ const exampleMessages = [
}
]
-export function EmptyScreen({ className }: React.ComponentProps<'div'>) {
- const { setDefaultMessage } = useChatStore()
-
+export function EmptyScreen({ setInput }: Pick) {
return (
-
-
- Welcome to Next.js Chatbot!
-
-
- This is an open source AI chatbot app built with{' '}
- Next.js and{' '}
-
- Vercel KV
-
- .
-
-
- You can start a conversation here or try the following examples:
-
-
- {exampleMessages.map((message, index) => (
-
- ))}
+
+
+
+ Welcome to Next.js Chatbot!
+
+
+ This is an open source AI chatbot app built with{' '}
+ Next.js and{' '}
+
+ Vercel KV
+
+ .
+
+
+ You can start a conversation here or try the following examples:
+
+
+ {exampleMessages.map((message, index) => (
+
+ ))}
+
)
diff --git a/components/header.tsx b/components/header.tsx
index b2ffc03..d59f67a 100644
--- a/components/header.tsx
+++ b/components/header.tsx
@@ -21,7 +21,7 @@ export async function Header() {
-
+
@@ -33,15 +33,15 @@ export async function Header() {
rel="noopener noreferrer"
className={cn(buttonVariants({ variant: 'outline' }))}
>
-
-
GitHub
+
+
GitHub
-
+
Deploy to Vercel
Deploy
diff --git a/components/login-button.tsx b/components/login-button.tsx
new file mode 100644
index 0000000..3aef62d
--- /dev/null
+++ b/components/login-button.tsx
@@ -0,0 +1,40 @@
+'use client'
+
+import * as React from 'react'
+import { signIn } from '@auth/nextjs/client'
+
+import { cn } from '@/lib/utils'
+import { Button, type ButtonProps } from '@/components/ui/button'
+import { IconGitHub, IconSpinner } from '@/components/ui/icons'
+
+interface LoginButtonProps extends ButtonProps {
+ text?: string
+}
+
+export function LoginButton({
+ className,
+ text = 'Login with GitHub',
+ ...props
+}: LoginButtonProps) {
+ const [isLoading, setIsLoading] = React.useState(false)
+
+ return (
+
+ )
+}
diff --git a/components/prompt-form.tsx b/components/prompt-form.tsx
index c250dcb..1fbc7b1 100644
--- a/components/prompt-form.tsx
+++ b/components/prompt-form.tsx
@@ -1,10 +1,7 @@
-'use client'
-
import * as React from 'react'
import Link from 'next/link'
import Textarea from 'react-textarea-autosize'
-import { useChatStore } from '@/lib/hooks/use-chat-store'
import { useEnterSubmit } from '@/lib/hooks/use-enter-submit'
import { cn } from '@/lib/utils'
import { Button, buttonVariants } from '@/components/ui/button'
@@ -15,15 +12,20 @@ import {
TooltipTrigger
} from '@/components/ui/tooltip'
import { IconArrowElbow, IconPlus } from '@/components/ui/icons'
+import { UseChatHelpers } from 'ai-connector'
-export interface PromptProps {
+export interface PromptProps
+ extends Pick
{
onSubmit: (value: string) => void
isLoading: boolean
}
-export function PromptForm({ onSubmit, isLoading }: PromptProps) {
- const { defaultMessage } = useChatStore()
- const [input, setInput] = React.useState(defaultMessage)
+export function PromptForm({
+ onSubmit,
+ input,
+ setInput,
+ isLoading
+}: PromptProps) {
const { formRef, onKeyDown } = useEnterSubmit()
const inputRef = React.useRef(null)
@@ -33,10 +35,6 @@ export function PromptForm({ onSubmit, isLoading }: PromptProps) {
}
}, [])
- React.useEffect(() => {
- setInput(defaultMessage)
- }, [defaultMessage])
-
return (
diff --git a/components/sidebar.tsx b/components/sidebar.tsx
index 75554e4..a4cbbc5 100644
--- a/components/sidebar.tsx
+++ b/components/sidebar.tsx
@@ -29,10 +29,7 @@ export function Sidebar({ session, children }: SidebarProps) {
Toggle Sidebar
-
+
Chat History
diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx
index 6d12ff7..97deab9 100644
--- a/components/ui/sheet.tsx
+++ b/components/ui/sheet.tsx
@@ -2,7 +2,6 @@
import * as React from 'react'
import * as SheetPrimitive from '@radix-ui/react-dialog'
-import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
import { IconClose } from '@/components/ui/icons'
@@ -42,33 +41,17 @@ const SheetOverlay = React.forwardRef<
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
-const sheetVariants = cva(
- 'fixed z-50 h-full scale-100 gap-4 border bg-background p-6 opacity-100 shadow-lg',
- {
- variants: {
- position: {
- left: 'data-[state=closed]:animate-slide-to-left data-[state=open]:animate-slide-from-left',
- right: 'h-full animate-in slide-in-from-right duration-300'
- }
- },
- defaultVariants: {
- position: 'left'
- }
- }
-)
-
-export interface DialogContentProps
- extends React.ComponentPropsWithoutRef,
- VariantProps {}
-
const SheetContent = React.forwardRef<
React.ElementRef,
- DialogContentProps
->(({ position, className, children, ...props }, ref) => (
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
{children}
@@ -85,13 +68,7 @@ const SheetHeader = ({
className,
...props
}: React.HTMLAttributes) => (
-
+
)
SheetHeader.displayName = 'SheetHeader'
diff --git a/components/user-menu.tsx b/components/user-menu.tsx
index 280fa3c..c5b96e2 100644
--- a/components/user-menu.tsx
+++ b/components/user-menu.tsx
@@ -1,37 +1,24 @@
'use client'
import * as React from 'react'
-import { signIn } from '@auth/nextjs/client'
import { type Session } from '@auth/nextjs/types'
-import { Button } from '@/components/ui/button'
-import { IconSpinner } from '@/components/ui/icons'
+import { LoginButton } from '@/components/login-button'
export interface UserMenuProps {
session?: Session
}
export function UserMenu({ session }: UserMenuProps) {
- const [isLoading, setIsLoading] = React.useState(false)
-
if (!session?.user) {
return (
-
+
)
}
return (
- Logged in as {session.user.name}
+
+ {session.user.name}
+
)
}
diff --git a/lib/hooks/use-chat-store.ts b/lib/hooks/use-chat-store.ts
deleted file mode 100644
index e6e913c..0000000
--- a/lib/hooks/use-chat-store.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { create } from 'zustand'
-
-interface UseChatStore {
- defaultMessage: string
- setDefaultMessage: (message: string) => void
-}
-
-export const useChatStore = create()(set => ({
- defaultMessage: '',
- setDefaultMessage: message => set({ defaultMessage: message })
-}))
diff --git a/package.json b/package.json
index 646b9b7..96a74ed 100644
--- a/package.json
+++ b/package.json
@@ -39,8 +39,7 @@
"react-syntax-highlighter": "^15.5.0",
"react-textarea-autosize": "^8.4.1",
"remark-gfm": "^3.0.1",
- "remark-math": "^5.1.1",
- "zustand": "^4.3.8"
+ "remark-math": "^5.1.1"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.9",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a5f796b..a765a30 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -86,9 +86,6 @@ dependencies:
remark-math:
specifier: ^5.1.1
version: 5.1.1
- zustand:
- specifier: ^4.3.8
- version: 4.3.8(react@18.2.0)
devDependencies:
'@tailwindcss/typography':
@@ -5070,22 +5067,6 @@ packages:
/zod@3.21.4:
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
- /zustand@4.3.8(react@18.2.0):
- resolution: {integrity: sha512-4h28KCkHg5ii/wcFFJ5Fp+k1J3gJoasaIbppdgZFO4BPJnsNxL0mQXBSFgOgAdCdBj35aDTPvdAJReTMntFPGg==}
- engines: {node: '>=12.7.0'}
- peerDependencies:
- immer: '>=9.0'
- react: '>=16.8'
- peerDependenciesMeta:
- immer:
- optional: true
- react:
- optional: true
- dependencies:
- react: 18.2.0
- use-sync-external-store: 1.2.0(react@18.2.0)
- dev: false
-
/zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
dev: false