import type { JobPosting } from '@/types/entities'; import React, { useState, useEffect } from 'react'; import { useWorkerProfiles, useMatchTalentForJob } from '@/lib/krowHooks'; import { Sparkles, Loader2, Briefcase, Star } from 'lucide-react'; import { Image } from '@/components/ui/image'; import { getScoreBand, toFICO } from '@/lib/talentHome'; import TalentDetailModal from '@/components/krow/TalentDetailModal'; import { useTranslation } from 'react-i18next'; const PORTRAIT_PHOTOS = [ 'photo-1500648767731-7d3514ad8b31', 'photo-1531123897727-8f129e1688ce', 'photo-1573496359142-b8d87734a5a2', 'photo-1487412720507-e7ab37603c6f', 'photo-1502685104226-ee3a97a2f2c8', 'photo-1544005313-94ddf0286df2', 'photo-1494790108377-be9c29b29330', 'photo-1438761681033-6461ffad8d80', 'photo-1517841905240-472988babdf9', 'photo-1463453091185-61582044d556', ]; function getPortraitSeed(name) { let h = 0; for (let i = 0; i < (name || '').length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0; return PORTRAIT_PHOTOS[h % PORTRAIT_PHOTOS.length]; } const RECO_STYLES = { Hire: 'bg-[#16A34A] text-white', Interview: 'bg-[#0838E0] text-white', Maybe: 'bg-[#D97706] text-white', Pass: 'bg-[#9CA3AF] text-white', }; interface SuggestedTalentProps { job: JobPosting; onContact?: (...args: any[]) => void; onSchedule?: (...args: any[]) => void; onHire?: (...args: any[]) => void; } export default function SuggestedTalent({ job, onContact, onSchedule, onHire }: SuggestedTalentProps) { const { t } = useTranslation(); const { data: profiles = [] } = useWorkerProfiles(); const matchTalent = useMatchTalentForJob(); const [matches, setMatches] = useState([]); const [selected, setSelected] = useState(null); // Auto-run matching when the job is published and there are profiles useEffect(() => { if (!job || profiles.length === 0) return; if (job.status !== 'active') return; let cancelled = false; (async () => { try { const res = await matchTalent.mutateAsync({ job, profiles }); if (!cancelled && res?.matches) setMatches(res.matches); } catch { if (!cancelled) setMatches([]); } })(); return () => { cancelled = true; }; }, [job?.id, job?.status, profiles.length]); const profileById = Object.fromEntries(profiles.map((p) => [p.id, p])); const enriched = matches .map((m) => ({ ...m, profile: profileById[m.profile_id] })) .filter((m) => m.profile) .slice(0, 6); const runMatch = () => { if (profiles.length === 0) return; /* KNOWN DEFECT, preserved deliberately — see the commit message: React Query's `mutate` returns `void`, so `.then` throws at run time. `mutateAsync` is what this means, but swapping it turns a crash into a working feature, which is a product change rather than a migration. */ (matchTalent.mutate({ job, profiles }) as any).then((res) => setMatches(res?.matches || [])).catch(() => setMatches([])); }; return (
{t('suggestedTalent.dontWaitForApplicationsKrowMatched')}
{matchTalent.isPending && matches.length === 0 ? ({t('suggestedTalent.noStrongMatchesYetTryWidening')}