diff --git a/apps/web/src/app/(app)/@user/card.tsx b/apps/web/src/app/(app)/@user/card.tsx index a0b3d9b..65e9bbf 100644 --- a/apps/web/src/app/(app)/@user/card.tsx +++ b/apps/web/src/app/(app)/@user/card.tsx @@ -1,7 +1,9 @@ "use client"; +import { useSearchParams } from "next/navigation"; import { api } from "@/trpc/react"; +import type { Message } from "@tanya.in/ui"; import { Card, CardContent, @@ -12,15 +14,22 @@ import { import { Chat } from "@tanya.in/ui/chat"; export function ChatCard() { + const searchParams = useSearchParams(); const utils = api.useUtils(); + const { data } = api.chat.show.useQuery({ id: searchParams.get("id") }); + const initialMessages = data?.messages as Message[] | undefined; + return ( Tanya.in saja! - utils.chat.get.invalidate()} /> + utils.chat.get.invalidate()} + initialMessages={initialMessages} + /> diff --git a/apps/web/src/app/(app)/@user/history.tsx b/apps/web/src/app/(app)/@user/history.tsx index 6ce32d2..3a31606 100644 --- a/apps/web/src/app/(app)/@user/history.tsx +++ b/apps/web/src/app/(app)/@user/history.tsx @@ -1,6 +1,7 @@ "use client"; import { useState } from "react"; +import Link from "next/link"; import { Drawer, DrawerContent, DrawerTrigger } from "@/components/drawer"; import { useMediaQuery } from "@/lib/hooks/useMediaQuery"; import { api } from "@/trpc/react"; @@ -15,45 +16,43 @@ function Content() { const chatHistory = api.chat.get.useQuery({}); const unsolvable = api.chat.get.useQuery({ unsolvable: true }); + function List(props: { data: NonNullable }) { + return ( +
    + {props.data.map((chat) => ( + + +

    + {chat.messages.at(0)?.content} +

    + +
    + ))} +
+ ); + } + return ( {chatHistory.data?.length ? ( -
    - {chatHistory.data.map((chat) => ( - -
  • -

    - {chat.messages.at(0)?.content} -

    -
  • -
    - ))} -
+ ) : (

No chat history

)}
{unsolvable.data?.length ? ( -
    - {unsolvable.data.map((chat) => ( -
  • -

    - {chat.messages.at(0)?.content} -

    -
  • - ))} -
+ ) : (

No unsolvable question

)} diff --git a/apps/web/src/server/api/routers/chat/chat.procedure.ts b/apps/web/src/server/api/routers/chat/chat.procedure.ts index d3d21c2..8d5e2e2 100644 --- a/apps/web/src/server/api/routers/chat/chat.procedure.ts +++ b/apps/web/src/server/api/routers/chat/chat.procedure.ts @@ -15,6 +15,24 @@ export const chatRouter = createTRPCRouter({ eq(chat.createdBy, ctx.session.user.id), eq(chat.unsolvable, input.unsolvable).if(input.unsolvable === true), ), + with: { + messages: { + limit: 1, + }, + }, + }); + }), + + show: protectedProcedure + .input( + z.object({ + id: z.string().nullable(), + }), + ) + .query(async ({ ctx, input }) => { + return await ctx.db.query.chats.findFirst({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + where: (chat, { eq }) => eq(chat.id, input.id!).if(input.id), with: { messages: true, }, diff --git a/packages/ui/src/chat.tsx b/packages/ui/src/chat.tsx index 27faf2f..11ad2f4 100644 --- a/packages/ui/src/chat.tsx +++ b/packages/ui/src/chat.tsx @@ -1,5 +1,6 @@ "use client"; +import type { UseChatOptions } from "ai/react"; import * as React from "react"; import { ScrollShadow } from "@nextui-org/scroll-shadow"; import { useChat } from "ai/react"; @@ -43,7 +44,7 @@ function getChatApi() { return undefined; } -export function Chat(props: { onFinish?: () => void }) { +export function Chat({ onFinish, initialMessages }: UseChatOptions) { const chatId = React.useMemo(() => crypto.randomUUID(), []); const { @@ -55,7 +56,8 @@ export function Chat(props: { onFinish?: () => void }) { streamMode: "text", onError: (error) => toast.error(error.message), sendExtraMessageFields: true, - onFinish: props.onFinish, + onFinish, + initialMessages, }); const chatContainerRef = useChatScroll(messages); diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 3e4438a..2b9eb5f 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -1,7 +1,8 @@ +import type { Message } from "ai"; import { NextUIProvider } from "@nextui-org/system"; import { cx } from "class-variance-authority"; import { twMerge } from "tailwind-merge"; const cn = (...inputs: Parameters) => twMerge(cx(inputs)); -export { cn, NextUIProvider }; +export { cn, NextUIProvider, type Message };