Skip to content

Commit a27e86a

Browse files
committed
style: refactor chat page
1 parent 0a083ff commit a27e86a

File tree

5 files changed

+74
-103
lines changed

5 files changed

+74
-103
lines changed

src/app/chat/page.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1+
import { Chat } from '@/components/chat/chat';
12

2-
import { Chat } from "@/components/chat/chat";
3-
4-
export default function chat() {
5-
return (
6-
<main className="relative container flex min-h-screen flex-col">
7-
<div className="flex flex-1 py-4">
8-
<div className="w-full">
9-
<Chat />
10-
</div>
11-
</div>
12-
</main>
13-
);
14-
}
3+
const chat = () => <Chat />;
4+
export default chat;

src/app/layout.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import type { Metadata, Viewport } from 'next';
22

33
import '@/styles/globals.css';
44

5+
import Navbar from '@/layout/navbar/Navbar';
6+
57
import { siteConfig } from '@/config/site';
68
import { inter } from '@/lib/fonts';
79

@@ -28,6 +30,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
2830
<body
2931
className={`min-h-scree bg-primary-950 antialiased ${inter.className}`}
3032
>
33+
<Navbar />
3134
{children}
3235
</body>
3336
</html>

src/components/chat/chat-line.tsx

Lines changed: 35 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,54 @@
1-
import Balancer from "react-wrap-balancer";
2-
import {
3-
Card,
4-
CardContent,
5-
CardDescription,
6-
CardFooter,
7-
CardHeader,
8-
CardTitle,
9-
} from "@/components/ui/card";
1+
import React from 'react';
2+
import { Message } from 'ai/react';
3+
import ReactMarkdown from 'react-markdown';
4+
5+
import { formattedText } from '@/lib/utils';
106
import {
117
Accordion,
128
AccordionContent,
139
AccordionItem,
1410
AccordionTrigger,
15-
} from "@/components/ui/accordion";
16-
import { Message } from "ai/react";
17-
import ReactMarkdown from "react-markdown";
18-
import { formattedText } from "@/lib/utils";
19-
20-
const convertNewLines = (text: string) =>
21-
text.split("\n").map((line, i) => (
22-
<span key={i}>
23-
{line}
24-
<br />
25-
</span>
26-
));
11+
} from '@/components/ui/accordion';
2712

2813
interface ChatLineProps extends Partial<Message> {
2914
sources: string[];
3015
}
3116

3217
export function ChatLine({
33-
role = "assistant",
18+
role = 'assistant',
3419
content,
3520
sources,
3621
}: ChatLineProps) {
37-
if (!content) {
38-
return null;
39-
}
40-
const formattedMessage = convertNewLines(content);
22+
if (!content) return null;
4123

4224
return (
43-
<div>
44-
<Card className="mb-2">
45-
<CardHeader>
46-
<CardTitle
47-
className={
48-
role != "assistant"
49-
? "text-amber-500 dark:text-amber-200"
50-
: "text-blue-500 dark:text-blue-200"
51-
}
52-
>
53-
{role == "assistant" ? "AI" : "You"}
54-
</CardTitle>
55-
</CardHeader>
56-
<CardContent className="text-sm">
57-
<Balancer>{formattedMessage}</Balancer>
58-
</CardContent>
59-
<CardFooter>
60-
<CardDescription className="w-full">
61-
{sources && sources.length ? (
62-
<Accordion type="single" collapsible className="w-full">
63-
{sources.map((source, index) => (
64-
<AccordionItem value={`source-${index}`} key={index}>
65-
<AccordionTrigger>{`Source ${index + 1}`}</AccordionTrigger>
66-
<AccordionContent>
67-
<ReactMarkdown >
68-
{formattedText(source)}
69-
</ReactMarkdown>
70-
</AccordionContent>
71-
</AccordionItem>
72-
))}
73-
</Accordion>
74-
) : (
75-
<></>
76-
)}
77-
</CardDescription>
78-
</CardFooter>
79-
</Card>
25+
<div className={`mb-4 ${role === 'user' ? 'text-right' : 'text-left'}`}>
26+
<div
27+
className={`inline-block max-w-[80%] rounded-lg p-4 ${
28+
role === 'user' ? 'bg-green-700' : 'bg-green-700'
29+
}`}
30+
>
31+
<p className="mb-2 text-sm font-semibold">
32+
{role === 'assistant' ? 'AI' : 'You'}
33+
</p>
34+
<p className="text-sm">{content}</p>
35+
{sources && sources.length > 0 && (
36+
<Accordion type="single" collapsible className="mt-2 w-full">
37+
{sources.map((source, index) => (
38+
<AccordionItem value={`source-${index}`} key={index}>
39+
<AccordionTrigger className="text-xs text-emerald-300">
40+
Source {index + 1}
41+
</AccordionTrigger>
42+
<AccordionContent>
43+
<ReactMarkdown className="text-xs text-emerald-200">
44+
{formattedText(source)}
45+
</ReactMarkdown>
46+
</AccordionContent>
47+
</AccordionItem>
48+
))}
49+
</Accordion>
50+
)}
51+
</div>
8052
</div>
8153
);
8254
}

