Skip to content

Commit

Permalink
feat(web): chat history detail
Browse files Browse the repository at this point in the history
  • Loading branch information
mrevanzak committed Jun 18, 2024
1 parent e51e65c commit 4de0482
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 33 deletions.
11 changes: 10 additions & 1 deletion apps/web/src/app/(app)/@user/card.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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 (
<Card className="m-2 mx-auto w-full duration-500 transition-size has-[[data-started=false]]:min-[450px]:w-96">
<CardHeader>
<CardTitle className="text-center">Tanya.in saja!</CardTitle>
</CardHeader>
<CardContent>
<Chat onFinish={() => utils.chat.get.invalidate()} />
<Chat
onFinish={() => utils.chat.get.invalidate()}
initialMessages={initialMessages}
/>
</CardContent>
<CardFooter>
<Card className="m-auto shadow-none">
Expand Down
57 changes: 28 additions & 29 deletions apps/web/src/app/(app)/@user/history.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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<typeof chatHistory.data> }) {
return (
<ul className="h-full space-y-4">
{props.data.map((chat) => (
<Tooltip
key={chat.id}
content={chat.messages.at(0)?.content}
placement="top-start"
delay={500}
closeDelay={0}
>
<Link
href={`?id=${chat.id}`}
className="flex rounded-r-md border-s-3 border-primary-its p-2 hover:bg-primary-its/20"
>
<p className="overflow-hidden text-ellipsis">
{chat.messages.at(0)?.content}
</p>
</Link>
</Tooltip>
))}
</ul>
);
}

return (
<Tabs color="warning" variant="bordered" fullWidth>
<Tab title="History">
{chatHistory.data?.length ? (
<ul className="h-full space-y-6">
{chatHistory.data.map((chat) => (
<Tooltip
key={chat.id}
content={chat.messages.at(0)?.content}
placement="top-start"
delay={500}
closeDelay={0}
>
<li className="rounded-r-md border-s-3 border-primary-its p-2 hover:bg-primary-its/20">
<p className="overflow-hidden text-ellipsis">
{chat.messages.at(0)?.content}
</p>
</li>
</Tooltip>
))}
</ul>
<List data={chatHistory.data} />
) : (
<p className="text-center">No chat history</p>
)}
</Tab>
<Tab title="Unsolvable">
{unsolvable.data?.length ? (
<ul className="h-full space-y-6">
{unsolvable.data.map((chat) => (
<li
key={chat.id}
className="rounded-r-md border-s-3 border-primary-its p-2 hover:bg-primary-its/20"
>
<p className="overflow-hidden text-ellipsis">
{chat.messages.at(0)?.content}
</p>
</li>
))}
</ul>
<List data={unsolvable.data} />
) : (
<p className="text-center">No unsolvable question</p>
)}
Expand Down
18 changes: 18 additions & 0 deletions apps/web/src/server/api/routers/chat/chat.procedure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
6 changes: 4 additions & 2 deletions packages/ui/src/chat.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 {
Expand All @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion packages/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -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<typeof cx>) => twMerge(cx(inputs));

export { cn, NextUIProvider };
export { cn, NextUIProvider, type Message };

0 comments on commit 4de0482

Please sign in to comment.