maitrang04's picture
Upload 91 files
d125a03 verified
import { ArrowRight, Mic, Brain, Shield, Zap, Volume2, Radio } from "lucide-react";
import { cn } from "@/lib/utils";
interface FlowBlockProps {
icon: React.ReactNode;
label: string;
sublabel?: string;
isActive?: boolean;
variant?: "input" | "process" | "output";
testId: string;
}
function FlowBlock({ icon, label, sublabel, isActive = false, variant = "process", testId }: FlowBlockProps) {
const variantStyles = {
input: "bg-emerald-500/10 border-emerald-500/30 text-emerald-600 dark:text-emerald-400",
process: "bg-primary/10 border-primary/30 text-primary",
output: "bg-amber-500/10 border-amber-500/30 text-amber-600 dark:text-amber-400",
};
return (
<div
className={cn(
"flex flex-col items-center justify-center px-3 py-2 rounded-lg border transition-all duration-300",
variantStyles[variant],
isActive && "ring-2 ring-offset-2 ring-primary/50"
)}
role="img"
aria-label={`${label}${sublabel ? `: ${sublabel}` : ""}`}
data-testid={testId}
>
<div className="mb-1">{icon}</div>
<span className="text-xs font-semibold whitespace-nowrap">{label}</span>
{sublabel && <span className="text-[10px] text-muted-foreground">{sublabel}</span>}
</div>
);
}
function FlowArrow() {
return (
<div className="flex items-center justify-center px-1">
<ArrowRight className="h-4 w-4 text-muted-foreground" aria-hidden="true" />
</div>
);
}
interface DataFlowDiagramProps {
activeStep?: number;
className?: string;
}
export function DataFlowDiagram({ activeStep = -1, className }: DataFlowDiagramProps) {
const steps = [
{ icon: <Mic className="h-4 w-4" />, label: "Audio In", sublabel: "Input", variant: "input" as const, testId: "flow-block-audio-in" },
{ icon: <Radio className="h-4 w-4" />, label: "ASR", sublabel: "Speech-to-Text", variant: "process" as const, testId: "flow-block-asr" },
{ icon: <Brain className="h-4 w-4" />, label: "Reasoning", sublabel: "LLM Layer", variant: "process" as const, testId: "flow-block-reasoning" },
{ icon: <Shield className="h-4 w-4" />, label: "Policy", sublabel: "Safety", variant: "process" as const, testId: "flow-block-policy" },
{ icon: <Zap className="h-4 w-4" />, label: "Action", sublabel: "Response", variant: "process" as const, testId: "flow-block-action" },
{ icon: <Volume2 className="h-4 w-4" />, label: "TTS", sublabel: "Text-to-Speech", variant: "process" as const, testId: "flow-block-tts" },
{ icon: <Mic className="h-4 w-4" />, label: "Audio Out", sublabel: "Output", variant: "output" as const, testId: "flow-block-audio-out" },
];
return (
<div
className={cn("flex items-center gap-1 overflow-x-auto py-2", className)}
role="img"
aria-label="Data flow diagram showing the AI call processing pipeline"
data-testid="data-flow-diagram"
>
{steps.map((step, index) => (
<div key={step.label + index} className="flex items-center">
<FlowBlock
icon={step.icon}
label={step.label}
sublabel={step.sublabel}
variant={step.variant}
isActive={activeStep === index}
testId={step.testId}
/>
{index < steps.length - 1 && <FlowArrow />}
</div>
))}
</div>
);
}