import { SchemaField, FileMetadata } from '../types'; import { LanguageCombobox, formatLanguageOption } from './LanguageCombobox'; import './DynamicFieldRenderer.css'; interface DynamicFieldRendererProps { fieldKey: string; schema: SchemaField; metadata: FileMetadata; onChange: (key: string, value: any) => void; readonly?: boolean; } /** * Renders a single metadata field based on its schema definition */ export function DynamicFieldRenderer({ fieldKey, schema, metadata, onChange, readonly = false, }: DynamicFieldRendererProps) { const isReadonly = readonly || schema.readonly; const fieldType = schema.type || 'string'; // Get value from metadata using path-style key const getValue = (): any => { // Handle path-style keys like "stream/duration" or "nfo/title" const parts = fieldKey.split('/'); let value: any = metadata; for (const part of parts) { if (value === undefined || value === null) return undefined; value = value[part]; } return value; }; // Set value in metadata using path-style key const setValue = (newValue: any) => { onChange(fieldKey, newValue); }; const value = getValue(); // Render link if configured const renderValueWithLink = (displayValue: string) => { if (schema.link && displayValue) { const url = schema.link.replace('{value}', encodeURIComponent(displayValue)); return ( {displayValue} ); } return displayValue; }; // Render based on field type switch (fieldType) { case 'boolean': return (
{schema.hint && {schema.hint}}
); case 'number': return (
setValue(e.target.value ? Number(e.target.value) : undefined)} disabled={isReadonly} min={schema.min} max={schema.max} placeholder={schema.placeholder} /> {schema.hint && {schema.hint}}
); case 'select': return (
{schema.hint && {schema.hint}}
); case 'text': return (