Skip to content

Commit a49a998

Browse files
committed
feat: Image and conversation in ask/id
1 parent d1af0a5 commit a49a998

3 files changed

Lines changed: 64 additions & 26 deletions

File tree

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
"use client";
22
import Chat from "@/app/_components/Chat";
3+
import { useParams } from "next/navigation";
34

45
export default function SingleChatPage() {
6+
const { chatId } = useParams();
57
return (
68
<>
7-
<Chat />
9+
<Chat chatId={chatId as string} />
810
</>
911
);
1012
}

src/app/_components/Chat.tsx

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
22
import React, { useState, useRef, useEffect, useCallback } from "react";
3-
import { useSession } from "next-auth/react";
43
import { Textarea } from "@/components/ui/textarea";
54
import { Button } from "@/components/ui/button";
65
import {
@@ -28,9 +27,8 @@ import SpeechRecognition, {
2827
import { useSpeechSynthesis } from "react-speech-kit";
2928
import { toast } from "sonner";
3029
import { useTheme } from "next-themes";
31-
import { WrapText } from "lucide-react";
30+
import { Globe, Loader2Icon, Paperclip, WrapText } from "lucide-react";
3231
import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs";
33-
import { useParams } from "next/navigation";
3432
import { api } from "@/trpc/react";
3533

3634
const geistMono = Geist_Mono({
@@ -52,25 +50,43 @@ interface Message {
5250
content: string;
5351
}
5452

55-
const Chat = () => {
56-
const { data: sessionData } = useSession();
53+
const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
5754
const [model, setModel] = useState<string>(DEFAULT_MODEL_ID);
5855
const [messages, setMessages] = useState<ChatMessage[]>([]);
56+
const [search, setSearch] = useState<boolean>(false);
5957
const [input, setInput] = useState("");
6058
const [isLoading, setIsLoading] = useState(false);
61-
const params = useParams();
6259
const [modeOfChatting, setModeOfChatting] = useState<"text" | "voice">(
6360
"text",
6461
);
6562
const [showWelcome, setShowWelcome] = useState(true);
6663
const [copied, setCopied] = useState(false);
67-
const chatId = params?.chatId as string | undefined;
6864
const messagesEndRef = useRef<HTMLDivElement>(null);
6965
const abortControllerRef = useRef<AbortController | null>(null);
7066
const welcomeSpokenRef = useRef(false);
7167
const [isWrapped, setIsWrapped] = useState(false);
7268
const { resolvedTheme } = useTheme();
7369
const [query, setQuery] = useState<string>("");
70+
const [attachments, setAttachments] = useState<File[]>([]);
71+
const [chatId, setChatId] = useState<string>(initialChatId);
72+
73+
const {data: chatMessages} = api.chat.getChatMessages.useQuery({
74+
chatId: chatId,
75+
});
76+
77+
useEffect(() => {
78+
setChatId(initialChatId);
79+
}, [initialChatId]);
80+
81+
useEffect(() => {
82+
if (chatMessages) {
83+
setMessages(chatMessages.messages.map((message) => ({
84+
id: message.id,
85+
role: message.role === "USER" ? "user" : "assistant",
86+
content: message.content,
87+
})));
88+
}
89+
}, [chatMessages]);
7490

7591
const toggleWrap = useCallback(() => {
7692
setIsWrapped((prev) => !prev);
@@ -156,12 +172,12 @@ const Chat = () => {
156172
const { done, value } = await reader.read();
157173

158174
if (done) {
159-
console.log("Stream complete");
175+
// console.log("Stream complete");
160176
break;
161177
}
162178

163179
const chunk = new TextDecoder().decode(value);
164-
console.log("Received chunk:", chunk);
180+
// console.log("Received chunk:", chunk);
165181

166182
buffer += chunk;
167183

@@ -180,7 +196,7 @@ const Chat = () => {
180196
}
181197

182198
try {
183-
console.log("Parsing JSON:", data);
199+
// console.log("Parsing JSON:", data);
184200
const parsedData = JSON.parse(data) as {
185201
choices?: Array<{
186202
delta?: {
@@ -191,7 +207,7 @@ const Chat = () => {
191207

192208
const content = parsedData.choices?.[0]?.delta?.content;
193209
if (content) {
194-
console.log("Received content:", content);
210+
// console.log("Received content:", content);
195211
accumulatedContent += content;
196212

197213
setMessages((prev) =>
@@ -209,7 +225,7 @@ const Chat = () => {
209225
}
210226
}
211227

212-
console.log("Saving chat to database:", userMessage, accumulatedContent);
228+
// console.log("Saving chat to database:", userMessage, accumulatedContent);
213229
} catch (error) {
214230
console.error("Error processing stream:", error);
215231
} finally {
@@ -218,12 +234,6 @@ const Chat = () => {
218234
}
219235
};
220236

221-
const createChat = api.chat.createChat.useMutation({
222-
onError: (error) => {
223-
console.error("Error saving chat:", error);
224-
},
225-
});
226-
227237
const handleCreateChat = async (e: React.FormEvent) => {
228238
e.preventDefault();
229239
if (!query.trim() || isLoading) return;
@@ -249,7 +259,6 @@ const Chat = () => {
249259
abortControllerRef.current = new AbortController();
250260

251261
try {
252-
const { chatId } = await createChat.mutateAsync();
253262
setTimeout(() => {
254263
void (async () => {
255264
try {
@@ -339,6 +348,7 @@ const Chat = () => {
339348
body: JSON.stringify({
340349
messages: [{ role: "user", content: currentMessage }],
341350
model: model,
351+
chatId: chatId,
342352
}),
343353
signal: abortControllerRef.current.signal,
344354
});
@@ -393,14 +403,28 @@ const Chat = () => {
393403
}
394404
};
395405

406+
407+
const handleFileInput = () => {
408+
const fileInput = document.createElement("input");
409+
fileInput.type = "file";
410+
fileInput.accept = "image/*";
411+
fileInput.onchange = (e) => {
412+
const file = (e.target as HTMLInputElement).files?.[0];
413+
if (file) {
414+
setAttachments((prev) => [...prev, file]);
415+
}
416+
};
417+
fileInput.click();
418+
};
419+
396420
return (
397421
<div className="h-[96vh] w-full">
398422
<div className="relative flex h-full w-full flex-col">
399-
<div className="flex flex-1 flex-col overflow-y-auto px-4 pb-40 md:px-4">
423+
<div className="no-scrollbar flex flex-1 flex-col overflow-y-auto px-4 pb-40 md:px-4">
400424
<div className="mx-auto w-full max-w-4xl py-4">
401425
{messages.length === 0 ? (
402426
<div className="text-muted-foreground flex h-[50vh] items-center justify-center">
403-
Start a conversation by typing a message below
427+
<Loader2Icon className="animate-spin" />
404428
</div>
405429
) : (
406430
<div className="no-scrollbar mt-6 flex h-full w-full flex-1 flex-col gap-4 overflow-y-auto px-4 pt-4 pb-10 md:px-8">
@@ -690,6 +714,17 @@ const Chat = () => {
690714
onValueChange={setModel}
691715
disabled={isLoading}
692716
/>
717+
718+
{/* Search */}
719+
<Button variant="ghost" size="sm" className={`text-xs ${search ? "bg-primary/60 hover:bg-primary/70" : ""}`} onClick={() => setSearch(!search)}>
720+
<Globe className="size-4" />
721+
Search
722+
</Button>
723+
724+
{/* Attachments */}
725+
<Button variant="ghost" size="sm" className="text-xs" onClick={handleFileInput}>
726+
<Paperclip className="size-4" />
727+
</Button>
693728
</div>
694729
<Button
695730
type="submit"

src/components/subscription/profile/profile.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import Image from "next/image";
66

77
export const Profile = ({ image, nickname, name, email, whatDoYouDo, customTraits, about, plan }: { image: string, nickname: string, name: string, email: string, whatDoYouDo: string, customTraits: string[], about: string, plan: string }) => {
88
const { isBlurred } = useBlur();
9-
console.log("isBlurred in profile:", isBlurred);
109
return (
1110
<div
1211
className={cn(
@@ -47,9 +46,11 @@ export const Profile = ({ image, nickname, name, email, whatDoYouDo, customTrait
4746
</Badge>
4847
)}
4948
</div>
50-
<Badge variant="secondary" className="text-white bg-pink-600">
51-
{plan}
52-
</Badge>
49+
{ plan && (
50+
<Badge variant="secondary" className="text-white bg-pink-600">
51+
{plan}
52+
</Badge>
53+
)}
5354
</div>
5455
</div>
5556
);

0 commit comments

Comments
 (0)