()
| 60 | }`; |
| 61 | |
| 62 | export function WebhookEditorPage() { |
| 63 | const { id } = useParams<{ id: string }>(); |
| 64 | const navigate = useNavigate(); |
| 65 | const location = useLocation(); |
| 66 | const { toast } = useToast(); |
| 67 | const isNew = !id || id === 'new'; |
| 68 | |
| 69 | // Get returnTo state for back button (if navigated from workflow webhooks sidebar) |
| 70 | const navigationState = location.state as { |
| 71 | returnTo?: { path: string; openWebhooksSidebar?: boolean }; |
| 72 | } | null; |
| 73 | const returnToPath = navigationState?.returnTo?.path; |
| 74 | const openWebhooksSidebarOnReturn = navigationState?.returnTo?.openWebhooksSidebar; |
| 75 | |
| 76 | // Derive active tab from URL |
| 77 | const activeTab = useMemo(() => { |
| 78 | if (location.pathname.endsWith('/deliveries')) return 'deliveries'; |
| 79 | if (location.pathname.endsWith('/settings')) return 'settings'; |
| 80 | return 'editor'; |
| 81 | }, [location.pathname]); |
| 82 | |
| 83 | const navigateToTab = (tab: string) => { |
| 84 | if (isNew) return; // Don't navigate for new webhooks |
| 85 | const basePath = `/webhooks/${id}`; |
| 86 | if (tab === 'editor') { |
| 87 | navigate(basePath); |
| 88 | } else { |
| 89 | navigate(`${basePath}/${tab}`); |
| 90 | } |
| 91 | }; |
| 92 | |
| 93 | const [isLoading, setIsLoading] = useState(!isNew); |
| 94 | const [isSaving, setIsSaving] = useState(false); |
| 95 | const [webhook, setWebhook] = useState<WebhookConfiguration | null>(null); |
| 96 | |
| 97 | // Form State |
| 98 | const [form, setForm] = useState<WebhookFormState>({ |
| 99 | workflowId: '', |
| 100 | name: 'New Webhook', |
| 101 | description: '', |
| 102 | parsingScript: DEFAULT_PARSING_SCRIPT, |
| 103 | expectedInputs: [], |
| 104 | }); |
| 105 | |
| 106 | const [initialForm, setInitialForm] = useState<WebhookFormState | null>( |
| 107 | isNew |
| 108 | ? { |
| 109 | workflowId: '', |
| 110 | name: 'New Webhook', |
| 111 | description: '', |
| 112 | parsingScript: DEFAULT_PARSING_SCRIPT, |
| 113 | expectedInputs: [], |
| 114 | } |
| 115 | : null, |
| 116 | ); |
| 117 | |
| 118 | const isDirty = useMemo(() => { |
| 119 | if (!initialForm) return false; |
nothing calls this directly
no test coverage detected