From 71732453c983bccaf04049697248bd73ac8af54a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:13:56 +0000 Subject: [PATCH 1/4] Initial plan From 81caafa3caaaf25ab0ffdf2fea179dd768a31802 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Jan 2026 19:22:26 +0000 Subject: [PATCH 2/4] Set up Next.js project structure with basic UI and database Co-authored-by: Stacey77 <54900383+Stacey77@users.noreply.github.com> --- .env.example | 8 + .gitignore | 40 + app/globals.css | 59 + app/layout.tsx | 27 + app/page.tsx | 5 + components/Dashboard.tsx | 206 + components/Sidebar.tsx | 100 + components/ui/badge.tsx | 36 + components/ui/button.tsx | 56 + components/ui/card.tsx | 79 + components/ui/input.tsx | 25 + components/ui/label.tsx | 24 + components/ui/progress.tsx | 26 + components/ui/tabs.tsx | 53 + components/ui/textarea.tsx | 24 + lib/db/prisma.ts | 9 + lib/export/csv.ts | 46 + lib/export/pdf.ts | 129 + lib/gemini/service.ts | 177 + lib/utils.ts | 26 + next.config.js | 13 + package-lock.json | 8092 ++++++++++++++++++++++++++++++++++++ package.json | 55 + postcss.config.js | 6 + prisma/schema.prisma | 55 + tailwind.config.ts | 80 + tsconfig.json | 26 + types/index.ts | 98 + 28 files changed, 9580 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 app/globals.css create mode 100644 app/layout.tsx create mode 100644 app/page.tsx create mode 100644 components/Dashboard.tsx create mode 100644 components/Sidebar.tsx create mode 100644 components/ui/badge.tsx create mode 100644 components/ui/button.tsx create mode 100644 components/ui/card.tsx create mode 100644 components/ui/input.tsx create mode 100644 components/ui/label.tsx create mode 100644 components/ui/progress.tsx create mode 100644 components/ui/tabs.tsx create mode 100644 components/ui/textarea.tsx create mode 100644 lib/db/prisma.ts create mode 100644 lib/export/csv.ts create mode 100644 lib/export/pdf.ts create mode 100644 lib/gemini/service.ts create mode 100644 lib/utils.ts create mode 100644 next.config.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 prisma/schema.prisma create mode 100644 tailwind.config.ts create mode 100644 tsconfig.json create mode 100644 types/index.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2569e6c --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Gemini AI API Key +GEMINI_API_KEY=your_api_key_here + +# Database URL (SQLite for development) +DATABASE_URL=file:./dev.db + +# App URL +NEXT_PUBLIC_APP_URL=http://localhost:3000 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d8bf46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# prisma +/prisma/dev.db +/prisma/dev.db-journal diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..10c2d37 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,59 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..5828116 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,27 @@ +import type { Metadata } from "next"; +import "./globals.css"; +import { Sidebar } from "@/components/Sidebar"; + +export const metadata: Metadata = { + title: "AI Workflow Automation Discovery Platform", + description: "Discover hidden automation opportunities in your operations through systematic interviews and AI-powered analysis", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + +
+ +
+ {children} +
+
+ + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..bb93abc --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,5 @@ +import { Dashboard } from '@/components/Dashboard'; + +export default function DashboardPage() { + return ; +} diff --git a/components/Dashboard.tsx b/components/Dashboard.tsx new file mode 100644 index 0000000..a752ded --- /dev/null +++ b/components/Dashboard.tsx @@ -0,0 +1,206 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Plus, TrendingUp, AlertTriangle, CheckCircle, Clock } from 'lucide-react'; +import Link from 'next/link'; +import { formatDateTime } from '@/lib/utils'; + +interface DashboardStats { + totalInterviews: number; + bottlenecksIdentified: number; + opportunitiesFound: number; + completedAnalyses: number; +} + +interface RecentActivity { + id: string; + type: 'interview' | 'analysis' | 'scan'; + title: string; + timestamp: Date; + status: string; +} + +export function Dashboard() { + const [stats, setStats] = useState({ + totalInterviews: 0, + bottlenecksIdentified: 0, + opportunitiesFound: 0, + completedAnalyses: 0, + }); + const [recentActivity, setRecentActivity] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // TODO: Fetch actual data from API + // For now, using mock data + setStats({ + totalInterviews: 0, + bottlenecksIdentified: 0, + opportunitiesFound: 0, + completedAnalyses: 0, + }); + setRecentActivity([]); + setLoading(false); + }, []); + + return ( +
+ {/* Header */} +
+
+

Dashboard

+

+ Welcome to your AI-powered workflow automation platform +

+
+
+ +
+
+ + {/* Stats Grid */} +
+ + + + Total Interviews + + + + +
{stats.totalInterviews}
+

+ Workflow analysis sessions +

+
+
+ + + + + Bottlenecks Identified + + + + +
{stats.bottlenecksIdentified}
+

+ Pain points discovered +

+
+
+ + + + + Opportunities Found + + + + +
{stats.opportunitiesFound}
+

+ Automation possibilities +

+
+
+ + + + + Completed Analyses + + + + +
{stats.completedAnalyses}
+

+ Full workflow reports +

+
+
+
+ + {/* Quick Actions */} + + + Quick Actions + + Start exploring your workflow automation opportunities + + + + + + + + + + {/* Recent Activity */} + + + Recent Activity + + Your latest workflow analysis activities + + + + {recentActivity.length === 0 ? ( +
+

+ No recent activity. Start by creating your first interview! +

+ +
+ ) : ( +
+ {recentActivity.map((activity) => ( +
+
+

{activity.title}

+

+ {formatDateTime(activity.timestamp)} +

+
+ + {activity.status} + +
+ ))} +
+ )} +
+
+
+ ); +} diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx new file mode 100644 index 0000000..3ce211e --- /dev/null +++ b/components/Sidebar.tsx @@ -0,0 +1,100 @@ +'use client'; + +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { + LayoutDashboard, + MessageSquare, + BarChart3, + Brain, + Shield, + Mic, + Video, + Database, + Menu, + X +} from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { Button } from '@/components/ui/button'; +import { useState } from 'react'; + +const navigation = [ + { name: 'Dashboard', href: '/', icon: LayoutDashboard }, + { name: 'Interview', href: '/interview', icon: MessageSquare }, + { name: 'Analysis', href: '/analysis', icon: BarChart3 }, + { name: 'Context Studio', href: '/context-studio', icon: Brain }, + { name: 'Security Scan', href: '/security', icon: Shield }, +]; + +export function Sidebar() { + const pathname = usePathname(); + const [isOpen, setIsOpen] = useState(true); + + return ( + <> + {/* Mobile menu button */} + + + {/* Sidebar */} + + + {/* Overlay for mobile */} + {isOpen && ( +
setIsOpen(false)} + /> + )} + + ); +} diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx new file mode 100644 index 0000000..f000e3e --- /dev/null +++ b/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/components/ui/button.tsx b/components/ui/button.tsx new file mode 100644 index 0000000..0ba4277 --- /dev/null +++ b/components/ui/button.tsx @@ -0,0 +1,56 @@ +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 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + 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/components/ui/card.tsx b/components/ui/card.tsx new file mode 100644 index 0000000..afa13ec --- /dev/null +++ b/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/components/ui/input.tsx b/components/ui/input.tsx new file mode 100644 index 0000000..677d05f --- /dev/null +++ b/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/components/ui/label.tsx b/components/ui/label.tsx new file mode 100644 index 0000000..683faa7 --- /dev/null +++ b/components/ui/label.tsx @@ -0,0 +1,24 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/components/ui/progress.tsx b/components/ui/progress.tsx new file mode 100644 index 0000000..105fb65 --- /dev/null +++ b/components/ui/progress.tsx @@ -0,0 +1,26 @@ +import * as React from "react" +import * as ProgressPrimitive from "@radix-ui/react-progress" + +import { cn } from "@/lib/utils" + +const Progress = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, value, ...props }, ref) => ( + + + +)) +Progress.displayName = ProgressPrimitive.Root.displayName + +export { Progress } diff --git a/components/ui/tabs.tsx b/components/ui/tabs.tsx new file mode 100644 index 0000000..f57fffd --- /dev/null +++ b/components/ui/tabs.tsx @@ -0,0 +1,53 @@ +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx new file mode 100644 index 0000000..9f9a6dc --- /dev/null +++ b/components/ui/textarea.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface TextareaProps + extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef( + ({ className, ...props }, ref) => { + return ( +