{"version":3,"sources":["FC_CartCheckoutButton.tsx"],"sourcesContent":["/*\n * Framer Commerce\n * Confidential and Proprietary - All Rights Reserved\n * Unauthorized use, reproduction, distribution, or disclosure of this\n * source code or any related information is strictly prohibited.\n *\n * This software is the exclusive property of Framer Commerce (\"Company\").\n * It is considered highly confidential and proprietary information.\n *\n * Any use, copying, modification, distribution, or sharing of this software,\n * in whole or in part, without the express written permission of the Company\n * is strictly prohibited and may result in legal action.\n *\n * DISCLAIMER: This software does not provide any express or\n * implied warranties, including, but not limited to, the implied warranties\n * of merchantability and fitness for a particular purpose. In no event shall\n * Framer Commerce be liable for any direct, indirect, incidental, special,\n * exemplary, or consequential damages (including, but not limited to, procurement\n * of substitute goods or services; loss of use, data, or profits; or business\n * interruption) however caused and on any theory of liability, whether in\n * contract, strict liability, or tort (including negligence or otherwise)\n * arising in any way out of the use of this software, even if advised of\n * the possibility of such damage.\n *\n * Any unauthorized possession, use, copying, distribution, or dissemination\n * of this software will be considered a breach of confidentiality and may\n * result in legal action.\n *\n * For inquiries, contact:\n * Framer Commerce\n * Email: hello@framercommerce.com\n *\n * © 2025 Butter Supply Inc. All Rights Reserved.\n */\n\nimport React, {\n    useEffect,\n    useState,\n    useCallback,\n    useRef,\n    cloneElement,\n} from \"react\"\nimport { appendUTMParamsToUrl, getUTMParameters } from \"../utils/utmParams.ts\"\nimport { throttle } from \"lodash-es\"\nimport { addPropertyControls, ControlType } from \"framer\"\nimport { appendLanguageToUrl } from \"../utils/locales.ts\"\n\ndeclare global {\n    interface Window {\n        __FcCheckoutConfigs?: {\n            locale?: string\n        }\n    }\n}\n\n/**\n * @framerDisableUnlink\n */\n\nexport default function FC_CartCheckoutButton({ componentInstance }) {\n    const [checkoutUrl, setCheckoutUrl] = useState(null)\n    const isFetching = useRef(false)\n\n    // Capture UTM parameters on component mount\n    useEffect(() => {\n        // Get UTM parameters when component mounts\n        getUTMParameters()\n    }, [])\n\n    const waitForCondition = useCallback(\n        (conditionFn, checkInterval = 100, timeout = 10000) => {\n            return new Promise((resolve, reject) => {\n                const startTime = Date.now()\n                const checkCondition = () => {\n                    if (conditionFn()) {\n                        resolve()\n                    } else if (Date.now() - startTime >= timeout) {\n                        reject(new Error(\"Condition not met within timeout\"))\n                    } else {\n                        setTimeout(checkCondition, checkInterval)\n                    }\n                }\n                checkCondition()\n            })\n        },\n        []\n    )\n\n    const fetchCartAndUpdateCheckoutUrl = useCallback(\n        async (cartId) => {\n            if (isFetching.current) return\n            isFetching.current = true\n            try {\n                await waitForCondition(\n                    () => window.shopXtools && window.shopXtools.fetchCart\n                )\n                const cartData = await window.shopXtools.fetchCart(cartId)\n                //console.log(\"Cart Data in checkout button\", cartData)\n                if (cartData) {\n                    //console.log(\"Cart Data in checkout button\", cartData)\n                    // Check for existing attributes\n                    const storedAttributes = JSON.parse(\n                        localStorage.getItem(\"fc_cart_attributes\") || \"[]\"\n                    )\n                    // console.log(\"Cart data received:\", {\n                    //     checkoutUrl: cartData.checkoutUrl,\n                    //     storedAttributes,\n                    // })\n\n                    window.shopXtools.cart = cartData\n                    setCheckoutUrl(cartData.checkoutUrl || null)\n                } else {\n                    console.error(\"Failed to fetch cart data from Shopify\")\n                    setCheckoutUrl(null)\n                }\n            } catch (error) {\n                console.error(\"Error fetching cart from Shopify:\", error)\n                setCheckoutUrl(null)\n            } finally {\n                isFetching.current = false\n            }\n        },\n        [waitForCondition]\n    )\n\n    const handleCartUpdate = useCallback(\n        throttle(async () => {\n            let cartId =\n                window[\"shopXtools\"]?.cart?.id ||\n                localStorage.getItem(\"shopX_cart_id\")\n            if (cartId) {\n                await fetchCartAndUpdateCheckoutUrl(cartId)\n            } else {\n                console.warn(\"No cart ID found. Cart is empty.\")\n                setCheckoutUrl(null)\n            }\n        }, 1000),\n        [fetchCartAndUpdateCheckoutUrl]\n    )\n\n    useEffect(() => {\n        handleCartUpdate()\n        window.addEventListener(\"shopXtools-cart-update\", handleCartUpdate)\n        return () => {\n            window.removeEventListener(\n                \"shopXtools-cart-update\",\n                handleCartUpdate\n            )\n        }\n    }, [handleCartUpdate])\n\n    const handleClick = async (e) => {\n        try {\n            // Aggregate all product-specific attributes from sessionStorage\n            const allAttributes = []\n            for (let i = 0; i < sessionStorage.length; i++) {\n                const key = sessionStorage.key(i)\n                if (key?.startsWith(\"fc_cart_attributes_\")) {\n                    const productAttributes = JSON.parse(\n                        sessionStorage.getItem(key) || \"{}\"\n                    )\n                    Object.entries(productAttributes).forEach(\n                        ([attrKey, attrValue]) => {\n                            allAttributes.push({\n                                key: attrKey,\n                                value: String(attrValue),\n                            })\n                        }\n                    )\n                }\n            }\n\n            // Update cart attributes if we have any\n            if (\n                allAttributes.length > 0 &&\n                window.shopXtools?.handleCartMutation\n            ) {\n                const updateCartMutation = `\n                    mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {\n                        cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {\n                            cart {\n                                id\n                                attributes {\n                                    key\n                                    value\n                                }\n                            }\n                            userErrors {\n                                field\n                                message\n                            }\n                        }\n                    }\n                `\n\n                try {\n                    await window.shopXtools.handleCartMutation(\n                        updateCartMutation,\n                        {\n                            cartId: window.shopXtools.cart.id,\n                            attributes: allAttributes,\n                        }\n                    )\n                } catch (error) {\n                    console.error(\"Failed to update cart attributes:\", error)\n                }\n            }\n\n            // Analytics\n            const cart = window.shopXtools?.cart\n            if (!cart) {\n                console.warn(\"No cart found.\")\n                return // Exit if no cart is available\n            }\n\n            // Check if lines is defined and is an array\n            const lines = cart.lines?.edges || []\n            if (!Array.isArray(lines)) {\n                console.error(\"Lines is not an array:\", lines)\n                return // Exit if lines is not an array\n            }\n            const cartItems = lines.map((line) => line.node) // Assuming line.node contains the item details\n\n            // const value = parseFloat(cartItems.reduce((total, item) => total + parseFloat(item.cost.totalAmount.amount) * item.quantity, 0).toFixed(2));\n            // const currency = cartItems.length > 0 ? cartItems[0].cost.totalAmount.currencyCode : 'USD';\n            const value = cart?.cost.subtotalAmount.amount\n            const currency = cart?.cost.subtotalAmount.currencyCode\n            const items = cartItems.map((item) => ({\n                item_id: item.merchandise.id,\n                item_name: item.merchandise.title,\n                price: item.merchandise.price.amount,\n                quantity: item.quantity,\n            }))\n            // Google Analytics tracking\n            if (typeof window.fcTrackGAEvent === \"function\") {\n                // console.log(\"Tracking Begin Checkout - google:\", {\n                //     currency,\n                //     value,\n                //     items,\n                // })\n\n                window.fcTrackGAEvent(\"begin_checkout\", {\n                    currency,\n                    value,\n                    items,\n                })\n            }\n            // Meta Pixel tracking\n            if (typeof fbq === \"function\") {\n                const contentIds = items.map((item) => item.item_id) // Get all item IDs\n                const totalItems = items.reduce(\n                    (total, item) => total + item.quantity,\n                    0\n                ) // Sum all quantities\n                // console.log(\"Tracking Begin Checkout - meta:\", {\n                //     content_type: \"product\",\n                //     content_ids: contentIds,\n                //     value,\n                //     currency,\n                //     num_items: totalItems,\n                // })\n\n                fbq(\"track\", \"InitiateCheckout\", {\n                    content_type: \"product\",\n                    content_ids: contentIds,\n                    value,\n                    currency,\n                    num_items: totalItems,\n                })\n            }\n            let finalCheckoutUrl = checkoutUrl\n            // Only proceed with UTM params and language if we have a valid checkout URL\n            if (finalCheckoutUrl) {\n                finalCheckoutUrl = appendUTMParamsToUrl(finalCheckoutUrl)\n                finalCheckoutUrl = appendLanguageToUrl(finalCheckoutUrl)\n\n                // Clear all product-specific attributes after successful checkout redirect\n                for (let i = 0; i < sessionStorage.length; i++) {\n                    const key = sessionStorage.key(i)\n                    if (key?.startsWith(\"shopX_cart_attributes_\")) {\n                        sessionStorage.removeItem(key)\n                    }\n                }\n\n                window.location.assign(finalCheckoutUrl) // Use assign instead of href to avoid page reload and make sure it works in Safari and Chrome\n            } else {\n                console.error(\"No checkout URL available\")\n            }\n        } catch (error) {\n            console.error(\"Error during checkout:\", error)\n        }\n    }\n\n    const content = Array.isArray(componentInstance)\n        ? componentInstance[0]\n        : componentInstance\n\n    if (!content || !React.isValidElement(content)) {\n        return (\n            <div\n                style={{\n                    width: \"100%\",\n                    height: \"100%\",\n                    display: \"flex\",\n                    alignItems: \"center\",\n                    justifyContent: \"center\",\n                    color: \"#666\",\n                    fontSize: \"14px\",\n                }}\n            >\n                Connect Instance\n            </div>\n        )\n    }\n\n    return (\n        <div style={{ height: \"100%\", width: \"100%\" }}>\n            {cloneElement(content, {\n                style: {\n                    ...(content.props?.style || {}),\n                    width: \"100%\",\n                    height: \"100%\",\n                },\n                onClick: (e) => {\n                    handleClick(e)\n                    if (content.props?.onClick) {\n                        content.props.onClick(e)\n                    }\n                },\n            })}\n        </div>\n    )\n}\n\naddPropertyControls(FC_CartCheckoutButton, {\n    componentInstance: {\n        type: ControlType.ComponentInstance,\n        title: \"Component Instance\",\n    },\n})\n"],"names":[],"mappings":"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"}