'use client'; import { useCallback, useEffect, useState } from 'react'; import { useTranslations } from 'next-intl'; import type { WidgetProps } from '../widget-registry'; import { fetchSearchProviders, updateWidgetConfig } from '@/lib/dashboard-api'; /** * Default hardcoded search providers (D-15). * Used as fallback if the API fetch fails so the widget always works. */ const DEFAULT_PROVIDERS = [ { id: 'google', name: 'Google', urlTemplate: 'https://www.google.com/search?q={query}', isDefault: true }, { id: 'bing', name: 'Bing', urlTemplate: 'https://www.bing.com/search?q={query}', isDefault: true }, { id: 'ddg', name: 'DuckDuckGo', urlTemplate: 'https://duckduckgo.com/?q={query}', isDefault: true }, ]; export interface SearchProvider { id: string; name: string; urlTemplate: string; isDefault: boolean; } /** * Search widget (DASH-04, D-14/D-15). * Horizontal layout: provider dropdown left, text input center, search button right. * Opens web search in a new tab via window.open with noopener,noreferrer. */ export function SearchWidget({ instanceId, config }: WidgetProps) { const t = useTranslations('widgets'); const [providers, setProviders] = useState(DEFAULT_PROVIDERS); const [selectedProviderId, setSelectedProviderId] = useState( (config.providerId as string) || 'google', ); const [query, setQuery] = useState(''); // Fetch providers from API, fallback to defaults on error useEffect(() => { let cancelled = false; fetchSearchProviders() .then((data) => { if (!cancelled && data.length > 0) { setProviders(data); } }) .catch(() => { // Keep default providers — widget always works }); return () => { cancelled = true; }; }, []); // Persist selected provider to widget config const handleProviderChange = useCallback( (providerId: string) => { setSelectedProviderId(providerId); updateWidgetConfig(instanceId, { providerId }).catch(() => { // Silently fail — provider selection is non-critical }); }, [instanceId], ); const handleSearch = useCallback(() => { if (!query.trim()) return; const provider = providers.find((p) => p.id === selectedProviderId) ?? providers[0]; if (!provider) return; const url = provider.urlTemplate.replace( '{query}', encodeURIComponent(query.trim()), ); window.open(url, '_blank', 'noopener,noreferrer'); }, [query, selectedProviderId, providers]); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleSearch(); } }, [handleSearch], ); return (
{/* Provider dropdown (D-14: ~120px left) */} {/* Search input (flex-1 center) */} setQuery(e.target.value)} onKeyDown={handleKeyDown} /> {/* Search button (right) */}
); }