Audited the implementation against DS_Delivery_Date_Time_App_Study.docx and closed the actionable gaps (see IMPLEMENTATION_REVIEW_2026-09-04.md). Core (code + unit tests, 156 green): - Wire excludeLocationsWithoutStock into resolveAvailabilityRequest; widget now sends variantIds so inventory-based location exclusion actually runs. - Live slot re-validation at checkout: new checkout-snapshot.server.ts writes a shop-metafield capacity snapshot; validation-slot's evaluateCheckout rejects a complete selection that has since filled / blacked out / closed / hit the daily cap / left the schedule. Refreshed on order webhooks and slot/blackout/location/enforcement edits. - Scopable checkout enforcement: Shop.enforcementMode (all|tagged|off) + enforcementTag, new app.settings.tsx admin page, honoured via the snapshot. - Per-day order cap: Location.dailyOrderCap threaded through getAvailability (dailyCap + consumedPerDate); admin field on the location screen. - Product-rule slot blocking: ProductRule.blockedStartMins, unioned in resolveProductRuleConstraints, enforced in the engine and resolveHoldRequest; admin field on the product rules screen. - Product-page placement: product-availability.liquid block + widget data-mode="preview" (read-only earliest-date line). - Second locale: datetime-widget fr.json / fr.schema.json. - Migration 20260904120000_review_gaps (apply with prisma migrate deploy). New Functions (source + unit tests; need `shopify app deploy` to ship): - extensions/payment-customization: cart.payment-methods.transform.run — hides cash-on-delivery / pay-in-store gateways on SHIPPING orders. - extensions/checkout-datetime/src: restored from a gitignored dist-only state — Plus native picker + Thank you / Order status confirmation blocks, all calling the existing checkout.scheduling.* routes (one capacity pool). tsconfig ships checkJs:false pending reconciliation with live checkout types. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2.1 KiB
checkout-datetime
Checkout UI Extension. Three targets in one extension:
| Module | Target | Plans |
|---|---|---|
src/Checkout.jsx |
purchase.checkout.block.render |
Plus only — native in-checkout date/time picker |
src/ThankYou.jsx |
purchase.thank-you.block.render |
all plans |
src/OrderStatus.jsx |
customer-account.order-status.block.render |
all plans |
The picker calls this app's own checkout.scheduling.availability /
checkout.scheduling.hold routes (session-token auth) and draws from the
same capacity pool as the storefront widget and POS. It only collects a
selection into checkout attributes — the validation-slot Function is still
what enforces it, so the extension is not a security boundary.
The all-plan confirmation is also covered by the theme block
extensions/datetime-widget/blocks/order-confirmation.liquid; the Thank you
/ Order status modules here are the Plus-native version of the same thing.
Before deploy
npm --prefix extensions/checkout-datetime install(pulls@shopify/ui-extensions+preact).- In the extension's settings (Partners dashboard or
shopify.extension.tomldefaults), set App backend URL to the same value asapplication_urlinshopify.app.toml— the extension runs on a different origin and needs the absolute URL to reach the backend. shopify app deploy.
The previous build output under
dist/is gitignored and regenerated on deploy — thissrc/tree is the source of record.
Type checking
tsconfig.json ships with checkJs: false because this source hasn't yet
been iterated against the live @shopify/ui-extensions checkout component
types (that needs the extension's deps installed and, ideally, a real
checkout to verify runtime shapes — same caveat pos-datetime carries).
Before deploying: npm install in this folder, flip checkJs back to
true, run npm run typecheck, and reconcile the <s-*> component props
against the real typings. The decision logic it depends on
(resolveAvailabilityRequest, resolveHoldRequest) is already fully
tested on the server side.