import { useState, useEffect } from 'react' import { Link } from 'react-router-dom' import { Terminal, Settings, Wand2, FileUp } from 'lucide-react' import { useScriptGeneratorStore } from '@/store/scriptGeneratorStore' import { usePermissions } from '@/hooks/usePermissions' import { ScriptFilterBar } from '@/components/scripts/ScriptFilterBar' import { ScriptTemplateList } from '@/components/scripts/ScriptTemplateList' import { ScriptConfigurePane } from '@/components/scripts/ScriptConfigurePane' import { ScriptPreview } from '@/components/scripts/ScriptPreview' import { ParameterizeAndSavePanel } from '@/components/scripts/ParameterizeAndSavePanel' import { scriptsApi } from '@/api' import type { ScriptParameter } from '@/types' type LibraryTab = 'all' | 'mine' | 'team' export default function ScriptLibraryPage() { const [paneMode, setPaneMode] = useState<'browse' | 'configure'>('browse') // inputValue owned here so it survives Configure ↔ Browse transitions const [inputValue, setInputValue] = useState('') const [activeTab, setActiveTab] = useState('all') const loadCategories = useScriptGeneratorStore(s => s.loadCategories) const loadTemplates = useScriptGeneratorStore(s => s.loadTemplates) const setSearch = useScriptGeneratorStore(s => s.setSearch) const selectTemplate = useScriptGeneratorStore(s => s.selectTemplate) const clearOutput = useScriptGeneratorStore(s => s.clearOutput) const selectedTemplate = useScriptGeneratorStore(s => s.selectedTemplate) const categories = useScriptGeneratorStore(s => s.categories) const { isEngineer } = usePermissions() const canGenerate = isEngineer const [showImportPanel, setShowImportPanel] = useState(false) const handleImportSave = async (payload: { name: string description: string | undefined category_id: string | undefined share_with_team: boolean script_body: string parameters_schema: { parameters: ScriptParameter[] } }) => { const categoryId = payload.category_id || categories[0]?.id if (!categoryId) { throw new Error('No categories available. Please create a category first.') } await scriptsApi.createTemplate({ category_id: categoryId, name: payload.name, description: payload.description, script_body: payload.script_body, parameters_schema: payload.parameters_schema, }) setShowImportPanel(false) const filters = activeTab === 'mine' ? { mine: true } : activeTab === 'team' ? { shared: true } : {} loadTemplates(filters) } useEffect(() => { loadCategories().then(() => { const filters = activeTab === 'mine' ? { mine: true } : activeTab === 'team' ? { shared: true } : {} loadTemplates(filters) }) }, [loadCategories, loadTemplates, activeTab]) const onTabChange = (tab: LibraryTab) => { setActiveTab(tab) setInputValue('') setSearch('') setPaneMode('browse') } const onClearSearch = () => { setInputValue('') setSearch('') } const onConfigure = (id: string) => { selectTemplate(id) setPaneMode('configure') } const onBack = () => { clearOutput() setPaneMode('browse') } const tabClass = (tab: LibraryTab) => tab === activeTab ? 'border-b-2 border-primary text-foreground' : 'text-muted-foreground hover:text-foreground' return (
{/* Page header */}

Script Library

Browse templates, fill in parameters, and generate ready-to-run scripts.

{isEngineer && ( <> Manage )} Build New Script
{/* Tab bar */}
{/* Two-column layout */}
{/* Left pane — Browse or Configure mode */} {paneMode === 'browse' ? (
) : ( )} {/* Right pane — read-only ScriptPreview */} {selectedTemplate === null ? (

Select a template to get started

) : (
)}
{/* Import script panel */} {showImportPanel && ( setShowImportPanel(false)} /> )}
) }