Skip to content

ApprovalQueue

The approval queue: status tabs with their counts, the number of results, an actions slot, and the flows as a list or, through children, a table. It never fetches; the caller passes useApprovalQueue's page.

import { ApprovalQueue } from "@evolve-storefront/feature-organization/approval/queue";

Renders inside OrganizationProvider.

Preview

PendingOpen in Storybook ↗

Usage

The pending tab as cards. Approve and reject show only where viewerCanDecide holds, so the buyer's own order has none.

const { data } = useApprovalQueue({ status: "PENDING" });
<ApprovalQueue
approvals={data?.items}
pagination={data?.pagination}
renderItem={(approval) => (
<ApprovalQueueItem approval={approval} actions={<ApproveRejectActions approval={approval} />} />
)}
/>;

Props

PropTypeDescription
approvals?OrderApproval[]

One page of the queue for activeState, from useApprovalQueue.

pagination?Pagination

The page's pagination; shows the number of results when given.

activeState?ApprovalStatus

The status tab currently shown.

onStateChange?((state: ApprovalStatus) => void)

Shows the status tabs, and reports the one chosen.

counts?Partial<Record<ApprovalStatus, number>> | null

Per-status counts for the tab labels: useApprovalQueue's data.counts.

actions?ReactNode

Beside the tabs, such as a link to manage the approval rules.

renderItem?ApprovalQueueItemRenderer<OrderApproval>

Renders each flow; required for the default list, ignored with children.

empty?ReactNode

Custom empty state for the default composition.

children?ReactNode

Replaces the default list, such as with an ApprovalTable.

Any other props go to the root element, like on a plain HTML element.

Change the layout

Pass children to ApprovalQueue to arrange its parts yourself. Every part is exported from @evolve-storefront/feature-organization/approval/queue.

const mine = data.items.filter((approval) => approval.viewerCanDecide);
const others = data.items.filter((approval) => !approval.viewerCanDecide);
<ApprovalQueue pagination={data.pagination}>
<h2>{t("waiting-for-you")}</h2>
<ApprovalQueueItems approvals={mine} renderItem={renderItem} />
<h2>{t("waiting-on-others")}</h2>
<ApprovalQueueItems approvals={others} renderItem={renderItem} />
</ApprovalQueue>;
ApprovalQueueItemOne flow in the queue as a card: order, who placed it and when, total, status, and who decided it, or "the seller" where no associate did.
PropTypeDescription
approvalOrderApproval
actions?ReactNode

Approve/reject actions, composed by the caller (usually ApproveRejectActions).

Any other props go to the root element, like on a plain HTML element.

ApprovalQueueItemsThe queue as a list, rendering the empty state itself when the page is empty.
PropTypeDescription
approvalsOrderApproval[]

One page of the queue. An explicit prop so renderItem's type flows from it.

renderItemApprovalQueueItemRenderer<OrderApproval>

Renders each flow. Required: the feature owns no row markup.

empty?ReactNode

Custom empty state. Defaults to <ApprovalQueueEmpty />.

Any other props go to the root element, like on a plain HTML element.

ApprovalQueueResultCount"12 results": how many orders the active tab holds.
PropTypeDescription
pagination?Pagination

The queue query's pagination; its totalCount is the number shown.

Any other props go to the root element, like on a plain HTML element.

Loading and empty states

Render these while the data loads or when there is nothing to show, so the page does not jump when it arrives.

EmptyApprovalQueueEmptyEmpty state for the approval queue (no orders in the active state).

Examples

Decided By SellerA decided flow says who decided it.
// Nothing to pass: a decision without an approver reads "Approved by the seller".
<ApprovalQueueItem approval={approval} />;
Open in Storybook ↗
As TableThe queue as a table, with a link to manage the rules beside the tabs.
<ApprovalQueue
activeState={status}
onStateChange={setStatus}
counts={data?.counts}
pagination={data?.pagination}
actions={<Link href="/account/approval-rules">{t("manage-rules")}</Link>}
>
<ApprovalTable
approvals={data?.items ?? []}
pagination={data?.pagination}
renderOrderLink={(approval, props) => (
<Link href={`/account/orders/${approval.order.orderNumber}`} {...props} />
)}
/>
</ApprovalQueue>;
Open in Storybook ↗
Without OrderA flow can have no order: on some engines the approval comes before the order is placed, and on others the order was deleted.
// Nothing to pass: a flow whose order is null renders from its own status.
<ApprovalQueueItem approval={approval} actions={<ApproveRejectActions approval={approval} />} />;
Open in Storybook ↗
Approve From The QueueConnected to the mock gateway: approving a flow sends its version, and the queue and every count are read again, so it leaves the pending tab.
const [status, setStatus] = useState<ApprovalStatus>("PENDING");
const { data } = useApprovalQueue({ status });
<ApprovalQueue
approvals={data?.items}
pagination={data?.pagination}
counts={data?.counts}
activeState={status}
onStateChange={setStatus}
renderItem={renderItem}
/>;
Open in Storybook ↗