diff --git a/frontend/src/components/scripts/ScriptFilterBar.tsx b/frontend/src/components/scripts/ScriptFilterBar.tsx index c8dd579e..aadd6798 100644 --- a/frontend/src/components/scripts/ScriptFilterBar.tsx +++ b/frontend/src/components/scripts/ScriptFilterBar.tsx @@ -15,9 +15,15 @@ export function ScriptFilterBar({ inputValue, setInputValue }: Props) { const setCategory = useScriptGeneratorStore(s => s.setCategory) const setSearch = useScriptGeneratorStore(s => s.setSearch) - // Debounce: 300ms after the input value settles, push to store + // Debounce: 300ms after the input value settles, push to store. + // Skip on initial mount (store.searchQuery is already '' and page already called loadTemplates). + const isFirstRender = useRef(true) const debounceRef = useRef | null>(null) useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false + return + } if (debounceRef.current) clearTimeout(debounceRef.current) debounceRef.current = setTimeout(() => { setSearch(inputValue) diff --git a/frontend/src/components/scripts/ScriptParameterField.tsx b/frontend/src/components/scripts/ScriptParameterField.tsx index d3c62f6e..5781ecf6 100644 --- a/frontend/src/components/scripts/ScriptParameterField.tsx +++ b/frontend/src/components/scripts/ScriptParameterField.tsx @@ -28,7 +28,12 @@ export function ScriptParameterField({ param, value, error, disabled }: Props) { let input: React.ReactNode + // Track whether the shared Input/Textarea component renders the error internally + // (so we skip the manual

at the bottom for these types) + let errorRenderedByComponent = false + if (param.type === 'text' || param.type === 'multi_text' || param.type === 'number') { + errorRenderedByComponent = true input = ( ) } else if (param.type === 'password') { + errorRenderedByComponent = true input = ( -

- - +
+
+ + +
) } else if (param.type === 'textarea') { + errorRenderedByComponent = true input = (