import { useState, useEffect, useContext, useMemo } from 'react' import { UseQueryResult } from 'react-query' import TransactionHeader from '../TransactionHeader' import { inferQueryOutput } from '~/utils/trpc' import TransactionUI from '../..' import useTransaction, { UI_STATE } from '../../useTransaction' import IVSpinner from '~/components/IVSpinner' import { ControlPanelContext } from '../ControlPanel' import { ActionMode } from '~/utils/types' import useBackPath from '~/utils/useBackPath' import { ActionGroup, Transaction } from '@prisma/client' import useDashboardStructure from '~/utils/useDashboardStructure' import { useParams } from 'react-router-dom' import ErrorState from '../ErrorState' interface TransactionLayoutProps { transaction: NonNullable> mode: ActionMode onNewTransaction?: () => void onStateChange?: (state: UI_STATE) => void history?: UseQueryResult> existingTransactionId?: string | null state?: UI_STATE | null breadcrumbs?: ActionGroup[] } export function PendingConnectionIndicator({ label, onRefresh, isFetching, className = 'py-24 -mt-24', delayDuration = 500, message, }: { label?: string onRefresh?: () => void isFetching?: boolean className?: string delayDuration?: number message?: string }) { const [shouldShow, setShouldShow] = useState(delayDuration === 0) useEffect(() => { const to = setTimeout(() => { setShouldShow(true) }, delayDuration) return () => { clearTimeout(to) } }, [delayDuration]) if (!shouldShow) return null return (
{label && (

{label}

)} {message &&

{message}

} {onRefresh && (
)}
) } export default function TransactionLayout(props: TransactionLayoutProps) { const params = useParams<{ '*': string }>() const actionSlugParam = params['*'] const { setState: setControlPanelState, clearState: clearControlPanelState } = useContext(ControlPanelContext) const [transactionUpdates, setTransactionUpdates] = useState | null>(null) const { uiRef, ...transactionState } = useTransaction({ transaction: props.transaction, mode: props.mode, updateTransaction: setTransactionUpdates, }) const { transaction } = props { const status = transaction?.status const { state, register } = transactionState useEffect(() => { if ( !status || status === 'RUNNING' || status === 'PENDING' || status === 'AWAITING_INPUT' ) { return register() } // We don't want to rerun this when status changes // eslint-disable-next-line react-hooks/exhaustive-deps }, [register]) const { onStateChange } = props useEffect(() => { if (onStateChange) { onStateChange(state) } }, [state, onStateChange]) } const actionSlug = transaction?.action.slug const { actionTitle } = useDashboardStructure({ mode: props.mode, actionSlug: actionSlug ?? actionSlugParam, action: transaction?.action, enabled: true, }) const backPath = useBackPath() useEffect(() => { setControlPanelState({ state: transactionState.state, logs: transactionState.logLines, notifications: transactionState.notifications, transaction, mode: props.mode, history: props.onNewTransaction ? { onNewTransaction: props.onNewTransaction, currentTransactionId: props.existingTransactionId, } : undefined, }) }, [ setControlPanelState, transaction, transactionState.state, transactionState.logLines, transactionState.notifications, props.mode, props.onNewTransaction, props.existingTransactionId, ]) useEffect(() => clearControlPanelState, [clearControlPanelState]) const updatedTransaction = useMemo(() => { return { ...props.transaction, ...transactionUpdates, } }, [props.transaction, transactionUpdates]) return (
) }