98979b58f8
Create reusable utility modules to eliminate duplication across main.js, cv-matcher.js, and legal.js: - js/utils/form-helpers.js: showFieldError, clearFieldErrors, isValidEmail, extractApiError — shared form validation and error handling - js/utils/i18n.js: currentLang, t, applyLanguage, updateLegalLinks, browserLang — shared translation and language switching - js/utils/api.js: checkApiLive, getRecaptchaWebKey, getGoogleTagManagerId, loadGoogleTagManager — shared API configuration loading - js/modules/cookie-consent.js: getConsent, setConsent, initConsent, setupConsentHandlers — cookie banner and consent management All utilities exposed on window.MyAi namespace for use by existing pages. Full JSDoc headers and inline comments for maintainability. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
122 lines
3.9 KiB
JavaScript
122 lines
3.9 KiB
JavaScript
/**
|
|
* API & Configuration Loading Utilities
|
|
*
|
|
* Shared helpers for API health checks and configuration retrieval.
|
|
* Handles reCaptcha key loading, Google Tag Manager setup, and API health checks.
|
|
*/
|
|
|
|
var reCaptchaSiteKey = null;
|
|
var gTagManagerId = null;
|
|
|
|
/**
|
|
* Check API /health/live endpoint and update status indicator if present.
|
|
* Updates #api-status element with "API: {status}" (green if OK, red if down).
|
|
* Logs result to console if element not found.
|
|
*
|
|
* @returns {object} - jQuery AJAX promise
|
|
*/
|
|
function checkApiLive() {
|
|
var $statusEl = $('#api-status');
|
|
return $.ajax({
|
|
url: '/api/health/live',
|
|
method: 'GET',
|
|
dataType: 'json',
|
|
timeout: 5000
|
|
}).done(function (data) {
|
|
var status = (data && data.status) ? data.status : 'unknown';
|
|
if ($statusEl.length) {
|
|
$statusEl.text('API: ' + status).removeClass('text-danger').addClass('text-success');
|
|
} else {
|
|
console.log('API live status:', status);
|
|
}
|
|
}).fail(function (jqXHR, textStatus, errorThrown) {
|
|
if ($statusEl.length) {
|
|
$statusEl.text('API: offline').removeClass('text-success').addClass('text-danger');
|
|
}
|
|
console.error('API health check failed:', textStatus, errorThrown);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Load reCaptcha public site key from /api/captcha endpoint.
|
|
* Dynamically injects reCaptcha script if not already loaded.
|
|
* Stores key on window for use by grecaptcha.execute().
|
|
*
|
|
* @returns {object} - jQuery AJAX promise
|
|
*/
|
|
function getRecaptchaWebKey() {
|
|
return $.get('/api/captcha').done(function (res) {
|
|
reCaptchaSiteKey = res;
|
|
if (reCaptchaSiteKey && !window.__recaptcha_loaded) {
|
|
window.__recaptcha_loaded = true;
|
|
var script = document.createElement('script');
|
|
script.setAttribute('src', 'https://www.google.com/recaptcha/api.js?render=' + reCaptchaSiteKey);
|
|
document.head.appendChild(script);
|
|
}
|
|
}).fail(function () {
|
|
console.warn('Could not load reCaptcha site key from /api/captcha');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Load Google Tag Manager ID from /api/google/tagmanager endpoint.
|
|
* Does not load GTM script—that happens in loadGoogleTagManager() once consent is given.
|
|
*
|
|
* @returns {object} - jQuery AJAX promise
|
|
*/
|
|
function getGoogleTagManagerId() {
|
|
return $.get('/api/google/tagmanager').done(function (res) {
|
|
gTagManagerId = res;
|
|
}).fail(function () {
|
|
console.warn('Could not load Google Tag Manager id from /api/google/tagmanager');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Load and inject Google Tag Manager script if consent is given and not already loaded.
|
|
* Sets up dataLayer and injects GTM script from googleapis.com.
|
|
* Called only after user accepts analytics consent.
|
|
*
|
|
* Requires gTagManagerId to be loaded first via getGoogleTagManagerId().
|
|
*/
|
|
function loadGoogleTagManager() {
|
|
if (window.__gtm_loaded || !gTagManagerId) return;
|
|
window.__gtm_loaded = true;
|
|
window.dataLayer = window.dataLayer || [];
|
|
window.dataLayer.push({
|
|
'gtm.start': new Date().getTime(),
|
|
event: 'gtm.js'
|
|
});
|
|
var script = document.createElement('script');
|
|
script.async = true;
|
|
script.src = 'https://www.googletagmanager.com/gtm/js?id=' + gTagManagerId;
|
|
document.head.appendChild(script);
|
|
}
|
|
|
|
/**
|
|
* Get the currently loaded reCaptcha site key.
|
|
* @returns {string|null} - reCaptcha site key or null if not yet loaded
|
|
*/
|
|
function getReCaptchaSiteKey() {
|
|
return reCaptchaSiteKey;
|
|
}
|
|
|
|
/**
|
|
* Get the currently loaded Google Tag Manager ID.
|
|
* @returns {string|null} - GTM ID or null if not yet loaded
|
|
*/
|
|
function getGoogleTagManagerId() {
|
|
return gTagManagerId;
|
|
}
|
|
|
|
// Expose API utilities on window.MyAi for use by other scripts
|
|
window.MyAi = window.MyAi || {};
|
|
window.MyAi.checkApiLive = checkApiLive;
|
|
window.MyAi.getRecaptchaWebKey = getRecaptchaWebKey;
|
|
window.MyAi.getGoogleTagManagerId = getGoogleTagManagerId;
|
|
window.MyAi.loadGoogleTagManager = loadGoogleTagManager;
|
|
window.MyAi.getReCaptchaSiteKey = getReCaptchaSiteKey;
|
|
window.MyAi.applyConsent = function(consent) {
|
|
if (consent && consent.analytics === true) loadGoogleTagManager();
|
|
};
|