Commit 8c4dc029 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat: kill chess-centric shell — EL3AB is now a game hub

- Sidebar: games (شطرنج/لودو/طاولة/دومينو) are the primary nav items
- Removed "العب الان" chess-only play button from sidebar
- Removed floating chess FAB from mobile nav
- Mobile nav: 5 tabs (home/games/leaderboard/social/profile)
- Header: shows account level instead of chess ELO
- Home page: games grid is the hero, no chess matchmaking widget
- Removed all chess-specific time control UI from home page
- Each game's lobby page handles its own matchmaking
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 0b3d240c
......@@ -13,8 +13,8 @@ document.addEventListener('DOMContentLoaded', async () => {
const data = await App.fetch('/api/profile');
if (data && data.profile) {
const p = data.profile;
const elo = document.getElementById('hdr-elo-val');
if (elo) elo.textContent = p.elo_blitz || 1200;
const lvl = document.getElementById('hdr-level-val');
if (lvl) lvl.textContent = 'Lv ' + (p.level || 1);
}
}
});
......
......@@ -27,9 +27,8 @@
<header class="hdr">
<a href="/" class="hdr-brand">EL3AB</a>
<div class="hdr-center">
<div class="hdr-rating" id="hdr-elo" title="تصنيف بليتز">
<svg class="icon-sm icon-fill hdr-rating-icon"><use href="/public/icons/sprite.svg#icon-star"></use></svg>
<span id="hdr-elo-val">1200</span>
<div class="hdr-rating" id="hdr-level" title="مستوى الحساب">
<span id="hdr-level-val">Lv 1</span>
</div>
</div>
<div class="hdr-actions">
......
......@@ -3,28 +3,7 @@
<div class="stack-5" id="home">
<!-- Hero: Quick Play (inline matchmaking from home) -->
<div class="hero-play">
<div class="hero-play-top">
<div>
<p class="hero-play-title" id="home-greeting">مرحبا</p>
<p class="hero-play-subtitle" id="home-rank"></p>
</div>
<div class="badge badge-gold" id="home-level">Lv 1</div>
</div>
<div class="chip-group" id="home-tc">
<button class="chip active" data-tc="bullet_1_1" data-time="60000" data-inc="1000">1+1</button>
<button class="chip" data-tc="blitz_3_0" data-time="180000" data-inc="0">3+0</button>
<button class="chip" data-tc="blitz_5_0" data-time="300000" data-inc="0">5+0</button>
<button class="chip" data-tc="rapid_10_0" data-time="600000" data-inc="0">10+0</button>
</div>
<button class="hero-play-btn" id="home-play-btn" onclick="quickPlay()">
<svg class="icon"><use href="/public/icons/sprite.svg#icon-search"></use></svg>
العب شطرنج الان
</button>
</div>
<!-- Daily Streak -->
<!-- Welcome + Daily Streak (compact bar) -->
<div class="streak-banner" id="streak-section">
<div class="streak-banner-icon">🔥</div>
<div class="streak-banner-text">
......@@ -33,21 +12,11 @@
</div>
<button class="streak-banner-btn" id="streak-btn">اجمع</button>
</div>
<div class="streak-cal" id="streak-cal">
<div class="streak-cal-day" data-day="1">1</div>
<div class="streak-cal-day" data-day="2">2</div>
<div class="streak-cal-day" data-day="3">3</div>
<div class="streak-cal-day" data-day="4">4</div>
<div class="streak-cal-day" data-day="5">5</div>
<div class="streak-cal-day" data-day="6">6</div>
<div class="streak-cal-day" data-day="7">7</div>
</div>
<!-- All Games Grid -->
<!-- GAMES: The hero of the app -->
<section>
<div class="sec-header">
<h2 class="sec-title">العاب</h2>
<a href="/games" class="sec-link">الكل</a>
<h2 class="sec-title">العب</h2>
</div>
<div class="quick-play-grid" id="home-games">
<div class="skel" style="height:110px;border-radius:var(--r-lg);"></div>
......@@ -61,11 +30,12 @@
<section id="ratings-section" style="display:none;">
<div class="sec-header">
<h2 class="sec-title">تصنيفاتي</h2>
<a href="/profile" class="sec-link">الكل</a>
</div>
<div class="stats-row" id="home-ratings"></div>
</section>
<!-- Recent Games -->
<!-- Recent Games (all games, not just chess) -->
<section>
<div class="sec-header">
<h2 class="sec-title">اخر المباريات</h2>
......@@ -87,8 +57,7 @@ document.addEventListener('DOMContentLoaded', async () => {
const data = await App.fetch('/api/profile');
if (data && data.profile) {
const p = data.profile;
document.getElementById('home-greeting').textContent = (p.display_name || p.username) + '، العب!';
document.getElementById('home-level').textContent = 'Lv ' + (p.level || 1);
document.getElementById('hdr-level-val').textContent = 'Lv ' + (p.level || 1);
const streak = p.daily_streak || 0;
document.getElementById('streak-day').textContent = 'اليوم ' + streak;
......@@ -102,17 +71,6 @@ document.addEventListener('DOMContentLoaded', async () => {
});
const claimedToday = p.last_daily_reward === new Date().toISOString().slice(0, 10);
const days = document.querySelectorAll('.streak-cal-day');
days.forEach((day, i) => {
const dayNum = i + 1;
const streakDay = ((streak - 1) % 7) + 1;
if (dayNum < streakDay || (dayNum === streakDay && claimedToday)) {
day.classList.add('claimed');
} else if (dayNum === streakDay + (claimedToday ? 0 : 1) || (streak === 0 && dayNum === 1)) {
day.classList.add('current');
}
});
if (claimedToday) {
const btn = document.getElementById('streak-btn');
btn.textContent = 'تم ✓';
......@@ -135,26 +93,10 @@ document.addEventListener('DOMContentLoaded', async () => {
const label = modeName ? gameName + ' ' + modeName : gameName;
return '<div class="stat"><div class="stat-val">' + r.rating + '</div><div class="stat-lbl">' + label + '</div></div>';
}).join('');
// Also update home-rank subtitle with best rating
const best = ratingsData.ratings.reduce((a, b) => a.rating > b.rating ? a : b);
const bestMode = modeNames[best.mode] || '';
const bestGame = gameNames[best.game_key] || '';
document.getElementById('home-rank').textContent = bestGame + ' ' + bestMode + ' ' + best.rating;
} else {
// Fallback to legacy profile elo fields
if (data && data.profile) {
const p = data.profile;
document.getElementById('home-rank').textContent = 'بليتز ' + (p.elo_blitz || 1200);
}
}
} catch (e) {
if (data && data.profile) {
document.getElementById('home-rank').textContent = 'بليتز ' + (data.profile.elo_blitz || 1200);
}
}
} catch (e) {}
// Games grid
// Games grid — this is the HERO of the page
try {
const gData = await App.cachedFetch('/api/games.php', 60000);
if (gData && gData.games) {
......@@ -216,23 +158,7 @@ document.addEventListener('DOMContentLoaded', async () => {
App.toast('لقد جمعت المكافأة اليوم', 'error');
}
});
// TC chip selection
document.querySelectorAll('#home-tc .chip').forEach(chip => {
chip.addEventListener('click', () => {
document.querySelectorAll('#home-tc .chip').forEach(c => c.classList.remove('active'));
chip.classList.add('active');
});
});
});
function quickPlay() {
const active = document.querySelector('#home-tc .chip.active');
const tc = active.dataset.tc;
const time = active.dataset.time;
const inc = active.dataset.inc;
window.location.href = '/matchmaking?tc=' + tc + '&time=' + time + '&inc=' + inc;
}
</script>
<?php require __DIR__ . '/../includes/footer-v2.php'; ?>
......@@ -289,29 +289,7 @@ img { display: block; max-width: 100%; }
flex-shrink: 0;
}
.sidebar-play-btn {
display: flex;
align-items: center;
justify-content: center;
gap: var(--sp-2);
width: 100%;
padding: var(--sp-3) var(--sp-4);
margin-bottom: var(--sp-5);
background: var(--gold);
color: var(--text-inverse);
font-weight: 700;
font-size: 15px;
border-radius: var(--r-md);
transition: transform 0.1s, box-shadow 0.2s;
box-shadow: var(--shadow-glow-gold);
}
.sidebar-play-btn:hover {
transform: translateY(-1px);
box-shadow: 0 0 30px rgba(245, 183, 49, 0.25);
}
.sidebar-play-btn:active { transform: scale(0.97); }
/* (sidebar-play-btn removed — games are individual nav items now) */
/* === BOTTOM NAV (Mobile) === */
.nav-m {
......@@ -322,7 +300,7 @@ img { display: block; max-width: 100%; }
z-index: 40;
height: calc(var(--nav-h) + env(safe-area-inset-bottom));
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: repeat(5, 1fr);
align-items: start;
padding-top: var(--sp-2);
padding-bottom: env(safe-area-inset-bottom);
......@@ -369,30 +347,7 @@ img { display: block; max-width: 100%; }
height: 22px;
}
/* Floating play button in center */
.nav-m-play {
position: fixed;
bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) - 16px);
left: 50%;
transform: translateX(-50%);
z-index: 41;
width: 56px;
height: 56px;
display: flex;
align-items: center;
justify-content: center;
background: var(--gold);
border-radius: 50%;
box-shadow: 0 4px 20px rgba(245, 183, 49, 0.35);
transition: transform 0.15s var(--ease-bounce);
}
@media (min-width: 1024px) {
.nav-m-play { display: none; }
}
.nav-m-play:active { transform: translateX(-50%) scale(0.9); }
.nav-m-play .icon { width: 24px; height: 24px; color: var(--text-inverse); stroke-width: 2.5; }
/* (floating play FAB removed — games are the nav now) */
/* === MAIN CONTENT === */
.main {
......@@ -678,82 +633,7 @@ img { display: block; max-width: 100%; }
color: var(--text-2);
}
/* === FEATURED PLAY CARD (Home hero) === */
.hero-play {
position: relative;
border-radius: var(--r-xl);
overflow: hidden;
background: linear-gradient(135deg, var(--bg-2) 0%, var(--bg-1) 100%);
border: 1px solid rgba(245, 183, 49, 0.2);
padding: var(--sp-5);
display: flex;
flex-direction: column;
gap: var(--sp-4);
}
.hero-play::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(245, 183, 49, 0.06) 0%, transparent 70%);
pointer-events: none;
}
.hero-play-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.hero-play-title {
font-size: 18px;
font-weight: 700;
}
.hero-play-subtitle {
font-size: 12px;
color: var(--text-3);
margin-top: 2px;
}
.hero-play-btn {
display: flex;
align-items: center;
justify-content: center;
gap: var(--sp-2);
width: 100%;
padding: 14px;
background: var(--gold);
color: var(--text-inverse);
font-weight: 700;
font-size: 15px;
border-radius: var(--r-md);
box-shadow: var(--shadow-glow-gold);
transition: transform 0.1s, box-shadow 0.2s;
position: relative;
overflow: hidden;
}
.hero-play-btn::after {
content: '';
position: absolute;
top: 0;
right: -100%;
width: 60%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
animation: shimmer 4s ease-in-out infinite;
}
@keyframes shimmer {
0% { right: -100%; }
100% { right: 200%; }
}
.hero-play-btn:active { transform: scale(0.97); }
/* (hero-play removed — home page is now a game hub grid, not a chess launcher) */
/* === STREAK BANNER === */
.streak-banner {
......
......@@ -4,17 +4,13 @@ $navItems = [
['/', 'icon-home', 'الرئيسية'],
['/games', 'icon-games', 'العاب'],
['/leaderboard', 'icon-leaderboard', 'ترتيب'],
['/friends', 'icon-friends', 'اجتماعي'],
['/profile', 'icon-profile', 'حسابي'],
];
?>
<!-- Floating play button -->
<a href="/play" class="nav-m-play" aria-label="العب الان">
<svg class="icon"><use href="/public/icons/sprite.svg#icon-play"></use></svg>
</a>
<nav class="nav-m" aria-label="التنقل">
<?php foreach ($navItems as $item):
<?php foreach ($navItems as $i => $item):
$href = $item[0]; $icon = $item[1]; $label = $item[2];
$route = trim($href, '/');
$isActive = ($route === '' && $currentRoute === '') || ($route !== '' && $currentRoute === $route);
......
<nav class="sidebar" aria-label="التنقل الرئيسي">
<span class="sidebar-brand">EL3AB</span>
<a href="/play" class="sidebar-play-btn">
<svg class="icon"><use href="/public/icons/sprite.svg#icon-play"></use></svg>
العب الان
</a>
<?php
$currentRoute = $_GET['route'] ?? '';
?>
<!-- Games ARE the primary nav -->
<div class="sidebar-section">
<span class="sidebar-label">العاب</span>
<?php
$currentRoute = $_GET['route'] ?? '';
$gameItems = [
['/games', 'icon-games', 'جميع الالعاب'],
['/puzzles', 'icon-puzzle', 'تمارين'],
$gameNav = [
['/play', 'icon-play', 'شطرنج'],
['/ludo', 'icon-ludo', 'لودو'],
['/backgammon', 'icon-backgammon', 'طاولة'],
['/domino', 'icon-domino', 'دومينو'],
];
foreach ($gameNav as $item):
$href = $item[0]; $icon = $item[1]; $label = $item[2];
$route = trim($href, '/');
$isActive = ($route !== '' && $currentRoute === $route);
?>
<a href="<?= $href ?>" class="sidebar-item <?= $isActive ? 'active' : '' ?>">
<svg class="icon"><use href="/public/icons/sprite.svg#<?= $icon ?>"></use></svg>
<?= $label ?>
</a>
<?php endforeach; ?>
</div>
<div class="sidebar-section">
<span class="sidebar-label">تنافس</span>
<?php
$competeItems = [
['/tournaments', 'icon-trophy', 'بطولات', 'tournaments_enabled'],
['/leaderboard', 'icon-leaderboard', 'المتصدرين'],
];
foreach ($gameItems as $item):
foreach ($competeItems as $item):
$href = $item[0]; $icon = $item[1]; $label = $item[2]; $flag = $item[3] ?? null;
if ($flag && !is_feature_enabled($flag)) continue;
$route = trim($href, '/');
......@@ -32,7 +51,6 @@
<span class="sidebar-label">اجتماعي</span>
<?php
$socialItems = [
['/leaderboard', 'icon-leaderboard', 'المتصدرين'],
['/friends', 'icon-friends', 'الاصدقاء'],
['/orgs', 'icon-org', 'الاندية'],
];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment