1Egyb commited on
Commit
49f56af
·
verified ·
1 Parent(s): 11ae435

Upload 10 files

Browse files
frontend/chat-interface.tsx ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState } from "react"
4
+ import { Button } from "@/components/ui/button"
5
+ import { Textarea } from "@/components/ui/textarea"
6
+ import { ScrollArea } from "@/components/ui/scroll-area"
7
+ import { Copy, Download, ThumbsUp, ThumbsDown } from 'lucide-react'
8
+ import { cn } from "@/lib/utils"
9
+
10
+ interface Message {
11
+ role: "agent" | "user"
12
+ content: string
13
+ timestamp: string
14
+ }
15
+
16
+ export default function ChatInterface() {
17
+ const [input, setInput] = useState("")
18
+ const [messages] = useState<Message[]>([
19
+ {
20
+ role: "agent",
21
+ content: "Hello, I am a generative AI agent. How may I assist you today?",
22
+ timestamp: "4:08:28 PM"
23
+ },
24
+ {
25
+ role: "user",
26
+ content: "Hi, I'd like to check my bill.",
27
+ timestamp: "4:08:37 PM"
28
+ },
29
+ {
30
+ role: "agent",
31
+ content: "Please hold for a second.\n\nOk, I can help you with that\n\nI'm pulling up your current bill information\n\nYour current bill is $150, and it is due on August 31, 2024.\n\nIf you need more details, feel free to ask!",
32
+ timestamp: "4:08:37 PM"
33
+ }
34
+ ])
35
+
36
+ return (
37
+ <div className="flex-1 flex flex-col">
38
+ <ScrollArea className="flex-1 p-4">
39
+ <div className="space-y-4">
40
+ {messages.map((message, index) => (
41
+ <div
42
+ key={index}
43
+ className={cn(
44
+ "flex gap-2 max-w-[80%]",
45
+ message.role === "user" && "ml-auto"
46
+ )}
47
+ >
48
+ {message.role === "agent" && (
49
+ <div className="h-8 w-8 rounded-full bg-primary flex-shrink-0" />
50
+ )}
51
+ <div className="space-y-2">
52
+ <div className="flex items-center gap-2">
53
+ <span className="text-sm font-medium">
54
+ {message.role === "agent" ? "GenerativeAgent" : "G5"}
55
+ </span>
56
+ <span className="text-sm text-muted-foreground">
57
+ {message.timestamp}
58
+ </span>
59
+ </div>
60
+ <div className="p-3 bg-muted/50 rounded-lg">
61
+ <p className="text-sm whitespace-pre-wrap">{message.content}</p>
62
+ </div>
63
+ {message.role === "agent" && (
64
+ <div className="flex items-center gap-2">
65
+ <Button variant="ghost" size="icon" className="h-8 w-8">
66
+ <Copy className="h-4 w-4" />
67
+ </Button>
68
+ <Button variant="ghost" size="icon" className="h-8 w-8">
69
+ <Download className="h-4 w-4" />
70
+ </Button>
71
+ <Button variant="ghost" size="icon" className="h-8 w-8">
72
+ <ThumbsUp className="h-4 w-4" />
73
+ </Button>
74
+ <Button variant="ghost" size="icon" className="h-8 w-8">
75
+ <ThumbsDown className="h-4 w-4" />
76
+ </Button>
77
+ </div>
78
+ )}
79
+ </div>
80
+ </div>
81
+ ))}
82
+ </div>
83
+ </ScrollArea>
84
+ <div className="p-4 border-t">
85
+ <div className="flex gap-2">
86
+ <Textarea
87
+ placeholder="Type a message as a customer"
88
+ value={input}
89
+ onChange={(e) => setInput(e.target.value)}
90
+ className="min-h-[44px] max-h-32"
91
+ />
92
+ <Button className="px-8">Send</Button>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ )
97
+ }
frontend/components.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "app/globals.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "@/components",
15
+ "utils": "@/lib/utils",
16
+ "ui": "@/components/ui",
17
+ "lib": "@/lib",
18
+ "hooks": "@/hooks"
19
+ },
20
+ "iconLibrary": "lucide"
21
+ }
frontend/layout.tsx ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { cn } from "@/lib/utils"
2
+ import { Button } from "@/components/ui/button"
3
+ import { ScrollArea } from "@/components/ui/scroll-area"
4
+ import { LayoutGrid, Settings, Users, SettingsIcon as Functions, Layers, Eye, BarChart2, X } from 'lucide-react'
5
+
6
+ export default function Layout({ children }: { children: React.ReactNode }) {
7
+ return (
8
+ <div className="flex h-screen bg-background">
9
+ {/* Sidebar */}
10
+ <div className="w-64 border-r bg-muted/10">
11
+ <div className="p-4 border-b">
12
+ <div className="flex items-center gap-2">
13
+ <div className="h-6 w-6 rounded-full bg-primary" />
14
+ <span className="font-semibold">GenerativeAgent</span>
15
+ </div>
16
+ </div>
17
+ <ScrollArea className="h-[calc(100vh-64px)]">
18
+ <div className="space-y-4 p-4">
19
+ <nav className="space-y-2">
20
+ <Button variant="ghost" className="w-full justify-start">
21
+ <LayoutGrid className="mr-2 h-4 w-4" />
22
+ Tasks
23
+ </Button>
24
+ <Button variant="ghost" className="w-full justify-start">
25
+ <Functions className="mr-2 h-4 w-4" />
26
+ Functions
27
+ </Button>
28
+ <Button variant="ghost" className="w-full justify-start">
29
+ <Layers className="mr-2 h-4 w-4" />
30
+ Integrations
31
+ </Button>
32
+ <Button variant="ghost" className="w-full justify-start">
33
+ <Users className="mr-2 h-4 w-4" />
34
+ Users
35
+ </Button>
36
+ <Button variant="ghost" className="w-full justify-start">
37
+ <Settings className="mr-2 h-4 w-4" />
38
+ Settings
39
+ </Button>
40
+ </nav>
41
+ <div className="pt-4 border-t">
42
+ <Button variant="ghost" className="w-full justify-start">
43
+ <Eye className="mr-2 h-4 w-4" />
44
+ Live preview
45
+ </Button>
46
+ <Button variant="ghost" className="w-full justify-start">
47
+ <BarChart2 className="mr-2 h-4 w-4" />
48
+ Performance
49
+ </Button>
50
+ </div>
51
+ </div>
52
+ </ScrollArea>
53
+ </div>
54
+
55
+ {/* Main Content */}
56
+ <div className="flex-1 flex">
57
+ <div className="flex-1 flex flex-col">
58
+ {/* Header */}
59
+ <header className="h-14 border-b px-4 flex items-center justify-between">
60
+ <h1 className="text-sm font-medium">Voice conversation</h1>
61
+ <div className="flex items-center gap-2">
62
+ <Button variant="ghost" size="sm">
63
+ Save conversation
64
+ </Button>
65
+ <Button variant="ghost" size="sm" className="h-8 w-8 p-0">
66
+ <X className="h-4 w-4" />
67
+ </Button>
68
+ </div>
69
+ </header>
70
+ {children}
71
+ </div>
72
+
73
+ {/* Right Panel */}
74
+ <div className="w-80 border-l">
75
+ <div className="h-14 border-b px-4 flex items-center">
76
+ <h2 className="font-medium">Conversation details</h2>
77
+ </div>
78
+ <div className="p-4">
79
+ <div className="flex gap-4 border-b pb-4">
80
+ <Button variant="secondary" size="sm" className="rounded-full">
81
+ Actions
82
+ </Button>
83
+ <Button variant="ghost" size="sm" className="rounded-full">
84
+ Customer
85
+ </Button>
86
+ <Button variant="ghost" size="sm" className="rounded-full">
87
+ Settings
88
+ </Button>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ )
95
+ }
frontend/next.config.mjs ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ typescript: {
4
+ ignoreBuildErrors: true,
5
+ },
6
+ images: {
7
+ unoptimized: true,
8
+ },
9
+ }
10
+
11
+ export default nextConfig
frontend/package.json ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "my-v0-project",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "build": "next build",
7
+ "dev": "next dev",
8
+ "lint": "eslint .",
9
+ "start": "next start"
10
+ },
11
+ "dependencies": {
12
+ "@hookform/resolvers": "^3.10.0",
13
+ "@radix-ui/react-accordion": "1.2.2",
14
+ "@radix-ui/react-alert-dialog": "1.1.4",
15
+ "@radix-ui/react-aspect-ratio": "1.1.1",
16
+ "@radix-ui/react-avatar": "1.1.2",
17
+ "@radix-ui/react-checkbox": "1.1.3",
18
+ "@radix-ui/react-collapsible": "1.1.2",
19
+ "@radix-ui/react-context-menu": "2.2.4",
20
+ "@radix-ui/react-dialog": "1.1.4",
21
+ "@radix-ui/react-dropdown-menu": "2.1.4",
22
+ "@radix-ui/react-hover-card": "1.1.4",
23
+ "@radix-ui/react-label": "2.1.1",
24
+ "@radix-ui/react-menubar": "1.1.4",
25
+ "@radix-ui/react-navigation-menu": "1.2.3",
26
+ "@radix-ui/react-popover": "1.1.4",
27
+ "@radix-ui/react-progress": "1.1.1",
28
+ "@radix-ui/react-radio-group": "1.2.2",
29
+ "@radix-ui/react-scroll-area": "1.2.2",
30
+ "@radix-ui/react-select": "2.1.4",
31
+ "@radix-ui/react-separator": "1.1.1",
32
+ "@radix-ui/react-slider": "1.2.2",
33
+ "@radix-ui/react-slot": "1.1.1",
34
+ "@radix-ui/react-switch": "1.1.2",
35
+ "@radix-ui/react-tabs": "1.1.2",
36
+ "@radix-ui/react-toast": "1.2.4",
37
+ "@radix-ui/react-toggle": "1.1.1",
38
+ "@radix-ui/react-toggle-group": "1.1.1",
39
+ "@radix-ui/react-tooltip": "1.1.6",
40
+ "@vercel/analytics": "1.3.1",
41
+ "autoprefixer": "^10.4.20",
42
+ "class-variance-authority": "^0.7.1",
43
+ "clsx": "^2.1.1",
44
+ "cmdk": "1.0.4",
45
+ "date-fns": "4.1.0",
46
+ "embla-carousel-react": "8.5.1",
47
+ "input-otp": "1.4.1",
48
+ "lucide-react": "^0.454.0",
49
+ "next": "15.2.6",
50
+ "next-themes": "^0.4.6",
51
+ "react": "^19",
52
+ "react-day-picker": "9.8.0",
53
+ "react-dom": "^19",
54
+ "react-hook-form": "^7.60.0",
55
+ "react-resizable-panels": "^2.1.7",
56
+ "recharts": "2.15.4",
57
+ "sonner": "^1.7.4",
58
+ "tailwind-merge": "^2.5.5",
59
+ "tailwindcss-animate": "^1.0.7",
60
+ "vaul": "^1.1.2",
61
+ "zod": "3.25.76"
62
+ },
63
+ "devDependencies": {
64
+ "@types/node": "^22",
65
+ "@types/react": "^19",
66
+ "@types/react-dom": "^19",
67
+ "postcss": "^8.5",
68
+ "tailwindcss": "^3.4.17",
69
+ "typescript": "^5"
70
+ }
71
+ }
frontend/page.tsx ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import Layout from "./layout"
2
+ import ChatInterface from "./chat-interface"
3
+
4
+ export default function Page() {
5
+ return (
6
+ <Layout>
7
+ <ChatInterface />
8
+ </Layout>
9
+ )
10
+ }
frontend/pnpm-lock.yaml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
frontend/postcss.config.mjs ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ /** @type {import('postcss-load-config').Config} */
2
+ const config = {
3
+ plugins: {
4
+ tailwindcss: {},
5
+ },
6
+ }
7
+
8
+ export default config
frontend/tailwind.config.ts ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Config } from 'tailwindcss'
2
+
3
+ // all in fixtures is set to tailwind v3 as interims solutions
4
+
5
+ const config: Config = {
6
+ darkMode: ['class'],
7
+ content: [
8
+ './pages/**/*.{js,ts,jsx,tsx,mdx}',
9
+ './components/**/*.{js,ts,jsx,tsx,mdx}',
10
+ './app/**/*.{js,ts,jsx,tsx,mdx}',
11
+ '*.{js,ts,jsx,tsx,mdx}',
12
+ ],
13
+ theme: {
14
+ extend: {
15
+ colors: {
16
+ background: 'hsl(var(--background))',
17
+ foreground: 'hsl(var(--foreground))',
18
+ card: {
19
+ DEFAULT: 'hsl(var(--card))',
20
+ foreground: 'hsl(var(--card-foreground))',
21
+ },
22
+ popover: {
23
+ DEFAULT: 'hsl(var(--popover))',
24
+ foreground: 'hsl(var(--popover-foreground))',
25
+ },
26
+ primary: {
27
+ DEFAULT: 'hsl(var(--primary))',
28
+ foreground: 'hsl(var(--primary-foreground))',
29
+ },
30
+ secondary: {
31
+ DEFAULT: 'hsl(var(--secondary))',
32
+ foreground: 'hsl(var(--secondary-foreground))',
33
+ },
34
+ muted: {
35
+ DEFAULT: 'hsl(var(--muted))',
36
+ foreground: 'hsl(var(--muted-foreground))',
37
+ },
38
+ accent: {
39
+ DEFAULT: 'hsl(var(--accent))',
40
+ foreground: 'hsl(var(--accent-foreground))',
41
+ },
42
+ destructive: {
43
+ DEFAULT: 'hsl(var(--destructive))',
44
+ foreground: 'hsl(var(--destructive-foreground))',
45
+ },
46
+ border: 'hsl(var(--border))',
47
+ input: 'hsl(var(--input))',
48
+ ring: 'hsl(var(--ring))',
49
+ chart: {
50
+ '1': 'hsl(var(--chart-1))',
51
+ '2': 'hsl(var(--chart-2))',
52
+ '3': 'hsl(var(--chart-3))',
53
+ '4': 'hsl(var(--chart-4))',
54
+ '5': 'hsl(var(--chart-5))',
55
+ },
56
+ sidebar: {
57
+ DEFAULT: 'hsl(var(--sidebar-background))',
58
+ foreground: 'hsl(var(--sidebar-foreground))',
59
+ primary: 'hsl(var(--sidebar-primary))',
60
+ 'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
61
+ accent: 'hsl(var(--sidebar-accent))',
62
+ 'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
63
+ border: 'hsl(var(--sidebar-border))',
64
+ ring: 'hsl(var(--sidebar-ring))',
65
+ },
66
+ },
67
+ borderRadius: {
68
+ lg: 'var(--radius)',
69
+ md: 'calc(var(--radius) - 2px)',
70
+ sm: 'calc(var(--radius) - 4px)',
71
+ },
72
+ keyframes: {
73
+ 'accordion-down': {
74
+ from: {
75
+ height: '0',
76
+ },
77
+ to: {
78
+ height: 'var(--radix-accordion-content-height)',
79
+ },
80
+ },
81
+ 'accordion-up': {
82
+ from: {
83
+ height: 'var(--radix-accordion-content-height)',
84
+ },
85
+ to: {
86
+ height: '0',
87
+ },
88
+ },
89
+ },
90
+ animation: {
91
+ 'accordion-down': 'accordion-down 0.2s ease-out',
92
+ 'accordion-up': 'accordion-up 0.2s ease-out',
93
+ },
94
+ },
95
+ },
96
+ plugins: [require('tailwindcss-animate')],
97
+ }
98
+ export default config
frontend/tsconfig.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["dom", "dom.iterable", "esnext"],
4
+ "allowJs": true,
5
+ "target": "ES6",
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./*"]
23
+ }
24
+ },
25
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26
+ "exclude": ["node_modules"]
27
+ }