From 18abc4b3f7cdce2cb15773127fa56194c41f8df3 Mon Sep 17 00:00:00 2001 From: Gregor Lohaus Date: Mon, 30 Mar 2026 18:06:38 +0200 Subject: [PATCH] chat fab --- .../@modal/(.)chat/_components/ChatModal.tsx | 4 +- src/app/@modal/(.)chat/page.tsx | 43 +++------ src/app/_components/ChatFAB.tsx | 19 ++++ src/app/_components/TopNav.tsx | 10 +- src/app/admin/_components/AdminSideBar.tsx | 3 + .../chat/_components/SystemPromptForm.tsx | 39 ++++++++ src/app/admin/chat/page.tsx | 22 +++++ src/app/api/chat/route.ts | 16 +--- src/app/chat/_components/AssistantMessage.tsx | 68 ++++++++++++++ src/app/chat/_components/ChatInterface.tsx | 91 ++++++------------- src/app/chat/_components/UserMessage.tsx | 23 +++++ src/app/chat/page.tsx | 39 ++------ src/app/layout.tsx | 2 + src/server/dbschema/schema.ts | 7 ++ src/server/routers/_app.ts | 2 + src/server/routers/chat.ts | 53 +++++++++++ 16 files changed, 301 insertions(+), 140 deletions(-) create mode 100644 src/app/_components/ChatFAB.tsx create mode 100644 src/app/admin/chat/_components/SystemPromptForm.tsx create mode 100644 src/app/admin/chat/page.tsx create mode 100644 src/app/chat/_components/AssistantMessage.tsx create mode 100644 src/app/chat/_components/UserMessage.tsx create mode 100644 src/server/routers/chat.ts diff --git a/src/app/@modal/(.)chat/_components/ChatModal.tsx b/src/app/@modal/(.)chat/_components/ChatModal.tsx index 91d1228..d5973b1 100644 --- a/src/app/@modal/(.)chat/_components/ChatModal.tsx +++ b/src/app/@modal/(.)chat/_components/ChatModal.tsx @@ -18,8 +18,8 @@ export default function ChatModal({ sessionId, initialMessages }: ChatModalProps const router = useRouter() return ( - router.back()}> - + router.back()}> + AI Recruiter diff --git a/src/app/@modal/(.)chat/page.tsx b/src/app/@modal/(.)chat/page.tsx index c4aaba6..00a66b8 100644 --- a/src/app/@modal/(.)chat/page.tsx +++ b/src/app/@modal/(.)chat/page.tsx @@ -1,34 +1,15 @@ -import { auth } from '@clerk/nextjs/server' -import { redirect } from 'next/navigation' -import { asc, desc, eq } from 'drizzle-orm' -import { db } from '~/server/db' -import { chatMessage, chatSession } from '~/server/dbschema/schema' +'use client' +import { Skeleton } from '~/components/ui/skeleton'; import ChatModal from './_components/ChatModal' +import { trpc } from '~/app/_trpc/Client' -export default async function ChatModalPage() { - const { userId } = await auth() - if (!userId) redirect('/') - - let session = await db - .select() - .from(chatSession) - .where(eq(chatSession.userId, userId)) - .orderBy(desc(chatSession.createdAt)) - .limit(1) - .then((r) => r[0]) - - if (!session) { - const [created] = await db.insert(chatSession).values({ userId }).returning() - session = created - } - - if (!session) redirect('/') - - const messages = await db - .select() - .from(chatMessage) - .where(eq(chatMessage.sessionId, session.id)) - .orderBy(asc(chatMessage.createdAt)) - - return +export default function ChatModalPage() { + const { data: session, error, isLoading } = trpc.chat.getSession.useQuery(); + return ( + <> + {session && } + {error &&
{error.message}
} + {isLoading && } + + ) } diff --git a/src/app/_components/ChatFAB.tsx b/src/app/_components/ChatFAB.tsx new file mode 100644 index 0000000..f99d738 --- /dev/null +++ b/src/app/_components/ChatFAB.tsx @@ -0,0 +1,19 @@ +'use client' +import Link from 'next/link' +import { MessageCircle } from 'lucide-react' +import { Show } from '@clerk/nextjs' +import { Button } from '~/components/ui/button' + +export default function ChatFAB() { + return ( + +
+ +
+
+ ) +} diff --git a/src/app/_components/TopNav.tsx b/src/app/_components/TopNav.tsx index 39a2606..7ae1b1e 100644 --- a/src/app/_components/TopNav.tsx +++ b/src/app/_components/TopNav.tsx @@ -24,7 +24,7 @@ export default function TopNav() { @@ -52,7 +52,13 @@ export default function TopNav() { diff --git a/src/app/admin/_components/AdminSideBar.tsx b/src/app/admin/_components/AdminSideBar.tsx index ddca0bc..9e473a7 100644 --- a/src/app/admin/_components/AdminSideBar.tsx +++ b/src/app/admin/_components/AdminSideBar.tsx @@ -26,6 +26,9 @@ export default function AdminSideBar() { Some Blog Action + + System Prompt + diff --git a/src/app/admin/chat/_components/SystemPromptForm.tsx b/src/app/admin/chat/_components/SystemPromptForm.tsx new file mode 100644 index 0000000..f2d2f28 --- /dev/null +++ b/src/app/admin/chat/_components/SystemPromptForm.tsx @@ -0,0 +1,39 @@ +'use client' +import { useState } from 'react' +import { Textarea } from '~/components/ui/textarea' +import { Button } from '~/components/ui/button' +import { trpc } from '~/app/_trpc/Client' + +export default function SystemPromptForm({ initialValue }: { initialValue: string }) { + const [value, setValue] = useState(initialValue) + const [saved, setSaved] = useState(false) + + const mutation = trpc.chat.updateSystemPrompt.useMutation({ + onSuccess: () => setSaved(true), + }) + + function handleSubmit(e: React.FormEvent) { + e.preventDefault() + setSaved(false) + mutation.mutate({ prompt: value }) + } + + return ( +
+