import React, { useState } from 'react' import { X, Globe, ExternalLink } from 'lucide-react' const ENTITY_COLORS = { startup: '#3B82F6', sme: '#10B981', college_ecell: '#FBBF24', incubator: '#A855F7', accelerator: '#EC4899', } const ENTITY_LABELS = { startup: '๐Ÿš€ Startup', sme: '๐Ÿข SME', college_ecell: '๐ŸŽ“ E-Cell', incubator: '๐Ÿงช Incubator', accelerator: 'โšก Accelerator', } function formatFunding(v) { if (!v || v === 0) return 'Bootstrapped' const cr = v / 10000000 if (cr >= 10000) return `โ‚น${(cr/100000).toFixed(2)} Lakh Cr` if (cr >= 100) return `โ‚น${cr.toLocaleString('en-IN', { maximumFractionDigits: 0 })} Cr` if (cr >= 1) return `โ‚น${cr.toFixed(1)} Cr` return `โ‚น${(v/100000).toFixed(0)} L` } // โ”€โ”€โ”€ URL Validation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function isValidHttpUrl(url) { if (!url || typeof url !== 'string') return false try { const u = new URL(url.trim()) const protocol = u.protocol.toLowerCase() if (protocol !== 'http:' && protocol !== 'https:') return false const hostname = u.hostname.toLowerCase() // Block private IPs and localhost if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '0.0.0.0') return false if (hostname.startsWith('192.168.') || hostname.startsWith('10.')) return false if (hostname.startsWith('172.')) { const parts = hostname.split('.') if (parts.length >= 2) { const second = parseInt(parts[1], 10) if (second >= 16 && second <= 31) return false } } return true } catch { return false } } function sanitizeUrl(url) { if (!url || typeof url !== 'string') return '' const trimmed = url.trim() const lower = trimmed.toLowerCase() if (lower.startsWith('javascript:') || lower.startsWith('data:') || lower.startsWith('vbscript:')) { return '' } return trimmed } const SOCIAL_CONFIG = { linkedin: { icon: '๐Ÿ’ผ', color: '#0A66C2', label: 'LinkedIn' }, twitter: { icon: '๐•', color: '#000000', label: 'X (Twitter)' }, instagram: { icon: '๐Ÿ“ธ', color: '#E4405F', label: 'Instagram' }, facebook: { icon: '๐Ÿ“˜', color: '#1877F2', label: 'Facebook' }, website: { icon: '๐ŸŒ', color: '#6366F1', label: 'Website' }, crunchbase: { icon: 'CB', color: '#0288D1', label: 'Crunchbase' }, tracxn: { icon: 'TX', color: '#FF6F00', label: 'Tracxn' }, google: { icon: '๐Ÿ”', color: '#4285F4', label: 'Google Search' }, } function SocialLinksGrid({ entity }) { const links = [] const name = entity.name if (entity.linkedin_url && isValidHttpUrl(entity.linkedin_url)) { links.push({ ...SOCIAL_CONFIG.linkedin, url: sanitizeUrl(entity.linkedin_url), verified: true }) } if (entity.twitter_url && isValidHttpUrl(entity.twitter_url)) { links.push({ ...SOCIAL_CONFIG.twitter, url: sanitizeUrl(entity.twitter_url), verified: true }) } if (entity.instagram_url && isValidHttpUrl(entity.instagram_url)) { links.push({ ...SOCIAL_CONFIG.instagram, url: sanitizeUrl(entity.instagram_url), verified: true }) } if (entity.facebook_url && isValidHttpUrl(entity.facebook_url)) { links.push({ ...SOCIAL_CONFIG.facebook, url: sanitizeUrl(entity.facebook_url), verified: true }) } if (entity.website && isValidHttpUrl(entity.website)) { links.push({ ...SOCIAL_CONFIG.website, url: sanitizeUrl(entity.website), verified: true }) } // Search links (always available, constructed safely) const slug = name.toLowerCase().replace(/\s+/g, '-').replace('.', '') const encName = encodeURIComponent(name) if (!entity.linkedin_url) links.push({ ...SOCIAL_CONFIG.linkedin, url: `https://www.linkedin.com/search/results/companies/?keywords=${encName}`, search: true }) if (!entity.twitter_url) links.push({ ...SOCIAL_CONFIG.twitter, url: `https://x.com/search?q=${encName}&src=typed_query`, search: true }) if (!entity.instagram_url) links.push({ ...SOCIAL_CONFIG.instagram, url: `https://www.instagram.com/${slug}`, search: true }) if (!entity.website) links.push({ ...SOCIAL_CONFIG.website, url: `https://www.google.com/search?q=${encName}+company`, search: true }) links.push({ ...SOCIAL_CONFIG.crunchbase, url: `https://www.crunchbase.com/organization/${slug}`, search: true }) links.push({ ...SOCIAL_CONFIG.tracxn, url: `https://tracxn.com/d/companies/${slug}/`, search: true }) links.push({ ...SOCIAL_CONFIG.google, url: `https://www.google.com/search?q=${encName}+startup+India+news+2024+2025`, search: true }) return (
{links.filter(l => isValidHttpUrl(l.url)).map(l => ( {l.icon} {l.label} {l.verified && } ))}
) } function AIAnalysisSection({ entity }) { const [analysis, setAnalysis] = useState(null) const [loading, setLoading] = useState(false) const runAnalysis = async () => { setLoading(true) try { const resp = await fetch('/api/agent/analyze-startup', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ company_name: entity.name, sector: Array.isArray(entity.sectors) ? entity.sectors[0] : entity.dpiit_category || '', city: entity.city || '', }), }) const data = await resp.json() setAnalysis(data) } catch (e) { setAnalysis({ summary: 'Analysis temporarily unavailable. Try again later.', latest_news: [], confidence: 'low' }) } setLoading(false) } return (
{!analysis && ( )} {analysis && (
๐Ÿค– AI Analysis {analysis.confidence} confidence

{analysis.summary}

{analysis.latest_news?.length > 0 && (
Latest News {analysis.latest_news.slice(0, 3).map((n, i) => ( โ€ข {n.title} ))}
)}
)}
) } export default function EntityDetail({ entity, onClose, onEntityClick, isMobile }) { if (!entity) return null const e = entity const color = ENTITY_COLORS[e.entity_type] || '#64748B' const label = ENTITY_LABELS[e.entity_type] || e.entity_type const sectors = Array.isArray(e.sectors) ? e.sectors : [] const investors = Array.isArray(e.investors) ? e.investors : [] const nearby = Array.isArray(e.nearby) ? e.nearby : [] return (
{/* Header */}
{e.entity_type === 'startup' ? '๐Ÿš€' : e.entity_type === 'sme' ? '๐Ÿข' : e.entity_type === 'college_ecell' ? '๐ŸŽ“' : e.entity_type === 'incubator' ? '๐Ÿงช' : 'โšก'}

{e.name}

๐Ÿ“ {e.city}, {e.state}

{label}
{/* Badges */}
{e.dpiit_recognized && } {e.unicorn_status === 'unicorn' && } {e.unicorn_status === 'soonicorn' && } {e.is_women_led && } {e.is_rural_impact && } {e.is_campus_startup && } {e.nsa_winner && } {!e.dpiit_recognized && }
{/* Scrollable body */}
{/* Social Media Links */}

Social & Profiles

{/* Description */} {e.description && (

{e.description}

)} {/* Key Metrics */}
{/* Sectors */} {sectors.length > 0 && (

Sectors

{sectors.map(s => ( {s} ))}
)} {/* Additional Info */}
{e.stage && l.toUpperCase())} />} {e.business_model && l.toUpperCase())} />} {e.dpiit_category && } {e.college_name && } {e.funding_stage && } {e.valuation_usd && }
{/* Investors */} {investors.length > 0 && (

Investors

{investors.map((inv, i) => ( {inv} ))}
)} {/* AI Web Analysis */} {/* Nearby Entities */} {nearby.length > 0 && (

Nearby ({nearby.length})

{nearby.slice(0, 5).map(n => ( ))}
)} {/* Report Error */}
๐Ÿšฉ Report an error in this data
) } function Badge({ text, cls }) { return {text} } function MetricCard({ label, value, icon }) { return (
{icon}

{value}

{label}

) } function InfoRow({ label, value }) { return (
{label} {value}
) }