Skip to content

Commit

Permalink
feat: recent question asked for example on mainpage
Browse files Browse the repository at this point in the history
  • Loading branch information
mrevanzak committed Jul 23, 2024
1 parent c89553c commit 7e4ff9d
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 33 deletions.
1 change: 1 addition & 0 deletions apps/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"title": "Tanya.in",
"chooseTopic": "Type '/' to choose the topic",
"hint": "Ask a question with english",
"examples": "Get started with an example below",
"history": {
"show": "Show history",
"title": "History",
Expand Down
1 change: 1 addition & 0 deletions apps/web/public/locales/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"title": "Tanya.in saja!",
"chooseTopic": "Ketik '/' untuk memilih topik",
"hint": "Tulis pertanyaan dengan bahasa Indonesia",
"examples": "Mulai dengan contoh di bawah ini",
"history": {
"show": "Tampilkan riwayat",
"title": "Riwayat",
Expand Down
10 changes: 8 additions & 2 deletions apps/web/src/app/(app)/@user/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { api } from "@/trpc/react";
import { useTranslations } from "next-intl";

import type { Message } from "@tanya.in/ui";
import { cn } from "@tanya.in/ui";
import {
Card,
CardContent,
Expand All @@ -14,7 +15,7 @@ import {
} from "@tanya.in/ui/card";
import { Chat } from "@tanya.in/ui/chat";

export function ChatCard() {
export function ChatCard(props: { className?: string }) {
const t = useTranslations("Home");
const searchParams = useSearchParams();
const utils = api.useUtils();
Expand All @@ -26,7 +27,12 @@ export function ChatCard() {
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">
<Card
className={cn(
"m-2 mx-auto w-full duration-500 transition-size has-[[data-started=false]]:min-[450px]:w-[28rem]",
props.className,
)}
>
<CardHeader>
<CardTitle className="text-center">{t("title")}</CardTitle>
</CardHeader>
Expand Down
27 changes: 25 additions & 2 deletions apps/web/src/app/(app)/@user/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
import { api } from "@/trpc/server";
import { getTranslations } from "next-intl/server";

import { Card, CardContent } from "@tanya.in/ui/card";

import { ChatCard } from "./card";

export default function HomePage() {
export default async function HomePage() {
const t = await getTranslations("Home");
const recent = await api.chat.getRecentQuestion();

return (
<div className="container flex-1 self-center md:-translate-x-6">
<ChatCard />
<ChatCard className="peer" />
<Card className="m-2 mx-auto max-w-[26rem] -translate-y-2 rounded-t-none bg-default-100 p-2 transition-transform delay-300 ease-in-out peer-has-[[data-started=true]]:-translate-y-24">
<p className="p-1 text-xs font-bold text-foreground/40">
{t("examples")}
</p>

<div className="flex flex-row gap-1">
{recent.map((chat) => (
<Card className="bg-card shadow-none" key={chat.id}>
<CardContent className="line-clamp-2 rounded-md p-2 text-sm">
{chat.content}
</CardContent>
</Card>
))}
</div>
</Card>
</div>
);
}
10 changes: 4 additions & 6 deletions apps/web/src/app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { env } from "@/env";
import { auth } from "@/server/auth";
import { db } from "@/server/db";
import { chats, messages } from "@/server/db/schema";
import { chats, insertMessageSchema, messages } from "@/server/db/schema";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
import { get } from "@vercel/edge-config";
Expand Down Expand Up @@ -34,11 +34,8 @@ export async function POST(req: Request) {
const body = z
.object({
chatId: z.string(),
messages: z
.object({
id: z.string(),
content: z.string(),
})
messages: insertMessageSchema
.pick({ id: true, content: true, role: true })
.array(),
})
.safeParse(await req.json());
Expand Down Expand Up @@ -92,6 +89,7 @@ export async function POST(req: Request) {
id: lastMessage.id,
chatId: chatId[0]?.id ?? body.data.chatId,
content: lastMessage.content,
role: lastMessage.role,
});

const reader = res.body.getReader();
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/sidebar/sidebar-user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export function SidebarUser() {
: router.push(`/?id=${crypto.randomUUID()}&new`);
}}
>
<NewChat className="size-5 translate-x-2 transition-all" />
<NewChat className="size-5 translate-x-2 transition-transform" />
<span className="absolute left-10">{t("new")}</span>
</Button>
</Tooltip>
Expand Down
38 changes: 36 additions & 2 deletions apps/web/src/server/api/routers/chat/chat.procedure.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
import { chats } from "@/server/db/schema";
import { eq } from "drizzle-orm";
import { chats, messages } from "@/server/db/schema";
import { and, desc, eq, ilike, notExists, or } from "drizzle-orm";
import { alias } from "drizzle-orm/pg-core";
import { z } from "zod";

export const chatRouter = createTRPCRouter({
Expand All @@ -20,13 +21,45 @@ export const chatRouter = createTRPCRouter({
),
with: {
messages: {
orderBy: (message, { asc }) => [asc(message.createdAt)],
limit: 1,
},
},
orderBy: (chat, { desc }) => [desc(chat.createdAt)],
});
}),

getRecentQuestion: protectedProcedure.query(async ({ ctx }) => {
const m = alias(messages, "m");
return await ctx.db
.select()
.from(m)
.where(
and(
eq(m.role, "user"),
notExists(
ctx.db
.select()
.from(messages)
.where(
and(
eq(messages.chatId, m.chatId),
eq(messages.role, "assistant"),
or(
ilike(messages.content, "%saya tidak tahu%"),
ilike(messages.content, "%hi %"),
ilike(messages.content, "%halo%"),
),
),
)
.orderBy(desc(messages.createdAt)),
),
),
)
.orderBy(desc(m.createdAt))
.limit(3);
}),

show: protectedProcedure
.input(
z.object({
Expand All @@ -41,6 +74,7 @@ export const chatRouter = createTRPCRouter({
columns: {
chatId: false,
},
orderBy: (message, { asc }) => [asc(message.createdAt)],
},
},
});
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/server/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import { drizzle } from "drizzle-orm/vercel-postgres";

import * as schema from "./schema";

export const db = drizzle(sql, { schema });
export const db = drizzle(sql, { schema, logger: true });
6 changes: 5 additions & 1 deletion apps/web/src/server/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
timestamp,
uuid,
} from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";

export const createTable = pgTableCreator((name) => `tanyain_${name}`);

const roleEnum = pgEnum("role", ["user", "admin"]);
export const roleEnum = pgEnum("role", ["user", "admin"]);
export const users = createTable("user", {
id: uuid("id")
.primaryKey()
Expand All @@ -37,10 +38,12 @@ export const chatRelations = relations(chats, ({ many }) => ({
messages: many(messages),
}));

export const senderEnum = pgEnum("sender", ["user", "assistant"]);
export const messages = createTable("message", {
id: text("id").primaryKey(),
content: text("content").notNull(),
createdAt: timestamp("created_at", { mode: "date" }).defaultNow(),
role: senderEnum("sender").notNull().default("assistant"),
chatId: uuid("chat_id")
.notNull()
.references(() => chats.id),
Expand All @@ -51,3 +54,4 @@ export const messageRelations = relations(messages, ({ one }) => ({
references: [chats.id],
}),
}));
export const insertMessageSchema = createInsertSchema(messages);
22 changes: 4 additions & 18 deletions packages/ui/src/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,19 @@ export function Chat({
>
<ScrollShadow ref={chatContainerRef}>
<div className="mb-4 space-y-3">
{messages.map((item, index) => (
{messages.map((item) => (
<div
key={index}
key={item.id}
className={cn(
"flex justify-between",
index % 2 === 0 ? "flex-row-reverse" : "flex-row",
item.role === "user" ? "flex-row-reverse" : "flex-row",
"space-x-2",
)}
>
<p
className={cn(
"rounded-lg px-3 py-2",
index % 2 === 0
item.role === "user"
? "ml-2 bg-primary text-white"
: "mr-2 bg-content2",
)}
Expand Down Expand Up @@ -159,20 +159,6 @@ export function Chat({
e.preventDefault();
await onSubmit();
}

// if (e.key === "ArrowDown") {
// e.preventDefault();
// setSelectedTopicIndex((prev) =>
// prev + 1 < TOPICS.length ? prev + 1 : 0,
// );
// }

// if (e.key === "ArrowUp") {
// e.preventDefault();
// setSelectedTopicIndex((prev) =>
// prev - 1 >= 0 ? prev - 1 : TOPICS.length - 1,
// );
// }
}}
onValueChange={(value) => {
if (value.startsWith("/") && !watch("topic")) {
Expand Down

0 comments on commit 7e4ff9d

Please sign in to comment.