Files
resolutionflow/frontend/src/pages/ScriptLibraryPage.tsx
Michael Chihlas 0b01692bbd fix: use subtle cyan pill for Manage Templates link, fix editor scroll
Replace pulsing dot with a light cyan background pill that's visible
but not distracting. Remove overflow-hidden from ScriptBodyEditor
wrapper so the textarea content scrolls properly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 15:27:02 -04:00

99 lines
3.7 KiB
TypeScript

import { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { Terminal, Settings } 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'
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 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 { isEngineer } = usePermissions()
const canGenerate = isEngineer
useEffect(() => {
loadCategories().then(() => loadTemplates())
}, [loadCategories, loadTemplates])
const onClearSearch = () => {
setInputValue('')
setSearch('')
}
const onConfigure = (id: string) => {
selectTemplate(id)
setPaneMode('configure')
}
const onBack = () => {
clearOutput()
setPaneMode('browse')
}
return (
<div className="flex flex-col gap-4 p-6 h-full">
{/* Page header */}
<div>
<h1 className="text-2xl font-heading font-bold text-foreground">Script Library</h1>
<p className="text-sm text-muted-foreground mt-1">
Browse PowerShell templates, fill in parameters, and generate ready-to-run scripts.
</p>
{isEngineer && (
<Link
to="/scripts/manage"
className="inline-flex items-center gap-1.5 text-xs text-primary bg-primary/10 hover:bg-primary/15 px-2.5 py-1 rounded-full transition-colors mt-2 group"
>
<Settings size={12} className="group-hover:rotate-90 transition-transform duration-300" />
Manage Templates
</Link>
)}
</div>
{/* Two-column layout */}
<div className="grid grid-cols-[320px_1fr] gap-4 flex-1 min-h-0">
{/* Left pane — Browse or Configure mode */}
{paneMode === 'browse' ? (
<div className="glass-card-static flex flex-col overflow-hidden">
<div className="p-2 pb-0">
<ScriptFilterBar inputValue={inputValue} setInputValue={setInputValue} />
</div>
<div className="flex-1 overflow-y-auto">
<ScriptTemplateList
inputValue={inputValue}
onClearSearch={onClearSearch}
onConfigure={onConfigure}
/>
</div>
</div>
) : (
<ScriptConfigurePane canGenerate={canGenerate} onBack={onBack} />
)}
{/* Right pane — read-only ScriptPreview */}
{selectedTemplate === null ? (
<div className="glass-card-static h-full flex flex-col items-center justify-center gap-3 text-center p-8">
<Terminal size={40} className="text-muted-foreground/40" />
<p className="text-sm text-muted-foreground">Select a template to get started</p>
</div>
) : (
<div className="glass-card-static h-full overflow-hidden p-4">
<ScriptPreview />
</div>
)}
</div>
</div>
)
}