90 lines
6.3 KiB
JavaScript
90 lines
6.3 KiB
JavaScript
(function(){
|
|
'use strict';
|
|
function showAuthenticationModal(message){
|
|
const html=`<div class="modal fade" id="authModal" tabindex="-1" aria-labelledby="authModalLabel" aria-hidden="true"><div class="modal-dialog modal-dialog-centered"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="authModalLabel"><i class="bi bi-lock me-2"></i>Authentication Required</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body text-center"><div class="mb-3"><i class="bi bi-person-circle text-primary" style="font-size: 3rem;"></i></div><p class="mb-3">${message}</p><div class="d-grid gap-2 d-md-flex justify-content-md-center"><a href="/login" class="btn btn-primary me-md-2"><i class="bi bi-box-arrow-in-right me-2"></i>Log In</a><a href="/register" class="btn btn-outline-primary"><i class="bi bi-person-plus me-2"></i>Register</a></div></div></div></div></div>`;
|
|
document.getElementById('authModal')?.remove();
|
|
document.body.insertAdjacentHTML('beforeend', html);
|
|
new bootstrap.Modal(document.getElementById('authModal')).show();
|
|
document.getElementById('authModal').addEventListener('hidden.bs.modal', function(){ this.remove(); });
|
|
}
|
|
function formatLocationDisplays(){
|
|
document.querySelectorAll('.node-location').forEach(el=>{
|
|
const loc=el.getAttribute('data-location');
|
|
if(!loc) return; const parts=loc.split(',').map(s=>s.trim());
|
|
el.textContent=(parts.length>=2 && parts[0]==='Unknown')?parts[1]:loc;
|
|
});
|
|
}
|
|
document.addEventListener('DOMContentLoaded', function(){
|
|
formatLocationDisplays();
|
|
document.querySelectorAll('.rent-product-btn').forEach(btn=>{
|
|
btn.addEventListener('click', async function(){
|
|
const id=this.dataset.productId, name=this.dataset.productName, price=this.dataset.price;
|
|
if(!confirm(`Rent "${name}" for $${price} per month?`)) return;
|
|
const orig=this.innerHTML; this.innerHTML='<i class="bi bi-hourglass-split me-1"></i>Processing...'; this.disabled=true;
|
|
try{
|
|
await window.apiJson(`/api/products/${id}/rent`, {
|
|
method:'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ product_id:id, duration:'monthly' })
|
|
});
|
|
this.innerHTML='<i class="bi bi-check-circle me-1"></i>Rented!';
|
|
this.classList.replace('btn-success','btn-info');
|
|
if (typeof window.showToast === 'function') { window.showToast(`Successfully rented "${name}"!`, 'success'); }
|
|
else { alert(`Successfully rented "${name}"!`); }
|
|
setTimeout(()=>{window.location.href='/dashboard';},1000);
|
|
}catch(e){
|
|
if (e && e.status === 402){ this.innerHTML=orig; this.disabled=false; return; }
|
|
this.innerHTML='<i class="bi bi-exclamation-triangle me-1"></i>Error';
|
|
this.classList.replace('btn-success','btn-danger');
|
|
if (typeof window.showToast === 'function') { window.showToast(`Rental failed: ${e.message || 'Unknown error'}`, 'error'); }
|
|
else { alert(`Rental failed: ${e.message || 'Unknown error'}`); }
|
|
setTimeout(()=>{ this.innerHTML=orig; this.classList.replace('btn-danger','btn-success'); this.disabled=false;},3000);
|
|
}
|
|
});
|
|
});
|
|
document.querySelectorAll('.buy-product-btn').forEach(btn=>{
|
|
btn.addEventListener('click', async function(){
|
|
const id=this.dataset.productId, name=this.dataset.productName, price=this.dataset.price;
|
|
if(!confirm(`Purchase "${name}" for $${price}?`)) return;
|
|
const orig=this.innerHTML; this.innerHTML='<i class="bi bi-hourglass-split me-1"></i>Processing...'; this.disabled=true;
|
|
try{
|
|
await window.apiJson(`/api/products/${id}/purchase`, { method:'POST' });
|
|
this.innerHTML='<i class="bi bi-check-circle me-1"></i>Purchased!';
|
|
this.classList.replace('btn-primary','btn-info');
|
|
if (typeof window.showToast === 'function') { window.showToast(`Successfully purchased "${name}"!`, 'success'); }
|
|
else { alert(`Successfully purchased "${name}"!`); }
|
|
setTimeout(()=>{window.location.href='/dashboard';},1000);
|
|
}catch(e){
|
|
if (e && e.status === 402){ this.innerHTML=orig; this.disabled=false; return; }
|
|
this.innerHTML='<i class="bi bi-exclamation-triangle me-1"></i>Error';
|
|
this.classList.replace('btn-primary','btn-danger');
|
|
if (typeof window.showToast === 'function') { window.showToast(`Purchase failed: ${e.message || 'Unknown error'}`, 'error'); }
|
|
else { alert(`Purchase failed: ${e.message || 'Unknown error'}`); }
|
|
setTimeout(()=>{ this.innerHTML=orig; this.classList.replace('btn-danger','btn-primary'); this.disabled=false;},3000);
|
|
}
|
|
});
|
|
});
|
|
document.querySelectorAll('.add-to-cart-btn').forEach(btn=>{
|
|
btn.addEventListener('click', function(){
|
|
const id=this.dataset.productId; const orig=this.innerHTML; this.innerHTML='<i class="bi bi-hourglass-split me-1"></i>Adding...'; this.disabled=true;
|
|
window.apiJson('/api/cart/add', { method:'POST', body:{ product_id:id, quantity:1 } })
|
|
.then(()=>{
|
|
this.innerHTML='<i class="bi bi-check-circle me-1"></i>Added!';
|
|
this.classList.replace('btn-primary','btn-success');
|
|
try { if (typeof window.updateCartCount === 'function') window.updateCartCount(); } catch(_){}
|
|
try { if (typeof window.emitCartUpdated === 'function') window.emitCartUpdated(); } catch(_){}
|
|
setTimeout(()=>{ this.innerHTML=orig; this.classList.replace('btn-success','btn-primary'); this.disabled=false;},2000);
|
|
})
|
|
.catch(e=>{
|
|
if (e && e.status === 401){ showAuthenticationModal(e.message || 'Make sure to register or log in to continue'); this.innerHTML=orig; this.disabled=false; return; }
|
|
if (e && e.status === 402){ this.innerHTML=orig; this.disabled=false; return; }
|
|
console.error('Error adding to cart:',e);
|
|
this.innerHTML='<i class="bi bi-exclamation-triangle me-1"></i>Error';
|
|
this.classList.replace('btn-primary','btn-danger');
|
|
setTimeout(()=>{ this.innerHTML=orig; this.classList.replace('btn-danger','btn-primary'); this.disabled=false;},2000);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
})();
|