"use client"; import { useState } from "react"; import { useProviderConfigs, useUpdateProvider, useTestProvider } from "@/hooks/use-admin-providers"; import { useConfig } from "@/hooks/use-config"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { CheckCircle, XCircle, Loader2 } from "lucide-react"; import { ApiRequestError } from "@/lib/api"; const PROVIDER_FIELDS: Record< string, Array<{ key: string; label: string; type?: string; required?: boolean }> > = { jellyfin: [ { key: "base_url", label: "Base URL", required: true }, { key: "api_key", label: "API Key", type: "password", required: true }, { key: "user_id", label: "User ID", required: true }, ], local_files: [ { key: "files_dir", label: "Files Directory", required: true }, { key: "transcode_dir", label: "Transcode Directory" }, { key: "cleanup_ttl_hours", label: "Cleanup TTL Hours" }, ], }; interface ProviderCardProps { providerType: string; existingConfig?: { config_json: Record; enabled: boolean }; } function ProviderCard({ providerType, existingConfig }: ProviderCardProps) { const fields = PROVIDER_FIELDS[providerType] ?? []; const [formValues, setFormValues] = useState>( () => existingConfig?.config_json ?? {}, ); const [enabled, setEnabled] = useState(existingConfig?.enabled ?? true); const [conflictError, setConflictError] = useState(false); const [testResult, setTestResult] = useState<{ ok: boolean; message: string } | null>(null); const updateProvider = useUpdateProvider(); const testProvider = useTestProvider(); const handleSave = async () => { setConflictError(false); try { await updateProvider.mutateAsync({ type: providerType, payload: { config_json: formValues, enabled }, }); } catch (e: unknown) { if (e instanceof ApiRequestError && e.status === 409) { setConflictError(true); } } }; const handleTest = async () => { setTestResult(null); const result = await testProvider.mutateAsync({ type: providerType, payload: { config_json: formValues, enabled: true }, }); setTestResult(result); }; return ( {providerType.replace("_", " ")}
Enabled
{conflictError && (
UI config disabled — set CONFIG_SOURCE=db on the server
)} {fields.map((field) => (
setFormValues((prev) => ({ ...prev, [field.key]: e.target.value })) } placeholder={ field.type === "password" ? "••••••••" : `Enter ${field.label.toLowerCase()}` } className="h-8 border-zinc-700 bg-zinc-800 text-xs text-zinc-100" />
))} {testResult && (
{testResult.ok ? ( ) : ( )} {testResult.message}
)}
); } export function ProviderSettingsPanel() { const { data: config } = useConfig(); const { data: providerConfigs = [] } = useProviderConfigs(); const availableTypes = config?.available_provider_types ?? []; return (

Provider Configuration

Configure media providers. Requires CONFIG_SOURCE=db on the server.

{availableTypes.length === 0 ? (

No providers available in this build.

) : (
{availableTypes.map((type) => { const existing = providerConfigs.find((c) => c.provider_type === type); return ( ); })}
)}
); }