import React, { useState, useEffect } from 'react'; import { X, Loader2, Search, CheckCircle, ArrowRight, MessageSquare, Briefcase, AlertTriangle } from 'lucide-react'; import { createPortal } from 'react-dom'; import { matchGrantsForProject, UserAnswer } from '../../api/client'; interface GrantMatchResult { program_id: string; program_name: string; score: number; rationale: string; is_recommended: boolean; requires_verification?: boolean; source?: string; legal_basis?: string; confidence_score?: number; } interface AdvancedMatcherModalProps { projectId: string; onClose: () => void; onMatchesSaved: (matches: GrantMatchResult[]) => void; } export default function AdvancedMatcherModal({ projectId, onClose, onMatchesSaved }: AdvancedMatcherModalProps) { const [step, setStep] = useState<'loading' | 'questions' | 'results'>('loading'); const [questions, setQuestions] = useState([]); const [answers, setAnswers] = useState>({}); const [matches, setMatches] = useState([]); const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const [userAnswersHistory, setUserAnswersHistory] = useState([]); useEffect(() => { runMatcher([]); }, [projectId]); const runMatcher = async (currentAnswers: UserAnswer[]) => { setStep('loading'); setError(null); try { const data = await matchGrantsForProject(projectId, currentAnswers); if (data.status === 'error') { setError('Wystąpił błąd podczas analizy dopasowań.'); setStep('questions'); // fallback return; } if (data.needs_more_info && data.clarifying_questions && data.clarifying_questions.length > 0) { setQuestions(data.clarifying_questions); // Inicjalizuj puste odpowiedzi const initialAnswers: Record = {}; data.clarifying_questions.forEach(q => { initialAnswers[q] = ''; }); setAnswers(initialAnswers); setStep('questions'); } else { setMatches(data.matches || []); onMatchesSaved(data.matches || []); setStep('results'); } } catch (err) { console.error('Error in matchGrantsForProject:', err); setError('Błąd połączenia z serwerem AI.'); setStep('questions'); } }; const handleAnswerSubmit = async () => { setIsSubmitting(true); // Zbierz nowe odpowiedzi const newAnswers: UserAnswer[] = questions.map(q => ({ question: q, answer: answers[q] || 'Brak odpowiedzi' })); const combinedAnswers = [...userAnswersHistory, ...newAnswers]; setUserAnswersHistory(combinedAnswers); await runMatcher(combinedAnswers); setIsSubmitting(false); }; const modalContent = (
{/* Header */}

Advanced AI Matcher

Wieloetapowe dopasowanie programów

{/* Content */}
{step === 'loading' && (

Analizuję opis projektu...

AI skanuje aktualne nabory w PARP i NCBR, aby znaleźć najlepsze dopasowania lub przygotować pytania doprecyzowujące.

)} {step === 'questions' && (
{error && (
{error}
)}

AI potrzebuje więcej informacji

Aby dokładnie dobrać programy dotacyjne, proszę odpowiedz na poniższe pytania. Twoje odpowiedzi zostaną zapisane i wykorzystane podczas tworzenia wniosku.

{questions.map((q, idx) => (