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'; const DEFAULT_CLARIFYING_QUESTIONS = [ 'Opisz cel projektu i planowane wydatki (inwestycja, B+R, zatrudnienie).', 'Podaj przybliżony przychód roczny i liczbę pracowników (FTE).', 'Czy projekt dotyczy głównej działalności firmy z rejestru PKD?', ]; 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([]); const initAnswers = (questionList: string[]) => { const initialAnswers: Record = {}; questionList.forEach((q) => { initialAnswers[q] = answers[q] || ''; }); setAnswers(initialAnswers); }; const applyQuestions = (questionList: string[]) => { const next = questionList.length > 0 ? questionList : DEFAULT_CLARIFYING_QUESTIONS; setQuestions(next); initAnswers(next); setStep('questions'); }; useEffect(() => { runMatcher([]); }, [projectId]); const runMatcher = async (currentAnswers: UserAnswer[]) => { setStep('loading'); setError(null); try { const data = await matchGrantsForProject(projectId, currentAnswers); if (data.status === 'error') { setError(data.detail || 'Wystąpił błąd podczas analizy dopasowań.'); applyQuestions(data.clarifying_questions || []); return; } if (data.needs_more_info && data.clarifying_questions && data.clarifying_questions.length > 0) { applyQuestions(data.clarifying_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.'); applyQuestions(DEFAULT_CLARIFYING_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.length > 0 ? questions : DEFAULT_CLARIFYING_QUESTIONS).map((q, idx) => (