import { useState, useRef, useEffect } from 'react'; import { Stack, Paper, Text, TextInput, Textarea, Button, Group, Card, Badge, Radio, Loader, ScrollArea, Box, ThemeIcon, Divider, Select, } from '@mantine/core'; import * as TablerIcons from '@tabler/icons-react'; const IconRobot = TablerIcons.IconRobot as React.FC<{ size?: number }>; const IconUser = TablerIcons.IconUser as React.FC<{ size?: number }>; const IconSend = TablerIcons.IconSend as React.FC<{ size?: number }>; const IconEdit = TablerIcons.IconEdit as React.FC<{ size?: number }>; const IconCheck = TablerIcons.IconCheck as React.FC<{ size?: number }>; /** * Input option for choice type */ export interface InputOption { label: string; value: string; description?: string; } /** * Input field for form type */ export interface InputField { name: string; label: string; type: 'text' | 'number' | 'email' | 'textarea'; required: boolean; placeholder?: string; } /** * Configuration for input requests */ export interface InputConfig { placeholder?: string; multiline?: boolean; options?: InputOption[]; fields?: InputField[]; } /** * A message in the interview conversation */ export interface InterviewMessage { id: string; role: 'assistant' | 'user'; content: string; timestamp: number; } /** * Pending input request */ export interface PendingRequest { requestId: string; inputType: 'text' | 'choice' | 'form'; prompt: string; config?: InputConfig; } /** * Generated report from interview */ export interface GeneratedReport { title: string; description: string; severity?: 'low' | 'medium' | 'high' | 'critical'; type?: 'feature_request' | 'change_request' | 'general'; priority?: 'nice_to_have' | 'important' | 'critical'; featureArea?: string; reproductionSteps?: string[]; } /** * Props for InterviewChat component */ export interface InterviewChatProps { /** Messages in the conversation */ messages: InterviewMessage[]; /** Whether we're waiting for AI response */ isThinking: boolean; /** Whether we're waiting for user input */ waitingForInput: boolean; /** Current pending input request */ pendingRequest?: PendingRequest; /** Whether the interview is complete */ isComplete: boolean; /** Generated report if complete */ generatedReport?: GeneratedReport; /** Report type */ reportType: 'bug' | 'feedback'; /** Callback when user submits input */ onSubmitInput: (response: string) => void; /** Callback when user confirms the generated report */ onConfirmReport: (report: GeneratedReport) => void; /** Callback when user wants to edit the report */ onEditReport?: () => void; /** Whether submission is in progress */ isSubmitting?: boolean; } /** * Message bubble component */ function MessageBubble({ message }: { message: InterviewMessage }) { const isAssistant = message.role === 'assistant'; return ( {isAssistant && ( )} {message.content} {!isAssistant && ( )} ); } /** * Text input form */ function TextInputForm({ config, onSubmit, isSubmitting, }: { config?: InputConfig; onSubmit: (value: string) => void; isSubmitting: boolean; }) { const [value, setValue] = useState(''); const handleSubmit = () => { if (value.trim()) { onSubmit(value.trim()); setValue(''); } }; if (config?.multiline) { return (