"use client"; import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb"; import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import Loading from "@/components/loading"; import { useGetTenderDocumentsQuery, useTenderDetailQuery, useTranslateTenderMutation, } from "@/hooks/queries"; import type { TTenderDetails } from "@/lib/api/types/Tenders"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { use, useCallback, useEffect, useMemo, useRef } from "react"; import { TenderDetailsContent } from "./components/tender-details-content"; import { TenderDetailsError } from "./components/tender-details-error"; import { TenderDetailsHeader } from "./components/tender-details-header"; import { useTenderSectionScrollSpy } from "./hooks/use-tender-section-scroll-spy"; import { getTenderNavItems } from "./tender-nav-utils"; import { shouldShowAiSummarySection } from "./tender-display-utils"; interface IProps { params: Promise<{ details: string; }>; } const TenderDetails = ({ params }: IProps) => { const { details } = use(params); const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const selectedLanguage = searchParams.get("lang") || "en"; const { mutate: translateTender, isPending: isTranslating } = useTranslateTenderMutation(); const { data, isLoading, isError, isFetching } = useTenderDetailQuery( details, { language: selectedLanguage }, ); const breadcrumbItems = [ { name: "Dashboard", href: "/" }, { name: "Tenders", href: "/tenders" }, { name: "Tender details", href: `/tenders/${details}` }, ]; const tenderForNav = data?.data; const hasValidAiSummary = tenderForNav ? shouldShowAiSummarySection(tenderForNav) : false; const { data: documentsResponse, isPending: isDocumentsLoading } = useGetTenderDocumentsQuery(details, { enabled: hasValidAiSummary }); const documents = documentsResponse?.data ?? []; const showDocumentsSection = hasValidAiSummary && (isDocumentsLoading || documents.length > 0); const tenderNavItems = useMemo( () => tenderForNav ? getTenderNavItems(tenderForNav, { showDocuments: showDocumentsSection, }) : [], [tenderForNav, showDocumentsSection], ); const sectionIds = useMemo( () => tenderNavItems.map((item) => item.id), [tenderNavItems], ); const activeSectionId = useTenderSectionScrollSpy(sectionIds); // Only translate when the user explicitly picks a language from the dropdown. // The ref is set inside handleLanguageChange and consumed by the effect once // the GET refetch resolves; initial page loads never trigger a translate. const userPendingLangRef = useRef(null); const attemptedRef = useRef>(new Set()); const handleLanguageChange = useCallback( (event: React.ChangeEvent) => { const nextLanguage = event.target.value; if (!nextLanguage) return; const prevLanguage = searchParams.get("lang") || "en"; if (nextLanguage === prevLanguage) return; userPendingLangRef.current = nextLanguage; const nextParams = new URLSearchParams(searchParams.toString()); nextParams.set("lang", nextLanguage); const queryString = nextParams.toString(); router.replace(queryString ? `${pathname}?${queryString}` : pathname); }, [pathname, router, searchParams], ); // ensureTranslation flow (per backend integration doc): // 1) User picks a language → handleLanguageChange marks it as pending. // 2) GET detail with ?language={selected} refetches. // 3) If the refetched data.language doesn't match, POST ai-translate. // The mutation's onSuccess invalidates the detail query → refetch binds title/description. // attemptedRef prevents a retry loop if translation fails. useEffect(() => { const fetched = data?.data; if (!fetched) return; if (isFetching || isTranslating) return; const pending = userPendingLangRef.current; if (!pending || pending !== selectedLanguage) return; if (fetched.language === selectedLanguage) { userPendingLangRef.current = null; return; } const key = `${details}::${selectedLanguage}`; if (attemptedRef.current.has(key)) { userPendingLangRef.current = null; return; } attemptedRef.current.add(key); userPendingLangRef.current = null; translateTender({ id: details, language: selectedLanguage }); }, [ data, details, isFetching, isTranslating, selectedLanguage, translateTender, ]); if (isLoading) return ; if (isError) { return ; } const tender: TTenderDetails = data!.data; return ( <> } className="!p-0" > ); }; export default TenderDetails;