ultimate-jekyll-manager 0.0.96 → 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/.playwright-mcp/page-2025-10-22T19-11-27-666Z.png +0 -0
- package/.playwright-mcp/page-2025-10-22T19-11-57-357Z.png +0 -0
- 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/_backup/cover-old.html +55 -0
- package/dist/assets/css/core/bindings.scss +7 -2
- package/dist/assets/css/core/utilities.scss +9 -1
- 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 +82 -43
- 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/{redirects/authentication/helpers/well-known-change-password.html → .well-known/change-password.html} +4 -1
- package/dist/defaults/dist/.well-known/security.txt +15 -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/app.html +1 -1
- 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 +42 -31
- 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/core/cover.html +6 -9
- 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 +83 -0
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/oauth2.html +42 -44
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/reset.html +57 -59
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +67 -69
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +76 -78
- 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/humans.txt +25 -0
- package/dist/defaults/dist/opensearch.xml +26 -0
- package/dist/defaults/dist/pages/test/account/dashboard.html +3 -0
- package/dist/defaults/dist/pages/test/index.md +2 -2
- package/dist/defaults/dist/pages/test/libraries/ads.html +3 -0
- package/dist/defaults/dist/pages/test/libraries/bootstrap-components.html +11 -2
- package/dist/defaults/dist/pages/test/libraries/cover.html +47 -0
- package/dist/defaults/dist/pages/test/libraries/error.html +3 -0
- package/dist/defaults/dist/pages/test/libraries/lazy-loading.html +3 -0
- package/dist/defaults/dist/pages/test/redirect/external.md +3 -0
- package/dist/defaults/dist/pages/test/redirect/internal.md +3 -0
- package/dist/defaults/dist/pages/test/translation/index.md +2 -2
- package/dist/defaults/dist/redirects/authentication/helpers/change-password.html +1 -1
- package/dist/defaults/dist/redirects/authentication/helpers/forgot.html +1 -1
- package/dist/defaults/dist/redirects/authentication/helpers/recover.html +1 -1
- package/dist/defaults/dist/redirects/authentication/helpers/reset-password.html +1 -1
- package/dist/defaults/dist/sitemap.html +112 -28
- package/dist/defaults/dist/sitemap.xml +6 -1
- package/firebase-debug.log +388 -0
- package/package.json +1 -1
- package/dist/assets/js/core/init.js +0 -36
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
### FULLSCREEN LAYOUT ###
|
|
3
|
+
layout: themes/[ site.theme.id ]/frontend/core/base
|
|
4
|
+
|
|
5
|
+
### FULLSCREEN PAGES ###
|
|
6
|
+
theme:
|
|
7
|
+
nav:
|
|
8
|
+
enabled: false
|
|
9
|
+
main:
|
|
10
|
+
class: "d-flex align-items-{{ page.resolved.theme.main.align | default: 'center' }} justify-content-center_ pt-0"
|
|
11
|
+
footer:
|
|
12
|
+
enabled: false
|
|
13
|
+
### CORE CONFIG ###
|
|
14
|
+
# core:
|
|
15
|
+
# cover:
|
|
16
|
+
# class: "align-top" # USED TO HAVE {{ page.resolved.theme.core.cover.class }} IN THE TOP LEVEL CLASS WITH w-100
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<!-- Critical inline CSS to prevent FOUC on cover pages -->
|
|
20
|
+
<style>
|
|
21
|
+
main.d-flex {
|
|
22
|
+
display: flex !important;
|
|
23
|
+
min-height: calc(100vh);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
main.d-flex.align-items-center {
|
|
27
|
+
align-items: center !important;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
main.d-flex.justify-content-center {
|
|
31
|
+
justify-content: center !important;
|
|
32
|
+
}
|
|
33
|
+
</style>
|
|
34
|
+
|
|
35
|
+
<!-- <div class="w-100">
|
|
36
|
+
<div class="row justify-content-center">
|
|
37
|
+
<div class="col-12 text-center">
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div> -->
|
|
41
|
+
|
|
42
|
+
<!-- <div class="w-100">
|
|
43
|
+
<div class="row justify-content-center">
|
|
44
|
+
<div class="col-12 text-center px-0">
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div> -->
|
|
48
|
+
|
|
49
|
+
<div class="w-100">
|
|
50
|
+
<div class="d-flex justify-content-center">
|
|
51
|
+
{{ content | uj_content_format }}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
|
|
@@ -24,6 +24,11 @@
|
|
|
24
24
|
|
|
25
25
|
// Subtle color overlay for text elements
|
|
26
26
|
color: transparent !important;
|
|
27
|
+
* {
|
|
28
|
+
// color: transparent !important;
|
|
29
|
+
// z-index: -1 !important;
|
|
30
|
+
opacity: 0 !important;
|
|
31
|
+
}
|
|
27
32
|
|
|
28
33
|
// Prevent text selection during loading
|
|
29
34
|
user-select: none;
|
|
@@ -31,8 +36,8 @@
|
|
|
31
36
|
|
|
32
37
|
// Minimum dimensions for empty elements
|
|
33
38
|
min-width: 50px;
|
|
34
|
-
min-height:
|
|
35
|
-
display: inline-block;
|
|
39
|
+
min-height: 1lh;
|
|
40
|
+
// display: inline-block;
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
// Dark theme overrides
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
.disabled,
|
|
14
14
|
[disabled],
|
|
15
|
-
:disabled
|
|
15
|
+
:disabled,
|
|
16
|
+
[data-page-loading] button.btn,
|
|
17
|
+
[data-page-loading] .btn-action {
|
|
16
18
|
cursor: not-allowed !important;
|
|
17
19
|
pointer-events: all !important;
|
|
18
20
|
|
|
@@ -23,6 +25,12 @@
|
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
[data-page-loading] button.btn,
|
|
29
|
+
[data-page-loading] .btn-action {
|
|
30
|
+
opacity: var(--bs-btn-disabled-opacity);
|
|
31
|
+
color: var(--bs-btn-disabled-color);
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
// Prevent pointer events on all children inside buttons and links
|
|
27
35
|
// This helps fix event bubbling issues for click listeners
|
|
28
36
|
button *, a * {
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
// Checkout Page Styles
|
|
1
|
+
// Checkout Page Styles
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// ============================================
|
|
4
|
+
// Order Summary Sticky Positioning
|
|
5
|
+
// ============================================
|
|
4
6
|
.order-summary-sticky {
|
|
5
7
|
position: sticky;
|
|
6
8
|
top: 2rem;
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
//
|
|
11
|
+
// ============================================
|
|
12
|
+
// Product Thumbnail
|
|
13
|
+
// ============================================
|
|
10
14
|
.product-thumbnail {
|
|
11
15
|
width: 60px;
|
|
12
16
|
height: 60px;
|
|
17
|
+
min-width: 60px;
|
|
18
|
+
min-height: 60px;
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
// Save badge positioning adjustment
|
|
@@ -62,8 +68,47 @@
|
|
|
62
68
|
#pay-with-paypal img {
|
|
63
69
|
filter: brightness(0.9);
|
|
64
70
|
}
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
71
|
+
|
|
72
|
+
// ============================================
|
|
73
|
+
// Loading States Enhancement for Bindings
|
|
74
|
+
// ============================================
|
|
75
|
+
// Smooth transitions when bindings update
|
|
76
|
+
// [data-wm-bind] {
|
|
77
|
+
// transition: opacity 0.3s ease-in-out;
|
|
78
|
+
// }
|
|
79
|
+
|
|
80
|
+
// Animation for elements appearing via bindings
|
|
81
|
+
// [data-wm-bind*="@show"]:not([hidden]) {
|
|
82
|
+
// animation: fadeIn 0.3s ease-in-out;
|
|
83
|
+
// }
|
|
84
|
+
|
|
85
|
+
// @keyframes fadeIn {
|
|
86
|
+
// from {
|
|
87
|
+
// opacity: 0;
|
|
88
|
+
// transform: translateY(-5px);
|
|
89
|
+
// }
|
|
90
|
+
// to {
|
|
91
|
+
// opacity: 1;
|
|
92
|
+
// transform: translateY(0);
|
|
93
|
+
// }
|
|
94
|
+
// }
|
|
95
|
+
|
|
96
|
+
// ============================================
|
|
97
|
+
// Discount Messages Animation
|
|
98
|
+
// ============================================
|
|
99
|
+
// [data-wm-bind*="checkout.discount"] {
|
|
100
|
+
// &:not([hidden]) {
|
|
101
|
+
// animation: slideDown 0.2s ease-out;
|
|
102
|
+
// }
|
|
103
|
+
// }
|
|
104
|
+
|
|
105
|
+
// @keyframes slideDown {
|
|
106
|
+
// from {
|
|
107
|
+
// opacity: 0;
|
|
108
|
+
// max-height: 0;
|
|
109
|
+
// }
|
|
110
|
+
// to {
|
|
111
|
+
// opacity: 1;
|
|
112
|
+
// max-height: 50px;
|
|
113
|
+
// }
|
|
69
114
|
// }
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Page Loader Module - Handles page loading state indicator
|
|
2
|
+
export default function (Manager, options) {
|
|
3
|
+
// Shortcuts
|
|
4
|
+
const { webManager } = Manager;
|
|
5
|
+
let removed = false;
|
|
6
|
+
|
|
7
|
+
// Log
|
|
8
|
+
console.log('Running complete()');
|
|
9
|
+
|
|
10
|
+
// Remove page loading state indicator
|
|
11
|
+
const removeLoadingState = (source) => {
|
|
12
|
+
// Check if already removed
|
|
13
|
+
if (removed) return;
|
|
14
|
+
removed = true;
|
|
15
|
+
|
|
16
|
+
// Log
|
|
17
|
+
console.log(`Removing page loading state (source: ${source})`);
|
|
18
|
+
|
|
19
|
+
// Use requestAnimationFrame for smooth transition
|
|
20
|
+
requestAnimationFrame(() => {
|
|
21
|
+
document.documentElement.removeAttribute('data-page-loading');
|
|
22
|
+
document.documentElement.setAttribute('aria-busy', 'false');
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Check document ready state
|
|
27
|
+
console.log('Document readyState:', document.readyState);
|
|
28
|
+
|
|
29
|
+
// For interactive state, we need to wait a bit for resources
|
|
30
|
+
// Since window.load is unreliable with async scripts, use a hybrid approach
|
|
31
|
+
|
|
32
|
+
// Immediately remove if already complete
|
|
33
|
+
if (document.readyState === 'complete') {
|
|
34
|
+
removeLoadingState('Complete');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Strategy 1: Try window load event (might not fire)
|
|
39
|
+
window.addEventListener('load', () => {
|
|
40
|
+
removeLoadingState('Load');
|
|
41
|
+
}, { once: true });
|
|
42
|
+
|
|
43
|
+
// Strategy 2: Poll for complete state
|
|
44
|
+
const pollInterval = setInterval(() => {
|
|
45
|
+
if (document.readyState === 'complete') {
|
|
46
|
+
clearInterval(pollInterval);
|
|
47
|
+
removeLoadingState('Polling');
|
|
48
|
+
}
|
|
49
|
+
}, 50);
|
|
50
|
+
|
|
51
|
+
// Strategy 3: Timeout fallback (max 3 seconds)
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
clearInterval(pollInterval);
|
|
54
|
+
removeLoadingState('Timeout');
|
|
55
|
+
}, 3000);
|
|
56
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Page Loader Module - Initialization
|
|
2
|
+
export default function (Manager, options) {
|
|
3
|
+
// Shortcuts
|
|
4
|
+
const { webManager } = Manager;
|
|
5
|
+
|
|
6
|
+
// Log
|
|
7
|
+
console.log('Running initialize()');
|
|
8
|
+
|
|
9
|
+
// The click prevention logic has been moved to an inline script in base.html
|
|
10
|
+
// for immediate execution to prevent race conditions
|
|
11
|
+
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
let webManager = null;
|
|
3
3
|
|
|
4
4
|
// Global variables
|
|
5
|
-
let hasLostFocus = false;
|
|
6
5
|
let launchTimeout;
|
|
7
6
|
let errorTimeout;
|
|
8
7
|
|
|
@@ -10,6 +9,7 @@ let errorTimeout;
|
|
|
10
9
|
let $launchButton;
|
|
11
10
|
let $downloadButton;
|
|
12
11
|
let $errorAlert;
|
|
12
|
+
let $spinner;
|
|
13
13
|
|
|
14
14
|
// Module
|
|
15
15
|
export default (Manager, options) => {
|
|
@@ -33,33 +33,16 @@ function setupPage() {
|
|
|
33
33
|
$launchButton = document.getElementById('launch-button');
|
|
34
34
|
$downloadButton = document.getElementById('download-button');
|
|
35
35
|
$errorAlert = document.getElementById('error-alert');
|
|
36
|
-
|
|
36
|
+
$spinner = document.querySelector('.spinner-border');
|
|
37
37
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
button.removeAttribute('disabled');
|
|
41
|
-
button.classList.remove('disabled');
|
|
42
|
-
});
|
|
38
|
+
// Hide spinner initially (will be shown again on launch)
|
|
39
|
+
$spinner.setAttribute('hidden', true);
|
|
43
40
|
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
// if (launchTimeout) {
|
|
47
|
-
// clearTimeout(launchTimeout);
|
|
48
|
-
// }
|
|
49
|
-
// });
|
|
50
|
-
|
|
51
|
-
// window.addEventListener('focus', () => {
|
|
52
|
-
// if (hasLostFocus) {
|
|
53
|
-
// window.close();
|
|
54
|
-
// }
|
|
55
|
-
// });
|
|
56
|
-
|
|
57
|
-
// Build app URL with parameters
|
|
58
|
-
const baseUrl = $launchButton.getAttribute('href');
|
|
59
|
-
const appUrl = `${baseUrl}${urlParams}`;
|
|
41
|
+
// Build deep link URL
|
|
42
|
+
const appUrl = buildDeepLinkUrl();
|
|
60
43
|
$launchButton.setAttribute('href', appUrl);
|
|
61
44
|
|
|
62
|
-
//
|
|
45
|
+
// Launch app immediately on page load
|
|
63
46
|
launchApp(appUrl);
|
|
64
47
|
|
|
65
48
|
// Handle launch button click
|
|
@@ -67,32 +50,88 @@ function setupPage() {
|
|
|
67
50
|
event.preventDefault();
|
|
68
51
|
launchApp(appUrl);
|
|
69
52
|
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Build deep link URL with path extraction and query passthrough
|
|
56
|
+
function buildDeepLinkUrl() {
|
|
57
|
+
const baseUrl = $launchButton.getAttribute('href'); // e.g., "myapp://"
|
|
58
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
59
|
+
|
|
60
|
+
// Define the special parameter name for the app path
|
|
61
|
+
const PATH_PARAM_NAMES = ['path']
|
|
70
62
|
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
// Find which path parameter is being used (if any)
|
|
64
|
+
let appPath = '';
|
|
65
|
+
let pathParamUsed = null;
|
|
66
|
+
|
|
67
|
+
for (const paramName of PATH_PARAM_NAMES) {
|
|
68
|
+
const value = urlParams.get(paramName);
|
|
69
|
+
if (value !== null) {
|
|
70
|
+
appPath = value;
|
|
71
|
+
pathParamUsed = paramName;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Build the query string for the deep link
|
|
77
|
+
// This includes all parameters EXCEPT the special path parameter
|
|
78
|
+
const deepLinkParams = new URLSearchParams();
|
|
79
|
+
|
|
80
|
+
for (const [key, value] of urlParams.entries()) {
|
|
81
|
+
// Skip the special path parameter
|
|
82
|
+
if (!PATH_PARAM_NAMES.includes(key)) {
|
|
83
|
+
deepLinkParams.append(key, value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Construct the final deep link URL
|
|
88
|
+
// Remove leading slash from path if present to avoid double slashes
|
|
89
|
+
const cleanPath = appPath.startsWith('/') ? appPath.substring(1) : appPath;
|
|
90
|
+
|
|
91
|
+
// Build the final URL
|
|
92
|
+
let finalUrl = baseUrl;
|
|
93
|
+
if (cleanPath) {
|
|
94
|
+
finalUrl += cleanPath;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Add query parameters if there are any
|
|
98
|
+
const queryString = deepLinkParams.toString();
|
|
99
|
+
if (queryString) {
|
|
100
|
+
// Add ? or & depending on whether the path already has query params
|
|
101
|
+
const separator = cleanPath.includes('?') ? '&' : '?';
|
|
102
|
+
finalUrl += separator + queryString;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log('Deep link constructed:', {
|
|
106
|
+
baseUrl: baseUrl,
|
|
107
|
+
pathParam: pathParamUsed,
|
|
108
|
+
appPath: appPath,
|
|
109
|
+
passedParams: queryString,
|
|
110
|
+
finalUrl: finalUrl
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return finalUrl;
|
|
78
114
|
}
|
|
79
115
|
|
|
80
116
|
function launchApp(appUrl) {
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
window.location.href = appUrl;
|
|
117
|
+
// Show spinner when attempting to launch
|
|
118
|
+
$spinner.removeAttribute('hidden');
|
|
84
119
|
|
|
85
|
-
// Clear any previous error timeout
|
|
120
|
+
// Clear any previous error timeout and hide error alert
|
|
86
121
|
clearTimeout(errorTimeout);
|
|
87
122
|
$errorAlert.setAttribute('hidden', true);
|
|
88
123
|
|
|
89
|
-
//
|
|
124
|
+
// Attempt to launch app
|
|
125
|
+
window.location.href = appUrl;
|
|
126
|
+
|
|
127
|
+
// Check if deep link failed after a delay
|
|
128
|
+
// Since browser prompts don't trigger blur, we can't reliably detect if app launched
|
|
129
|
+
// We'll show download options after a delay - user can dismiss if app actually launched
|
|
90
130
|
errorTimeout = setTimeout(() => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}, 1000);
|
|
131
|
+
// Hide spinner
|
|
132
|
+
$spinner.setAttribute('hidden', true);
|
|
133
|
+
|
|
134
|
+
// Show download options
|
|
135
|
+
$errorAlert.removeAttribute('hidden');
|
|
136
|
+
}, 2000);
|
|
98
137
|
}
|
|
@@ -48,12 +48,6 @@ function setupPlatformDetection() {
|
|
|
48
48
|
|
|
49
49
|
// Show loading state initially, then switch to detected platform
|
|
50
50
|
setTimeout(() => {
|
|
51
|
-
// Enable all platform buttons
|
|
52
|
-
const $platformButtons = document.querySelectorAll('.platform-btn');
|
|
53
|
-
$platformButtons.forEach($btn => {
|
|
54
|
-
$btn.disabled = false;
|
|
55
|
-
});
|
|
56
|
-
|
|
57
51
|
// Activate the detected platform tab using Bootstrap's tab API
|
|
58
52
|
const $detectedTab = document.querySelector(`#${detectedPlatform}-tab`);
|
|
59
53
|
if ($detectedTab) {
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
// Libraries
|
|
2
|
-
import {
|
|
2
|
+
import { raw } from './modules/state.js';
|
|
3
3
|
import { fetchProductDetails, fetchTrialEligibility, warmupServer } from './modules/api.js';
|
|
4
4
|
import { initializeRecaptcha } from './modules/recaptcha.js';
|
|
5
5
|
import {
|
|
6
6
|
updateAllUI,
|
|
7
7
|
handleBillingCycleChange,
|
|
8
8
|
showError,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from './modules/ui.js';
|
|
12
|
-
import { applyDiscountCode, autoApplyWelcomeCoupon } from './modules/discount.js';
|
|
9
|
+
updatePaymentButtonVisibility,
|
|
10
|
+
initializeCheckoutUI
|
|
11
|
+
} from './modules/ui-bindings.js';
|
|
12
|
+
import { applyDiscountCode, autoApplyWelcomeCoupon } from './modules/discount-bindings.js';
|
|
13
13
|
import { paymentManager } from './modules/processors-main.js';
|
|
14
14
|
import { FormManager } from '__main_assets__/js/libs/form-manager.js';
|
|
15
15
|
import {
|
|
16
16
|
generateCheckoutId,
|
|
17
17
|
buildPaymentIntentData,
|
|
18
18
|
} from './modules/session.js';
|
|
19
|
+
import { calculatePrices } from './modules/pricing.js';
|
|
19
20
|
let webManager = null;
|
|
20
21
|
let formManager = null;
|
|
21
22
|
|
|
@@ -134,7 +135,7 @@ function setupEventListeners() {
|
|
|
134
135
|
|
|
135
136
|
// Handle billing cycle changes
|
|
136
137
|
if (fieldName === 'billing-cycle') {
|
|
137
|
-
handleBillingCycleChange(fieldValue);
|
|
138
|
+
handleBillingCycleChange(fieldValue, webManager);
|
|
138
139
|
}
|
|
139
140
|
});
|
|
140
141
|
|
|
@@ -143,7 +144,7 @@ function setupEventListeners() {
|
|
|
143
144
|
const { action } = event.detail;
|
|
144
145
|
|
|
145
146
|
if (action === 'apply-discount') {
|
|
146
|
-
applyDiscountCode();
|
|
147
|
+
applyDiscountCode(webManager);
|
|
147
148
|
}
|
|
148
149
|
});
|
|
149
150
|
|
|
@@ -165,15 +166,15 @@ function setupEventListeners() {
|
|
|
165
166
|
return;
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
// Set payment method in
|
|
169
|
-
|
|
169
|
+
// Set payment method in raw
|
|
170
|
+
raw.paymentMethod = paymentMethod;
|
|
170
171
|
|
|
171
172
|
// Track add_payment_info event when payment method is selected
|
|
172
|
-
const basePrice =
|
|
173
|
-
? (
|
|
174
|
-
:
|
|
173
|
+
const basePrice = raw.product.is_subscription
|
|
174
|
+
? (raw.billingCycle === 'monthly' ? raw.product.price_monthly : raw.product.price_annually)
|
|
175
|
+
: raw.product.price;
|
|
175
176
|
|
|
176
|
-
trackAddPaymentInfo(
|
|
177
|
+
trackAddPaymentInfo(raw.product, basePrice, raw.billingCycle, paymentMethod);
|
|
177
178
|
console.log('Tracked add_payment_info event:', paymentMethod);
|
|
178
179
|
|
|
179
180
|
// Process the payment
|
|
@@ -203,8 +204,8 @@ async function completePurchase() {
|
|
|
203
204
|
// Get form data from FormManager
|
|
204
205
|
const formData = formManager.getData();
|
|
205
206
|
|
|
206
|
-
// Store form data in
|
|
207
|
-
|
|
207
|
+
// Store form data in raw
|
|
208
|
+
raw.formData = formData;
|
|
208
209
|
|
|
209
210
|
// Wait 1 second to simulate processing time
|
|
210
211
|
if (webManager.isDevelopment()) {
|
|
@@ -212,7 +213,7 @@ async function completePurchase() {
|
|
|
212
213
|
}
|
|
213
214
|
|
|
214
215
|
// Add custom validation if needed
|
|
215
|
-
if (!
|
|
216
|
+
if (!raw.paymentMethod) {
|
|
216
217
|
throw new Error('Please select a payment method');
|
|
217
218
|
}
|
|
218
219
|
|
|
@@ -222,14 +223,17 @@ async function completePurchase() {
|
|
|
222
223
|
// Log the structured payment data
|
|
223
224
|
console.log('🟢 Payment intent data:', paymentIntentData);
|
|
224
225
|
|
|
226
|
+
// Calculate pricing for analytics
|
|
227
|
+
const prices = calculatePrices(raw);
|
|
228
|
+
|
|
225
229
|
// Store pre-payment analytics data
|
|
226
230
|
const analyticsData = {
|
|
227
|
-
transaction_id:
|
|
228
|
-
value:
|
|
231
|
+
transaction_id: raw.checkoutId,
|
|
232
|
+
value: prices.total,
|
|
229
233
|
currency: 'USD',
|
|
230
234
|
items: [{
|
|
231
|
-
item_name:
|
|
232
|
-
price:
|
|
235
|
+
item_name: raw.product.name,
|
|
236
|
+
price: prices.total,
|
|
233
237
|
quantity: 1
|
|
234
238
|
}]
|
|
235
239
|
};
|
|
@@ -241,15 +245,15 @@ async function completePurchase() {
|
|
|
241
245
|
|
|
242
246
|
// Store order data for confirmation page (legacy format for now)
|
|
243
247
|
const orderData = {
|
|
244
|
-
orderId:
|
|
245
|
-
product:
|
|
246
|
-
productId:
|
|
247
|
-
total:
|
|
248
|
-
subtotal:
|
|
249
|
-
discountPercent:
|
|
250
|
-
billingCycle:
|
|
251
|
-
hasFreeTrial:
|
|
252
|
-
paymentMethod:
|
|
248
|
+
orderId: raw.checkoutId,
|
|
249
|
+
product: raw.product.name,
|
|
250
|
+
productId: raw.product.id,
|
|
251
|
+
total: prices.total,
|
|
252
|
+
subtotal: prices.subtotal,
|
|
253
|
+
discountPercent: raw.discountPercent,
|
|
254
|
+
billingCycle: raw.billingCycle,
|
|
255
|
+
hasFreeTrial: raw.product.has_free_trial,
|
|
256
|
+
paymentMethod: raw.paymentMethod,
|
|
253
257
|
email: webManager.auth().getUser().email,
|
|
254
258
|
timestamp: new Date().toISOString(),
|
|
255
259
|
formData: formData
|
|
@@ -257,11 +261,11 @@ async function completePurchase() {
|
|
|
257
261
|
|
|
258
262
|
sessionStorage.setItem('pendingOrder', JSON.stringify(orderData));
|
|
259
263
|
|
|
260
|
-
// Store the payment intent data in
|
|
261
|
-
|
|
264
|
+
// Store the payment intent data in raw for processors to use
|
|
265
|
+
raw.paymentIntentData = paymentIntentData;
|
|
262
266
|
|
|
263
267
|
// Process payment with selected processor (will redirect)
|
|
264
|
-
await paymentManager.processPayment(
|
|
268
|
+
await paymentManager.processPayment(raw.paymentMethod);
|
|
265
269
|
|
|
266
270
|
// This code won't run if redirect is successful
|
|
267
271
|
// If we get here, something went wrong
|
|
@@ -283,9 +287,12 @@ async function completePurchase() {
|
|
|
283
287
|
// Initialize checkout with parallel API calls
|
|
284
288
|
async function initializeCheckout() {
|
|
285
289
|
try {
|
|
290
|
+
// Initialize UI with loading states (replaces fullscreen loader)
|
|
291
|
+
initializeCheckoutUI();
|
|
292
|
+
|
|
286
293
|
// Generate or retrieve checkout session ID
|
|
287
|
-
|
|
288
|
-
console.log('Checkout session ID:',
|
|
294
|
+
raw.checkoutId = generateCheckoutId();
|
|
295
|
+
console.log('Checkout session ID:', raw.checkoutId);
|
|
289
296
|
|
|
290
297
|
// Get product ID from URL params
|
|
291
298
|
const urlParams = new URLSearchParams(window.location.search);
|
|
@@ -318,9 +325,7 @@ async function initializeCheckout() {
|
|
|
318
325
|
}
|
|
319
326
|
|
|
320
327
|
// Set product data
|
|
321
|
-
|
|
322
|
-
state.isSubscription = state.product.is_subscription;
|
|
323
|
-
state.hasFreeTrial = state.product.has_free_trial;
|
|
328
|
+
raw.product = productData.value;
|
|
324
329
|
|
|
325
330
|
// Create mutable trial eligibility result for testing
|
|
326
331
|
let trialEligibilityResult = trialEligible;
|
|
@@ -336,12 +341,12 @@ async function initializeCheckout() {
|
|
|
336
341
|
|
|
337
342
|
// Apply trial eligibility with server/test response
|
|
338
343
|
if (trialEligibilityResult.status === 'fulfilled') {
|
|
339
|
-
|
|
344
|
+
raw.product.has_free_trial = trialEligibilityResult.value && raw.product.has_free_trial;
|
|
340
345
|
}
|
|
341
346
|
|
|
342
347
|
// Initialize payment processors with API keys
|
|
343
|
-
if (
|
|
344
|
-
paymentManager.initialize(
|
|
348
|
+
if (raw.apiKeys) {
|
|
349
|
+
paymentManager.initialize(raw.apiKeys, webManager);
|
|
345
350
|
}
|
|
346
351
|
|
|
347
352
|
// Update payment button visibility based on available processors
|
|
@@ -356,7 +361,7 @@ async function initializeCheckout() {
|
|
|
356
361
|
|
|
357
362
|
if (availableMethods.length === 0) {
|
|
358
363
|
console.error('No payment methods available! Check API keys configuration.');
|
|
359
|
-
showError('No payment methods are currently available. Please contact support for assistance.');
|
|
364
|
+
showError('No payment methods are currently available. Please contact support for assistance.', webManager);
|
|
360
365
|
return; // Stop initialization since we can't proceed without payment methods
|
|
361
366
|
}
|
|
362
367
|
|
|
@@ -369,12 +374,12 @@ async function initializeCheckout() {
|
|
|
369
374
|
|
|
370
375
|
// Set billing cycle from URL parameter (before UI updates)
|
|
371
376
|
if (frequency === 'monthly' || frequency === 'annually') {
|
|
372
|
-
|
|
377
|
+
raw.billingCycle = frequency;
|
|
373
378
|
console.log('Setting billing cycle from URL:', frequency);
|
|
374
379
|
}
|
|
375
380
|
|
|
376
381
|
// Update UI with product details
|
|
377
|
-
updateAllUI();
|
|
382
|
+
updateAllUI(webManager);
|
|
378
383
|
|
|
379
384
|
// Set up event listeners and FormManager
|
|
380
385
|
setupEventListeners();
|
|
@@ -383,23 +388,24 @@ async function initializeCheckout() {
|
|
|
383
388
|
formManager.setFormState('ready');
|
|
384
389
|
|
|
385
390
|
// Track begin_checkout event on page load
|
|
386
|
-
const basePrice =
|
|
387
|
-
? (
|
|
388
|
-
:
|
|
391
|
+
const basePrice = raw.product.is_subscription
|
|
392
|
+
? (raw.billingCycle === 'monthly' ? raw.product.price_monthly : raw.product.price_annually)
|
|
393
|
+
: raw.product.price;
|
|
389
394
|
|
|
390
|
-
trackBeginCheckout(
|
|
391
|
-
console.log('Tracked begin_checkout event for:',
|
|
395
|
+
trackBeginCheckout(raw.product, basePrice, raw.billingCycle);
|
|
396
|
+
console.log('Tracked begin_checkout event for:', raw.product.id);
|
|
392
397
|
|
|
393
398
|
// Auto-apply welcome coupon
|
|
394
|
-
autoApplyWelcomeCoupon();
|
|
399
|
+
autoApplyWelcomeCoupon(webManager);
|
|
395
400
|
|
|
396
401
|
} catch (error) {
|
|
397
402
|
console.error('Checkout initialization failed:', error);
|
|
398
|
-
showError(error.message || 'Failed to load checkout. Please refresh the page and try again.');
|
|
403
|
+
showError(error.message || 'Failed to load checkout. Please refresh the page and try again.', webManager);
|
|
399
404
|
} finally {
|
|
400
|
-
//
|
|
405
|
+
// The bindings system handles loading states, no need for a separate preloader
|
|
406
|
+
// Auth listener is still useful for other purposes
|
|
401
407
|
webManager.auth().listen({}, () => {
|
|
402
|
-
|
|
408
|
+
console.log('Auth state updated');
|
|
403
409
|
});
|
|
404
410
|
}
|
|
405
411
|
}
|