{"version":3,"file":"checkout_controller.js","sources":["../../../assets/controllers/cart/checkout_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus';\n\nexport default class extends Controller {\n    static targets = ['label', 'shippingCost', 'total'];\n\n    declare readonly labelTargets: HTMLElement[];\n    declare readonly hasShippingCostTarget: boolean;\n    declare readonly shippingCostTarget: HTMLElement;\n    declare readonly hasTotalTarget: boolean;\n    declare readonly totalTarget: HTMLElement;\n\n    declare readonly element: HTMLElement;\n\n    connect() {\n        // Address step\n        if (document.getElementById('new-address-form')) {\n            this.toggleNewAddressForm();\n            this.toggleNewBillingAddressForm();\n        }\n\n        // Shipping step\n        if (this.hasShippingCostTarget) {\n            this.updateSummary();\n        }\n    }\n\n    // --- Address Step ---\n\n    selectAddress(event: Event) {\n        this.toggleNewAddressForm();\n    }\n\n    selectBillingAddress(event: Event) {\n        this.toggleNewBillingAddressForm();\n    }\n\n    toggleNewAddressForm() {\n        const selectedRadio = this.element.querySelector('input[name=\"selected_address\"]:checked') as HTMLInputElement;\n        const newAddressForm = document.getElementById('new-address-form');\n        if (!newAddressForm) return;\n\n        const inputs = newAddressForm.querySelectorAll('input, select');\n\n        if (selectedRadio && selectedRadio.value === 'new') {\n            newAddressForm.classList.remove('hidden');\n            inputs.forEach(input => {\n                if ((input as HTMLInputElement).type !== 'checkbox') {\n                    (input as HTMLInputElement).required = true;\n                }\n            });\n        } else if (selectedRadio) {\n            newAddressForm.classList.add('hidden');\n            inputs.forEach(input => {\n                (input as HTMLInputElement).required = false;\n            });\n        }\n    }\n\n    toggleNewBillingAddressForm() {\n        const selectedRadio = this.element.querySelector('input[name=\"selected_billing_address\"]:checked') as HTMLInputElement;\n        const form = document.getElementById('new-billing-address-form');\n        if (!form) return;\n\n        const inputs = form.querySelectorAll('input, select');\n\n        if (selectedRadio && selectedRadio.value === 'new') {\n            form.classList.remove('hidden');\n            inputs.forEach(input => {\n                (input as HTMLInputElement).required = true;\n            });\n        } else if (selectedRadio) {\n            form.classList.add('hidden');\n            inputs.forEach(input => {\n                (input as HTMLInputElement).required = false;\n            });\n        }\n    }\n\n    toggleBillingSection(event: Event) {\n        const checkbox = event.currentTarget as HTMLInputElement;\n        const billingSection = document.getElementById('billing-section');\n        if (!billingSection) return;\n\n        if (checkbox.checked) {\n            billingSection.classList.add('hidden');\n            // Remove required from billing fields\n            billingSection.querySelectorAll('input, select').forEach(input => {\n                (input as HTMLInputElement).required = false;\n            });\n        } else {\n            billingSection.classList.remove('hidden');\n            // Toggle required on billing new-address fields if visible\n            this.toggleNewBillingAddressForm();\n        }\n    }\n\n    async submitAddress(event: Event) {\n        event.preventDefault();\n\n        const form = event.currentTarget as HTMLFormElement;\n        const formData = new FormData(form);\n        const selectedAddress = formData.get('selected_address') as string;\n        const sameBilling = formData.get('same_billing');\n\n        // --- Resolve shipping address ---\n        let shippingAddressId: string;\n\n        if (selectedAddress && selectedAddress !== 'new') {\n            shippingAddressId = selectedAddress;\n        } else {\n            // Create new shipping address via API\n            const id = await this.createAddressFromForm(form, 'shipping');\n            if (!id) return;\n            shippingAddressId = id;\n        }\n\n        sessionStorage.setItem('checkout_shipping_address_id', shippingAddressId);\n\n        // --- Resolve billing address ---\n        if (sameBilling) {\n            sessionStorage.setItem('checkout_billing_address_id', shippingAddressId);\n        } else {\n            const selectedBilling = formData.get('selected_billing_address') as string;\n\n            if (selectedBilling && selectedBilling !== 'new') {\n                sessionStorage.setItem('checkout_billing_address_id', selectedBilling);\n            } else {\n                // Create new billing address via API\n                const id = await this.createAddressFromForm(form, 'billing');\n                if (!id) return;\n                sessionStorage.setItem('checkout_billing_address_id', id);\n            }\n        }\n\n        window.location.href = form.action;\n    }\n\n    /**\n     * Creates an address via POST /api/addresses from form fields.\n     * @param type 'shipping' uses unprefixed fields (#firstName), 'billing' uses billing_ prefix (#billing_firstName)\n     * @returns The new address ID as string, or null on error\n     */\n    private async createAddressFromForm(form: HTMLFormElement, type: 'shipping' | 'billing'): Promise<string | null> {\n        const prefix = type === 'billing' ? 'billing_' : '';\n\n        const firstName = (form.querySelector(`#${prefix}firstName`) as HTMLInputElement)?.value?.trim();\n        const lastName = (form.querySelector(`#${prefix}lastName`) as HTMLInputElement)?.value?.trim();\n        const street = (form.querySelector(`#${prefix}street`) as HTMLInputElement)?.value?.trim();\n        const postalCode = (form.querySelector(`#${prefix}postalCode`) as HTMLInputElement)?.value?.trim();\n        const city = (form.querySelector(`#${prefix}city`) as HTMLInputElement)?.value?.trim();\n        const country = (form.querySelector(`#${prefix}country`) as HTMLSelectElement)?.value;\n        const phone = (form.querySelector(`#${prefix}phone`) as HTMLInputElement)?.value?.trim();\n\n        if (!firstName || !lastName || !street || !postalCode || !city) {\n            alert(`Veuillez remplir tous les champs obligatoires de l'adresse de ${type === 'shipping' ? 'livraison' : 'facturation'}.`);\n            return null;\n        }\n\n        try {\n            const response = await fetch('/api/addresses', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application/json',\n                    'Accept': 'application/json',\n                    'X-Requested-With': 'XMLHttpRequest'\n                },\n                body: JSON.stringify({\n                    firstName,\n                    lastName,\n                    street,\n                    postalCode,\n                    city,\n                    country: country || 'FR',\n                    phone: phone || null,\n                    isShipping: type === 'shipping',\n                    isBilling: type === 'billing'\n                })\n            });\n\n            const data = await response.json();\n\n            if (!response.ok) {\n                alert(data.error || 'Erreur lors de la création de l\\'adresse.');\n                return null;\n            }\n\n            return String(data.id);\n        } catch (error) {\n            console.error('Error creating address:', error);\n            alert('Une erreur réseau est survenue.');\n            return null;\n        }\n    }\n\n    // --- Shipping Step ---\n\n    selectMethod(event: Event) {\n        // Update styling of labels\n        this.labelTargets.forEach(label => {\n            label.classList.remove('border-primary', 'bg-base-200/50');\n        });\n\n        const currentTarget = event.currentTarget as HTMLElement;\n        const selectedLabel = currentTarget.closest('label');\n        if (selectedLabel) {\n            selectedLabel.classList.add('border-primary', 'bg-base-200/50');\n        }\n\n        this.updateSummary();\n    }\n\n    updateSummary() {\n        const selectedRadio = this.element.querySelector('input[name=\"shipping_method\"]:checked') as HTMLInputElement;\n        if (selectedRadio) {\n            const cost = parseFloat(selectedRadio.dataset.cost || '0');\n\n            // Update shipping cost display\n            if (this.hasShippingCostTarget) {\n                this.shippingCostTarget.textContent = cost.toFixed(2).replace('.', ',') + '€';\n            }\n\n            // Update total display\n            if (this.hasTotalTarget) {\n                const baseTotal = parseFloat(this.totalTarget.dataset.baseTotal || '0');\n                const newTotal = baseTotal + cost;\n                this.totalTarget.textContent = newTotal.toFixed(2).replace('.', ',') + '€';\n            }\n        }\n    }\n\n    // --- Final Checkout Submission ---\n\n    async submitCheckout(event: Event) {\n        event.preventDefault();\n\n        const form = event.currentTarget as HTMLFormElement;\n        const submitButton = form.querySelector('button[type=\"submit\"]') as HTMLButtonElement;\n\n        if (submitButton) {\n            submitButton.disabled = true;\n            submitButton.textContent = 'Redirection vers le paiement...';\n        }\n\n        const formData = new FormData(form);\n        const shippingMethod = formData.get('shipping_method');\n\n        const shippingAddressId = sessionStorage.getItem('checkout_shipping_address_id');\n        const billingAddressId = sessionStorage.getItem('checkout_billing_address_id');\n\n        if (!shippingAddressId) {\n            alert('Veuillez sélectionner une adresse de livraison.');\n            window.location.href = '/commande/adresse';\n            return;\n        }\n\n        try {\n            const response = await fetch('/api/checkout/create-session', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application/json',\n                    'Accept': 'application/json',\n                    'X-Requested-With': 'XMLHttpRequest'\n                },\n                body: JSON.stringify({\n                    shipping_method: shippingMethod,\n                    shipping_address_id: shippingAddressId,\n                    billing_address_id: billingAddressId\n                })\n            });\n\n            const data = await response.json();\n\n            if (response.ok && data.url) {\n                window.location.href = data.url;\n            } else {\n                console.error('Checkout error:', data.error);\n                alert(data.error || 'Une erreur est survenue lors de la création de la session de paiement.');\n                if (submitButton) {\n                    submitButton.disabled = false;\n                    submitButton.textContent = 'Continuer vers le paiement';\n                }\n            }\n        } catch (error) {\n            console.error('Network error:', error);\n            alert('Une erreur réseau est survenue.');\n            if (submitButton) {\n                submitButton.disabled = false;\n                submitButton.textContent = 'Continuer vers le paiement';\n            }\n        }\n    }\n}"],"names":[],"mappings":"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"}