"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
/*
Checkout -- finalize purchase and pay.
*/
const icon_1 = require("@cocalc/frontend/components/icon");
const utils_1 = require("@cocalc/util/licenses/purchase/utils");
const misc_1 = require("@cocalc/util/misc");
const antd_1 = require("antd");
const payment_methods_1 = __importDefault(require("components/billing/payment-methods"));
const A_1 = __importDefault(require("components/misc/A"));
const loading_1 = __importDefault(require("components/share/loading"));
const site_name_1 = __importDefault(require("components/share/site-name"));
const post_1 = __importDefault(require("lib/api/post"));
const api_1 = __importDefault(require("lib/hooks/api"));
const mounted_1 = __importDefault(require("lib/hooks/mounted"));
const use_customize_1 = __importDefault(require("lib/use-customize"));
const router_1 = require("next/router");
const react_1 = require("react");
const react_google_recaptcha_v3_1 = require("react-google-recaptcha-v3");
const compute_cost_1 = require("./compute-cost");
const site_license_cost_1 = require("./site-license-cost");
function CheckoutWithCaptcha() {
    const { reCaptchaKey } = (0, use_customize_1.default)();
    return ((0, jsx_runtime_1.jsx)(react_google_recaptcha_v3_1.GoogleReCaptchaProvider, { reCaptchaKey: reCaptchaKey, children: (0, jsx_runtime_1.jsx)(Checkout, {}) }));
}
exports.default = CheckoutWithCaptcha;
function Checkout() {
    const { reCaptchaKey } = (0, use_customize_1.default)();
    const { executeRecaptcha } = (0, react_google_recaptcha_v3_1.useGoogleReCaptcha)();
    const router = (0, router_1.useRouter)();
    const isMounted = (0, mounted_1.default)();
    const [placingOrder, setPlacingOrder] = (0, react_1.useState)(false);
    const [orderError, setOrderError] = (0, react_1.useState)("");
    const [subTotal, setSubTotal] = (0, react_1.useState)(0);
    const [taxRate, setTaxRate] = (0, react_1.useState)(0);
    // most likely, user will do the purchase and then see the congratulations page
    (0, react_1.useEffect)(() => {
        router.prefetch("/store/congrats");
    }, []);
    const cart = (0, api_1.default)("/shopping/cart/get");
    const items = (0, react_1.useMemo)(() => {
        if (!cart.result)
            return undefined;
        const x = [];
        let subTotal = 0;
        for (const item of cart.result) {
            if (!item.checked)
                continue;
            item.cost = (0, compute_cost_1.computeCost)(item.description);
            subTotal += item.cost.discounted_cost;
            x.push(item);
        }
        setSubTotal(subTotal);
        return x;
    }, [cart.result]);
    if (cart.error) {
        return (0, jsx_runtime_1.jsx)(antd_1.Alert, { type: "error", message: cart.error });
    }
    if (!items) {
        return (0, jsx_runtime_1.jsx)(loading_1.default, { center: true });
    }
    async function placeOrder() {
        try {
            setOrderError("");
            setPlacingOrder(true);
            let reCaptchaToken;
            if (reCaptchaKey) {
                if (!executeRecaptcha) {
                    throw Error("Please wait a few seconds, then try again.");
                }
                reCaptchaToken = await executeRecaptcha("checkout");
            }
            // This api call tells the backend, "buy everything in my shopping cart."
            // It succeeds if the purchase goes through.
            await (0, post_1.default)("/shopping/cart/checkout", { reCaptchaToken });
            // Success!
            if (!isMounted.current)
                return;
            // If the user is still viewing the page after the purchase happened, we
            // send them to the congrats page, which shows them what they recently purchased,
            // with links about how to use it, etc.
            router.push("/store/congrats");
        }
        catch (err) {
            // The purchase failed.
            setOrderError(err.message);
        }
        finally {
            if (!isMounted.current)
                return;
            setPlacingOrder(false);
        }
    }
    function renderProjectID(project_id) {
        if (!project_id || !(0, misc_1.isValidUUID)(project_id))
            return null;
        return ((0, jsx_runtime_1.jsxs)("div", { children: ["For project: ", (0, jsx_runtime_1.jsx)("code", { children: project_id })] }));
    }
    const columns = [
        {
            responsive: ["xs"],
            render: ({ cost, description, project_id }) => {
                return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(DescriptionColumn, { cost: cost, description: description }), renderProjectID(project_id), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("b", { style: { fontSize: "11pt" }, children: (0, jsx_runtime_1.jsx)(site_license_cost_1.DisplayCost, { cost: cost, simple: true, oneLine: true }) }) })] }));
            },
        },
        {
            responsive: ["sm"],
            title: "Product",
            align: "center",
            render: () => ((0, jsx_runtime_1.jsxs)("div", { style: { color: "darkblue" }, children: [(0, jsx_runtime_1.jsx)(icon_1.Icon, { name: "key", style: { fontSize: "24px" } }), (0, jsx_runtime_1.jsx)("div", { style: { fontSize: "10pt" }, children: "Site License" })] })),
        },
        {
            responsive: ["sm"],
            width: "60%",
            render: (_, { cost, description, project_id }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(DescriptionColumn, { cost: cost, description: description }), " ", renderProjectID(project_id)] })),
        },
        {
            responsive: ["sm"],
            title: "Price",
            align: "right",
            render: (_, { cost }) => ((0, jsx_runtime_1.jsx)("b", { style: { fontSize: "11pt" }, children: (0, jsx_runtime_1.jsx)(site_license_cost_1.DisplayCost, { cost: cost, simple: true }) })),
        },
    ];
    function placeOrderButton() {
        return ((0, jsx_runtime_1.jsx)(antd_1.Button, { disabled: subTotal == 0 || placingOrder, style: { marginTop: "7px", marginBottom: "15px" }, size: "large", type: "primary", onClick: placeOrder, children: placingOrder ? ((0, jsx_runtime_1.jsx)(loading_1.default, { delay: 0, children: "Placing Order..." })) : ("Place Your Order") }));
    }
    function renderOrderError() {
        if (!orderError)
            return;
        return ((0, jsx_runtime_1.jsx)(antd_1.Alert, { type: "error", message: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("b", { children: "Error placing order:" }), " ", orderError] }), style: { margin: "30px 0" } }));
    }
    function emptyCart() {
        return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("h3", { children: [(0, jsx_runtime_1.jsx)(icon_1.Icon, { name: "shopping-cart", style: { marginRight: "5px" } }), cart.result?.length > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Nothing in Your ", (0, jsx_runtime_1.jsx)(site_name_1.default, {}), " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "/store/cart", children: "Shopping Cart" }), " is Selected"] })), (cart.result?.length ?? 0) == 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Your ", (0, jsx_runtime_1.jsx)(site_name_1.default, {}), " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "/store/cart", children: "Shopping Cart" }), " is Empty"] }))] }), (0, jsx_runtime_1.jsx)(A_1.default, { href: "/store/site-license", children: "Buy a License" })] }));
    }
    function nonemptyCart(items) {
        return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [renderOrderError(), (0, jsx_runtime_1.jsxs)(antd_1.Row, { children: [(0, jsx_runtime_1.jsx)(antd_1.Col, { md: 14, sm: 24, children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("h3", { style: { fontSize: "16pt" }, children: [(0, jsx_runtime_1.jsx)(icon_1.Icon, { name: "list", style: { marginRight: "5px" } }), "Checkout (", (0, jsx_runtime_1.jsxs)(A_1.default, { href: "/store/cart", children: [items.length, " items"] }), ")"] }), (0, jsx_runtime_1.jsx)("h4", { style: { fontSize: "13pt", marginTop: "20px" }, children: "1. Payment Method" }), (0, jsx_runtime_1.jsx)("p", { children: "The default payment method shown below will be used for this purchase." }), (0, jsx_runtime_1.jsx)(payment_methods_1.default, { startMinimized: true, setTaxRate: setTaxRate })] }) }), (0, jsx_runtime_1.jsx)(antd_1.Col, { md: { offset: 1, span: 9 }, sm: { span: 24, offset: 0 }, children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { style: {
                                            textAlign: "center",
                                            border: "1px solid #ddd",
                                            padding: "15px",
                                            borderRadius: "5px",
                                            minWidth: "300px",
                                        }, children: [placeOrderButton(), (0, jsx_runtime_1.jsx)(Terms, {}), (0, jsx_runtime_1.jsx)(OrderSummary, { items: items, taxRate: taxRate }), (0, jsx_runtime_1.jsx)("span", { style: { fontSize: "13pt" }, children: (0, jsx_runtime_1.jsx)(TotalCost, { items: items, taxRate: taxRate }) })] }), (0, jsx_runtime_1.jsx)(GetAQuote, { items: items })] }) })] }), (0, jsx_runtime_1.jsxs)("h4", { style: { fontSize: "13pt", marginTop: "15px" }, children: ["2. Review Items (", items.length, ")"] }), (0, jsx_runtime_1.jsx)("div", { style: { border: "1px solid #eee" }, children: (0, jsx_runtime_1.jsx)(antd_1.Table, { showHeader: false, columns: columns, dataSource: items, rowKey: "id", pagination: { hideOnSinglePage: true } }) }), (0, jsx_runtime_1.jsx)("h4", { style: { fontSize: "13pt", marginTop: "30px" }, children: "3. Place Your Order" }), (0, jsx_runtime_1.jsx)("div", { style: { fontSize: "12pt" }, children: (0, jsx_runtime_1.jsxs)(antd_1.Row, { children: [(0, jsx_runtime_1.jsx)(antd_1.Col, { sm: 12, children: placeOrderButton() }), (0, jsx_runtime_1.jsx)(antd_1.Col, { sm: 12, children: (0, jsx_runtime_1.jsxs)("div", { style: { fontSize: "15pt" }, children: [(0, jsx_runtime_1.jsx)(TotalCost, { items: cart.result, taxRate: taxRate }), (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)(Terms, {})] }) })] }) })] }));
    }
    return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [items.length == 0 && emptyCart(), items.length > 0 && nonemptyCart(items), renderOrderError()] }));
}
function fullCost(items) {
    let full_cost = 0;
    for (const { cost, checked } of items) {
        if (checked) {
            full_cost += cost.cost;
        }
    }
    return full_cost;
}
function discountedCost(items) {
    let discounted_cost = 0;
    for (const { cost, checked } of items) {
        if (checked) {
            discounted_cost += cost.discounted_cost;
        }
    }
    return discounted_cost;
}
function TotalCost({ items, taxRate }) {
    const cost = discountedCost(items) * (1 + taxRate);
    return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Total: ", (0, jsx_runtime_1.jsx)("b", { style: { float: "right", color: "darkred" }, children: (0, utils_1.money)(cost) })] }));
}
function OrderSummary({ items, taxRate }) {
    const cost = discountedCost(items);
    const full = fullCost(items);
    const tax = cost * taxRate;
    return ((0, jsx_runtime_1.jsxs)("div", { style: { textAlign: "left" }, children: [(0, jsx_runtime_1.jsx)("b", { style: { fontSize: "14pt" }, children: "Order Summary" }), (0, jsx_runtime_1.jsxs)("div", { children: ["Items (", items.length, "):", " ", (0, jsx_runtime_1.jsx)("span", { style: { float: "right" }, children: (0, utils_1.money)(full, true) })] }), full - cost > 0 && ((0, jsx_runtime_1.jsxs)("div", { children: ["Self-service discount (25%):", " ", (0, jsx_runtime_1.jsxs)("span", { style: { float: "right" }, children: ["-", (0, utils_1.money)(full - cost, true)] })] })), (0, jsx_runtime_1.jsxs)("div", { children: ["Estimated tax:", " ", (0, jsx_runtime_1.jsx)("span", { style: { float: "right" }, children: (0, utils_1.money)(tax, true) })] })] }));
}
function Terms() {
    return ((0, jsx_runtime_1.jsxs)("div", { style: { color: "#666", fontSize: "10pt" }, children: ["By placing your order, you agree to", " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "/policies/terms", external: true, children: "our terms of service" }), " ", "regarding refunds and subscriptions."] }));
}
function DescriptionColumn({ cost, description }) {
    const { input } = cost;
    return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)("div", { style: { fontSize: "12pt" }, children: [description.title && ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("b", { children: description.title }) })), description.description && (0, jsx_runtime_1.jsx)("div", { children: description.description }), (0, site_license_cost_1.describeItem)({ info: input })] }) }));
}
const MIN_AMOUNT = 100;
function GetAQuote({ items }) {
    const router = (0, router_1.useRouter)();
    const [more, setMore] = (0, react_1.useState)(false);
    let isSub;
    for (const item of items) {
        if (item.description.period != "range") {
            isSub = true;
            break;
        }
    }
    function createSupportRequest() {
        const x = [];
        for (const item of items) {
            x.push({
                cost: (0, utils_1.money)(item.cost.cost),
                ...(0, misc_1.copy_without)(item, [
                    "account_id",
                    "added",
                    "removed",
                    "purchased",
                    "checked",
                    "cost",
                ]),
            });
        }
        const body = `Hello,\n\nI would like to request a quote.  I filled out the online form with the\ndetails listed below:\n\n\`\`\`\n${JSON.stringify(x, undefined, 2)}\n\`\`\``;
        router.push({
            pathname: "/support/new",
            query: {
                hideExtra: true,
                subject: "Request for a quote",
                body,
                type: "question",
            },
        });
    }
    return ((0, jsx_runtime_1.jsxs)("div", { style: { paddingTop: "15px" }, children: [(0, jsx_runtime_1.jsx)(A_1.default, { onClick: () => setMore(!more), children: "Need to obtain a quote, invoice, modified terms, a purchase order, to use PayPal or pay via wire transfer, etc.?" }), more && ((0, jsx_runtime_1.jsx)("div", { children: fullCost(items) <= MIN_AMOUNT || isSub ? ((0, jsx_runtime_1.jsx)(antd_1.Alert, { showIcon: true, style: {
                        margin: "15px 0",
                        fontSize: "12pt",
                        borderRadius: "5px",
                    }, type: "warning", message: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Customized payment is available only for", " ", (0, jsx_runtime_1.jsxs)("b", { children: ["non-subscription purchases over $", MIN_AMOUNT] }), ". Make sure your cost before tax and discounts is over $", MIN_AMOUNT, " ", "and ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "/store/cart", children: "convert" }), " any subscriptions in your cart to explicit date ranges, then try again. If this is confusing, ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "/support/new", children: "make a support request" }), "."] }) })) : ((0, jsx_runtime_1.jsx)(antd_1.Alert, { showIcon: true, style: {
                        margin: "15px 0",
                        fontSize: "12pt",
                        borderRadius: "5px",
                    }, type: "info", message: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Click the button below to copy your shopping cart contents to a support request, and we will take if from there. Note that the 25% self-service discount is ", (0, jsx_runtime_1.jsx)("b", { children: "only available" }), " when you purchase from this page.", (0, jsx_runtime_1.jsx)("div", { style: { textAlign: "center", marginTop: "5px" }, children: (0, jsx_runtime_1.jsxs)(antd_1.Button, { onClick: createSupportRequest, children: [(0, jsx_runtime_1.jsx)(icon_1.Icon, { name: "medkit" }), " Copy cart to support request"] }) })] }) })) }))] }));
}
//# sourceMappingURL=checkout.js.map