@voyantjs/availability-ui
v0.75.0
Published
Reusable availability UI primitives and page compositions for Voyant operator/admin apps.
Readme
@voyantjs/availability-ui
Reusable availability UI primitives and page compositions for Voyant operator/admin apps.
Exports
| Entry | Description |
| --- | --- |
| . | Barrel re-exports |
| ./i18n | Availability UI message provider, defaults, and helpers |
| ./components/* | Availability UI components |
| ./utils | Small formatting helpers |
Surface
The package exports reusable pieces that keep app-owned routing and the availability batch mutations injected through props:
AvailabilityPageAvailabilityRuleDetailPage,AvailabilitySlotDetailPage,AvailabilityStartTimeDetailPageAvailabilityOverviewAvailabilitySlotsTab,AvailabilityRulesTab,AvailabilityStartTimesTabAvailabilityCloseoutsTab,AvailabilityPickupPointsTabAvailabilityRuleDialog,AvailabilityStartTimeDialog,AvailabilitySlotDialogAvailabilityCloseoutDialog,AvailabilityPickupPointDialogAvailabilityPageSkeleton,AvailabilityBodySkeleton, detail skeletonsavailability*Columnstable column buildersAvailabilitySectionHeaderAvailabilityUiMessagesProviderand i18n helpers from./i18nformatLocalizedSelectionLabel
Usage
AvailabilityPage owns the common operator availability shell, data hooks,
filters, overview metrics, table tabs, calendar tab, and rule/slot/start-time
dialogs. Route navigation and batch mutations stay app-specific:
import { AvailabilityPage } from "@voyantjs/availability-ui"
<AvailabilityPage
onSlotOpen={(id) => navigate({ to: "/availability/$id", params: { id } })}
onRuleOpen={(id) => navigate({ to: "/availability/rules/$id", params: { id } })}
onStartTimeOpen={(id) =>
navigate({ to: "/availability/start-times/$id", params: { id } })
}
onProductOpen={(id) => navigate({ to: "/products/$id", params: { id } })}
onBulkUpdate={handleAvailabilityBulkUpdate}
onBulkDelete={handleAvailabilityBulkDelete}
/>Closeout and pickup-point mutations are not owned by availability-react yet.
Pass onCloseoutSubmit and onPickupPointSubmit to use the package dialogs, or
use the slots.dialogs escape hatch to render app-owned dialogs.
Detail pages expose query/loader helpers that accept the app's API client:
import {
AvailabilitySlotDetailPage,
loadAvailabilitySlotDetailPage,
} from "@voyantjs/availability-ui"
import { defaultFetcher } from "@voyantjs/availability-react"
const client = { baseUrl: getApiUrl(), fetcher: defaultFetcher }
export const Route = createFileRoute("/_workspace/availability/$id")({
loader: ({ context, params }) =>
loadAvailabilitySlotDetailPage(context.queryClient, client, params.id),
component: () => {
const { id } = Route.useParams()
return (
<AvailabilitySlotDetailPage
id={id}
onBack={() => navigate({ to: "/availability" })}
onOpenProduct={(productId) =>
navigate({ to: "/products/$id", params: { id: productId } })
}
onOpenStartTime={(startTimeId) =>
navigate({ to: "/availability/start-times/$id", params: { id: startTimeId } })
}
/>
)
},
})Wrap consumers in AvailabilityUiMessagesProvider for package-level copy and
locale-aware formatting. Without a provider the package falls back to English.
import { AvailabilityUiMessagesProvider } from "@voyantjs/availability-ui/i18n"
<AvailabilityUiMessagesProvider locale={resolvedLocale}>
<AvailabilityPage onBulkUpdate={handleBulkUpdate} onBulkDelete={handleBulkDelete} />
</AvailabilityUiMessagesProvider>Leaf components remain available for custom page shells:
import { AvailabilitySectionHeader } from "@voyantjs/availability-ui"
function SlotsHeader() {
return (
<AvailabilitySectionHeader
title="Slots"
description="Manage generated capacity."
actionLabel="Create slot"
onAction={() => setOpen(true)}
/>
)
}Table column builders are available for apps that use @voyantjs/ui's
DataTable and keep routing behavior app-owned:
import { availabilitySlotColumns } from "@voyantjs/availability-ui"
<DataTable
columns={availabilitySlotColumns(products, openSlotRoute, messages.availability)}
data={slots}
/>Dialogs expose the reusable form UI and validation while the app decides how to persist the payload:
import { AvailabilitySlotDialog } from "@voyantjs/availability-ui"
<AvailabilitySlotDialog
messages={messages.availability}
open={open}
onOpenChange={setOpen}
products={products}
rules={rules}
startTimes={startTimes}
onSubmit={(payload, context) =>
context.isEditing
? api.patch(`/v1/availability/slots/${context.id}`, payload)
: api.post("/v1/availability/slots", payload)
}
onSuccess={refresh}
/>