The bag (saved in localStorage, synced across tabs); ready is false until it's read
add, setQty, remove, clear
Change it. setQty(…, 0) removes. Quantities cap at maxQty (default 10).
quote, quoting, quoteError
The bag priced by Dakio, refreshed as it changes; null when empty
couponCode, setCouponCode
Re-quotes with the coupon
district, setDistrict
Re-quotes with the delivery charge
isOpen, open, close
For a bag drawer
CartProvider takes storageKey (one per store if a domain hosts several) and maxQty. Instead of dakio you can pass quote={fn} to price the bag yourself, for example through a server action.
phase is idle, submitting, otp, verifying, placed or error. error holds the last refusal { code, message, productId?, attemptsLeft? }; reset() starts over. One Idempotency-Key is kept per attempt, so a double tap or retry never orders twice, and the bag is cleared once the order is placed.