'use client'; import { useState, useCallback } from 'react'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Search, CheckCircle2, XCircle, Loader2, ExternalLink, Package } from 'lucide-react'; import { useUserTimezone } from '@/lib/hooks/use-user-timezone'; interface ComplianceMismatch { id: number; company_id: number | null; company_name: string | null; configuration_item_id: number | null; veeam_workload_uid: string | null; mismatch_type: string; backup_type_udf: string | null; device_name: string; contract_name: string | null; veeam_workload_name: string | null; billing_covered: boolean | null; billing_contract_name: string | null; billing_contracted_qty: number | null; billing_contract_id: number | null; coverage_source: string | null; } interface ContractService { id: number; service_id: number | null; display_name: string; description: string | null; unit_price: number | null; unit_cost: number | null; quantity: number | null; adjusted_price: number | null; period_label: string | null; start_date: string | null; end_date: string | null; } interface ContractDetail { id: number; contract_name: string; company_name: string; status: number; contract_type: number | null; start_date: string | null; end_date: string | null; description: string | null; } interface ComplianceDetailTableProps { mismatches: ComplianceMismatch[]; } const BACKUP_SERVICE_PATTERNS = [ /workstation.*backup/i, /w\/ backup/i, /windows server/i, /server virtual/i, /server phys/i, /esxi host/i, /wulf 365 it complete (endpoint|server)/i, /wulf it complete \((server|endpoint)\)/i, ]; function isBackupService(name: string): boolean { return BACKUP_SERVICE_PATTERNS.some((re) => re.test(name)); } function ContractCoverageModal({ contractId, companyName, open, onClose, tz, }: { contractId: number | null; companyName: string | null; open: boolean; onClose: () => void; tz: string; }) { const [data, setData] = useState<{ contract: ContractDetail; services: ContractService[] } | null>(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [loadedId, setLoadedId] = useState(null); const load = useCallback(async (id: number) => { if (loadedId === id) return; setLoading(true); setError(null); try { const res = await fetch(`/api/data/contracts/${id}/services`); if (!res.ok) throw new Error('Failed to load contract details'); const json = await res.json(); setData(json); setLoadedId(id); } catch (e) { setError(e instanceof Error ? e.message : 'Unknown error'); } finally { setLoading(false); } }, [loadedId]); if (open && contractId && loadedId !== contractId && !loading) { load(contractId); } const contract = data?.contract; const services = data?.services ?? []; const backupServices = services.filter((s) => isBackupService(s.display_name)); const otherServices = services.filter((s) => !isBackupService(s.display_name)); return ( !v && onClose()}> Contract Coverage {contract && ( — {contract.company_name} )} {loading && (
)} {error && (

{error}

)} {!loading && !error && contract && (
{/* Contract header */}

{contract.contract_name}

{contract.company_name}

View in Autotask
{contract.start_date && ( Start: {new Date(contract.start_date).toLocaleDateString(undefined, { timeZone: tz })} )} {contract.end_date && ( End: {new Date(contract.end_date).toLocaleDateString(undefined, { timeZone: tz })} )} {contract.status === 1 ? 'Active' : 'Inactive'}
{/* Backup-relevant services */} {backupServices.length > 0 && (

Backup-Covered Services

)} {/* Other services */} {otherServices.length > 0 && (

All Services ({services.length})

)} {services.length === 0 && (

No service lines found for this contract.

)}
)}
); } function ServiceTable({ services, highlight }: { services: ContractService[]; highlight?: boolean }) { return (
Service Unit Price Unit Cost {services.map((s) => ( {highlight && } {s.display_name} {s.unit_price != null ? `$${Number(s.unit_price).toFixed(2)}` : '—'} {s.unit_cost != null ? `$${Number(s.unit_cost).toFixed(2)}` : '—'} ))}
); } export function ComplianceDetailTable({ mismatches }: ComplianceDetailTableProps) { const tz = useUserTimezone(); const [search, setSearch] = useState(''); const [typeFilter, setTypeFilter] = useState('all'); const [modalContractId, setModalContractId] = useState(null); const [modalCompanyName, setModalCompanyName] = useState(null); const [modalOpen, setModalOpen] = useState(false); const openModal = (contractId: number, companyName: string | null) => { setModalContractId(contractId); setModalCompanyName(companyName); setModalOpen(true); }; const filtered = mismatches.filter((m) => { const matchesSearch = (m.device_name || '').toLowerCase().includes(search.toLowerCase()) || (m.company_name || '').toLowerCase().includes(search.toLowerCase()); const matchesType = typeFilter === 'all' || m.mismatch_type === typeFilter; return matchesSearch && matchesType; }); return (
setSearch(e.target.value)} className="pl-9" />
{[ { key: 'all', label: 'All' }, { key: 'contracted_not_backed_up', label: 'Missing Backup' }, { key: 'backed_up_not_contracted', label: 'No Contract' }, ].map((f) => ( ))}
Company Device Issue Backup UDF Contract Coverage Veeam Workload {filtered.length === 0 ? ( {mismatches.length === 0 ? 'No compliance issues found — all clear!' : 'No matching results'} ) : ( filtered.map((m) => ( {m.company_name || '-'} {m.device_name} {m.mismatch_type === 'contracted_not_backed_up' ? 'Missing Backup' : 'No Contract'} {m.backup_type_udf || '-'} {m.billing_covered && m.billing_contract_id ? ( ) : m.billing_covered ? (
{m.billing_contract_name || 'Active'}
) : (
No backup contract
)}
{m.veeam_workload_name || '-'}
)) )}
setModalOpen(false)} tz={tz} />
); }