AgentGraph / frontend /src /components /shared /WelcomeGuideModal.tsx
wu981526092's picture
🚀 Deploy AgentGraph: Complete agent monitoring and knowledge graph system
c2ea5ed
import React, { useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
Info,
PlayCircle,
Star,
CheckCircle,
AlertCircle,
ChevronRight,
Lightbulb,
} from "lucide-react";
import { welcomeGuideConfig } from "@/lib/welcomeGuideConfig";
import { WelcomeGuideSection } from "@/types";
import { AgentGraphImpact } from "@/components/features/dashboard/visualizations/AgentGraphImpact";
interface WelcomeGuideModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
const iconMap = {
Info,
PlayCircle,
Star,
CheckCircle,
AlertCircle,
};
export function WelcomeGuideModal({
open,
onOpenChange,
}: WelcomeGuideModalProps) {
const [activeSection, setActiveSection] = useState<string>("overview");
const renderSection = (section: WelcomeGuideSection) => {
const IconComponent = iconMap[section.icon as keyof typeof iconMap] || Info;
// Special rendering for AgentGraph Impact section
if (section.id === "agentgraph-impact") {
return (
<div key={section.id} className="mb-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<IconComponent className="h-5 w-5 text-primary" />
{section.title}
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground leading-relaxed mb-6">
{section.content}
</p>
<AgentGraphImpact className="w-full" />
</CardContent>
</Card>
</div>
);
}
// Default rendering for other sections
return (
<Card key={section.id} className="mb-6">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<IconComponent className="h-5 w-5 text-primary" />
{section.title}
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<p className="text-muted-foreground leading-relaxed">
{section.content}
</p>
{section.steps && section.steps.length > 0 && (
<div className="space-y-4">
{section.steps.map((step) => (
<div
key={step.number}
className="border-l-2 border-primary/20 pl-4"
>
<div className="flex items-start gap-3">
<Badge
variant="outline"
className="shrink-0 w-8 h-8 rounded-full flex items-center justify-center p-0 font-semibold"
>
{step.number}
</Badge>
<div className="flex-1 space-y-2">
<h4 className="font-semibold text-foreground">
{step.title}
</h4>
<p className="text-sm text-muted-foreground leading-relaxed">
{step.description}
</p>
{step.tips && step.tips.length > 0 && (
<div className="bg-muted/50 p-3 rounded-lg">
<div className="flex items-center gap-2 mb-2">
<Lightbulb className="h-4 w-4 text-yellow-600" />
<span className="text-sm font-medium">Tips</span>
</div>
<ul className="text-xs text-muted-foreground space-y-1">
{step.tips.map((tip, index) => (
<li
key={index}
className="flex items-start gap-2"
>
<ChevronRight className="h-3 w-3 mt-0.5 shrink-0" />
{tip}
</li>
))}
</ul>
</div>
)}
</div>
</div>
</div>
))}
</div>
)}
</CardContent>
</Card>
);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-4xl max-h-[90vh] p-0">
<DialogHeader className="p-6 pb-0">
<DialogTitle className="text-2xl font-bold">
{welcomeGuideConfig.title}
</DialogTitle>
<DialogDescription className="text-base">
{welcomeGuideConfig.subtitle}
</DialogDescription>
</DialogHeader>
<div className="flex flex-1 min-h-0">
{/* Navigation Sidebar */}
<div className="w-64 border-r bg-muted/20 p-4">
<nav className="space-y-2">
{welcomeGuideConfig.sections.map((section) => {
const IconComponent =
iconMap[section.icon as keyof typeof iconMap] || Info;
return (
<Button
key={section.id}
variant={
activeSection === section.id ? "secondary" : "ghost"
}
className="w-full justify-start gap-2 h-auto p-3"
onClick={() => setActiveSection(section.id)}
>
<IconComponent className="h-4 w-4" />
<span className="text-sm font-medium">{section.title}</span>
</Button>
);
})}
</nav>
</div>
{/* Content Area */}
<div className="flex-1 min-w-0">
<ScrollArea className="h-[70vh] p-6">
{welcomeGuideConfig.sections
.filter((section) => section.id === activeSection)
.map((section) => renderSection(section))}
</ScrollArea>
</div>
</div>
<Separator />
<div className="p-6 pt-4 flex justify-between items-center">
<div className="text-sm text-muted-foreground">
Navigate through sections using the sidebar or scroll through all
content
</div>
<Button onClick={() => onOpenChange(false)}>Got it, thanks!</Button>
</div>
</DialogContent>
</Dialog>
);
}