"use client"; import { useMemo, useState, useRef, useEffect } from "react"; import BrandLoader from "./BrandLoader"; import type { Tender } from "../lib/types"; import { Language, translations } from "../lib/translations"; import AgentChat from "./AgentChat"; import type { CompanyProfile } from "../lib/types"; type Props = { tenders: Tender[]; onSearch: (params: { keyword?: string; buyer?: string; provider_code?: string; org_code?: string; status?: string; code?: string; date?: string; type_code?: string; skip?: number; limit?: number; isAgile?: boolean }) => void; onAnalyze: (tender: Tender) => void; forceShowFollowed?: boolean; initialKeyword?: string; lang: Language; companyProfile: CompanyProfile; }; export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFollowed = false, initialKeyword = "", lang, companyProfile }: Props) { const t = translations[lang]; const [keyword, setKeyword] = useState(initialKeyword); const [buyerCode, setBuyerCode] = useState(""); const [providerCode, setProviderCode] = useState(""); const [orgCode, setOrgCode] = useState(""); const [status, setStatus] = useState(""); const [date, setDate] = useState(""); const [typeCode, setTypeCode] = useState(""); const [showAdvanced, setShowAdvanced] = useState(false); const [selectedTenderForModal, setSelectedTenderForModal] = useState(null); const [selectedCodes, setSelectedCodes] = useState([]); const [isSyncingToAgents, setIsSyncingToAgents] = useState(false); const [activeDetailTab, setActiveDetailTab] = useState<"Overview" | "Agent Chat">("Overview"); const [followedTenders, setFollowedTenders] = useState(() => { if (typeof window !== 'undefined') { const saved = localStorage.getItem('andes_followed_tenders_full'); return saved ? JSON.parse(saved) : []; } return []; }); const followedCodes = useMemo(() => followedTenders.map(item => item.code), [followedTenders]); const [showOnlyFollowed, setShowOnlyFollowed] = useState(forceShowFollowed); const [isLoading, setIsLoading] = useState(false); const [isAgileMode, setIsAgileMode] = useState(false); const isSearchPending = useRef(false); const filteredTenders = useMemo(() => { if (showOnlyFollowed) return followedTenders; let list = tenders; if (isAgileMode) { list = list.filter(item => item.code.includes('COT26') || item.name.toLowerCase().includes('compra Γ‘gil') || item.sector?.toLowerCase().includes('agil') ); } return list; }, [tenders, showOnlyFollowed, followedTenders, isAgileMode]); useEffect(() => { if (forceShowFollowed) setShowOnlyFollowed(true); }, [forceShowFollowed]); useEffect(() => { localStorage.setItem('andes_followed_tenders_full', JSON.stringify(followedTenders)); }, [followedTenders]); const toggleFollow = (tender: Tender) => { setFollowedTenders(prev => { const isFollowing = prev.some(item => item.code === tender.code); return isFollowing ? prev.filter(item => item.code !== tender.code) : [...prev, tender]; }); }; const handleSearch = async (e?: React.FormEvent) => { if (e) e.preventDefault(); if (isSearchPending.current) return; isSearchPending.current = true; setIsLoading(true); try { const isCode = /^[0-9]+-[0-9]+-[A-Z0-9]+$/i.test(keyword); const searchParams = { keyword: isCode ? undefined : keyword, code: isCode ? keyword : undefined, org_code: orgCode || undefined, status: status || undefined, type_code: typeCode || undefined, date, skip: 0, limit: 50, isAgile: isAgileMode }; console.log("[TenderSearch] Searching with params:", searchParams); await onSearch(searchParams); } catch (error) { console.error("[TenderSearch] Search failed:", error); const errorMsg = error instanceof Error ? error.message : "Search failed. Check your backend connection."; alert(`Search Error: ${errorMsg}`); } finally { setIsLoading(false); isSearchPending.current = false; } }; const isTenderCode = /^[0-9]+-[0-9]+-[A-Z0-9]+$/i.test(keyword); const isLiveSearch = Boolean(isTenderCode || orgCode || status || date || typeCode); const searchButtonLabel = isLoading ? t.searching : isLiveSearch ? t.liveMPSearch : t.fetchActiveTenders; // VIEW: Search & List const renderListView = () => (
{forceShowFollowed ? "β˜…" : "πŸ“‘"}

{forceShowFollowed ? t.myPortfolio : t.tenderDiscovery}

{t.realTimeAccess}

{!forceShowFollowed && (
setKeyword(e.target.value)} />
{showAdvanced && (
setDate(e.target.value)} />
setOrgCode(e.target.value)} />
)}
)}
{filteredTenders.map((item) => ( ))}
{t.opportunityId} {t.opportunity} {t.buyer} {t.status} {t.analyze}
{item.code}
{item.name}
{item.buyer}
{item.buyer} {item.status}
); // VIEW: Detail Modal const renderDetailView = (tender: Tender) => (
{activeDetailTab === "Overview" ? (
{tender.code} {tender.status} {tender.type || "N/A"}

{tender.name}

{t.estimatedInvestment}

{tender.estimated_amount ? new Intl.NumberFormat("es-CL", { style: "currency", currency: tender.currency || "CLP", maximumFractionDigits: 0 }).format(tender.estimated_amount) : "N/A"}

{t.closingDeadline}

{tender.closing_date ? new Date(tender.closing_date).toLocaleDateString() : "---"}

{t.region}

{tender.region || "Nacional"}

{t.sector}

{tender.sector || "General"}

{t.detailedDescription}

{tender.description || "No description provided."}
{tender.evaluation_criteria && tender.evaluation_criteria.length > 0 && (

βš–οΈ {t.evaluationCriteria}

{tender.evaluation_criteria.map((crit, idx) => (
{crit.weight}%
{crit.name} {crit.weight}%
{crit.description &&

{crit.description}

}
))}
)} {/* Lifecycle Section */}

πŸ”„ {t.procurementLifecycle}

{[ { label: "Preguntas", icon: "❓", status: "Active" }, { label: "Historial", icon: "πŸ“œ", status: "Available" }, { label: "Apertura", icon: "πŸ”“", status: "Pending" }, { label: "AdjudicaciΓ³n", icon: "πŸ†", status: "Future" } ].map((step, i) => (
{step.icon}
{step.label}
{step.status}
))}
{tender.items && tender.items.length > 0 && (

{t.productsServices}

{tender.items.map((item, idx) => ( ))}
Item Name Quantity
{item.name} {item.quantity} {item.unit}
)}

{t.decisionIntelligence}

{t.launchAIPipeline}

{t.documentsAttachments}

{tender.attachments && tender.attachments.length > 0 ? (
{tender.attachments.map((att, idx) => (
πŸ“„ {att.name}
πŸ“₯
))}
) : (
πŸ“„

{t.noAttachments}

)}
) : ( )}
); return (
{selectedTenderForModal ? renderDetailView(selectedTenderForModal) : renderListView()} {isLoading && }
); }