EdgeInteract
Examples
Complete, real-world examples combining EdgeInteract React bindings for common scenarios: real-time approval flows, confirmation dialogs, and dynamic form collection.
Example 1 — Approval Flow (Sending Side)
A component that triggers an approval interaction from the frontend and shows real-time status:
import { useInteraction } from 'edge-interact-react';
import { InteractionTimeoutError } from 'edge-interact-core';
function InvoiceApprovalButton({ invoice, managerId }: Props) {
const { sendInteraction, isSending } = useInteraction();
const [decision, setDecision] = useState<string | null>(null);
const [decidedBy, setDecidedBy] = useState<string>('');
const requestApproval = async () => {
setDecision(null);
try {
const response = await sendInteraction({
type: 'approval',
targetUserId: managerId,
title: `Approve Invoice ${invoice.id}`,
payload: {
context: `Invoice ${invoice.id} from ${invoice.vendor} for ${invoice.amount}.`,
fields: [
{ key: 'vendor', label: 'Vendor', value: invoice.vendor },
{ key: 'amount', label: 'Amount', value: invoice.amount },
{ key: 'due', label: 'Due Date', value: invoice.dueDate }
]
},
timeoutMs: 86_400_000,
priority: 'high'
});
setDecision(response.outcome);
setDecidedBy(response.respondedBy);
} catch (err) {
if (err instanceof InteractionTimeoutError) {
setDecision('timeout');
} else {
setDecision('error');
}
}
};
return (
<div>
<button onClick={requestApproval} disabled={isSending}>
{isSending ? 'Waiting for approval...' : 'Request Approval'}
</button>
{decision === 'approved' && <p>Approved by {decidedBy}</p>}
{decision === 'rejected' && <p>Rejected by {decidedBy}</p>}
{decision === 'timeout' && <p>No response received — approval timed out.</p>}
</div>
);
}
Example 2 — Confirmation Dialog (Self-Targeted)
The user confirms their own destructive action before it is executed:
function DeleteAccountButton({ userId }: { userId: string }) {
const { sendInteraction } = useInteraction();
const handleDelete = async () => {
const response = await sendInteraction({
type: 'confirmation',
targetUserId: userId, // targeting the current user themselves
title: 'Delete Your Account',
payload: {
message: 'Are you sure you want to permanently delete your account? All your data will be lost.',
confirmLabel: 'Yes, Delete My Account',
cancelLabel: 'Cancel',
severity: 'danger'
},
timeoutMs: 60_000 // 1 minute
});
if (response.outcome === 'confirmed') {
await accountApi.deleteAccount(userId);
navigate('/goodbye');
}
};
return <button onClick={handleDelete}>Delete Account</button>;
}
Example 3 — WorkDesk HIL Inbox (Receiving Side)
A full HIL inbox that renders all interaction types with the appropriate components:
import { useInteractionReceiver } from 'edge-interact-react';
import {
InteractionContainer,
ApprovalComponent,
ConfirmationComponent,
NotificationComponent,
PickerComponent,
FormComponent
} from 'edge-interact-ui';
const RENDERERS: Record<string, React.ComponentType<any>> = {
approval: ApprovalComponent,
confirmation: ConfirmationComponent,
notification: NotificationComponent,
picker: PickerComponent,
form: FormComponent
};
function WorkDeskInbox() {
const { queue, respond, queueLength } = useInteractionReceiver();
return (
<div className="workdesk-inbox">
<header>
<h1>My Inbox</h1>
{queueLength > 0 && <span className="count">{queueLength}</span>}
</header>
{queue.map(interaction => {
const Renderer = RENDERERS[interaction.type];
if (!Renderer) return null;
return (
<Renderer
key={interaction.interactionId}
interaction={interaction}
respond={(outcome, data) => respond(interaction.interactionId, outcome, data)}
/>
);
})}
{queueLength === 0 && <p className="empty">All caught up!</p>}
</div>
);
}