/* ═══════════════════════════════════════════════════════════
GAMEHUS — Core Engine
Auth Guard · Tab System · Wallet · Toast · Counters
═══════════════════════════════════════════════════════════ */
'use strict';
// ─── Fake Auth Store (will be replaced by Firebase Auth later) ───────────────
const TEST_USERS = [
{ email: 'admin@gamehus.com', password: 'admin123', username: 'Admin', role: 'admin', vip: true, gold: 15000, silver: 8400 },
{ email: 'vip@gamehus.com', password: 'vip123', username: 'VIP_Player', role: 'user', vip: true, gold: 5200, silver: 3100 },
{ email: 'test@gamehus.com', password: 'test123', username: 'TestUser', role: 'user', vip: false, gold: 0, silver: 1200 },
{ email: 'player1@gamehus.com', password: 'play123', username: 'ProShooter', role: 'user', vip: false, gold: 200, silver: 4500 },
{ email: 'player2@gamehus.com', password: 'play456', username: 'ChessMaster', role: 'user', vip: true, gold: 800, silver: 6700 },
];
const AUTH_KEY = 'gh_session';
const SESSION_TTL = 24 * 60 * 60 * 1000; // 24h
// ─── AUTH MODULE ─────────────────────────────────────────────────────────────
const Auth = (() => {
function getSession() {
try {
const raw = sessionStorage.getItem(AUTH_KEY) || localStorage.getItem(AUTH_KEY);
if (!raw) return null;
const data = JSON.parse(raw);
if (Date.now() - data.ts > SESSION_TTL) { clearSession(); return null; }
return data.user;
} catch { return null; }
}
function saveSession(user, remember = false) {
const payload = JSON.stringify({ user, ts: Date.now() });
sessionStorage.setItem(AUTH_KEY, payload);
if (remember) localStorage.setItem(AUTH_KEY, payload);
}
function clearSession() {
sessionStorage.removeItem(AUTH_KEY);
localStorage.removeItem(AUTH_KEY);
}
function login(identifier, password, remember = false) {
const user = TEST_USERS.find(u =>
(u.email === identifier || u.username === identifier) && u.password === password
);
if (!user) return { ok: false, msg: 'بيانات الدخول غير صحيحة' };
const { password: _, ...safeUser } = user;
saveSession(safeUser, remember);
return { ok: true, user: safeUser };
}
function logout() {
clearSession();
window.location.href = 'login.html';
}
function requireAuth() {
const user = getSession();
if (!user) {
window.location.replace('login.html');
return null;
}
// reveal page
document.querySelectorAll('.auth-guard').forEach(el => el.classList.add('revealed'));
return user;
}
return { getSession, saveSession, clearSession, login, logout, requireAuth };
})();
// ─── TOAST MODULE ─────────────────────────────────────────────────────────────
const Toast = (() => {
let container;
function getContainer() {
if (!container) {
container = document.createElement('div');
container.className = 'toast-container';
document.body.appendChild(container);
}
return container;
}
function show(msg, type = 'success', duration = 3000) {
const icons = { success: '✅', gold: '🪙', error: '❌', info: 'ℹ️' };
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.innerHTML = `${icons[type] || '💬'}${msg}`;
getContainer().appendChild(toast);
setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateX(20px)'; toast.style.transition = 'all 0.3s'; setTimeout(() => toast.remove(), 300); }, duration);
}
return { show };
})();
// ─── TAB SYSTEM ───────────────────────────────────────────────────────────────
const TabSystem = (() => {
const instances = new Map(); // instanceId -> { tabs, activeId, container }
function create(containerId, tabs, options = {}) {
const container = document.getElementById(containerId);
if (!container) return;
const state = { tabs: [...tabs], activeId: tabs[0]?.id, container, options };
instances.set(containerId, state);
render(containerId);
return { activate: (id) => activate(containerId, id), addTab: (tab) => addTab(containerId, tab), removeTab: (id) => removeTab(containerId, id) };
}
function render(cid) {
const state = instances.get(cid);
if (!state) return;
const { tabs, activeId, container, options } = state;
// Tab bar
let barEl = container.querySelector('.tab-bar');
if (!barEl) { barEl = document.createElement('div'); barEl.className = 'tab-bar'; container.prepend(barEl); }
barEl.innerHTML = tabs.map(tab => `
${tab.icon ? `${tab.icon}` : ''}
${tab.label}
${!tab.pinned ? `` : ''}
`).join('') + (options.addable ? `` : '');
// click events
barEl.querySelectorAll('.tab-item').forEach(el => {
el.addEventListener('click', (e) => {
if (e.target.closest('.tab-close')) return;
activate(cid, el.dataset.tid);
});
});
barEl.querySelectorAll('.tab-close').forEach(btn => {
btn.addEventListener('click', () => removeTab(cid, btn.dataset.close));
});
// panels
let panelsEl = container.querySelector('.tab-panels');
if (!panelsEl) { panelsEl = document.createElement('div'); panelsEl.className = 'tab-panels'; container.appendChild(panelsEl); }
tabs.forEach(tab => {
let panel = panelsEl.querySelector(`[data-panel="${tab.id}"]`);
if (!panel) {
panel = document.createElement('div');
panel.className = 'tab-panel animate-in';
panel.dataset.panel = tab.id;
panel.innerHTML = tab.content || '';
panelsEl.appendChild(panel);
}
panel.classList.toggle('active', tab.id === activeId);
});
}
function activate(cid, id) {
const state = instances.get(cid);
if (!state || !state.tabs.find(t => t.id === id)) return;
state.activeId = id;
render(cid);
state.options.onActivate?.(id);
}
function addTab(cid, tab) {
const state = instances.get(cid);
if (!state) return;
if (!state.tabs.find(t => t.id === tab.id)) state.tabs.push(tab);
activate(cid, tab.id);
}
function removeTab(cid, id) {
const state = instances.get(cid);
if (!state) return;
const idx = state.tabs.findIndex(t => t.id === id);
if (idx === -1 || state.tabs[idx].pinned) return;
state.tabs.splice(idx, 1);
if (state.activeId === id) state.activeId = state.tabs[Math.max(0, idx - 1)]?.id;
render(cid);
}
return { create, activate, addTab, removeTab };
})();
// ─── INNER TABS (simple, CSS-driven) ────────────────────────────────────────
function setupInnerTabs(containerEl) {
const tabs = containerEl.querySelectorAll('.inner-tab');
const panels = containerEl.querySelectorAll('.inner-panel');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
panels.forEach(p => p.classList.remove('active'));
tab.classList.add('active');
const target = containerEl.querySelector(`[data-inner-panel="${tab.dataset.innerTab}"]`);
if (target) target.classList.add('active');
});
});
if (tabs[0]) tabs[0].click();
}
// ─── TOPBAR BUILDER ─────────────────────────────────────────────────────────
function buildTopbar(user) {
const bar = document.getElementById('topbar');
if (!bar || !user) return;
bar.innerHTML = `
💎
GAMEHUS
🪙 ${(user.gold||0).toLocaleString('ar')}
🔘 ${(user.silver||0).toLocaleString('ar')}
8,432 متصل
`;
// user menu dropdown
document.getElementById('user-menu-btn')?.addEventListener('click', () => {
const existing = document.getElementById('user-dropdown');
if (existing) { existing.remove(); return; }
const dropdown = document.createElement('div');
dropdown.id = 'user-dropdown';
dropdown.style.cssText = `position:fixed;top:${65}px;left:16px;background:var(--bg-card);border:1px solid var(--border-gold);border-radius:12px;padding:8px;min-width:180px;z-index:100;box-shadow:var(--glow-gold);animation:fadeIn 0.2s ease;`;
dropdown.innerHTML = `
${user.username}
${user.email}
👤 الملف الشخصي
🪙 شحن الذهب
🚪 تسجيل الخروج
`;
document.body.appendChild(dropdown);
setTimeout(() => document.addEventListener('click', function handler(e) {
if (!dropdown.contains(e.target) && e.target.id !== 'user-menu-btn') { dropdown.remove(); document.removeEventListener('click', handler); }
}), 10);
});
// pulse online count
const el = document.getElementById('online-count');
if (el) {
const base = 8432;
let tick = 0;
setInterval(() => { tick++; el.textContent = (base + Math.round(Math.sin(tick/3)*18)).toLocaleString('ar'); }, 7000);
}
}
// ─── SIDEBAR BUILDER ─────────────────────────────────────────────────────────
function buildSidebar(user, activePage = '') {
const sb = document.getElementById('sidebar');
if (!sb) return;
const items = [
{ id: 'dashboard', icon: '🏠', label: 'الرئيسية', href: 'index.html' },
{ id: 'games', icon: '🎮', label: 'الألعاب', href: 'games.html' },
{ id: 'rooms', icon: '🏠', label: 'الغرف', href: 'rooms.html' },
{ id: 'top', icon: '🏆', label: 'المتصدرون', href: 'top.html' },
{ id: 'chat', icon: '💬', label: 'الدردشة', href: 'chat.html', badge: '3' },
{ divider: true },
{ id: 'train', icon: '🚂', label: 'محطات الجوائز', href: 'train.html' },
{ id: 'shop', icon: '🛍️', label: 'المتجر', href: 'shop.html' },
{ id: 'tournaments',icon:'🥇', label: 'البطولات', href: 'tournaments.html' },
{ divider: true },
{ id: 'profile', icon: '👤', label: 'الملف الشخصي', href: 'profile.html' },
...(user?.role === 'admin' ? [{ id: 'admin', icon: '⚙️', label: 'لوحة الإدارة', href: 'admin.html' }] : []),
];
sb.innerHTML = `
${user?.vip ? `
✨ VIP مفعّل
تذكرة القطار الذهبي نشطة
` : `
🚂 ترقية إلى VIP
جوائز أكبر في كل المحطات
اشترِ التذكرة
`}
`;
}
// ─── COUNTERS ────────────────────────────────────────────────────────────────
function animateCounters() {
document.querySelectorAll('[data-count]').forEach(el => {
const target = parseInt(el.getAttribute('data-count') || '0', 10);
if (!target) return;
let cur = 0; const inc = target / 60;
const t = setInterval(() => {
cur += inc;
if (cur >= target) { cur = target; clearInterval(t); }
el.textContent = Math.floor(cur).toLocaleString('ar');
}, 16);
});
}
// ─── SHOP MODAL (quick open) ──────────────────────────────────────────────────
function openShop() {
const existing = document.getElementById('shop-modal');
if (existing) existing.remove();
const modal = document.createElement('div');
modal.id = 'shop-modal';
modal.className = 'modal-overlay';
modal.innerHTML = `
🪙
شحن الذهب
الذهب عملة مدفوعة تُستخدم لشراء العناصر الحصرية
${[
{ gold: 500, price: '4.99$', label: 'مبتدئ', bonus: '' },
{ gold: 1200, price: '9.99$', label: 'شائع', bonus: '+100 مجاناً' },
{ gold: 2800, price: '19.99$', label: 'محترف', bonus: '+300 مجاناً' },
{ gold: 6500, price: '39.99$', label: 'احترافي', bonus: '+700 مجاناً' },
].map(p => `
🪙
${p.gold.toLocaleString()}
${p.label}
${p.bonus ? `
${p.bonus}
` : ''}
${p.price}
`).join('')}
🔒 جميع المعاملات آمنة ومشفرة — سيتم ربط بوابة الدفع قريباً
`;
modal.addEventListener('click', e => { if (e.target === modal) modal.remove(); });
document.body.appendChild(modal);
}
// ─── PAGE INIT ────────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
const page = document.body.dataset.page || '';
const isAuthPage = ['login', 'register'].includes(page);
if (!isAuthPage) {
const user = Auth.requireAuth();
if (!user) return;
buildTopbar(user);
buildSidebar(user, page);
animateCounters();
// setup any inner-tab containers on the page
document.querySelectorAll('[data-inner-tabs]').forEach(el => setupInnerTabs(el));
}
});
// expose globally
window.Auth = Auth;
window.Toast = Toast;
window.TabSystem = TabSystem;
window.openShop = openShop;
window.setupInnerTabs = setupInnerTabs;