'use client' import { useState, useEffect, useCallback } from 'react' import ProtectedRoute from '@/components/ProtectedRoute' import Modal from '@/components/Modal' import LoadingSpinner from '@/components/LoadingSpinner' import Link from 'next/link' import { toast } from 'react-hot-toast' import { FileText, Plus, Search, Calendar, Building2, DollarSign, AlertCircle, ArrowLeft, Eye, Loader2, } from 'lucide-react' import { tendersAPI, Tender, CreateTenderData, TenderFilters } from '@/lib/api/tenders' import { useLanguage } from '@/contexts/LanguageContext' const SOURCE_LABELS: Record = { GOVERNMENT_SITE: 'Government site', OFFICIAL_GAZETTE: 'Official gazette', PERSONAL: 'Personal relations', PARTNER: 'Partner companies', WHATSAPP_TELEGRAM: 'WhatsApp/Telegram', PORTAL: 'Tender portals', EMAIL: 'Email', MANUAL: 'Manual entry', } const ANNOUNCEMENT_LABELS: Record = { FIRST: 'First announcement', RE_ANNOUNCEMENT_2: 'Re-announcement 2nd', RE_ANNOUNCEMENT_3: 'Re-announcement 3rd', RE_ANNOUNCEMENT_4: 'Re-announcement 4th', } function TendersContent() { const { t } = useLanguage() const [tenders, setTenders] = useState([]) const [loading, setLoading] = useState(true) const [currentPage, setCurrentPage] = useState(1) const [totalPages, setTotalPages] = useState(1) const [total, setTotal] = useState(0) const pageSize = 10 const [searchTerm, setSearchTerm] = useState('') const [selectedStatus, setSelectedStatus] = useState('all') const [showCreateModal, setShowCreateModal] = useState(false) const [formData, setFormData] = useState({ tenderNumber: '', issuingBodyName: '', title: '', termsValue: 0, bondValue: 0, announcementDate: '', closingDate: '', source: 'MANUAL', announcementType: 'FIRST', }) const [formErrors, setFormErrors] = useState>({}) const [submitting, setSubmitting] = useState(false) const [possibleDuplicates, setPossibleDuplicates] = useState([]) const [showDuplicateWarning, setShowDuplicateWarning] = useState(false) const [sourceValues, setSourceValues] = useState([]) const [announcementTypeValues, setAnnouncementTypeValues] = useState([]) const fetchTenders = useCallback(async () => { setLoading(true) try { const filters: TenderFilters = { page: currentPage, pageSize } if (searchTerm) filters.search = searchTerm if (selectedStatus !== 'all') filters.status = selectedStatus const data = await tendersAPI.getAll(filters) setTenders(data.tenders) setTotal(data.total) setTotalPages(data.totalPages) } catch { toast.error(t('tenders.loadError') || 'Failed to load tenders') } finally { setLoading(false) } }, [currentPage, searchTerm, selectedStatus, t]) useEffect(() => { fetchTenders() }, [fetchTenders]) useEffect(() => { tendersAPI.getSourceValues().then(setSourceValues).catch(() => {}) tendersAPI.getAnnouncementTypeValues().then(setAnnouncementTypeValues).catch(() => {}) }, []) const handleCreate = async (e: React.FormEvent) => { e.preventDefault() const errors: Record = {} if (!formData.tenderNumber?.trim()) errors.tenderNumber = t('common.required') if (!formData.issuingBodyName?.trim()) errors.issuingBodyName = t('common.required') if (!formData.title?.trim()) errors.title = t('common.required') if (!formData.announcementDate) errors.announcementDate = t('common.required') if (!formData.closingDate) errors.closingDate = t('common.required') //if (Number(formData.termsValue) < 0) errors.termsValue = t('common.required') if (Number(formData.bondValue) < 0) errors.bondValue = t('common.required') setFormErrors(errors) if (Object.keys(errors).length > 0) return setSubmitting(true) try { const result = await tendersAPI.create(formData) if (result.possibleDuplicates && result.possibleDuplicates.length > 0) { setPossibleDuplicates(result.possibleDuplicates) setShowDuplicateWarning(true) toast(t('tenders.duplicateWarning') || 'Possible duplicates found. Please review.', { icon: '⚠️' }) } else { toast.success(t('tenders.createSuccess') || 'Tender created successfully') setShowCreateModal(false) resetForm() fetchTenders() } } catch (err: any) { toast.error(err.response?.data?.message || 'Failed to create tender') } finally { setSubmitting(false) } } const resetForm = () => { setFormData({ tenderNumber: '', issuingBodyName: '', title: '', termsValue: 0, bondValue: 0, announcementDate: '', closingDate: '', source: 'MANUAL', announcementType: 'FIRST', }) setFormErrors({}) setPossibleDuplicates([]) setShowDuplicateWarning(false) } return (

{t('nav.tenders') || 'Tenders'}

{t('tenders.subtitle') || 'Tender Management'}

setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" />
{loading ? (
) : tenders.length === 0 ? (
{t('tenders.noTenders') || 'No tenders found.'}
) : (
{tenders.map((tender) => ( ))}
{t('tenders.tenderNumber') || 'Number'} {t('tenders.title') || 'Title'} {t('tenders.issuingBody') || 'Issuing body'} {t('tenders.closingDate') || 'Closing date'} {t('common.status')} {t('common.actions')}
{tender.tenderNumber} {tender.title} {tender.issuingBodyName} {tender.closingDate?.split('T')[0]} {tender.status} {t('common.view') || 'View'}
)} {totalPages > 1 && (

{t('common.showing') || 'Showing'} {(currentPage - 1) * pageSize + 1}–{Math.min(currentPage * pageSize, total)} {t('common.of') || 'of'} {total}

)}
{ setShowCreateModal(false); setShowDuplicateWarning(false); resetForm(); }} title={t('tenders.addTender') || 'Add Tender'} >
setFormData({ ...formData, tenderNumber: e.target.value })} className="w-full px-3 py-2 border rounded-lg" /> {formErrors.tenderNumber &&

{formErrors.tenderNumber}

}
setFormData({ ...formData, issuingBodyName: e.target.value })} className="w-full px-3 py-2 border rounded-lg" /> {formErrors.issuingBodyName &&

{formErrors.issuingBodyName}

}
setFormData({ ...formData, title: e.target.value })} className="w-full px-3 py-2 border rounded-lg" /> {formErrors.title &&

{formErrors.title}

}
setFormData({ ...formData, termsValue: Number(e.target.value) || 0 })} className="w-full px-3 py-2 border rounded-lg" />
setFormData({ ...formData, bondValue: Number(e.target.value) || 0 })} className="w-full px-3 py-2 border rounded-lg" />
setFormData({ ...formData, announcementDate: e.target.value })} className="w-full px-3 py-2 border rounded-lg" /> {formErrors.announcementDate &&

{formErrors.announcementDate}

}
setFormData({ ...formData, closingDate: e.target.value })} className="w-full px-3 py-2 border rounded-lg" /> {formErrors.closingDate &&

{formErrors.closingDate}

}
setFormData({ ...formData, announcementLink: e.target.value })} className="w-full px-3 py-2 border rounded-lg" />