diff --git a/.eslintrc.json b/.eslintrc.json index 3722418..2cfeb98 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,6 @@ { - "extends": ["next/core-web-vitals", "next/typescript"] + "extends": ["next/core-web-vitals", "next/typescript"], + "rules": { + "@typescript-eslint/no-empty-interface": "off" + } } diff --git a/bun.lockb b/bun.lockb index faef721..06a4eac 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 9d3f7d5..e618893 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "@ai-sdk/openai": "^0.0.72", "@monaco-editor/react": "^4.6.0", "@prisma/client": "5.22.0", + "@radix-ui/react-avatar": "^1.1.1", + "@radix-ui/react-slot": "^1.1.0", "ai": "^3.4.33", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 748524e..fcee612 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import localFont from "next/font/local"; import "./globals.css"; +import ChatSupport from "@/components/chat-support"; const geistSans = localFont({ src: "./fonts/GeistVF.woff", @@ -29,6 +30,7 @@ export default function RootLayout({ className={`${geistSans.variable} ${geistMono.variable} antialiased`} >
{children}
+ ); diff --git a/src/components/chat-support.tsx b/src/components/chat-support.tsx new file mode 100644 index 0000000..106365e --- /dev/null +++ b/src/components/chat-support.tsx @@ -0,0 +1,44 @@ +import { + ChatBubble, + ChatBubbleAvatar, + ChatBubbleMessage, +} from "@/components/ui/chat/chat-bubble"; +import { ChatInput } from "@/components/ui/chat/chat-input"; +import { + ExpandableChat, + ExpandableChatHeader, + ExpandableChatBody, + ExpandableChatFooter, +} from "@/components/ui/chat/expandable-chat"; +import { ChatMessageList } from "@/components/ui/chat/chat-message-list"; +import { Button } from "./ui/button"; +import { Send } from "lucide-react"; + +export default function ChatSupport() { + return ( + + +

Chat with our AI ✨

+

Ask any question for our AI to answer

+
+ + +
+
+ + + + + {/* {message.content} */} + + + + + + + +
+ ); +} diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..65d4fcd --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx new file mode 100644 index 0000000..e56b0af --- /dev/null +++ b/src/components/ui/textarea.tsx @@ -0,0 +1,22 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Textarea = React.forwardRef< + HTMLTextAreaElement, + React.ComponentProps<"textarea"> +>(({ className, ...props }, ref) => { + return ( +