import React, { useState, useEffect } from 'react'; import { Globe, CheckCircle, AlertTriangle, Loader2, FileText, Copy, Calendar, Check, ArrowUpRight, Zap } from 'lucide-react'; import { ToolViewProps } from '../types'; import { formatTimestamp, getToolTitle, } from '../utils'; import { extractWebScrapeData } from './_utils'; import { cn, truncateString } from '@/lib/utils'; import { useTheme } from 'next-themes'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Progress } from '@/components/ui/progress'; import { ScrollArea } from "@/components/ui/scroll-area"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; export function WebScrapeToolView({ name = 'scrape-webpage', assistantContent, toolContent, assistantTimestamp, toolTimestamp, isSuccess = true, isStreaming = false, }: ToolViewProps) { const { resolvedTheme } = useTheme(); const [progress, setProgress] = useState(0); const [copiedFile, setCopiedFile] = useState(null); const { url, files, actualIsSuccess, actualToolTimestamp, actualAssistantTimestamp } = extractWebScrapeData( assistantContent, toolContent, isSuccess, toolTimestamp, assistantTimestamp ); const toolTitle = getToolTitle(name); const formatDomain = (url: string): string => { try { const urlObj = new URL(url); return urlObj.hostname.replace('www.', ''); } catch (e) { return url; } }; const domain = url ? formatDomain(url) : 'Unknown'; const getFavicon = (url: string) => { try { const domain = new URL(url).hostname; return `https://www.google.com/s2/favicons?domain=${domain}&sz=128`; } catch (e) { return null; } }; const favicon = url ? getFavicon(url) : null; useEffect(() => { if (isStreaming) { const timer = setInterval(() => { setProgress((prevProgress) => { if (prevProgress >= 95) { clearInterval(timer); return prevProgress; } return prevProgress + 5; }); }, 300); return () => clearInterval(timer); } else { setProgress(100); } }, [isStreaming]); const copyFilePath = async (filePath: string) => { try { await navigator.clipboard.writeText(filePath); setCopiedFile(filePath); setTimeout(() => setCopiedFile(null), 2000); } catch (err) { console.error('Failed to copy:', err); } }; const formatFileInfo = (filePath: string) => { const timestampMatch = filePath.match(/(\d{8}_\d{6})/); const domainMatch = filePath.match(/(\w+)_com\.json$/); const fileName = filePath.split('/').pop() || filePath; return { timestamp: timestampMatch ? timestampMatch[1] : '', domain: domainMatch ? domainMatch[1] : 'unknown', fileName, fullPath: filePath }; }; return (
{toolTitle}
{!isStreaming && ( {actualIsSuccess ? ( ) : ( )} {actualIsSuccess ? 'Scraping completed' : 'Scraping failed'} )}
{isStreaming ? (

Extracting Content

Analyzing and processing {domain}

{progress}% complete

) : url ? ( // Results State
{/* Target URL Section */}
Source URL
{favicon && ( { (e.target as HTMLImageElement).style.display = 'none'; }} /> )}

{truncateString(url, 70)}

{domain}

{/* Results Section */}
Generated Files
{files.length} file{files.length !== 1 ? 's' : ''}
{/* File List */} {files.length > 0 ? (
{files.map((filePath, idx) => { const fileInfo = formatFileInfo(filePath); const isCopied = copiedFile === filePath; return (
JSON {fileInfo.timestamp && ( {fileInfo.timestamp.replace('_', ' ')} )}

{fileInfo.fileName}

{fileInfo.fullPath}

{isCopied ? 'Copied!' : 'Copy file path'}

); })}
) : (

No files generated

)}
) : (

No URL Detected

Unable to extract a valid URL from the scraping request

)}
{/* Footer */}
{!isStreaming && files.length > 0 && (
{files.length} file{files.length !== 1 ? 's' : ''} saved )}
{actualToolTimestamp && !isStreaming ? formatTimestamp(actualToolTimestamp) : actualAssistantTimestamp ? formatTimestamp(actualAssistantTimestamp) : ''}
); }