import { useState } from 'react'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { useI18n } from '@/lib/hooks/use-i18n'; import { useSettingsStore } from '@/lib/store/settings'; import { PDF_PROVIDERS } from '@/lib/pdf/constants'; import type { PDFProviderId } from '@/lib/pdf/types'; import { CheckCircle2, Eye, EyeOff, Loader2, Zap, XCircle } from 'lucide-react'; import { cn } from '@/lib/utils'; /** * Get display label for feature */ function getFeatureLabel(feature: string, t: (key: string) => string): string { const labels: Record = { text: t('settings.featureText'), images: t('settings.featureImages'), tables: t('settings.featureTables'), formulas: t('settings.featureFormulas'), 'layout-analysis': t('settings.featureLayoutAnalysis'), metadata: t('settings.featureMetadata'), }; return labels[feature] || feature; } interface PDFSettingsProps { selectedProviderId: PDFProviderId; } export function PDFSettings({ selectedProviderId }: PDFSettingsProps) { const { t } = useI18n(); const [showApiKey, setShowApiKey] = useState(false); const [testStatus, setTestStatus] = useState<'idle' | 'testing' | 'success' | 'error'>('idle'); const [testMessage, setTestMessage] = useState(''); const pdfProvidersConfig = useSettingsStore((state) => state.pdfProvidersConfig); const setPDFProviderConfig = useSettingsStore((state) => state.setPDFProviderConfig); const pdfProvider = PDF_PROVIDERS[selectedProviderId]; const isServerConfigured = !!pdfProvidersConfig[selectedProviderId]?.isServerConfigured; const providerConfig = pdfProvidersConfig[selectedProviderId]; const hasApiKey = !!providerConfig?.apiKey; const hasBaseUrl = !!providerConfig?.baseUrl; const isCloud = selectedProviderId === 'mineru-cloud'; const isSelfHosted = selectedProviderId === 'mineru'; const needsRemoteConfig = isSelfHosted || isCloud; // For cloud: test requires API key (user-entered or server-configured); for self-hosted: test requires base URL const canTest = isCloud ? hasApiKey || isServerConfigured : hasBaseUrl || isServerConfigured; // Reset state when provider changes const [prevSelectedProviderId, setPrevSelectedProviderId] = useState(selectedProviderId); if (selectedProviderId !== prevSelectedProviderId) { setPrevSelectedProviderId(selectedProviderId); setShowApiKey(false); setTestStatus('idle'); setTestMessage(''); } const handleTestConnection = async () => { setTestStatus('testing'); setTestMessage(''); try { const response = await fetch('/api/verify-pdf-provider', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ providerId: selectedProviderId, apiKey: providerConfig?.apiKey || '', baseUrl: providerConfig?.baseUrl || '', }), }); const data = await response.json(); if (data.success) { setTestStatus('success'); setTestMessage(t('settings.connectionSuccess')); } else { setTestStatus('error'); setTestMessage(`${t('settings.connectionFailed')}: ${data.error}`); } } catch (err) { setTestStatus('error'); const message = err instanceof Error ? err.message : String(err); setTestMessage(`${t('settings.connectionFailed')}: ${message}`); } }; return (
{/* Server-configured notice */} {isServerConfigured && (
{t('settings.serverConfiguredNotice')}
)} {/* Configuration section (for remote providers) */} {(needsRemoteConfig || isServerConfigured) && ( <>
{/* API Key — shown first for cloud, second for self-hosted */} {isCloud && (
setPDFProviderConfig(selectedProviderId, { apiKey: e.target.value }) } className="font-mono text-sm pr-10" />
)} {/* Base URL */} {(isSelfHosted || isCloud) && (
setPDFProviderConfig(selectedProviderId, { baseUrl: e.target.value }) } className="text-sm" /> {/* Test button for self-hosted (next to base URL) */} {isSelfHosted && ( )}
)} {/* API Key for self-hosted (optional, second column) */} {isSelfHosted && (
setPDFProviderConfig(selectedProviderId, { apiKey: e.target.value }) } className="font-mono text-sm pr-10" />
)}
{/* Test result message */} {testMessage && (
{testStatus === 'success' && } {testStatus === 'error' && } {testMessage}
)} {/* Request URL Preview */} {(() => { if (isCloud) { const base = providerConfig?.baseUrl || 'https://mineru.net/api/v4'; return (

{t('settings.requestUrl')}: {base}/file-urls/batch

); } const effectiveBaseUrl = providerConfig?.baseUrl || ''; if (!effectiveBaseUrl) return null; return (

{t('settings.requestUrl')}: {effectiveBaseUrl}/file_parse

); })()} )} {/* Features List */}
{pdfProvider.features.map((feature) => ( {getFeatureLabel(feature, t)} ))}
); }