@coursebuilder/commerce-next
Version:
Commerce Functionality for Course Builder with Next.js
58 lines (57 loc) • 3.29 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { usePathname } from 'next/navigation.js';
import { useQuery } from '@tanstack/react-query';
import { z } from 'zod';
import { buildStripeCheckoutPath } from '@coursebuilder/core/pricing/build-stripe-checkout-path';
import { PriceDisplay } from '../pricing/price-display';
import { useDebounce } from '../utils/use-debounce';
const buyMoreSeatsSchema = z.object({
productId: z.string(),
userId: z.string(),
buttonLabel: z.string().default('Buy').nullish(),
className: z.string().optional(),
});
export const BuyMoreSeats = ({ productId, userId, buttonLabel = 'Buy', className = '', }) => {
const [quantity, setQuantity] = React.useState(5);
const debouncedQuantity = useDebounce(quantity, 250);
const pathname = usePathname();
const cancelUrl = process.env.NEXT_PUBLIC_URL + pathname;
const { data: formattedPrice, status } = useQuery({
queryKey: ['prices-formatted', productId, debouncedQuantity],
queryFn: async () => {
return await fetch(`${process.env.NEXT_PUBLIC_URL}/api/coursebuilder/prices-formatted`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
productId,
quantity: debouncedQuantity,
}),
}).then(async (res) => {
return (await res.json());
});
},
});
return (_jsx("form", { "data-buy-more-seats-form": "", action: buildStripeCheckoutPath({
userId,
quantity: debouncedQuantity,
productId,
bulk: Boolean(formattedPrice?.bulk),
couponId: formattedPrice?.appliedMerchantCoupon?.id,
cancelUrl,
}), method: "POST", className: className, children: _jsxs("fieldset", { id: "team-upgrade-pricing-inline", children: [_jsxs("div", { "data-seats-form": "", children: [_jsx("label", { children: "Seats" }), _jsx("button", { type: "button", "aria-label": "decrease seat quantity by one", onClick: () => {
if (quantity === 1)
return;
setQuantity(quantity - 1);
}, children: "-" }), _jsx("input", { value: quantity, required: true, type: "number", min: 1, max: 100, step: 1, onChange: (e) => {
const newQuantity = Number(e.target.value);
setQuantity(newQuantity);
} }), _jsx("button", { type: "button", "aria-label": "increase seat quantity by one", onClick: () => {
if (quantity === 100)
return;
setQuantity(quantity + 1);
}, children: "+" })] }), _jsx("div", { "data-pricing-product": "", children: _jsxs("div", { "data-pricing-product-header": "", children: [_jsx(PriceDisplay, { status: status, formattedPrice: formattedPrice }), _jsx("button", { type: "submit", disabled: status !== 'success', children: buttonLabel })] }) })] }) }));
};