PageSourceSearch

https://cdn.simplystamps.com/skin/frontend/zephyr/default/js/components/promo-code.js?v=1114

js simplystamps.com collected 2026-09-24 20:30:19 UTC 4,805 bytes, 144 lines download raw bytes

1/**
2 * Zephyr Promo Code Component
3 *
4 * Alpine.js store and helper functions for the promo code modal
5 */
6
7// Promo code configuration (set from PHP template)
8var promoCodeConfig = {
9    applyCouponUrl: '',
10    removeCouponUrl: '',
11    formKey: ''
12};
13
14document.addEventListener('alpine:init', function() {
15    // Promo code store
16    Alpine.store('promo', {
17        isOpen: false,
18        code: '',
19        isLoading: false,
20        error: '',
21        appliedCode: null,
22        success: false,
23        successMessage: '',
24        discount: '',
25
26        open: function() {
27            this.isOpen = true;
28            this.error = '';
29            this.code = '';
30            this.success = false;
31            this.successMessage = '';
32            this.discount = '';
33            // Focus input after modal opens
34            var self = this;
35            setTimeout(function() {
36                var input = document.getElementById('promo-code-input');
37                if (input) input.focus();
38            }, 100);
39        },
40
41        close: function() {
42            var self = this;
43            this.isOpen = false;
44            // Reset state after modal transition completes
45            setTimeout(function() {
46                self.error = '';
47                self.code = '';
48                self.isLoading = false;
49                self.success = false;
50                self.successMessage = '';
51                self.discount = '';
52            }, 200);
53        },
54
55        apply: function() {
56            var self = this;
57            var code = this.code.trim();
58
59            if (!code) {
60                this.error = 'Please enter a promo code';
61                return;
62            }
63
64            this.isLoading = true;
65            this.error = '';
66
67            fetch(promoCodeConfig.applyCouponUrl, {
68                method: 'POST',
69                headers: {
70                    'Content-Type': 'application/x-www-form-urlencoded',
71                    'X-Requested-With': 'XMLHttpRequest'
72                },
73                credentials: 'same-origin',
74                body: 'coupon_code=' + encodeURIComponent(code) + '&form_key=' + promoCodeConfig.formKey
75            })
76            .then(function(response) {
77                return response.json();
78            })
79            .then(function(data) {
80                self.isLoading = false;
81                if (data.success) {
82                    // Show success state
83                    self.appliedCode = code.toUpperCase();
84                    self.success = true;
85                    self.successMessage = 'Promo code applied!';
86                    self.discount = data.discount || '';
87
88                    // Refresh cart to show updated totals
89                    if (Alpine.store('cart')) {
90                        Alpine.store('cart').refresh();
91                    }
92                    // Notify the full cart page component to reload its data
93                    window.dispatchEvent(new CustomEvent('cart-updated'));
94                } else {
95                    self.error = data.error || 'Invalid promo code';
96                }
97            })
98            .catch(function(error) {
99                self.isLoading = false;
100                self.error = 'An error occurred. Please try again.';
101                console.error('Promo code error:', error);
102            });
103        },
104
105        remove: function() {
106            var self = this;
107            this.isLoading = true;
108
109            fetch(promoCodeConfig.removeCouponUrl, {
110                method: 'POST',
111                headers: {
112                    'Content-Type': 'application/x-www-form-urlencoded',
113                    'X-Requested-With': 'XMLHttpRequest'
114                },
115                credentials: 'same-origin',
116                body: 'form_key=' + promoCodeConfig.formKey
117            })
118            .then(function(response) {
119                return response.json();
120            })
121            .then(function(data) {
122                self.isLoading = false;
123                if (data.success) {
124                    self.appliedCode = null;
125                    // Refresh cart to show updated totals
126                    if (Alpine.store('cart')) {
127                        Alpine.store('cart').refresh();
128                    }
129                    // Notify the full cart page component to reload its data
130                    window.dispatchEvent(new CustomEvent('cart-updated'));
131                }
132            })
133            .catch(function(error) {
134                self.isLoading = false;
135                console.error('Remove coupon error:', error);
136            });
137        },
138
139        // Set applied code from cart data (called when cart refreshes)
140        setAppliedCode: function(code) {
141            this.appliedCode = code ? code.toUpperCase() : null;
142        }
143    });
144});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.