Skip to content

Commit 7274d4c

Browse files
committed
feat: add chatbot and new model ml
1 parent 139d4cc commit 7274d4c

16 files changed

+3721
-2378
lines changed

pnpm-lock.yaml

Lines changed: 2977 additions & 2376 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/gif/constellations-ml.gif

Loading

public/images/circle-user.png

1.27 KB
Loading

src/app/layout.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Metadata } from "next";
44
import { Inter } from "next/font/google";
55

66
import Providers from "@/app/providers";
7+
import ChatSupport from "./sections/chat-support";
78

89
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
910

@@ -21,7 +22,10 @@ export default function RootLayout({
2122
return (
2223
<html lang="en" className="scroll-smooth">
2324
<body className={inter.className}>
24-
<Providers>{children}</Providers>
25+
<Providers>
26+
{children}
27+
<ChatSupport />
28+
</Providers>
2529
</body>
2630
</html>
2731
);

src/app/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
"use client";
22

33
import Layout from "@/layouts/Layout";
4+
import ChatSupport from "./sections/chat-support";
45
import ChatBot from "./sections/chatbot";
6+
import Constellations from "./sections/constellations";
57
import { BentoGallery } from "./sections/gallery";
68
import Hero from "./sections/hero";
79
import LookBackGraph from "./sections/lookback";
@@ -14,13 +16,15 @@ export default function Home() {
1416
return (
1517
<>
1618
<Layout withFooter withNavbar>
19+
<ChatSupport />
1720
<ChatBot />
1821
<Hero />
1922
<MainBuild />
2023
<LookBackGraph />
2124
<World />
2225
<Neutrack />
2326
<Moonface />
27+
<Constellations />
2428
<BentoGallery />
2529
</Layout>
2630
</>

src/app/sections/chat-support.tsx

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"use client";
2+
3+
import { Button } from "@/components/ui/button";
4+
import {
5+
ChatBubble,
6+
ChatBubbleAvatar,
7+
ChatBubbleMessage,
8+
} from "@/components/ui/chat/chat-bubble";
9+
import { ChatInput } from "@/components/ui/chat/chat-input";
10+
import { ChatMessageList } from "@/components/ui/chat/chat-message-list";
11+
import {
12+
ExpandableChat,
13+
ExpandableChatBody,
14+
ExpandableChatFooter,
15+
ExpandableChatHeader,
16+
} from "@/components/ui/chat/expandable-chat";
17+
import { sendMessageToGemini } from "@/lib/geminiApi"; // Import API handler
18+
import { Send } from "lucide-react";
19+
import { useState } from "react";
20+
21+
export default function ChatSupport() {
22+
const [messages, setMessages] = useState([
23+
{ sender: "bot", text: "Hello, how can I assist you today?" },
24+
]);
25+
const [input, setInput] = useState("");
26+
27+
const handleSendMessage = async () => {
28+
if (!input.trim()) return;
29+
30+
// Add user message to the chat
31+
const newMessage = { sender: "user", text: input };
32+
setMessages((prev) => [...prev, newMessage]);
33+
setInput("");
34+
35+
try {
36+
// Send message to the API
37+
const response = await sendMessageToGemini(input);
38+
const botReply = response.reply || "No response received";
39+
40+
// Add bot response to the chat
41+
setMessages((prev) => [...prev, { sender: "bot", text: botReply }]);
42+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
43+
// biome-ignore lint/correctness/noUnusedVariables: <explanation>
44+
} catch (error: any) {
45+
setMessages((prev) => [
46+
...prev,
47+
{ sender: "bot", text: "Error communicating with API." },
48+
]);
49+
}
50+
};
51+
52+
return (
53+
<ExpandableChat
54+
size="lg"
55+
position="bottom-right"
56+
className="bg-neutral-900 border-[0.5px] border-neutral-50 rounded-xl"
57+
>
58+
<ExpandableChatHeader className="flex-col text-center justify-center">
59+
<h1 className="text-xl text-white font-semibold">
60+
Chat with our AI ✨
61+
</h1>
62+
<p className="text-white">Ask any question for our AI to answer</p>
63+
{/* <div className="flex gap-2 text-white items-center pt-2">
64+
<Button variant="secondary" className="text-white">
65+
New Chat
66+
</Button>
67+
<Button variant="secondary" className="text-white">
68+
See FAQ
69+
</Button>
70+
</div> */}
71+
</ExpandableChatHeader>
72+
<ExpandableChatBody>
73+
<ChatMessageList>
74+
{messages.map((msg, idx) => (
75+
<ChatBubble
76+
key={idx}
77+
variant={msg.sender === "user" ? "sent" : "received"}
78+
>
79+
<ChatBubbleAvatar
80+
src={
81+
msg.sender === "user"
82+
? "./images/circle-user.png"
83+
: "./images/mascot-neutrack.png"
84+
}
85+
/>
86+
<ChatBubbleMessage>{msg.text}</ChatBubbleMessage>
87+
</ChatBubble>
88+
))}
89+
</ChatMessageList>
90+
</ExpandableChatBody>
91+
<ExpandableChatFooter className="flex items-center gap-2">
92+
<ChatInput
93+
value={input}
94+
onChange={(e) => setInput(e.target.value)}
95+
onKeyDown={(e) => e.key === "Enter" && handleSendMessage()}
96+
placeholder="Type your message..."
97+
/>
98+
<Button type="submit" size="icon" onClick={handleSendMessage}>
99+
<Send className="size-6 text-white" />
100+
</Button>
101+
</ExpandableChatFooter>
102+
</ExpandableChat>
103+
);
104+
}

src/app/sections/constellations.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { BentoCard, BentoGrid } from "@/components/BentoGrid";
2+
import ButtonLink from "@/components/links/ButtonLink";
3+
import { Bot } from "lucide-react";
4+
5+
const features = [
6+
{
7+
Icon: Bot,
8+
name: "Machine Learning Preview",
9+
description:
10+
"Integrating machine learning to astrophysics, we are working to modeling datasets.",
11+
href: "",
12+
cta: "",
13+
className: "",
14+
background: (
15+
<div className="absolute h-full w-full [mask-image:linear-gradient(to_top,transparent_5%,#000_100%)] ">
16+
<video
17+
src="https://res.cloudinary.com/dzaky/video/upload/v1728227378/constellations-ml_c4ay13.mp4"
18+
autoPlay
19+
loop
20+
muted
21+
playsInline
22+
className="pointer-events-none h-full w-full object-cover group-hover:scale-105"
23+
/>
24+
</div>
25+
),
26+
},
27+
];
28+
29+
export default function Constellations() {
30+
return (
31+
<section
32+
id="moonface"
33+
className="mx-4 my-16 sm:mx-auto rounded-lg p-4 max-w-screen-xl border-[0.5px] border-gray-700"
34+
>
35+
<div className="gap-8 flex flex-col-reverse lg:grid lg:grid-cols-2">
36+
<div className="flex flex-col gap-2">
37+
<h1 className="text-center text-sm font-regular text-white md:text-lg pb-4">
38+
Neutrack Constellation Prediction Model
39+
</h1>
40+
<p className="text-white text-justify py-8 ">
41+
This computer vision model is designed to identify constellations
42+
from images of the night sky. As an additional concept for NeuTrack,
43+
a device aimed at making the universe more accessible, this model
44+
provides a way for users to discover which constellations are above
45+
them without relying on sight. By analyzing images of star-filled
46+
skies, it accurately classifies the visible constellations, offering
47+
an intuitive understanding of what's overhead. This innovative tool
48+
blends astronomy with accessibility, enriching the experience for
49+
anyone curious about the Cosmos.
50+
</p>
51+
<ButtonLink
52+
href="https://huggingface.co/spaces/SteelAwsm/testgrad"
53+
openNewTab
54+
>
55+
Let's try the machine!
56+
</ButtonLink>
57+
</div>
58+
59+
<BentoGrid>
60+
{features.map((feature, idx) => (
61+
<BentoCard key={idx} {...feature} />
62+
))}
63+
</BentoGrid>
64+
</div>
65+
</section>
66+
);
67+
}

src/app/sections/neutrack.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function Neutrack() {
3535
href="https://memoryreboot.pythonanywhere.com/"
3636
openNewTab
3737
>
38-
Click for GPS tracker!
38+
Click for the GPS tracker!
3939
</ButtonLink>
4040
</div>
4141

src/components/ui/avatar.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client";
2+
3+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
4+
import * as React from "react";
5+
6+
import { cn } from "@/lib/utils";
7+
8+
const Avatar = React.forwardRef<
9+
React.ElementRef<typeof AvatarPrimitive.Root>,
10+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11+
>(({ className, ...props }, ref) => (
12+
<AvatarPrimitive.Root
13+
ref={ref}
14+
className={cn(
15+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
16+
className,
17+
)}
18+
{...props}
19+
/>
20+
));
21+
Avatar.displayName = AvatarPrimitive.Root.displayName;
22+
23+
const AvatarImage = React.forwardRef<
24+
React.ElementRef<typeof AvatarPrimitive.Image>,
25+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
26+
>(({ className, ...props }, ref) => (
27+
<AvatarPrimitive.Image
28+
ref={ref}
29+
className={cn("aspect-square h-full w-full", className)}
30+
{...props}
31+
/>
32+
));
33+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
34+
35+
const AvatarFallback = React.forwardRef<
36+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
37+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
38+
>(({ className, ...props }, ref) => (
39+
<AvatarPrimitive.Fallback
40+
ref={ref}
41+
className={cn(
42+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
43+
className,
44+
)}
45+
{...props}
46+
/>
47+
));
48+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
49+
50+
export { Avatar, AvatarImage, AvatarFallback };

0 commit comments

Comments
 (0)