first push message
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
.app-card {
|
||||
cursor: pointer;
|
||||
background: #fff;
|
||||
transition: border-color .15s ease, box-shadow .15s ease;
|
||||
border: 1px solid #dee2e6 !important;
|
||||
}
|
||||
.app-card:hover {
|
||||
border-color: #714B67 !important;
|
||||
}
|
||||
.app-card-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
object-fit: contain;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
label.app-card.selected {
|
||||
border-color: #714B67 !important;
|
||||
box-shadow: 0 0 0 2px rgba(113, 75, 103, .25);
|
||||
background: #faf7f9;
|
||||
}
|
||||
.app-card-check {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: -10px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
border: 1px solid #714B67;
|
||||
color: #714B67;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
#selected_apps_list li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/** SaaS Trial Portal - Frontend interactions
|
||||
* Drives the 2-step /trial wizard:
|
||||
* Step 1: Choose your Apps (card grid + live sidebar)
|
||||
* Step 2: Your Information (registration form)
|
||||
*
|
||||
* NOTE: Odoo bundles/loads frontend JS assets and this script can run
|
||||
* AFTER DOMContentLoaded has already fired (depending on bundle timing).
|
||||
* Relying only on the DOMContentLoaded event can mean init() never runs.
|
||||
* So we check document.readyState first and run immediately if the DOM
|
||||
* is already parsed, falling back to the event listener otherwise.
|
||||
*/
|
||||
(function () {
|
||||
function init() {
|
||||
console.log('[saas_trial_portal] trial_form.js init');
|
||||
|
||||
var selected = {}; // { appId: appName }
|
||||
|
||||
var countEls = [document.getElementById('selected_count'), document.getElementById('selected_count_2')];
|
||||
var listEl = document.getElementById('selected_apps_list');
|
||||
var sidebar = document.getElementById('trial_sidebar');
|
||||
var continueBtn = document.getElementById('btn_continue');
|
||||
var stepApps = document.getElementById('trial_step_apps');
|
||||
var stepForm = document.getElementById('trial_step_form');
|
||||
var changeBtn = document.getElementById('btn_change_selection');
|
||||
var hiddenAppIds = document.getElementById('app_ids_json');
|
||||
|
||||
// Bail out quietly if we're not on the /trial page at all
|
||||
// (this JS is bundled site-wide via web.assets_frontend).
|
||||
if (!stepApps) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cardCount = document.querySelectorAll('.app-card').length;
|
||||
console.log('[saas_trial_portal] found', cardCount, 'app cards');
|
||||
|
||||
function render() {
|
||||
var ids = Object.keys(selected);
|
||||
countEls.forEach(function (el) { if (el) { el.textContent = ids.length; } });
|
||||
|
||||
if (listEl) {
|
||||
listEl.innerHTML = '';
|
||||
ids.forEach(function (id) {
|
||||
var li = document.createElement('li');
|
||||
li.className = 'mb-2';
|
||||
li.textContent = selected[id];
|
||||
listEl.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
if (sidebar) {
|
||||
sidebar.classList.toggle('d-none', ids.length === 0);
|
||||
}
|
||||
|
||||
if (hiddenAppIds) {
|
||||
hiddenAppIds.value = JSON.stringify(ids);
|
||||
}
|
||||
}
|
||||
|
||||
// Delegated click handler - resilient to render timing and to
|
||||
// the native <label for="..."> forwarding clicks to its hidden
|
||||
// checkbox.
|
||||
document.addEventListener('click', function (ev) {
|
||||
var card = ev.target.closest('.app-card');
|
||||
if (!card) { return; }
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
var id = card.getAttribute('data-app-id');
|
||||
var name = card.getAttribute('data-app-name');
|
||||
var checkbox = card.querySelector('.app-card-checkbox');
|
||||
var checkMark = card.querySelector('.app-card-check');
|
||||
|
||||
if (selected[id]) {
|
||||
delete selected[id];
|
||||
card.classList.remove('selected');
|
||||
if (checkbox) { checkbox.checked = false; }
|
||||
if (checkMark) { checkMark.classList.add('d-none'); }
|
||||
} else {
|
||||
selected[id] = name;
|
||||
card.classList.add('selected');
|
||||
if (checkbox) { checkbox.checked = true; }
|
||||
if (checkMark) { checkMark.classList.remove('d-none'); }
|
||||
}
|
||||
console.log('[saas_trial_portal] selected apps:', selected);
|
||||
render();
|
||||
});
|
||||
|
||||
if (continueBtn) {
|
||||
continueBtn.addEventListener('click', function () {
|
||||
if (Object.keys(selected).length === 0) { return; }
|
||||
stepApps.classList.add('d-none');
|
||||
stepForm.classList.remove('d-none');
|
||||
window.scrollTo({top: 0, behavior: 'smooth'});
|
||||
});
|
||||
}
|
||||
|
||||
if (changeBtn) {
|
||||
changeBtn.addEventListener('click', function () {
|
||||
stepForm.classList.add('d-none');
|
||||
stepApps.classList.remove('d-none');
|
||||
window.scrollTo({top: 0, behavior: 'smooth'});
|
||||
});
|
||||
}
|
||||
|
||||
render();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
// DOM already parsed by the time this script executed - run now.
|
||||
init();
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user