src/components/chat/chat.tsx

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,59 @@
1-
"use client";
1+
'use client';
22

3-
import { scrollToBottom, initialMessages, getSources } from "@/lib/utils";
4-
import { ChatLine } from "./chat-line";
5-
import { useChat, Message } from "ai-stream-experimental/react";
6-
import { Input } from "@/components/ui/input";
7-
import { Button } from "@/components/ui/button";
8-
import { Spinner } from "@/components/ui/spinner";
9-
import { useEffect, useRef } from "react";
3+
import React, { useEffect, useRef } from 'react';
4+
import { Message, useChat } from 'ai-stream-experimental/react';
5+
import { LuSend } from 'react-icons/lu';
6+
7+
import { getSources, initialMessages, scrollToBottom } from '@/lib/utils';
8+
import { Button } from '@/components/ui/button';
9+
import { Input } from '@/components/ui/input';
10+
import { Spinner } from '@/components/ui/spinner';
11+
12+
import { ChatLine } from './chat-line';
1013

1114
export function Chat() {
12-
const containerRef = useRef<HTMLDivElement | null>(null);
13-
const { messages, input, handleInputChange, handleSubmit, isLoading, data } =
15+
const containerRef = useRef<HTMLDivElement | null>(null);
16+
const { messages, input, handleInputChange, handleSubmit, isLoading, data } =
1417
useChat({
15-
initialMessages: initialMessages.map((message) => ({
16-
...message,
17-
role: message.role as "function" | "system" | "user" | "assistant",
18-
})),
18+
initialMessages: initialMessages.map((message) => ({
19+
...message,
20+
role: message.role as 'function' | 'system' | 'user' | 'assistant',
21+
})),
1922
});
2023

21-
useEffect(() => {
24+
useEffect(() => {
2225
setTimeout(() => scrollToBottom(containerRef), 100);
23-
}, [messages]);
26+
}, [messages]);
2427

2528
return (
26-
<div className="rounded-2xl border h-[75vh] flex flex-col justify-between">
27-
<div className="p-6 overflow-auto" ref={containerRef}>
29+
<div className=" flex h-[100vh] flex-col justify-between bg-gradient-to-l from-green-900 to-green-900 text-white">
30+
<div className="flex-grow overflow-auto px-44 py-32" ref={containerRef}>
2831
{messages.map(({ id, role, content }: Message, index) => (
2932
<ChatLine
3033
key={id}
3134
role={role}
3235
content={content}
33-
// Start from the third message of the assistant
3436
sources={data?.length ? getSources(data, role, index) : []}
3537
/>
3638
))}
3739
</div>
3840

39-
<form onSubmit={handleSubmit} className="p-4 flex clear-both">
41+
<form
42+
onSubmit={handleSubmit}
43+
className="clear-both flex items-center justify-center p-4"
44+
>
4045
<Input
4146
value={input}
42-
placeholder={"Type to chat with AI..."}
47+
placeholder="Type to chat with AI..."
4348
onChange={handleInputChange}
44-
className="mr-2"
49+
className="mr-2 w-[70%] rounded-3xl border-gray-500 bg-green-700 py-6 text-white placeholder:text-white focus:border-green-500"
4550
/>
46-
47-
<Button type="submit" className="w-24">
48-
{isLoading ? <Spinner /> : "Ask"}
51+
<Button
52+
type="submit"
53+
className="rounded-full border border-gray-500 bg-green-700 px-3 py-6 shadow-lg hover:bg-green-500"
54+
disabled={!input}
55+
>
56+
{isLoading ? <Spinner /> : <LuSend size={24} />}
4957
</Button>
5058
</form>
5159
</div>

src/components/home/Homepage.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import Footer from '@/layout/footer/Footer';
2-
import Navbar from '@/layout/navbar/Navbar';
32

43
import ExploreProjectsSection from './section/ExploreProjectsSection';
54
import FeaturesSection from './section/FeaturesSection';
@@ -8,7 +7,6 @@ import HeroSection from './section/HeroSection';
87
const Homepage = () => {
98
return (
109
<div className="bg-primary-950">
11-
<Navbar />
1210
<HeroSection />
1311
<ExploreProjectsSection />
1412
<FeaturesSection />

0 commit comments

Comments
 (0)