PR G: portal /transactions page + 12-state machine view (#11)
Some checks failed
CI / Frontend Lint (push) Failing after 6s
CI / Frontend Type Check (push) Failing after 6s
CI / Frontend Build (push) Failing after 6s
CI / Frontend E2E Tests (push) Failing after 9s
CI / Orchestrator Build (push) Failing after 6s
CI / Contracts Compile (push) Failing after 6s
CI / Contracts Test (push) Failing after 6s
Security Scan / Dependency Vulnerability Scan (push) Failing after 4s
Security Scan / OWASP ZAP Scan (push) Failing after 4s
Some checks failed
CI / Frontend Lint (push) Failing after 6s
CI / Frontend Type Check (push) Failing after 6s
CI / Frontend Build (push) Failing after 6s
CI / Frontend E2E Tests (push) Failing after 9s
CI / Orchestrator Build (push) Failing after 6s
CI / Contracts Compile (push) Failing after 6s
CI / Contracts Test (push) Failing after 6s
Security Scan / Dependency Vulnerability Scan (push) Failing after 4s
Security Scan / OWASP ZAP Scan (push) Failing after 4s
This commit was merged in pull request #11.
This commit is contained in:
51
src/components/portal/StateMachineView.tsx
Normal file
51
src/components/portal/StateMachineView.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { TRANSACTION_STATES, type StateTransition, type TransactionState } from '../../services/orchestrator';
|
||||
|
||||
interface StateMachineViewProps {
|
||||
current: TransactionState;
|
||||
transitions: StateTransition[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the 12-state transaction machine from the architecture note
|
||||
* §8. Visited states are highlighted in the order they were entered;
|
||||
* the current state is emphasised. Intended as an audit-friendly view
|
||||
* for the /transactions page, NOT a full graph editor.
|
||||
*/
|
||||
export default function StateMachineView({ current, transitions }: StateMachineViewProps) {
|
||||
const visited = new Set<string>(transitions.map((t) => t.to_state));
|
||||
if (transitions.length > 0 && transitions[0].from_state === null) {
|
||||
visited.add(transitions[0].to_state);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="state-machine-view">
|
||||
<div className="state-machine-grid">
|
||||
{TRANSACTION_STATES.map((state) => {
|
||||
const isCurrent = state === current;
|
||||
const isVisited = visited.has(state);
|
||||
const isTerminal = state === 'COMMITTED' || state === 'ABORTED' || state === 'CLOSED';
|
||||
const classes = [
|
||||
'state-pill',
|
||||
isCurrent ? 'state-pill--current' : '',
|
||||
!isCurrent && isVisited ? 'state-pill--visited' : '',
|
||||
!isVisited ? 'state-pill--pending' : '',
|
||||
isTerminal ? 'state-pill--terminal' : '',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
return (
|
||||
<div key={state} className={classes} data-testid={`state-${state}`}>
|
||||
<span className="state-pill-dot" aria-hidden="true" />
|
||||
<span className="state-pill-label">{state.replace(/_/g, ' ')}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="state-machine-legend">
|
||||
<span className="legend-item"><span className="dot dot--current" />current</span>
|
||||
<span className="legend-item"><span className="dot dot--visited" />visited</span>
|
||||
<span className="legend-item"><span className="dot dot--pending" />not yet reached</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user