import React, { useState, useMemo } from "react"; import { base44 } from "@/api/base44Client"; import { useQuery } from "@tanstack/react-query"; import { Link } from "react-router-dom"; import { createPageUrl } from "@/utils"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Briefcase, Plus, Search, MapPin, DollarSign, Edit, Building2, TrendingUp, AlertTriangle, CheckCircle2, Users, Target, LayoutGrid, List } from "lucide-react"; import PageHeader from "../components/common/PageHeader"; export default function PartnerManagement() { const [searchTerm, setSearchTerm] = useState(""); const [viewMode, setViewMode] = useState("grid"); // New state for view mode const { data: partners = [], isLoading: partnersLoading } = useQuery({ queryKey: ['partners'], queryFn: () => base44.entities.Partner.list('-created_date'), initialData: [], }); const { data: businesses = [], isLoading: businessesLoading } = useQuery({ queryKey: ['businesses'], queryFn: () => base44.entities.Business.list('-created_date'), initialData: [], }); const { data: sectors = [] } = useQuery({ queryKey: ['sectors'], queryFn: () => base44.entities.Sector.list('-created_date'), initialData: [], }); const { data: enterprises = [] } = useQuery({ queryKey: ['enterprises'], queryFn: () => base44.entities.Enterprise.list('-created_date'), initialData: [], }); // Consolidate businesses by company name const consolidatedBusinesses = useMemo(() => { const grouped = {}; businesses.forEach(business => { let companyName = business.business_name; // Extract company name (remove hub suffix if present) const dashIndex = companyName.indexOf(' - '); if (dashIndex > 0) { companyName = companyName.substring(0, dashIndex).trim(); } if (!grouped[companyName]) { grouped[companyName] = { company_name: companyName, partner_type: "Corporate", hubs: [], primary_contact: business.contact_name, primary_email: business.email, primary_phone: business.phone, sector: business.sector || business.area || '', total_hubs: 0, company_logo: business.company_logo || null, }; } grouped[companyName].hubs.push({ id: business.id, hub_name: business.business_name, contact_name: business.contact_name, email: business.email, phone: business.phone, address: business.address, city: business.city, area: business.area, rate_group: business.rate_group, company_logo: business.company_logo, }); grouped[companyName].total_hubs++; // Use the first hub's logo if available if (business.company_logo && !grouped[companyName].company_logo) { grouped[companyName].company_logo = business.company_logo; } }); return Object.values(grouped); }, [businesses]); // Operator coverage data const operatorMetrics = { totalCoverage: 94, activeIncidents: 2, clientSatisfaction: 4.8, forecastAccuracy: 91 }; const hubCoverageData = [ { hub: 'San Jose', enterprise: 'Compass', sector: 'Bon Appétit', coverage: 97, incidents: 0, satisfaction: 4.9, partners: 12 }, { hub: 'San Francisco', enterprise: 'Compass', sector: 'Eurest', coverage: 92, incidents: 1, satisfaction: 4.7, partners: 8 }, { hub: 'Oakland', enterprise: 'Compass', sector: 'Bon Appétit', coverage: 89, incidents: 2, satisfaction: 4.5, partners: 6 }, { hub: 'Sacramento', enterprise: 'Compass', sector: 'Chartwells', coverage: 95, incidents: 1, satisfaction: 4.8, partners: 10 }, ]; const filteredPartners = partners.filter(p => !searchTerm || p.partner_name?.toLowerCase().includes(searchTerm.toLowerCase()) || p.partner_number?.toLowerCase().includes(searchTerm.toLowerCase()) ); const filteredBusinesses = consolidatedBusinesses.filter(b => !searchTerm || b.company_name?.toLowerCase().includes(searchTerm.toLowerCase()) || b.primary_contact?.toLowerCase().includes(searchTerm.toLowerCase()) ); const totalPartnerCount = filteredPartners.length + filteredBusinesses.length; const totalHubCount = filteredBusinesses.reduce((sum, b) => sum + b.total_hubs, 0) + filteredPartners.reduce((sum, p) => sum + (p.sites?.length || 0), 0); const isLoading = partnersLoading || businessesLoading; return (
Coverage Rate
{operatorMetrics.totalCoverage}%
Active Incidents
{operatorMetrics.activeIncidents}
Client Satisfaction
{operatorMetrics.clientSatisfaction}
Forecast Accuracy
{operatorMetrics.forecastAccuracy}%
Real-time coverage across all hubs and sectors
{hub.enterprise} • {hub.sector}
Partners
{hub.partners}
Incidents
0 ? 'text-red-600' : 'text-emerald-600'}`}> {hub.incidents}
Rating
{hub.satisfaction}/5.0
Enterprises
{enterprises.length}
Sectors
{sectors.length}
Partners
{totalPartnerCount}
PN-{String(idx + 1000).padStart(4, '0')}
{partner.partner_number}
| Partner Name | Type | Sector | Hubs/Sites | Contact | Status | Actions |
|---|---|---|---|---|---|---|
|
{business.company_logo ? (
{business.company_name?.charAt(0) || 'B'}
)}
{business.company_name} |
{business.partner_type} | {business.sector || '—'} |
|
{business.primary_contact || '—'} |
|
|
|
{partner.partner_name} {partner.partner_number} |
{partner.partner_type} | {partner.sector_name || '—'} |
|
{partner.primary_contact_name || '—'} |
|
Add your first partner client