ultimate-jekyll-manager 0.0.97 → 0.0.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +42 -0
- package/README.md +66 -0
- package/_backup/checkout copy 2.html +392 -0
- package/_backup/checkout copy 3.html +376 -0
- package/_backup/checkout copy 4.html +365 -0
- package/_backup/checkout copy.html +331 -0
- package/_backup/checkout-semi.html +331 -0
- package/dist/assets/css/core/bindings.scss +7 -2
- package/dist/assets/css/core/utilities.scss +8 -2
- package/dist/assets/css/pages/payment/checkout/index.scss +52 -7
- package/dist/assets/js/core/complete.js +56 -0
- package/dist/assets/js/core/initialize.js +11 -0
- package/dist/assets/js/pages/app/index.js +72 -17
- package/dist/assets/js/pages/download/index.js +0 -6
- package/dist/assets/js/pages/payment/checkout/index.js +58 -52
- package/dist/assets/js/pages/payment/checkout/modules/discount-bindings.js +51 -0
- package/dist/assets/js/pages/payment/checkout/modules/pricing.js +55 -30
- package/dist/assets/js/pages/payment/checkout/modules/state.js +68 -14
- package/dist/assets/js/pages/payment/checkout/modules/ui-bindings.js +160 -0
- package/dist/assets/js/pages/payment/checkout/modules/ui.js +27 -42
- package/dist/assets/js/pages/payment/confirmation/index.js +58 -53
- package/dist/assets/js/pages/payment/confirmation/modules/bindings.js +28 -0
- package/dist/assets/js/pages/payment/confirmation/modules/state.js +19 -0
- package/dist/assets/js/ultimate-jekyll-manager.js +6 -2
- package/dist/assets/themes/classy/css/base/_spacing.scss +27 -0
- package/dist/defaults/dist/_includes/core/body.html +31 -0
- package/dist/defaults/dist/_includes/core/foot.html +35 -0
- package/dist/defaults/dist/_layouts/blueprint/payment/checkout.html +6 -1
- package/dist/defaults/dist/_layouts/blueprint/payment/confirmation.html +6 -1
- package/dist/defaults/dist/_layouts/core/root.html +1 -0
- package/dist/defaults/dist/_layouts/modules/utilities/redirect.html +43 -32
- package/dist/defaults/dist/_layouts/themes/classy/backend/core/base.html +0 -35
- package/dist/defaults/dist/_layouts/themes/classy/frontend/core/base.html +0 -34
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/404.html +35 -44
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/account/index.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/app.html +3 -3
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/oauth2.html +37 -37
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/reset.html +45 -45
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +2 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +58 -58
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/download.html +1 -4
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/checkout.html +291 -240
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/confirmation.html +43 -47
- package/dist/defaults/dist/pages/test/libraries/cover.html +1 -1
- package/firebase-debug.log +380 -0
- package/package.json +1 -1
- package/dist/assets/js/core/init.js +0 -36
package/CLAUDE.md
CHANGED
|
@@ -63,6 +63,48 @@ When creating pages in the consuming project, follow these guidelines:
|
|
|
63
63
|
DO NOT USE `bg-light`, `bg-dark`, `text-light`, or `text-dark`. We support BOTH light and dark mode, so instead use `bg-body`, `bg-body-secondary`, `bg-body-tertiary`, `text-body` and for buttons you can use `btn-adaptive` or `btn-outline-adaptive`.
|
|
64
64
|
These classes adapt to light and dark mode automatically.
|
|
65
65
|
|
|
66
|
+
## Page Loading State & Button Protection
|
|
67
|
+
Ultimate Jekyll implements a sophisticated system to prevent premature button clicks during page initialization. This prevents race conditions and ensures JavaScript is fully loaded before users can trigger actions.
|
|
68
|
+
|
|
69
|
+
### How It Works:
|
|
70
|
+
1. **Initial State**: The HTML element starts with `data-page-loading="true"` and `aria-busy="true"` attributes (set in `src/defaults/dist/_layouts/core/root.html`)
|
|
71
|
+
2. **Protection During Load**: While `data-page-loading` is present, certain elements are automatically disabled via CSS and JavaScript
|
|
72
|
+
3. **Ready State**: When JavaScript initialization completes, these attributes are removed by `src/assets/js/core/complete.js`
|
|
73
|
+
|
|
74
|
+
### What Gets Protected:
|
|
75
|
+
When `data-page-loading` is active, the following elements are automatically protected from clicks:
|
|
76
|
+
|
|
77
|
+
- **All form buttons**: `<button>`, `<input type="submit">`, `<input type="button">`, `<input type="reset">`
|
|
78
|
+
- **Elements with `.btn` class**: Standard Bootstrap buttons
|
|
79
|
+
- **Elements with `.btn-action` class**: Custom action triggers (see below)
|
|
80
|
+
- **Always disabled**: Any element with `disabled` attribute, `.disabled` class, or `:disabled` state
|
|
81
|
+
|
|
82
|
+
### The `.btn-action` Class:
|
|
83
|
+
Use the `.btn-action` class to selectively protect non-standard elements that trigger important actions:
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<!-- These will be protected during page load -->
|
|
87
|
+
<a href="/api/delete" class="custom-link btn-action">Delete Item</a>
|
|
88
|
+
<div class="card-action btn-action" onclick="processData()">Process</div>
|
|
89
|
+
<span class="text-link btn-action" data-action="save">Save Changes</span>
|
|
90
|
+
|
|
91
|
+
<!-- These will NOT be protected (regular navigation/UI) -->
|
|
92
|
+
<a href="/about" class="btn btn-primary">About Us</a>
|
|
93
|
+
<button data-bs-toggle="modal">Show Info</button>
|
|
94
|
+
<button data-bs-toggle="collapse">Toggle Details</button>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### When to Use `.btn-action`:
|
|
98
|
+
- **Use it for**: API calls, form submissions, data modifications, payment processing, destructive actions
|
|
99
|
+
- **Don't use it for**: Navigation links, UI toggles, modals, accordions, tabs, harmless interactions
|
|
100
|
+
|
|
101
|
+
### Implementation Files:
|
|
102
|
+
- **CSS Styles**: `src/assets/css/core/utilities.scss` - Applies `cursor: not-allowed` and disabled styling
|
|
103
|
+
- **Click Prevention**: `src/defaults/dist/_includes/core/body.html` - Inline script that prevents clicks
|
|
104
|
+
- **State Removal**: `src/assets/js/core/complete.js` - Removes `data-page-loading` when ready
|
|
105
|
+
|
|
106
|
+
This system ensures a smooth, error-free user experience by preventing premature interactions while maintaining full flexibility for developers.
|
|
107
|
+
|
|
66
108
|
## Lazy Loading
|
|
67
109
|
Ultimate Jekyll uses a custom lazy loading system powered by web-manager. Elements can be lazy-loaded using the `data-lazy` attribute with the following format:
|
|
68
110
|
|
package/README.md
CHANGED
|
@@ -196,6 +196,72 @@ member:
|
|
|
196
196
|
`uj-language-dropdown`:
|
|
197
197
|
`uj-language-dropdown-item`
|
|
198
198
|
|
|
199
|
+
### Utility Classes
|
|
200
|
+
|
|
201
|
+
#### Max-Width Utilities
|
|
202
|
+
Ultimate Jekyll includes max-width utility classes based on Bootstrap's breakpoint sizes. These classes constrain an element's maximum width to match Bootstrap's standard responsive breakpoints:
|
|
203
|
+
|
|
204
|
+
- `.mw-sm` - Sets max-width to 576px
|
|
205
|
+
- `.mw-md` - Sets max-width to 768px
|
|
206
|
+
- `.mw-lg` - Sets max-width to 992px
|
|
207
|
+
- `.mw-xl` - Sets max-width to 1200px
|
|
208
|
+
- `.mw-xxl` - Sets max-width to 1400px
|
|
209
|
+
|
|
210
|
+
**Usage Examples:**
|
|
211
|
+
```html
|
|
212
|
+
<!-- Constrain a form to medium width -->
|
|
213
|
+
<form class="mw-md">
|
|
214
|
+
<!-- Form content stays readable at max 768px wide -->
|
|
215
|
+
</form>
|
|
216
|
+
|
|
217
|
+
<!-- Limit content width for better readability -->
|
|
218
|
+
<div class="container mw-lg">
|
|
219
|
+
<!-- Content won't exceed 992px even on larger screens -->
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<!-- Combine with margin utilities for centering -->
|
|
223
|
+
<div class="mw-sm mx-auto">
|
|
224
|
+
<!-- Content is max 576px wide and centered -->
|
|
225
|
+
</div>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
These utilities are particularly useful for:
|
|
229
|
+
- Improving readability by preventing text from spanning too wide
|
|
230
|
+
- Creating consistent content widths across different sections
|
|
231
|
+
- Constraining forms, cards, and modals to reasonable sizes
|
|
232
|
+
- Maintaining design consistency with Bootstrap's grid system
|
|
233
|
+
|
|
234
|
+
### Page Loading Protection System
|
|
235
|
+
|
|
236
|
+
Ultimate Jekyll includes an automatic protection system that prevents users from clicking buttons before JavaScript is fully loaded, eliminating race conditions and errors.
|
|
237
|
+
|
|
238
|
+
#### How It Works
|
|
239
|
+
1. Pages start with `data-page-loading="true"` on the HTML element
|
|
240
|
+
2. Certain buttons are automatically protected from clicks during this state
|
|
241
|
+
3. When JavaScript finishes loading, the attribute is removed and buttons become clickable
|
|
242
|
+
|
|
243
|
+
#### Protected Elements
|
|
244
|
+
During page load, these elements are automatically protected:
|
|
245
|
+
- All form buttons (`<button>`, `<input type="submit">`, etc.)
|
|
246
|
+
- Elements with `.btn` class (Bootstrap buttons)
|
|
247
|
+
- Elements with `.btn-action` class (custom action triggers)
|
|
248
|
+
|
|
249
|
+
#### Using `.btn-action` Class
|
|
250
|
+
Add the `.btn-action` class to protect custom elements that trigger important actions:
|
|
251
|
+
|
|
252
|
+
```html
|
|
253
|
+
<!-- These will be protected during page load -->
|
|
254
|
+
<a href="/api/delete" class="custom-link btn-action">Delete Item</a>
|
|
255
|
+
<div onclick="saveData()" class="btn-action">Save</div>
|
|
256
|
+
|
|
257
|
+
<!-- Regular navigation links are NOT protected -->
|
|
258
|
+
<a href="/about">About Us</a>
|
|
259
|
+
<button data-bs-toggle="modal">Show Modal</button>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Use `.btn-action` for:** API calls, form submissions, data modifications, payments, destructive actions
|
|
263
|
+
**Don't use for:** Navigation, UI toggles, modals, accordions, harmless interactions
|
|
264
|
+
|
|
199
265
|
### Special Query Parameters
|
|
200
266
|
|
|
201
267
|
#### Authentication
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
---
|
|
2
|
+
### ALL PAGES ###
|
|
3
|
+
layout: themes/[ site.theme.id ]/frontend/core/cover
|
|
4
|
+
|
|
5
|
+
### THEME CONFIG ###
|
|
6
|
+
theme:
|
|
7
|
+
main:
|
|
8
|
+
align: "start"
|
|
9
|
+
|
|
10
|
+
### WEB MANAGER CONFIG ###
|
|
11
|
+
web_manager:
|
|
12
|
+
auth:
|
|
13
|
+
config:
|
|
14
|
+
policy: "authenticated"
|
|
15
|
+
|
|
16
|
+
### PAGE CONFIG ###
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<!-- Fullscreen Preloader -->
|
|
20
|
+
<div id="checkout-preloader" class="position-fixed top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center bg-body" style="z-index: 9999;">
|
|
21
|
+
<div class="text-center">
|
|
22
|
+
<div class="spinner-border spinner-border-lg text-primary mb-3" role="status">
|
|
23
|
+
<span class="visually-hidden">Loading...</span>
|
|
24
|
+
</div>
|
|
25
|
+
<h5 class="text-muted">Loading secure checkout...</h5>
|
|
26
|
+
<p class="text-muted small mb-0">Please be patient while your order is prepared.</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<!-- Error Message Container -->
|
|
31
|
+
<div id="checkout-error-container" class="d-none">
|
|
32
|
+
<div class="row justify-content-center">
|
|
33
|
+
<div class="col-lg-8">
|
|
34
|
+
<div class="alert alert-danger" role="alert">
|
|
35
|
+
<h4 class="alert-heading">Oops! Something went wrong</h4>
|
|
36
|
+
<p id="checkout-error-message"></p>
|
|
37
|
+
<hr>
|
|
38
|
+
<button class="btn btn-outline-danger" onclick="window.location.reload()">
|
|
39
|
+
Try again
|
|
40
|
+
</button>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<!-- Checkout Section -->
|
|
47
|
+
<section id="checkout-content" class="col-12 col-xl-10 mw-xl">
|
|
48
|
+
<div class="row mb-4">
|
|
49
|
+
<div class="col-12">
|
|
50
|
+
<h1 class="h2 mb-0 text-center text-lg-start">Checkout</h1>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="card border-0 shadow-lg">
|
|
54
|
+
<div class="card-body p-3 p-md-5">
|
|
55
|
+
<!-- Title Row -->
|
|
56
|
+
<!-- <div class="row mb-4">
|
|
57
|
+
<div class="col-12">
|
|
58
|
+
<h1 class="h2 mb-0 text-center text-lg-start">Checkout</h1>
|
|
59
|
+
</div>
|
|
60
|
+
</div> -->
|
|
61
|
+
|
|
62
|
+
<!-- Main Checkout Form -->
|
|
63
|
+
<form id="checkout-form" autocomplete="on" novalidate>
|
|
64
|
+
<!-- Content Row -->
|
|
65
|
+
<div class="row">
|
|
66
|
+
<!-- Section 1: Billing Cycle & Customer Info -->
|
|
67
|
+
<div class="col-12 col-lg-7 mb-4 order-1">
|
|
68
|
+
<!-- Billing Cycle Selection -->
|
|
69
|
+
<div class="_card _border-1 _border-secondary _shadow-sm mb-4">
|
|
70
|
+
<div class="card-body">
|
|
71
|
+
<h3 class="h5 fw-bold mb-3">Billing Cycle</h3>
|
|
72
|
+
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
73
|
+
<h6 class="fw-bold mb-0">
|
|
74
|
+
<span id="selected-plan-name">Loading...</span> Plan
|
|
75
|
+
</h6>
|
|
76
|
+
<a href="/pricing" class="small text-decoration-none">
|
|
77
|
+
{% uj_icon "arrow-left", "me-1" %}
|
|
78
|
+
Change plan
|
|
79
|
+
</a>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<!-- Subscription Toggle (hidden by default) -->
|
|
83
|
+
<div id="subscription-toggle" class="d-none">
|
|
84
|
+
<div class="row g-3">
|
|
85
|
+
<div class="col-6">
|
|
86
|
+
<input type="radio" class="btn-check" name="billing-cycle" id="annually" value="annually">
|
|
87
|
+
<label class="btn btn-outline-secondary text-body w-100 p-3 position-relative border-2 rounded-3 _animation-hover-up" for="annually">
|
|
88
|
+
<span id="savings-badge" class="position-absolute top-0 start-50 translate-middle badge rounded-pill bg-primary px-3 py-2">Save --</span>
|
|
89
|
+
<div class="d-flex align-items-center justify-content-center mb-2">
|
|
90
|
+
<span class="bg-secondary bg-opacity-25 text-secondary rounded-circle d-inline-flex align-items-center justify-content-center">
|
|
91
|
+
{% uj_icon "check", "fa-md p-1" %}
|
|
92
|
+
</span>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="fs-4 mb-1">
|
|
95
|
+
<span id="annually-price-lg">$--</span>
|
|
96
|
+
<span class="text-muted fs-6 fw-normal">/mo</span>
|
|
97
|
+
</div>
|
|
98
|
+
<div class="text-muted small">Annual Plan</div>
|
|
99
|
+
</label>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="col-6">
|
|
102
|
+
<input type="radio" class="btn-check" name="billing-cycle" id="monthly" value="monthly">
|
|
103
|
+
<label class="btn btn-outline-secondary text-body w-100 p-3 border-2 rounded-3 _animation-hover-up" for="monthly">
|
|
104
|
+
<div class="d-flex align-items-center justify-content-center mb-2">
|
|
105
|
+
<span class="bg-secondary bg-opacity-25 text-secondary rounded-circle d-inline-flex align-items-center justify-content-center">
|
|
106
|
+
{% uj_icon "check", "fa-md p-1" %}
|
|
107
|
+
</span>
|
|
108
|
+
</div>
|
|
109
|
+
<div class="fs-4 mb-1">
|
|
110
|
+
<span id="monthly-price-lg">$--</span>
|
|
111
|
+
<span class="text-muted fs-6 fw-normal">/mo</span>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="text-muted small">Monthly Plan</div>
|
|
114
|
+
</label>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<!-- Payment text under the boxes -->
|
|
119
|
+
<div class="text-muted small text-center mt-2">
|
|
120
|
+
* Pay <span class="mb-0" id="billing-cycle-payment-text">$-- monthly</span>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<!-- Free Trial Badge -->
|
|
124
|
+
<div id="trial-badge" class="alert alert-success mt-3 mb-0 p-2 d-none">
|
|
125
|
+
<small class="d-flex align-items-center mb-0">
|
|
126
|
+
{% uj_icon "gift", "me-2" %}
|
|
127
|
+
<span id="trial-message"></span>
|
|
128
|
+
</small>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<hr>
|
|
135
|
+
|
|
136
|
+
<!-- Customer Information Card -->
|
|
137
|
+
<div class="_card _border-1 _border-secondary _shadow-sm mb-3">
|
|
138
|
+
<div class="card-body">
|
|
139
|
+
<h3 class="h5 fw-bold mb-3">Customer Information</h3>
|
|
140
|
+
|
|
141
|
+
<div class="text-start">
|
|
142
|
+
Managing order for <strong data-wm-bind="@text auth.user.email"></strong>, <a href="#" id="switch-account">switch account</a>.
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<!-- Customer form fields will go here when needed -->
|
|
146
|
+
<div id="customer-fields" class="text-start">
|
|
147
|
+
<!-- Future form fields like shipping address, VAT number, etc. -->
|
|
148
|
+
<!-- <div class="mb-3">
|
|
149
|
+
<label for="customer-name" class="form-label fw-semibold">
|
|
150
|
+
Name <span class="text-danger">*</span>
|
|
151
|
+
</label>
|
|
152
|
+
<input type="text" class="form-control form-control-md" id="customer-name" name="customer_name" placeholder="Enter your full name" autocomplete="name" required>
|
|
153
|
+
</div> -->
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<!-- Divider between Customer Info and Payment Method -->
|
|
159
|
+
<hr>
|
|
160
|
+
|
|
161
|
+
<!-- Payment Method Card (Desktop position - in same column) -->
|
|
162
|
+
<div class="_card _border-1 _border-secondary _shadow-sm mb-0 d-none d-lg-block">
|
|
163
|
+
<div class="card-body">
|
|
164
|
+
<h3 class="h5 fw-bold mb-3">Payment Method</h3>
|
|
165
|
+
|
|
166
|
+
<!-- Direct Payment Buttons -->
|
|
167
|
+
<div class="d-grid gap-3">
|
|
168
|
+
<!-- Credit/Debit Card Button -->
|
|
169
|
+
<button type="submit" class="btn btn-adaptive btn-lg py-3 d-flex align-items-center justify-content-center" id="pay-with-card" data-payment-method="card" data-action="pay-card">
|
|
170
|
+
{% uj_icon "credit-card", "me-2 fa-3xl" %}
|
|
171
|
+
<span class="fw-semibold">Credit/Debit</span>
|
|
172
|
+
</button>
|
|
173
|
+
|
|
174
|
+
<!-- PayPal Button -->
|
|
175
|
+
<button type="submit" class="btn btn-paypal btn-lg py-3 d-flex align-items-center justify-content-center" id="pay-with-paypal" data-payment-method="paypal" data-action="pay-paypal">
|
|
176
|
+
<img src="https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-200px.png"
|
|
177
|
+
alt="PayPal"
|
|
178
|
+
height="28"
|
|
179
|
+
style="max-height: 28px;">
|
|
180
|
+
</button>
|
|
181
|
+
|
|
182
|
+
<!-- Apple Pay Button (shown conditionally) -->
|
|
183
|
+
<button type="submit" class="btn btn-dark btn-lg py-3 d-flex align-items-center justify-content-center d-none" id="pay-with-apple-pay" data-payment-method="apple-pay" data-action="pay-apple-pay">
|
|
184
|
+
{% uj_icon "apple", "me-2 fa-3xl" %}
|
|
185
|
+
<span class="fw-semibold">Apple Pay</span>
|
|
186
|
+
</button>
|
|
187
|
+
|
|
188
|
+
<!-- Google Pay Button (shown conditionally) -->
|
|
189
|
+
<button type="submit" class="btn btn-outline-dark btn-lg py-3 d-flex align-items-center justify-content-center d-none" id="pay-with-google-pay" data-payment-method="google-pay" data-action="pay-google-pay">
|
|
190
|
+
<img src="https://www.gstatic.com/instantbuy/svg/dark_gpay.svg"
|
|
191
|
+
alt="Google Pay"
|
|
192
|
+
height="24"
|
|
193
|
+
class="me-2">
|
|
194
|
+
<span class="fw-semibold">Google Pay</span>
|
|
195
|
+
</button>
|
|
196
|
+
|
|
197
|
+
<!-- Crypto Button -->
|
|
198
|
+
<button type="submit" class="btn btn-outline-adaptive btn-lg py-3 d-flex align-items-center justify-content-center" id="pay-with-crypto" data-payment-method="crypto" data-action="pay-crypto">
|
|
199
|
+
{% uj_icon "bitcoin", "me-2 fa-3xl" %}
|
|
200
|
+
<span class="fw-semibold">Crypto</span>
|
|
201
|
+
</button>
|
|
202
|
+
|
|
203
|
+
<p class="text-muted small text-center mb-0">
|
|
204
|
+
By purchasing, you agree to our <a href="/terms" target="_blank">Terms of Service</a> and <a href="/privacy" target="_blank">Privacy Policy</a>.
|
|
205
|
+
</p>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<!-- Security badges -->
|
|
211
|
+
<div class="text-center mt-2 d-none d-lg-block">
|
|
212
|
+
<div class="d-flex justify-content-center align-items-center gap-3 small text-muted">
|
|
213
|
+
<span>{% uj_icon "shield-check", "text-success" %} Secure Checkout</span>
|
|
214
|
+
<span>{% uj_icon "lock", "text-success" %} SSL Encrypted</span>
|
|
215
|
+
<span>{% uj_icon "check-circle", "text-success" %} Money-back guarantee</span>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<!-- Section 2: Order Summary -->
|
|
221
|
+
<div class="col-12 col-lg-5 mb-4 mb-lg-0 order-2 order-lg-2">
|
|
222
|
+
<div class="order-summary-sticky">
|
|
223
|
+
<div class="_card _border-1 _border-secondary _shadow-sm">
|
|
224
|
+
<div class="card-body">
|
|
225
|
+
<h3 class="h5 fw-bold mb-3">Order Summary</h3>
|
|
226
|
+
|
|
227
|
+
<!-- Product Item -->
|
|
228
|
+
<div class="order-item mb-4">
|
|
229
|
+
<div class="d-flex align-items-center">
|
|
230
|
+
<div class="position-relative me-3">
|
|
231
|
+
<div class="product-thumbnail bg-light rounded-3 d-flex align-items-center justify-content-center">
|
|
232
|
+
<img src="{{ site.brand.images.brandmark }}?cb={{ site.uj.cache_breaker }}" class="img-fluid p-3" alt="{{ site.brand.name }} Plan Icon"/>
|
|
233
|
+
</div>
|
|
234
|
+
<span class="position-absolute badge rounded-pill bg-primary" style="top: -0.375rem; right: -0.375rem;">
|
|
235
|
+
1
|
|
236
|
+
<span class="visually-hidden">quantity</span>
|
|
237
|
+
</span>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="flex-grow-1 text-start">
|
|
240
|
+
<h6 class="mb-1" id="product-name">Loading...</h6>
|
|
241
|
+
<p class="text-muted small mb-0" id="product-description">Loading product details...</p>
|
|
242
|
+
</div>
|
|
243
|
+
<div class="text-end d-none">
|
|
244
|
+
<div class="fw-bold" id="product-price">$--</div>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<!-- Discount Code -->
|
|
250
|
+
<div class="mb-4">
|
|
251
|
+
<div class="input-group">
|
|
252
|
+
<input type="text" class="form-control rounded-start-3 border py-2 px-3 text-start" id="discount-code" name="discount-code" placeholder="Discount code" autocomplete="off">
|
|
253
|
+
<button class="btn btn-adaptive rounded-end-3 border px-4" type="button" id="apply-discount" data-action="apply-discount">Apply</button>
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
<!-- Discount Messages -->
|
|
257
|
+
<div class="text-start">
|
|
258
|
+
<div id="discount-message-loading" class="mt-2 text-primary small d-none">
|
|
259
|
+
{% uj_icon "clock", "me-1" %} Checking code...
|
|
260
|
+
</div>
|
|
261
|
+
<div id="discount-message-success" class="mt-2 text-success small d-none">
|
|
262
|
+
{% uj_icon "check-circle", "me-1" %} <span id="confirmation-text">Discount applied</span>
|
|
263
|
+
</div>
|
|
264
|
+
<div id="discount-message-error" class="mt-2 text-danger small d-none">
|
|
265
|
+
{% uj_icon "times-circle", "me-1" %} <span id="error-text">Invalid discount code</span>
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
<!-- Price Breakdown -->
|
|
271
|
+
<div>
|
|
272
|
+
<div class="d-flex justify-content-between mb-2">
|
|
273
|
+
<span class="text-muted">Subtotal</span>
|
|
274
|
+
<span id="subtotal">$--</span>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<div class="d-flex justify-content-between mb-2 text-success d-none" id="discount-row">
|
|
278
|
+
<span>Discount (<span id="discount-percent"></span>)</span>
|
|
279
|
+
<span>-$<span id="discount-amount"></span></span>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<div class="d-flex justify-content-between mb-3 text-success d-none" id="trial-discount-row">
|
|
283
|
+
<span>Free Trial Discount</span>
|
|
284
|
+
<span>-$<span id="trial-discount-amount"></span></span>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
288
|
+
<span class="fw-bold fs-5">Total Due Today</span>
|
|
289
|
+
<span class="fw-bold fs-4" id="total-price">$--</span>
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
<hr class="my-3">
|
|
293
|
+
|
|
294
|
+
<div class="d-flex justify-content-between align-items-center text-muted">
|
|
295
|
+
<span>Recurring</span>
|
|
296
|
+
<span id="recurring-amount">$-- <span id="recurring-period">monthly</span></span>
|
|
297
|
+
</div>
|
|
298
|
+
|
|
299
|
+
<!-- Subscription Terms -->
|
|
300
|
+
<div id="subscription-terms" class="mt-3 rounded-3 small text-body-tertiary d-none text-start">
|
|
301
|
+
<span id="terms-text"></span>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
|
|
307
|
+
<!-- Trust Badges -->
|
|
308
|
+
<div class="text-center mt-2">
|
|
309
|
+
<div class="d-flex justify-content-center align-items-center gap-3 text-muted">
|
|
310
|
+
<a href="javascript:;" class="text-decoration-none btn-link" id="checkout-help-button">
|
|
311
|
+
{% uj_icon "messages-question", "text-primary" %} Need help? Chat with us now!
|
|
312
|
+
</a>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
<!-- Section 3: Payment Method (Mobile only) -->
|
|
319
|
+
<div class="col-12 mb-4 order-3 d-lg-none">
|
|
320
|
+
<!-- Payment Method Card (Mobile position) -->
|
|
321
|
+
<div class="_card _border-1 _border-secondary _shadow-sm mb-0">
|
|
322
|
+
<div class="card-body">
|
|
323
|
+
<h3 class="h5 fw-bold mb-3">Payment Method</h3>
|
|
324
|
+
|
|
325
|
+
<!-- Direct Payment Buttons -->
|
|
326
|
+
<div class="d-grid gap-3">
|
|
327
|
+
<!-- Credit/Debit Card Button -->
|
|
328
|
+
<button type="submit" class="btn btn-adaptive btn-lg py-3 d-flex align-items-center justify-content-center" id="pay-with-card" data-payment-method="card" data-action="pay-card">
|
|
329
|
+
{% uj_icon "credit-card", "me-2 fa-3xl" %}
|
|
330
|
+
<span class="fw-semibold">Credit/Debit</span>
|
|
331
|
+
</button>
|
|
332
|
+
|
|
333
|
+
<!-- PayPal Button -->
|
|
334
|
+
<button type="submit" class="btn btn-paypal btn-lg py-3 d-flex align-items-center justify-content-center" id="pay-with-paypal" data-payment-method="paypal" data-action="pay-paypal">
|
|
335
|
+
<img src="https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-200px.png"
|
|
336
|
+
alt="PayPal"
|
|
337
|
+
height="28"
|
|
338
|
+
style="max-height: 28px;">
|
|
339
|
+
</button>
|
|
340
|
+
|
|
341
|
+
<!-- Apple Pay Button (shown conditionally) -->
|
|
342
|
+
<button type="submit" class="btn btn-dark btn-lg py-3 d-flex align-items-center justify-content-center d-none" id="pay-with-apple-pay" data-payment-method="apple-pay" data-action="pay-apple-pay">
|
|
343
|
+
{% uj_icon "apple", "me-2 fa-3xl" %}
|
|
344
|
+
<span class="fw-semibold">Apple Pay</span>
|
|
345
|
+
</button>
|
|
346
|
+
|
|
347
|
+
<!-- Google Pay Button (shown conditionally) -->
|
|
348
|
+
<button type="submit" class="btn btn-outline-dark btn-lg py-3 d-flex align-items-center justify-content-center d-none" id="pay-with-google-pay" data-payment-method="google-pay" data-action="pay-google-pay">
|
|
349
|
+
<img src="https://www.gstatic.com/instantbuy/svg/dark_gpay.svg"
|
|
350
|
+
alt="Google Pay"
|
|
351
|
+
height="24"
|
|
352
|
+
class="me-2">
|
|
353
|
+
<span class="fw-semibold">Google Pay</span>
|
|
354
|
+
</button>
|
|
355
|
+
|
|
356
|
+
<!-- Crypto Button -->
|
|
357
|
+
<button type="submit" class="btn btn-outline-adaptive btn-lg py-3 d-flex align-items-center justify-content-center" id="pay-with-crypto" data-payment-method="crypto" data-action="pay-crypto">
|
|
358
|
+
{% uj_icon "bitcoin", "me-2 fa-3xl" %}
|
|
359
|
+
<span class="fw-semibold">Crypto</span>
|
|
360
|
+
</button>
|
|
361
|
+
|
|
362
|
+
<!-- Divider -->
|
|
363
|
+
<!-- <div class="d-flex align-items-center my-2">
|
|
364
|
+
<hr class="flex-grow-1">
|
|
365
|
+
<span class="text-muted small px-3">or pay with cryptocurrency</span>
|
|
366
|
+
<hr class="flex-grow-1">
|
|
367
|
+
</div> -->
|
|
368
|
+
|
|
369
|
+
<p class="text-muted small text-center mb-0">
|
|
370
|
+
By purchasing, you agree to our <a href="/terms" target="_blank">Terms of Service</a> and <a href="/privacy" target="_blank">Privacy Policy</a>.
|
|
371
|
+
</p>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
|
|
376
|
+
<!-- Security badges (Mobile) -->
|
|
377
|
+
<div class="text-center mt-2 d-lg-none">
|
|
378
|
+
<div class="d-flex justify-content-center align-items-center gap-3 small text-muted">
|
|
379
|
+
<span>{% uj_icon "shield-check", "text-success" %} Secure Checkout</span>
|
|
380
|
+
<span>{% uj_icon "lock", "text-success" %} SSL Encrypted</span>
|
|
381
|
+
<span>{% uj_icon "check-circle", "text-success" %} Money-back guarantee</span>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
|
|
386
|
+
</div>
|
|
387
|
+
</form>
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
</section>
|
|
391
|
+
|
|
392
|
+
{{ content | uj_content_format }}
|