Order
Order management components for displaying and managing customer orders in e-commerce applications.
Purpose
This library provides components for displaying and managing customer orders, including order details, order history, and order status tracking. It's designed as a headless component that provides all the order logic while allowing complete UI customization. Use this library when you need to display order confirmation details, order history, or allow customers to view their past orders.
Features
- Order details display with loading and error states
- Order line item management via integrated OrderLines components
- Order totals and pricing calculations
- Shipping lines display with method names and prices
- Shipping and billing address display
- Order summary with subtotal, shipping, and total calculations
- Generic field component for displaying any order property
Installation
- npm
- Yarn
npm install @haus-storefront-react/order
yarn add @haus-storefront-react/order
Note: This is not a public package. Contact the Haus Tech Team for access.
API Reference
Order.Root
Root component that fetches order data and provides context for all child components. Must be used as the wrapper for all other Order components.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
orderCode | string | Yes | - | The order code to fetch order details |
children | ChildrenProps<OrderContextValue> | No | - | Render prop function that receives order data and loading states |
Order.Field
Generic component for displaying any order property. Must be used within Order.Root.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
field | keyof OrderType | Yes | - | The order field to display (e.g., 'code', 'state', 'totalQuantity') |
formatter | (value: OrderType[keyof OrderType]) => string | No | - | Optional function to format the value |
children | React.ReactNode | ((props: { value, formattedValue }) => React.ReactNode) | No | - | Optional render prop or content |
asChild | boolean | No | false | Render as a child element instead of a div |
Order.Items
Container component for displaying order items. Must be used within Order.Root.
Order.Items.Root
Container that provides order lines context. Uses the order code from Order.Root context automatically. Provides order lines via render prop.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | ((props: { orderLines: OrderLine[] | undefined }) => React.ReactNode) | No | - | Render prop that receives order lines array |
Order.Items.Item
Individual order item component. Must be used within Order.Items.Root.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
orderLine | OrderLine | Yes | - | The order line data to display |
asChild | boolean | No | false | Render as a child element instead of default element |
Order.Items.Image
Product image display component. Must be used within Order.Items.Item. Inherits from OrderLines.Image component, from @haus-storefront-react/order-lines.
Order.Items.Price
Price display component for order lines. Must be used within Order.Items.Item. Inherits from OrderLines.Price component, from @haus-storefront-react/order-lines.
Order.ShippingLines
Container component for shipping lines. Must be used within Order.Root. Provides shipping lines array to children via render prop.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | ((props: { shippingLines }) => React.ReactNode) | No | - | Render prop that receives shipping lines array |
asChild | boolean | No | false | Render as a child element instead of a div |
Order.ShippingLine
Individual shipping line component. Must be used within Order.ShippingLines. Provides shipping method name, price, price with tax, and currency code to children via render prop.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
shippingLine | ShippingLine | Yes | - | The shipping line data to display |
children | React.ReactNode | ((props: { name, price, priceWithTax, currencyCode }) => React.ReactNode) | No | - | Render prop that receives shipping data |
asChild | boolean | No | false | Render as a child element instead of a div |
Order.Summary
Summary component for displaying order totals. Must be used within Order.Root. Provides order summary data to children via render prop.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | ((props: OrderSummaryData) => React.ReactNode) | No | - | Render prop that receives order summary data |
asChild | boolean | No | false | Render as a child element instead of a div |
Render Prop Data
| Property | Type | Description |
|---|---|---|
totalPrice | number | Order total price (without tax) |
totalWithTax | number | Order total price (with tax) |
subTotal | number | Order subtotal (without tax) |
subTotalWithTax | number | Order subtotal (with tax) |
shipping | number | Shipping cost (without tax) |
shippingWithTax | number | Shipping cost (with tax) |
taxSummary | OrderTaxSummary[] | Array of tax summary entries |
currencyCode | CurrencyCode | Currency code for the order |
Order.Addresses
Container component for displaying shipping and billing addresses. Must be used within Order.Root.
Order.Addresses.Root
Container for address components.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
asChild | boolean | No | false | Render as a child element instead of a div |
children | React.ReactNode | No | - | Child components |
Order.Addresses.Shipping
Component that provides shipping address to children via render prop. Must be used within Order.Addresses.Root.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | ((address: OrderAddress | null) => React.ReactNode) | No | - | Render prop that receives shipping address or null |
asChild | boolean | No | false | Render as a child element instead of a div |
Order.Addresses.Billing
Component that provides billing address to children via render prop. Must be used within Order.Addresses.Root.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | ((address: OrderAddress | undefined | null) => React.ReactNode) | No | - | Render prop that receives billing address, undefined, or null |
asChild | boolean | No | false | Render as a child element instead of a div |
useOrderContext
Internal hook for accessing Order context. Used internally by Order components. Not typically needed by consumers, but exported for advanced use cases.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
componentName | string | Yes | Component name for error messaging |
scope | Scope | No | Optional scope for context isolation |
Returns
OrderContextValue - Order context value with order data and loading states
createOrderScope
Creates a new scope for Order context. Used for advanced use cases when multiple Order instances need to be nested.
Returns
Scope - A new scope identifier for Order context
Basic Usage
Simple Order Display
- React
- React Native
import { Order } from '@haus-storefront-react/order'
import { Price } from '@haus-storefront-react/common-ui'
function OrderConfirmation({ orderCode }) {
return (
<Order.Root orderCode={orderCode}>
{({ order, isLoading, error, isError, isSuccess }) => (
<div>
{isLoading && <div>Loading...</div>}
{isError && error && <div>Error: {error.message}</div>}
{isSuccess && order && (
<div>
<h2>Thank you for your order!</h2>
<p>Order #{order.code}</p>
<p>
Placed on {new Date(order.orderPlacedAt).toLocaleDateString()}
</p>
<p>Status: {order.state}</p>
<Order.Items.Root>
{({ orderLines }) =>
orderLines?.map((line) => (
<Order.Items.Item key={line.id} orderLine={line}>
<Order.Items.Image />
<Order.Items.Price />
<span>{line.quantity} x</span>
</Order.Items.Item>
))
}
</Order.Items.Root>
<Order.Summary>
{({ totalPrice, currencyCode }) => (
<div>
<p>
Total: {totalPrice} {currencyCode}
</p>
</div>
)}
</Order.Summary>
</div>
)}
</div>
)}
</Order.Root>
)
}
import { Text } from 'react-native'
import { Order } from '@haus-storefront-react/order'
function OrderConfirmation({ orderCode }) {
return (
<Order.Root orderCode={orderCode}>
{({ order, isLoading, error, isError, isSuccess }) => (
<>
{isLoading && <Text>Loading...</Text>}
{isError && error && <Text>Error: {error.message}</Text>}
{isSuccess && order && (
<>
<Text>Thank you for your order!</Text>
<Text>Order #{order.code}</Text>
<Text>
Placed on {new Date(order.orderPlacedAt).toLocaleDateString()}
</Text>
<Text>Status: {order.state}</Text>
<Order.Items.Root>
{({ orderLines }) =>
orderLines?.map((line) => (
<Order.Items.Item key={line.id} orderLine={line}>
<Order.Items.Image />
<Order.Items.Price />
<Text>{line.quantity} x</Text>
</Order.Items.Item>
))
}
</Order.Items.Root>
<Order.Summary>
{({ totalPrice, currencyCode }) => (
<Text>
Total: {totalPrice} {currencyCode}
</Text>
)}
</Order.Summary>
</>
)}
</>
)}
</Order.Root>
)
}
Basic Hook Usage
The Order component uses hooks internally via useOrderProps. For direct order fetching, use hooks from @haus-storefront-react/hooks:
- React
- React Native
import { useOrderByCode } from '@haus-storefront-react/hooks'
function MyComponent({ orderCode }) {
const { data: order, isLoading, error } = useOrderByCode(orderCode)
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
if (!order) return <div>Order not found</div>
return (
<div>
<h1>Order #{order.code}</h1>
<p>Status: {order.state}</p>
</div>
)
}
import { Text } from 'react-native'
import { useOrderByCode } from '@haus-storefront-react/hooks'
function MyComponent({ orderCode }) {
const { data: order, isLoading, error } = useOrderByCode(orderCode)
if (isLoading) return <Text>Loading...</Text>
if (error) return <Text>Error: {error.message}</Text>
if (!order) return <Text>Order not found</Text>
return (
<>
<Text>Order #{order.code}</Text>
<Text>Status: {order.state}</Text>
</>
)
}
Advanced Usage
Using Order.Field for Custom Display
- React
- React Native
import { Order } from '@haus-storefront-react/order'
function OrderWithCustomFields({ orderCode }) {
return (
<Order.Root orderCode={orderCode}>
{({ order, isLoading, isSuccess }) => {
if (!isSuccess || !order) return null
return (
<div>
<Order.Field field='code'>
{({ value, formattedValue }) => (
<h1>Order #{formattedValue}</h1>
)}
</Order.Field>
<Order.Field
field='orderPlacedAt'
formatter={(value) => new Date(value).toLocaleDateString()}
>
{({ formattedValue }) => <p>Placed on {formattedValue}</p>}
</Order.Field>
<Order.Field field='state'>
{({ value }) => (
<span className={`status status-${value?.toLowerCase()}`}>
{value}
</span>
)}
</Order.Field>
<Order.Field field='totalQuantity'>
{({ value }) => <p>Total items: {value}</p>}
</Order.Field>
</div>
)
}}
</Order.Root>
)
}
import { View, Text } from 'react-native'
import { Order } from '@haus-storefront-react/order'
function OrderWithCustomFields({ orderCode }) {
return (
<Order.Root orderCode={orderCode}>
{({ order, isLoading, isSuccess }) => {
if (!isSuccess || !order) return null
return (
<View>
<Order.Field field='code'>
{({ formattedValue }) => <Text>Order #{formattedValue}</Text>}
</Order.Field>
<Order.Field
field='orderPlacedAt'
formatter={(value) => new Date(value).toLocaleDateString()}
>
{({ formattedValue }) => <Text>Placed on {formattedValue}</Text>}
</Order.Field>
<Order.Field field='state'>
{({ value }) => <Text>Status: {value}</Text>}
</Order.Field>
<Order.Field field='totalQuantity'>
{({ value }) => <Text>Total items: {value}</Text>}
</Order.Field>
</View>
)
}}
</Order.Root>
)
}
Order History List
- React
- React Native
import { Order } from '@haus-storefront-react/order'
import { useActiveCustomerOrders } from '@haus-storefront-react/hooks'
import { Price } from '@haus-storefront-react/common-ui'
function OrderHistory() {
const {
data: orders,
isLoading,
error,
} = useActiveCustomerOrders({
take: 20,
})
if (isLoading) return <div>Loading orders...</div>
if (error) return <div>Error: {error.message}</div>
if (!orders?.items.length) return <div>No orders found</div>
return (
<div className='order-history'>
<h1>Order History</h1>
{orders.items.map((order) => (
<Order.Root key={order.id} orderCode={order.code}>
{({ order: orderData, isLoading: orderLoading, isSuccess }) => (
<div className='order-history-item'>
{orderLoading && <div>Loading order details...</div>}
{isSuccess && orderData && (
<>
<div className='order-header'>
<h3>Order #{orderData.code}</h3>
<span className='order-date'>
{new Date(orderData.orderPlacedAt).toLocaleDateString()}
</span>
</div>
<div className='order-summary'>
<div className='order-items-count'>
{orderData.totalQuantity} items
</div>
<div className='order-total'>
<Price.Root
price={orderData.total}
priceWithTax={orderData.totalWithTax}
currencyCode={orderData.currencyCode}
>
<Price.Amount withCurrency />
</Price.Root>
</div>
<div className='order-status'>
<span
className={`status-badge status-${orderData.state.toLowerCase()}`}
>
{orderData.state}
</span>
</div>
</div>
<div className='order-actions'>
<a href={`/orders/${orderData.code}`}>View Details</a>
</div>
</>
)}
</div>
)}
</Order.Root>
))}
</div>
)
}
import { View, Text, ScrollView, Pressable } from 'react-native'
import { Order } from '@haus-storefront-react/order'
import { useActiveCustomerOrders } from '@haus-storefront-react/hooks'
import { Price } from '@haus-storefront-react/common-ui'
function OrderHistory() {
const {
data: orders,
isLoading,
error,
} = useActiveCustomerOrders({
take: 20,
})
if (isLoading) return <Text>Loading orders...</Text>
if (error) return <Text>Error: {error.message}</Text>
if (!orders?.items.length) return <Text>No orders found</Text>
return (
<ScrollView>
<Text>Order History</Text>
{orders.items.map((order) => (
<Order.Root key={order.id} orderCode={order.code}>
{({ order: orderData, isLoading: orderLoading, isSuccess }) => (
<View>
{orderLoading && <Text>Loading order details...</Text>}
{isSuccess && orderData && (
<View>
<Text>Order #{orderData.code}</Text>
<Text>
{new Date(orderData.orderPlacedAt).toLocaleDateString()}
</Text>
<Text>{orderData.totalQuantity} items</Text>
<Price.Root
price={orderData.total}
priceWithTax={orderData.totalWithTax}
currencyCode={orderData.currencyCode}
>
<Price.Amount withCurrency />
</Price.Root>
<Text>Status: {orderData.state}</Text>
<Pressable>
<Text>View Details</Text>
</Pressable>
</View>
)}
</View>
)}
</Order.Root>
))}
</ScrollView>
)
}
Conditional Rendering Patterns
- React
- React Native
import { Order } from '@haus-storefront-react/order'
import { Price } from '@haus-storefront-react/common-ui'
function ConditionalOrderDisplay({ orderCode }) {
return (
<Order.Root orderCode={orderCode}>
{({ order, isLoading, isError, isSuccess }) => {
if (isLoading) {
return (
<div className='order-loading'>
<div className='spinner' />
<p>Loading order details...</p>
</div>
)
}
if (isError || !isSuccess) {
return (
<div className='order-error'>
<p>Unable to load order details.</p>
<button onClick={() => window.location.reload()}>
Try Again
</button>
</div>
)
}
if (!order) {
return (
<div className='order-not-found'>
<p>Order not found.</p>
</div>
)
}
return (
<div className='order-display'>
<div className='order-header'>
<h1>Order #{order.code}</h1>
<Order.Field field='state'>
{({ value }) => (
<span className={`badge badge-${value?.toLowerCase()}`}>
{value}
</span>
)}
</Order.Field>
</div>
<Order.Items.Root>
{({ orderLines }) =>
orderLines && orderLines.length > 0 ? (
orderLines.map((line) => (
<Order.Items.Item key={line.id} orderLine={line}>
<Order.Items.Image />
<div className='item-info'>
<h3>{line.productVariant.product.name}</h3>
<p>Quantity: {line.quantity}</p>
</div>
<Order.Items.Price />
</Order.Items.Item>
))
) : (
<p>No items in this order</p>
)
}
</Order.Items.Root>
{order.shippingLines && order.shippingLines.length > 0 ? (
<Order.ShippingLines>
{({ shippingLines }) => (
<div className='shipping-section'>
<h2>Shipping</h2>
{shippingLines.map((shippingLine) => (
<Order.ShippingLine
key={shippingLine.id || shippingLine.shippingMethod.id}
shippingLine={shippingLine}
>
{({ name, price, priceWithTax, currencyCode }) => (
<div className='shipping-line'>
<span>{name}</span>
<Price.Root
price={price}
priceWithTax={priceWithTax}
currencyCode={currencyCode}
>
<Price.Amount withCurrency />
</Price.Root>
</div>
)}
</Order.ShippingLine>
))}
</div>
)}
</Order.ShippingLines>
) : (
<p>No shipping information available</p>
)}
<Order.Summary>
{({ totalPrice, totalWithTax, currencyCode }) => (
<div className='order-total'>
<h2>Total</h2>
<Price.Root
price={totalPrice}
priceWithTax={totalWithTax}
currencyCode={currencyCode}
>
<Price.Amount withCurrency />
</Price.Root>
</div>
)}
</Order.Summary>
</div>
)
}}
</Order.Root>
)
}
import { View, Text, ScrollView, Pressable } from 'react-native'
import { Order } from '@haus-storefront-react/order'
import { Price } from '@haus-storefront-react/common-ui'
function ConditionalOrderDisplay({ orderCode }) {
return (
<Order.Root orderCode={orderCode}>
{({ order, isLoading, isError, isSuccess }) => {
if (isLoading) {
return (
<View>
<Text>Loading order details...</Text>
</View>
)
}
if (isError || !isSuccess) {
return (
<View>
<Text>Unable to load order details.</Text>
<Pressable onPress={() => null}>
<Text>Try Again</Text>
</Pressable>
</View>
)
}
if (!order) {
return (
<View>
<Text>Order not found.</Text>
</View>
)
}
return (
<ScrollView>
<View>
<Text>Order #{order.code}</Text>
<Order.Field field='state'>
{({ value }) => <Text>Status: {value}</Text>}
</Order.Field>
</View>
<Order.Items.Root>
{({ orderLines }) =>
orderLines && orderLines.length > 0 ? (
orderLines.map((line) => (
<Order.Items.Item key={line.id} orderLine={line}>
<Order.Items.Image />
<View>
<Text>{line.productVariant.product.name}</Text>
<Text>Quantity: {line.quantity}</Text>
</View>
<Order.Items.Price />
</Order.Items.Item>
))
) : (
<Text>No items in this order</Text>
)
}
</Order.Items.Root>
{order.shippingLines && order.shippingLines.length > 0 ? (
<Order.ShippingLines>
{({ shippingLines }) => (
<View>
<Text>Shipping</Text>
{shippingLines.map((shippingLine) => (
<Order.ShippingLine
key={shippingLine.id || shippingLine.shippingMethod.id}
shippingLine={shippingLine}
>
{({ name, price, priceWithTax, currencyCode }) => (
<View>
<Text>{name}</Text>
<Price.Root
price={price}
priceWithTax={priceWithTax}
currencyCode={currencyCode}
>
<Price.Amount withCurrency />
</Price.Root>
</View>
)}
</Order.ShippingLine>
))}
</View>
)}
</Order.ShippingLines>
) : (
<Text>No shipping information available</Text>
)}
<Order.Summary>
{({ totalPrice, totalWithTax, currencyCode }) => (
<View>
<Text>Total</Text>
<Price.Root
price={totalPrice}
priceWithTax={totalWithTax}
currencyCode={currencyCode}
>
<Price.Amount withCurrency />
</Price.Root>
</View>
)}
</Order.Summary>
</ScrollView>
)
}}
</Order.Root>
)
}
Made with ❤️ by Haus Tech Team