@cimplify/sdk 0.20.2 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@
10
10
  "files": [
11
11
  {
12
12
  "path": "order-summary.tsx",
13
- "content": "\"use client\";\n\nimport React from \"react\";\nimport type { Order, LineItem, OrderStatus, PaymentState } from \"@cimplify/sdk\";\nimport { useOrder } from \"@cimplify/sdk/react\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { parsePrice } from \"@cimplify/sdk\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface OrderSummaryClassNames {\n root?: string;\n header?: string;\n orderId?: string;\n status?: string;\n paymentState?: string;\n fulfillmentDetails?: string;\n deliveryAddress?: string;\n items?: string;\n lineItem?: string;\n notes?: string;\n totals?: string;\n customer?: string;\n loading?: string;\n serviceInfo?: string;\n digitalInfo?: string;\n bundleBreakdown?: string;\n compositeBreakdown?: string;\n trackingLink?: string;\n}\n\nexport interface OrderSummaryProps {\n /** Pass an Order object directly (skips fetch). */\n order?: Order;\n /** Or pass an order ID to fetch via useOrder. */\n orderId?: string;\n /** Poll for status updates. */\n poll?: boolean;\n /** Custom line item renderer. */\n renderLineItem?: (item: LineItem) => React.ReactNode;\n className?: string;\n classNames?: OrderSummaryClassNames;\n}\n\nconst STATUS_LABELS: Record<OrderStatus, string> = {\n pending: \"Pending\",\n created: \"Created\",\n confirmed: \"Confirmed\",\n in_preparation: \"In Preparation\",\n ready_to_serve: \"Ready\",\n partially_served: \"Partially Served\",\n served: \"Served\",\n delivered: \"Delivered\",\n picked_up: \"Picked Up\",\n completed: \"Completed\",\n cancelled: \"Cancelled\",\n refunded: \"Refunded\",\n};\n\nconst PAYMENT_STATE_LABELS: Record<PaymentState, string> = {\n not_paid: \"Not Paid\",\n paid: \"Paid\",\n partially_refunded: \"Partially Refunded\",\n refunded: \"Refunded\",\n};\n\n/**\n * OrderSummary — displays a single order's details, line items, and totals.\n *\n * Accepts either a pre-loaded `order` object or an `orderId` to fetch.\n * Supports polling for live status updates.\n */\nexport function OrderSummary({\n order: orderProp,\n orderId,\n poll = false,\n renderLineItem,\n className,\n classNames,\n}: OrderSummaryProps): React.ReactElement {\n const { order: fetched, isLoading } = useOrder(orderProp ? null : orderId, {\n enabled: !orderProp && !!orderId,\n poll,\n });\n\n const order = orderProp ?? fetched;\n\n if (isLoading && !order) {\n return (\n <div\n data-cimplify-order-summary\n aria-busy=\"true\"\n className={cn(className, classNames?.root, classNames?.loading)}\n >\n <div data-cimplify-order-summary-skeleton />\n </div>\n );\n }\n\n if (!order) {\n return (\n <div data-cimplify-order-summary className={cn(className, classNames?.root)}>\n <p>Order not found.</p>\n </div>\n );\n }\n\n return (\n <div data-cimplify-order-summary className={cn(className, classNames?.root)}>\n {/* Header */}\n <div data-cimplify-order-header className={classNames?.header}>\n <span data-cimplify-order-id className={classNames?.orderId}>\n Order #{order.user_friendly_id}\n </span>\n <span\n data-cimplify-order-status\n data-status={order.status}\n className={classNames?.status}\n >\n {STATUS_LABELS[order.status] ?? order.status}\n </span>\n {order.payment_state && (\n <span\n data-cimplify-order-payment-state\n data-payment-state={order.payment_state}\n className={classNames?.paymentState}\n >\n {PAYMENT_STATE_LABELS[order.payment_state] ?? order.payment_state}\n </span>\n )}\n </div>\n\n {/* Fulfillment details */}\n {order.order_type === \"pickup\" && order.pickup_time && (\n <div data-cimplify-order-fulfillment className={classNames?.fulfillmentDetails}>\n <span>Pickup time: {new Date(order.pickup_time).toLocaleString()}</span>\n </div>\n )}\n {order.order_type === \"dine-in\" && order.table_number && (\n <div data-cimplify-order-fulfillment className={classNames?.fulfillmentDetails}>\n <span>Table: {order.table_number}</span>\n </div>\n )}\n\n {/* Date */}\n <time data-cimplify-order-date dateTime={order.created_at}>\n {new Date(order.created_at).toLocaleDateString(undefined, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n })}\n </time>\n\n {/* Customer info */}\n {(order.customer_name || order.customer_email) && (\n <div data-cimplify-order-customer className={classNames?.customer}>\n {order.customer_name && (\n <span data-cimplify-order-customer-name>{order.customer_name}</span>\n )}\n {order.customer_email && (\n <span data-cimplify-order-customer-email>{order.customer_email}</span>\n )}\n </div>\n )}\n\n {/* Delivery address */}\n {order.delivery_address && (\n <div data-cimplify-order-delivery-address className={classNames?.deliveryAddress}>\n <span>Delivery address</span>\n <p>{order.delivery_address}</p>\n </div>\n )}\n\n {/* Line items */}\n <div data-cimplify-order-items className={classNames?.items}>\n {order.items.map((item) =>\n renderLineItem ? (\n <React.Fragment key={item.id}>{renderLineItem(item)}</React.Fragment>\n ) : (\n <div key={item.id} data-cimplify-order-line-item className={classNames?.lineItem}>\n <div data-cimplify-order-line-info>\n <span data-cimplify-order-line-qty>{item.quantity}&times;</span>\n <span data-cimplify-order-line-key>{item.line_key}</span>\n </div>\n <Price amount={item.price} />\n {item.fulfillment_type === \"digital\" && item.fulfillment_id && (\n <a\n href={item.fulfillment_id}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cimplify-order-line-download\n className=\"text-sm text-primary underline\"\n >\n Download\n </a>\n )}\n\n {/* Service items: show scheduling and confirmation details */}\n {item.configuration.type === \"service\" && (\n <div data-cimplify-order-service-info className={classNames?.serviceInfo}>\n {item.configuration.scheduled_start && (\n <span>{\"\\u{1F4C5}\"} {new Date(item.configuration.scheduled_start).toLocaleDateString()} at {new Date(item.configuration.scheduled_start).toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" })}</span>\n )}\n {item.configuration.confirmation_code && (\n <span>Confirmation: {item.configuration.confirmation_code}</span>\n )}\n {item.configuration.service_status && (\n <span data-status={item.configuration.service_status}>{item.configuration.service_status}</span>\n )}\n </div>\n )}\n\n {/* Digital items: instant delivery badge */}\n {item.configuration.type === \"digital\" && (\n <div data-cimplify-order-digital-info className={classNames?.digitalInfo}>\n <span>{\"\\u26A1\"} Instant digital delivery</span>\n </div>\n )}\n\n {/* Bundle items: component breakdown */}\n {item.configuration.type === \"bundle\" && item.configuration.resolved && (\n <div data-cimplify-order-bundle-breakdown className={classNames?.bundleBreakdown}>\n {item.configuration.resolved.selections.map((sel) => (\n <div key={sel.component_id} data-product-type={sel.product_type}>\n <span>{sel.quantity}&times; {sel.product_name}</span>\n {sel.product_type === \"service\" && sel.scheduling?.scheduled_start && (\n <span> &mdash; {new Date(sel.scheduling.scheduled_start).toLocaleDateString()}</span>\n )}\n {sel.product_type === \"digital\" && <span> &mdash; Digital</span>}\n </div>\n ))}\n </div>\n )}\n\n {/* Composite items: component breakdown with pricing */}\n {item.configuration.type === \"composite\" && item.configuration.resolved && (\n <div data-cimplify-order-composite-breakdown className={classNames?.compositeBreakdown}>\n {item.configuration.resolved.selections.map((sel) => (\n <div key={sel.component_id} data-product-type={sel.product_type}>\n <span>{sel.quantity}&times; {sel.component_name}</span>\n {sel.product_type === \"service\" && sel.scheduling?.scheduled_start && (\n <span> &mdash; {new Date(sel.scheduling.scheduled_start).toLocaleDateString()}</span>\n )}\n <Price amount={sel.unit_price} />\n </div>\n ))}\n </div>\n )}\n </div>\n ),\n )}\n </div>\n\n {/* Customer notes / special instructions */}\n {order.customer_notes && order.customer_notes.length > 0 && (\n <div data-cimplify-order-notes className={classNames?.notes}>\n <span>Notes</span>\n {order.customer_notes.map((note, index) => (\n <p key={index} data-cimplify-order-note>{note}</p>\n ))}\n </div>\n )}\n\n {/* Totals */}\n <div data-cimplify-order-totals className={classNames?.totals}>\n {order.total_discount != null && parsePrice(order.total_discount) !== 0 && (\n <div data-cimplify-order-discount>\n <span>Discount</span>\n <Price amount={order.total_discount} prefix=\"-\" />\n </div>\n )}\n {order.delivery_fee != null && parsePrice(order.delivery_fee) > 0 && (\n <div data-cimplify-order-delivery-fee>\n <span>Delivery fee</span>\n <Price amount={order.delivery_fee} />\n </div>\n )}\n {order.service_charge != null && parsePrice(order.service_charge) !== 0 && (\n <div data-cimplify-order-service-charge>\n <span>Service charge</span>\n <Price amount={order.service_charge} />\n </div>\n )}\n {order.tax != null && parsePrice(order.tax) !== 0 && (\n <div data-cimplify-order-tax>\n <span>Tax</span>\n <Price amount={order.tax} />\n </div>\n )}\n <div data-cimplify-order-total>\n <span>Total</span>\n <Price amount={order.total_price} />\n </div>\n </div>\n\n {/* Tracking */}\n {order.tracking_link && (\n <a\n href={order.tracking_link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cimplify-order-tracking\n className={classNames?.trackingLink}\n >\n Track your order\n </a>\n )}\n </div>\n );\n}\n"
13
+ "content": "\"use client\";\n\nimport React from \"react\";\nimport type { Order, LineItem, OrderStatus, PaymentState } from \"@cimplify/sdk\";\nimport { useOrder } from \"@cimplify/sdk/react\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { parsePrice } from \"@cimplify/sdk\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface OrderSummaryClassNames {\n root?: string;\n header?: string;\n orderId?: string;\n status?: string;\n paymentState?: string;\n fulfillmentDetails?: string;\n deliveryAddress?: string;\n items?: string;\n lineItem?: string;\n notes?: string;\n totals?: string;\n customer?: string;\n loading?: string;\n serviceInfo?: string;\n digitalInfo?: string;\n bundleBreakdown?: string;\n compositeBreakdown?: string;\n trackingLink?: string;\n reorderButton?: string;\n}\n\nexport interface OrderSummaryProps {\n /** Pass an Order object directly (skips fetch). */\n order?: Order;\n /** Or pass an order ID to fetch via useOrder. */\n orderId?: string;\n /** Poll for status updates. */\n poll?: boolean;\n /** Custom line item renderer. */\n renderLineItem?: (item: LineItem) => React.ReactNode;\n /** Called when the reorder button is clicked. */\n onReorder?: (order: Order) => void;\n /** Called when the order status changes during polling. */\n onStatusChange?: (previousStatus: OrderStatus, newStatus: OrderStatus, order: Order) => void;\n className?: string;\n classNames?: OrderSummaryClassNames;\n}\n\nconst STATUS_LABELS: Record<OrderStatus, string> = {\n pending: \"Pending\",\n created: \"Created\",\n confirmed: \"Confirmed\",\n in_preparation: \"In Preparation\",\n ready_to_serve: \"Ready\",\n partially_served: \"Partially Served\",\n served: \"Served\",\n delivered: \"Delivered\",\n picked_up: \"Picked Up\",\n completed: \"Completed\",\n cancelled: \"Cancelled\",\n refunded: \"Refunded\",\n};\n\nconst PAYMENT_STATE_LABELS: Record<PaymentState, string> = {\n not_paid: \"Not Paid\",\n paid: \"Paid\",\n partially_refunded: \"Partially Refunded\",\n refunded: \"Refunded\",\n};\n\n/**\n * OrderSummary — displays a single order's details, line items, and totals.\n *\n * Accepts either a pre-loaded `order` object or an `orderId` to fetch.\n * Supports polling for live status updates.\n */\nexport function OrderSummary({\n order: orderProp,\n orderId,\n poll = false,\n renderLineItem,\n onReorder,\n onStatusChange,\n className,\n classNames,\n}: OrderSummaryProps): React.ReactElement {\n const { order: fetched, isLoading } = useOrder(orderProp ? null : orderId, {\n enabled: !orderProp && !!orderId,\n poll,\n onStatusChange,\n });\n\n const order = orderProp ?? fetched;\n\n if (isLoading && !order) {\n return (\n <div\n data-cimplify-order-summary\n aria-busy=\"true\"\n className={cn(className, classNames?.root, classNames?.loading)}\n >\n <div data-cimplify-order-summary-skeleton />\n </div>\n );\n }\n\n if (!order) {\n return (\n <div data-cimplify-order-summary className={cn(className, classNames?.root)}>\n <p>Order not found.</p>\n </div>\n );\n }\n\n return (\n <div data-cimplify-order-summary className={cn(className, classNames?.root)}>\n {/* Header */}\n <div data-cimplify-order-header className={classNames?.header}>\n <span data-cimplify-order-id className={classNames?.orderId}>\n Order #{order.user_friendly_id}\n </span>\n <span\n data-cimplify-order-status\n data-status={order.status}\n className={classNames?.status}\n >\n {STATUS_LABELS[order.status] ?? order.status}\n </span>\n {order.payment_state && (\n <span\n data-cimplify-order-payment-state\n data-payment-state={order.payment_state}\n className={classNames?.paymentState}\n >\n {PAYMENT_STATE_LABELS[order.payment_state] ?? order.payment_state}\n </span>\n )}\n </div>\n\n {/* Fulfillment details */}\n {order.order_type === \"pickup\" && order.pickup_time && (\n <div data-cimplify-order-fulfillment className={classNames?.fulfillmentDetails}>\n <span>Pickup time: {new Date(order.pickup_time).toLocaleString()}</span>\n </div>\n )}\n {order.order_type === \"dine-in\" && order.table_number && (\n <div data-cimplify-order-fulfillment className={classNames?.fulfillmentDetails}>\n <span>Table: {order.table_number}</span>\n </div>\n )}\n\n {/* Date */}\n <time data-cimplify-order-date dateTime={order.created_at}>\n {new Date(order.created_at).toLocaleDateString(undefined, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n })}\n </time>\n\n {/* Customer info */}\n {(order.customer_name || order.customer_email) && (\n <div data-cimplify-order-customer className={classNames?.customer}>\n {order.customer_name && (\n <span data-cimplify-order-customer-name>{order.customer_name}</span>\n )}\n {order.customer_email && (\n <span data-cimplify-order-customer-email>{order.customer_email}</span>\n )}\n </div>\n )}\n\n {/* Delivery address */}\n {order.delivery_address && (\n <div data-cimplify-order-delivery-address className={classNames?.deliveryAddress}>\n <span>Delivery address</span>\n <p>{order.delivery_address}</p>\n </div>\n )}\n\n {/* Line items */}\n <div data-cimplify-order-items className={classNames?.items}>\n {order.items.map((item) =>\n renderLineItem ? (\n <React.Fragment key={item.id}>{renderLineItem(item)}</React.Fragment>\n ) : (\n <div key={item.id} data-cimplify-order-line-item className={classNames?.lineItem}>\n <div data-cimplify-order-line-info>\n <span data-cimplify-order-line-qty>{item.quantity}&times;</span>\n <span data-cimplify-order-line-key>{item.line_key}</span>\n </div>\n <Price amount={item.price} />\n {item.fulfillment_type === \"digital\" && item.fulfillment_id && (\n <a\n href={item.fulfillment_id}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cimplify-order-line-download\n className=\"text-sm text-primary underline\"\n >\n Download\n </a>\n )}\n\n {/* Service items: show scheduling and confirmation details */}\n {item.configuration.type === \"service\" && (\n <div data-cimplify-order-service-info className={classNames?.serviceInfo}>\n {item.configuration.scheduled_start && (\n <span>{\"\\u{1F4C5}\"} {new Date(item.configuration.scheduled_start).toLocaleDateString()} at {new Date(item.configuration.scheduled_start).toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" })}</span>\n )}\n {item.configuration.confirmation_code && (\n <span>Confirmation: {item.configuration.confirmation_code}</span>\n )}\n {item.configuration.service_status && (\n <span data-status={item.configuration.service_status}>{item.configuration.service_status}</span>\n )}\n </div>\n )}\n\n {/* Digital items: instant delivery badge */}\n {item.configuration.type === \"digital\" && (\n <div data-cimplify-order-digital-info className={classNames?.digitalInfo}>\n <span>{\"\\u26A1\"} Instant digital delivery</span>\n </div>\n )}\n\n {/* Bundle items: component breakdown */}\n {item.configuration.type === \"bundle\" && item.configuration.resolved && (\n <div data-cimplify-order-bundle-breakdown className={classNames?.bundleBreakdown}>\n {item.configuration.resolved.selections.map((sel) => (\n <div key={sel.component_id} data-product-type={sel.product_type}>\n <span>{sel.quantity}&times; {sel.product_name}</span>\n {sel.product_type === \"service\" && sel.scheduling?.scheduled_start && (\n <span> &mdash; {new Date(sel.scheduling.scheduled_start).toLocaleDateString()}</span>\n )}\n {sel.product_type === \"digital\" && <span> &mdash; Digital</span>}\n </div>\n ))}\n </div>\n )}\n\n {/* Composite items: component breakdown with pricing */}\n {item.configuration.type === \"composite\" && item.configuration.resolved && (\n <div data-cimplify-order-composite-breakdown className={classNames?.compositeBreakdown}>\n {item.configuration.resolved.selections.map((sel) => (\n <div key={sel.component_id} data-product-type={sel.product_type}>\n <span>{sel.quantity}&times; {sel.component_name}</span>\n {sel.product_type === \"service\" && sel.scheduling?.scheduled_start && (\n <span> &mdash; {new Date(sel.scheduling.scheduled_start).toLocaleDateString()}</span>\n )}\n <Price amount={sel.unit_price} />\n </div>\n ))}\n </div>\n )}\n </div>\n ),\n )}\n </div>\n\n {/* Customer notes / special instructions */}\n {order.customer_notes && order.customer_notes.length > 0 && (\n <div data-cimplify-order-notes className={classNames?.notes}>\n <span>Notes</span>\n {order.customer_notes.map((note, index) => (\n <p key={index} data-cimplify-order-note>{note}</p>\n ))}\n </div>\n )}\n\n {/* Totals */}\n <div data-cimplify-order-totals className={classNames?.totals}>\n {order.total_discount != null && parsePrice(order.total_discount) !== 0 && (\n <div data-cimplify-order-discount>\n <span>Discount</span>\n <Price amount={order.total_discount} prefix=\"-\" />\n </div>\n )}\n {order.delivery_fee != null && parsePrice(order.delivery_fee) > 0 && (\n <div data-cimplify-order-delivery-fee>\n <span>Delivery fee</span>\n <Price amount={order.delivery_fee} />\n </div>\n )}\n {order.service_charge != null && parsePrice(order.service_charge) !== 0 && (\n <div data-cimplify-order-service-charge>\n <span>Service charge</span>\n <Price amount={order.service_charge} />\n </div>\n )}\n {order.tax != null && parsePrice(order.tax) !== 0 && (\n <div data-cimplify-order-tax>\n <span>Tax</span>\n <Price amount={order.tax} />\n </div>\n )}\n <div data-cimplify-order-total>\n <span>Total</span>\n <Price amount={order.total_price} />\n </div>\n </div>\n\n {/* Tracking */}\n {order.tracking_link && (\n <a\n href={order.tracking_link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cimplify-order-tracking\n className={classNames?.trackingLink}\n >\n Track your order\n </a>\n )}\n\n {onReorder && (\n <button\n type=\"button\"\n onClick={() => onReorder(order)}\n data-cimplify-order-reorder\n className={classNames?.reorderButton}\n >\n Reorder\n </button>\n )}\n </div>\n );\n}\n"
14
14
  }
15
15
  ]
16
16
  }