| Server IP : 3.111.61.48 / Your IP : 216.73.216.67 Web Server : Apache System : Linux ip-10-0-5-176 6.8.0-1057-aws #60~22.04.1-Ubuntu SMP Wed May 27 08:16:59 UTC 2026 x86_64 User : ubuntu ( 1000) PHP Version : 8.2.31 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/vhost/book.gyaniguru.org/js/ |
Upload File : |
/* ================================================================
GYANI GURU — Account Dashboard JS (account.js)
================================================================ */
document.addEventListener('DOMContentLoaded', function () {
// ---- Guard: redirect if not logged in ----
if (!AuthManager.isLoggedIn()) {
window.location.href = 'login.html?from=account.html';
return;
}
// ---- Load user data ----
initAccountPage();
// ---- Tab Navigation ----
document.querySelectorAll('.acc-nav-item[data-tab]').forEach(item => {
item.addEventListener('click', function (e) {
e.preventDefault();
const tab = this.dataset.tab;
switchTab(tab);
});
});
// ---- Logout ----
document.getElementById('logoutBtn')?.addEventListener('click', function (e) {
e.preventDefault();
confirmLogout();
});
// ---- Profile Edit ----
document.getElementById('editProfileBtn')?.addEventListener('click', function () {
document.getElementById('profileViewMode').style.display = 'none';
document.getElementById('profileEditMode').style.display = 'block';
this.style.display = 'none';
});
document.getElementById('cancelEditBtn')?.addEventListener('click', function () {
document.getElementById('profileViewMode').style.display = 'block';
document.getElementById('profileEditMode').style.display = 'none';
document.getElementById('editProfileBtn').style.display = 'flex';
});
document.getElementById('saveProfileBtn')?.addEventListener('click', saveProfile);
// ---- Avatar Upload ----
document.getElementById('changeAvatarBtn')?.addEventListener('click', function () {
document.getElementById('avatarInput').click();
});
document.getElementById('avatarInput')?.addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function (ev) {
const src = ev.target.result;
// Update all avatar displays
const avatarEls = [
document.getElementById('profileAvatarLarge'),
document.getElementById('sidebarAvatar')
];
avatarEls.forEach(el => {
if (el) el.innerHTML = `<img src="${src}" alt="Profile Photo" style="width:100%;height:100%;object-fit:cover;border-radius:50%">`;
});
// Store in localStorage
localStorage.setItem('gg_avatar', src);
showToast('Profile photo updated!', 'bi-check-circle-fill');
};
reader.readAsDataURL(file);
});
// ---- Order Filters ----
document.querySelectorAll('.acc-chip[data-filter]').forEach(chip => {
chip.addEventListener('click', function () {
document.querySelectorAll('.acc-chip[data-filter]').forEach(c => c.classList.remove('active'));
this.classList.add('active');
filterOrders(this.dataset.filter);
});
});
// ---- Add Address button ----
document.getElementById('addAddressBtn')?.addEventListener('click', function () {
document.getElementById('addAddressModal')?.classList.add('active');
});
// ---- Close modals on overlay click ----
document.querySelectorAll('.acc-modal-overlay').forEach(overlay => {
overlay.addEventListener('click', function (e) {
if (e.target === this) this.classList.remove('active');
});
});
// ---- Load wishlist ----
loadWishlistTab();
// ---- URL hash tab support ----
const hash = window.location.hash.replace('#', '');
if (hash && document.getElementById(`tab-${hash}`)) {
switchTab(hash);
}
});
// ================================================================
// Init
// ================================================================
function initAccountPage() {
const user = AuthManager.getUser();
const profile = AuthManager.getProfile();
if (!user) return;
const displayName = profile
? `${profile.firstName} ${profile.lastName}`.trim()
: (user.name || 'Gyani Member');
const initial = displayName.charAt(0).toUpperCase();
// Sidebar
safeText('sidebarName', displayName);
safeText('sidebarEmail', user.email || '');
safeText('sidebarAvatar', initial);
// Profile tab
safeText('profileDisplayName', displayName);
safeText('profileAvatarLarge', initial);
// Restore avatar if saved
const savedAvatar = localStorage.getItem('gg_avatar');
if (savedAvatar) {
const avatarEls = [document.getElementById('profileAvatarLarge'), document.getElementById('sidebarAvatar')];
avatarEls.forEach(el => {
if (el) el.innerHTML = `<img src="${savedAvatar}" alt="Avatar" style="width:100%;height:100%;object-fit:cover;border-radius:50%">`;
});
}
// Info fields
if (profile) {
safeText('viewName', `${profile.firstName} ${profile.lastName}`.trim());
safeText('viewEmail', profile.email || user.email || '');
safeText('viewPhone', profile.phone || 'Not set');
safeText('viewDob', profile.dob ? formatDate(profile.dob) : 'Not set');
safeText('viewGender', profile.gender || 'Not set');
safeText('viewCity', profile.city || 'Not set');
safeText('profile-display-joined', profile.joinedDate ? `Member since ${profile.joinedDate}` : '');
// Edit fields
setVal('editFirstName', profile.firstName);
setVal('editLastName', profile.lastName);
setVal('editEmail', profile.email || user.email);
setVal('editPhone', profile.phone || '');
setVal('editDob', profile.dob || '');
setVal('editGender', profile.gender || 'Male');
setVal('editCity', profile.city || '');
}
// Wishlist badge
updateWishlistBadge();
// Order count stats
const orderCount = document.querySelectorAll('.order-card').length;
safeText('totalOrdersCount', orderCount);
}
// ================================================================
// Tab Switch
// ================================================================
function switchTab(tabName) {
document.querySelectorAll('.acc-tab-content').forEach(tc => tc.classList.remove('active'));
document.querySelectorAll('.acc-nav-item[data-tab]').forEach(item => item.classList.remove('active'));
const tabEl = document.getElementById(`tab-${tabName}`);
if (tabEl) tabEl.classList.add('active');
const navItem = document.querySelector(`.acc-nav-item[data-tab="${tabName}"]`);
if (navItem) navItem.classList.add('active');
// Lazy-load wishlist on switch
if (tabName === 'wishlist') loadWishlistTab();
// Scroll to top of content
window.scrollTo({ top: 200, behavior: 'smooth' });
}
// ================================================================
// Save Profile
// ================================================================
function saveProfile() {
const firstName = document.getElementById('editFirstName')?.value?.trim() || '';
const lastName = document.getElementById('editLastName')?.value?.trim() || '';
const email = document.getElementById('editEmail')?.value?.trim() || '';
const phone = document.getElementById('editPhone')?.value?.trim() || '';
const dob = document.getElementById('editDob')?.value || '';
const gender = document.getElementById('editGender')?.value || '';
const city = document.getElementById('editCity')?.value?.trim() || '';
if (!firstName) { showToast('First name is required', 'bi-exclamation-circle', true); return; }
const profile = AuthManager.getProfile() || {};
const updatedProfile = { ...profile, firstName, lastName, email, phone, dob, gender, city };
AuthManager.setProfile(updatedProfile);
// Update user record
const user = AuthManager.getUser();
if (user) {
user.name = `${firstName} ${lastName}`.trim();
user.email = email;
AuthManager.setUser(user);
}
// Refresh view
safeText('viewName', `${firstName} ${lastName}`.trim());
safeText('viewEmail', email);
safeText('viewPhone', phone || 'Not set');
safeText('viewDob', dob ? formatDate(dob) : 'Not set');
safeText('viewGender', gender || 'Not set');
safeText('viewCity', city || 'Not set');
safeText('profileDisplayName', `${firstName} ${lastName}`.trim());
safeText('sidebarName', `${firstName} ${lastName}`.trim());
safeText('sidebarEmail', email);
// Switch back to view mode
document.getElementById('profileViewMode').style.display = 'block';
document.getElementById('profileEditMode').style.display = 'none';
document.getElementById('editProfileBtn').style.display = 'flex';
showToast('Profile updated successfully! 🙏', 'bi-check-circle-fill');
}
// ================================================================
// Orders
// ================================================================
function filterOrders(filter) {
document.querySelectorAll('.order-card').forEach(card => {
if (filter === 'all' || card.dataset.status === filter) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
}
function trackOrder(orderId) {
const el = document.getElementById('trackOrderIdDisplay');
if (el) el.textContent = `Order #${orderId}`;
document.getElementById('trackOrderModal')?.classList.add('active');
}
function downloadInvoice(orderId) {
showToast(`Invoice for #${orderId} download started`, 'bi-download');
}
function cancelOrder(orderId) {
if (confirm(`Are you sure you want to cancel order #${orderId}?`)) {
showToast(`Order #${orderId} cancellation requested`, 'bi-x-circle', false);
}
}
function reorder(orderId) {
showToast('Items added to cart!', 'bi-bag-plus-fill');
setTimeout(() => { window.location.href = 'cart.html'; }, 1500);
}
function writeReview(orderId) {
showToast('Review feature coming soon!', 'bi-star-fill');
}
// ================================================================
// Wishlist Tab
// ================================================================
function loadWishlistTab() {
const wishlistData = JSON.parse(localStorage.getItem('gg_wishlist') || '[]');
const grid = document.getElementById('wishlistGrid');
const empty = document.getElementById('wishlistEmpty');
const badge = document.getElementById('wishlistBadge');
const countEl = document.getElementById('wishlistCount');
if (badge) badge.textContent = wishlistData.length;
if (countEl) countEl.textContent = wishlistData.length;
if (!grid) return;
grid.innerHTML = '';
if (wishlistData.length === 0) {
if (empty) empty.style.display = 'block';
grid.style.display = 'none';
return;
}
if (empty) empty.style.display = 'none';
grid.style.display = '';
wishlistData.forEach(book => {
const col = document.createElement('div');
col.className = 'col-6 col-sm-4 col-md-3';
col.innerHTML = `
<div class="wishlist-book-card">
<button class="wishlist-remove-btn" onclick="removeFromWishlist('${book.id}')">
<i class="bi bi-x"></i>
</button>
<div class="wishlist-book-img">
<img src="${book.image}" alt="${book.title}"
onerror="this.parentElement.innerHTML='<span style=\\'font-size:2rem\\'>📚</span>'"
style="width:100%;height:100%;object-fit:cover">
</div>
<div class="wishlist-book-title">${book.title}</div>
<div class="wishlist-book-price">₹${book.price}</div>
<button class="btn-cart" style="font-size:0.75rem;padding:8px;"
onclick="addToCartFromWishlist('${book.id}')">
<i class="bi bi-bag-plus"></i> Add to Cart
</button>
</div>`;
grid.appendChild(col);
});
}
function updateWishlistBadge() {
const data = JSON.parse(localStorage.getItem('gg_wishlist') || '[]');
const badge = document.getElementById('wishlistBadge');
const count = document.getElementById('wishlistCount');
if (badge) badge.textContent = data.length;
if (count) count.textContent = data.length;
}
function removeFromWishlist(bookId) {
let wishlist = JSON.parse(localStorage.getItem('gg_wishlist') || '[]');
wishlist = wishlist.filter(b => b.id !== bookId);
localStorage.setItem('gg_wishlist', JSON.stringify(wishlist));
loadWishlistTab();
showToast('Removed from wishlist', 'bi-heart');
}
function addToCartFromWishlist(bookId) {
const wishlist = JSON.parse(localStorage.getItem('gg_wishlist') || '[]');
const book = wishlist.find(b => b.id === bookId);
if (!book) return;
// Use Store if available
if (typeof Store !== 'undefined') {
Store.addToCart(book);
showToast('Added to cart!', 'bi-bag-plus-fill');
}
}
// ================================================================
// Addresses
// ================================================================
function saveNewAddress() {
const name = document.getElementById('addrName')?.value?.trim();
const line1 = document.getElementById('addrLine1')?.value?.trim();
if (!name || !line1) {
showToast('Name and address are required', 'bi-exclamation-circle', true);
return;
}
document.getElementById('addAddressModal')?.classList.remove('active');
showToast('Address saved successfully!', 'bi-geo-alt-fill');
}
function editAddress(id) { showToast('Edit address — coming soon!', 'bi-pencil'); }
function deleteAddress(id) {
if (confirm('Delete this address?')) {
showToast('Address removed', 'bi-trash');
}
}
function setDefaultAddress(id) { showToast('Default address updated!', 'bi-check-circle-fill'); }
// ================================================================
// Settings
// ================================================================
function changePassword() {
const cur = document.getElementById('currentPwd')?.value;
const newP = document.getElementById('newPwd')?.value;
const conf = document.getElementById('confirmPwd')?.value;
if (!cur || !newP || !conf) { showToast('Please fill all password fields', 'bi-exclamation-circle', true); return; }
if (newP.length < 8) { showToast('New password must be at least 8 characters', 'bi-exclamation-circle', true); return; }
if (newP !== conf) { showToast('New passwords do not match', 'bi-exclamation-circle', true); return; }
const btn = document.getElementById('savePwdBtn');
if (btn) { btn.disabled = true; btn.innerHTML = '<span class="spinner" style="display:inline-block;margin-right:8px"></span> Updating...'; }
setTimeout(() => {
if (btn) { btn.disabled = false; btn.innerHTML = '<i class="bi bi-shield-lock me-2"></i>Update Password'; }
document.getElementById('currentPwd').value = '';
document.getElementById('newPwd').value = '';
document.getElementById('confirmPwd').value = '';
showToast('Password updated successfully! 🔐', 'bi-shield-check-fill');
}, 1500);
}
function saveNotifSettings() {
const settings = {
orders: document.getElementById('notifOrders')?.checked,
promos: document.getElementById('notifPromos')?.checked,
books: document.getElementById('notifBooks')?.checked,
newsletter: document.getElementById('notifNewsletter')?.checked,
whatsapp: document.getElementById('notifWhatsapp')?.checked
};
localStorage.setItem('gg_notif_settings', JSON.stringify(settings));
showToast('Notification preferences saved!', 'bi-bell-fill');
}
function togglePwd(inputId, btn) {
const input = document.getElementById(inputId);
if (!input) return;
const icon = btn.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
if (icon) icon.className = 'bi bi-eye-slash';
} else {
input.type = 'password';
if (icon) icon.className = 'bi bi-eye';
}
}
// ================================================================
// Logout & Delete
// ================================================================
function confirmLogout() {
if (confirm('Are you sure you want to logout?')) {
AuthManager.logout();
}
}
function confirmDeleteAccount() {
if (confirm('⚠️ This will permanently delete your account. This action cannot be undone. Proceed?')) {
if (confirm('Are you absolutely sure?')) {
AuthManager.logout();
}
}
}
// ================================================================
// Toast
// ================================================================
function showToast(msg, icon = 'bi-check-circle-fill', isError = false) {
const toast = document.getElementById('globalToast');
const toastMsg = document.getElementById('toastMsg');
const toastIcon = document.getElementById('toastIcon');
if (!toast) return;
if (toastMsg) toastMsg.textContent = msg;
if (toastIcon) toastIcon.className = `bi ${icon}`;
toast.style.borderColor = isError ? 'var(--maroon)' : 'var(--gold)';
toast.classList.add('show');
clearTimeout(window._toastTimer);
window._toastTimer = setTimeout(() => toast.classList.remove('show'), 3000);
}
// ================================================================
// Helpers
// ================================================================
function safeText(id, text) {
const el = document.getElementById(id);
if (el) el.textContent = text;
}
function setVal(id, value) {
const el = document.getElementById(id);
if (el) el.value = value || '';
}
function formatDate(dateStr) {
if (!dateStr) return '';
try {
return new Date(dateStr).toLocaleDateString('en-IN', { day: 'numeric', month: 'long', year: 'numeric' });
} catch { return dateStr; }
}