Commit 344b3714 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat: i18n tournament arena, detail, and live scenes

Replace hardcoded Arabic in tournament-arena.js (7 strings),
tournament-detail.js (10 strings), tournament-live.js (8 strings).
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 4140b7da
...@@ -142,7 +142,7 @@ async function loadArenaStandings(el, tournamentId) { ...@@ -142,7 +142,7 @@ async function loadArenaStandings(el, tournamentId) {
return ` return `
<div style="display:flex;align-items:center;padding:6px 8px;background:${isMe ? '#1a2e1a' : '#1a1a2e'};border-radius:6px;margin-bottom:4px;border:${isMe ? '1px solid #E4AC38' : '1px solid transparent'};"> <div style="display:flex;align-items:center;padding:6px 8px;background:${isMe ? '#1a2e1a' : '#1a1a2e'};border-radius:6px;margin-bottom:4px;border:${isMe ? '1px solid #E4AC38' : '1px solid transparent'};">
<span style="width:24px;font-size:${i < 3 ? '14px' : '11px'};text-align:center;">${i < 3 ? medals[i] : (i + 1)}</span> <span style="width:24px;font-size:${i < 3 ? '14px' : '11px'};text-align:center;">${i < 3 ? medals[i] : (i + 1)}</span>
<span style="flex:1;font-size:12px;color:#f8fafc;font-weight:${isMe ? '700' : '400'};">${p.name}${isMe ? ' (أنت)' : ''}</span> <span style="flex:1;font-size:12px;color:#f8fafc;font-weight:${isMe ? '700' : '400'};">${p.name}${isMe ? ` (${t('common.you')})` : ''}</span>
<span style="font-size:12px;font-weight:700;color:#E4AC38;">${p.points}</span> <span style="font-size:12px;font-weight:700;color:#E4AC38;">${p.points}</span>
<span style="font-size:10px;color:#64748b;margin-right:4px;width:50px;text-align:left;">${p.wins}W ${p.draws}D ${p.losses}L</span> <span style="font-size:10px;color:#64748b;margin-right:4px;width:50px;text-align:left;">${p.wins}W ${p.draws}D ${p.losses}L</span>
</div> </div>
......
...@@ -16,16 +16,16 @@ export async function mountTournamentDetail(el, params) { ...@@ -16,16 +16,16 @@ export async function mountTournamentDetail(el, params) {
<div style="display:flex;flex-direction:column;height:100%;background:#0a0a1a;"> <div style="display:flex;flex-direction:column;height:100%;background:#0a0a1a;">
<div style="display:flex;align-items:center;gap:12px;padding:10px 14px;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.06);"> <div style="display:flex;align-items:center;gap:12px;padding:10px 14px;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.06);">
<button class="btn btn-secondary" id="back-btn" style="min-height:32px;padding:4px 12px;font-size:12px;">←</button> <button class="btn btn-secondary" id="back-btn" style="min-height:32px;padding:4px 12px;font-size:12px;">←</button>
<span id="tour-title" style="font-size:15px;font-weight:700;color:#f8fafc;flex:1;">بطولة</span> <span id="tour-title" style="font-size:15px;font-weight:700;color:#f8fafc;flex:1;">${t('tournament.title')}</span>
</div> </div>
<!-- Tabs --> <!-- Tabs -->
<div style="display:flex;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.04);padding:0 8px;overflow-x:auto;"> <div style="display:flex;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.04);padding:0 8px;overflow-x:auto;">
<button class="tour-tab active" data-tab="info">معلومات</button> <button class="tour-tab active" data-tab="info">${t('tournament.tab_info')}</button>
<button class="tour-tab" data-tab="standings">الترتيب</button> <button class="tour-tab" data-tab="standings">${t('tournament.tab_standings')}</button>
<button class="tour-tab" data-tab="rounds">الجولات</button> <button class="tour-tab" data-tab="rounds">${t('tournament.tab_rounds')}</button>
<button class="tour-tab" data-tab="my-games">مبارياتي</button> <button class="tour-tab" data-tab="my-games">${t('tournament.tab_my_games')}</button>
<button class="tour-tab" data-tab="bracket" id="tab-bracket" style="display:none;">الشجرة</button> <button class="tour-tab" data-tab="bracket" id="tab-bracket" style="display:none;">${t('tournament.tab_bracket')}</button>
<button class="tour-tab" data-tab="arena" id="tab-arena" style="display:none;">أرينا</button> <button class="tour-tab" data-tab="arena" id="tab-arena" style="display:none;">${t('tournament.tab_arena')}</button>
</div> </div>
<!-- Content --> <!-- Content -->
<div id="tour-content" style="flex:1;overflow-y:auto;padding:14px;"></div> <div id="tour-content" style="flex:1;overflow-y:auto;padding:14px;"></div>
...@@ -68,7 +68,7 @@ async function loadTab(el, tournamentId, tab) { ...@@ -68,7 +68,7 @@ async function loadTab(el, tournamentId, tab) {
} }
const content = el.querySelector('#tour-content'); const content = el.querySelector('#tour-content');
content.innerHTML = '<div style="text-align:center;color:#64748b;padding:24px;">جاري التحميل...</div>'; content.innerHTML = `<div style="text-align:center;color:#64748b;padding:24px;">${t('common.loading')}</div>`;
switch (tab) { switch (tab) {
case 'info': await loadInfo(content, tournamentId, el); break; case 'info': await loadInfo(content, tournamentId, el); break;
...@@ -84,7 +84,7 @@ async function loadInfo(content, tournamentId, el) { ...@@ -84,7 +84,7 @@ async function loadInfo(content, tournamentId, el) {
if (data.error) throw new Error(data.error); if (data.error) throw new Error(data.error);
tournamentData = data; tournamentData = data;
el.querySelector('#tour-title').textContent = data.name || 'بطولة'; el.querySelector('#tour-title').textContent = data.name || t('tournament.title');
// Show format-specific tabs // Show format-specific tabs
const format = data.format || ''; const format = data.format || '';
...@@ -98,7 +98,7 @@ async function loadInfo(content, tournamentId, el) { ...@@ -98,7 +98,7 @@ async function loadInfo(content, tournamentId, el) {
} }
const statusColors = { registration: '#34D399', in_progress: '#E4AC38', completed: '#64748b', draft: '#3B82F6' }; const statusColors = { registration: '#34D399', in_progress: '#E4AC38', completed: '#64748b', draft: '#3B82F6' };
const statusLabels = { registration: 'تسجيل مفتوح', in_progress: 'جارية', completed: 'منتهية', draft: 'قريباً' }; const statusLabels = { registration: t('tournament.registration_open'), in_progress: t('tournament.active'), completed: t('tournament.completed'), draft: t('tournament.coming_soon') };
content.innerHTML = ` content.innerHTML = `
<div style="text-align:center;margin-bottom:16px;"> <div style="text-align:center;margin-bottom:16px;">
......
...@@ -3,6 +3,7 @@ import * as net from '../../../core/net.js'; ...@@ -3,6 +3,7 @@ import * as net from '../../../core/net.js';
import * as audio from '../../../core/audio.js'; import * as audio from '../../../core/audio.js';
import * as store from '../../../core/store.js'; import * as store from '../../../core/store.js';
import { emoji } from '../../../core/theme.js'; import { emoji } from '../../../core/theme.js';
import { t } from '../../../core/i18n.js';
let refreshInterval = null; let refreshInterval = null;
...@@ -15,7 +16,7 @@ export function mountTournamentLive(el, params) { ...@@ -15,7 +16,7 @@ export function mountTournamentLive(el, params) {
<div style="display:flex;flex-direction:column;height:100%;background:#0a0a1a;"> <div style="display:flex;flex-direction:column;height:100%;background:#0a0a1a;">
<div style="display:flex;align-items:center;gap:12px;padding:10px 14px;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.06);"> <div style="display:flex;align-items:center;gap:12px;padding:10px 14px;background:#0f0f1e;border-bottom:1px solid rgba(255,255,255,0.06);">
<button class="btn btn-secondary" id="back-btn" style="min-height:32px;padding:4px 12px;font-size:12px;">←</button> <button class="btn btn-secondary" id="back-btn" style="min-height:32px;padding:4px 12px;font-size:12px;">←</button>
<span style="font-size:15px;font-weight:700;color:#f8fafc;flex:1;">${emoji('live', '🔴', 12)} LIVE — ${tournamentName || 'بطولة'}</span> <span style="font-size:15px;font-weight:700;color:#f8fafc;flex:1;">${emoji('live', '🔴', 12)} LIVE — ${tournamentName || t('tournament.title')}</span>
</div> </div>
<div id="live-content" style="flex:1;overflow-y:auto;padding:14px;"></div> <div id="live-content" style="flex:1;overflow-y:auto;padding:14px;"></div>
</div> </div>
...@@ -50,8 +51,8 @@ async function loadLiveData(el, tournamentId) { ...@@ -50,8 +51,8 @@ async function loadLiveData(el, tournamentId) {
// Current round info // Current round info
if (currentRound) { if (currentRound) {
html += `<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;"> html += `<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<span style="font-size:14px;font-weight:700;color:#f8fafc;">الجولة ${currentRound.round_number}/${rounds.length}</span> <span style="font-size:14px;font-weight:700;color:#f8fafc;">${t('tournament.round_n', { n: currentRound.round_number, total: rounds.length })}</span>
<span style="font-size:11px;padding:3px 8px;border-radius:99px;background:${currentRound.status === 'in_progress' ? '#E4AC38' : '#64748b'};color:#000;font-weight:600;">${currentRound.status === 'in_progress' ? 'جارية' : 'منتهية'}</span> <span style="font-size:11px;padding:3px 8px;border-radius:99px;background:${currentRound.status === 'in_progress' ? '#E4AC38' : '#64748b'};color:#000;font-weight:600;">${currentRound.status === 'in_progress' ? t('tournament.active') : t('tournament.completed')}</span>
</div>`; </div>`;
// Show pairings for current round // Show pairings for current round
...@@ -62,7 +63,7 @@ async function loadLiveData(el, tournamentId) { ...@@ -62,7 +63,7 @@ async function loadLiveData(el, tournamentId) {
if (pairings.length > 0) { if (pairings.length > 0) {
html += `<div style="margin-bottom:16px;">`; html += `<div style="margin-bottom:16px;">`;
html += `<div style="font-size:12px;font-weight:700;color:#94a3b8;margin-bottom:8px;">مباريات جارية</div>`; html += `<div style="font-size:12px;font-weight:700;color:#94a3b8;margin-bottom:8px;">${t('tournament.live_matches')}</div>`;
pairings.forEach(p => { pairings.forEach(p => {
const hasResult = !!p.result; const hasResult = !!p.result;
html += ` html += `
...@@ -70,7 +71,7 @@ async function loadLiveData(el, tournamentId) { ...@@ -70,7 +71,7 @@ async function loadLiveData(el, tournamentId) {
<span style="flex:1;font-size:12px;color:#f8fafc;text-align:right;">${p.white_name || p.player_a || '?'}</span> <span style="flex:1;font-size:12px;color:#f8fafc;text-align:right;">${p.white_name || p.player_a || '?'}</span>
<span style="padding:2px 8px;font-size:11px;font-weight:700;color:${hasResult ? '#34D399' : '#E4AC38'};">${p.result || 'vs'}</span> <span style="padding:2px 8px;font-size:11px;font-weight:700;color:${hasResult ? '#34D399' : '#E4AC38'};">${p.result || 'vs'}</span>
<span style="flex:1;font-size:12px;color:#f8fafc;text-align:left;">${p.black_name || p.player_b || '?'}</span> <span style="flex:1;font-size:12px;color:#f8fafc;text-align:left;">${p.black_name || p.player_b || '?'}</span>
${!hasResult ? `<button class="spectate-btn" data-white="${p.player_a || p.white_id || ''}" data-black="${p.player_b || p.black_id || ''}" style="margin-right:4px;padding:2px 8px;background:#3B82F6;border:none;border-radius:4px;color:#fff;font-size:10px;font-weight:600;cursor:pointer;">شاهد</button>` : ''} ${!hasResult ? `<button class="spectate-btn" data-white="${p.player_a || p.white_id || ''}" data-black="${p.player_b || p.black_id || ''}" style="margin-right:4px;padding:2px 8px;background:#3B82F6;border:none;border-radius:4px;color:#fff;font-size:10px;font-weight:600;cursor:pointer;">${t('spectate.watch')}</button>` : ''}
</div> </div>
`; `;
}); });
...@@ -81,7 +82,7 @@ async function loadLiveData(el, tournamentId) { ...@@ -81,7 +82,7 @@ async function loadLiveData(el, tournamentId) {
// Standings // Standings
if (standings.length > 0) { if (standings.length > 0) {
html += `<div style="font-size:12px;font-weight:700;color:#94a3b8;margin-bottom:8px;">الترتيب</div>`; html += `<div style="font-size:12px;font-weight:700;color:#94a3b8;margin-bottom:8px;">${t('tournament.tab_standings')}</div>`;
html += standings.slice(0, 15).map((p, i) => { html += standings.slice(0, 15).map((p, i) => {
const medals = ['🥇', '🥈', '🥉']; const medals = ['🥇', '🥈', '🥉'];
return ` return `
...@@ -95,7 +96,7 @@ async function loadLiveData(el, tournamentId) { ...@@ -95,7 +96,7 @@ async function loadLiveData(el, tournamentId) {
} }
if (!html) { if (!html) {
html = '<div style="text-align:center;color:#64748b;padding:32px;">لا توجد بيانات بعد</div>'; html = `<div style="text-align:center;color:#64748b;padding:32px;">${t('common.empty')}</div>`;
} }
content.innerHTML = html; content.innerHTML = html;
...@@ -117,13 +118,13 @@ async function loadLiveData(el, tournamentId) { ...@@ -117,13 +118,13 @@ async function loadLiveData(el, tournamentId) {
if (data2.match_id) { if (data2.match_id) {
scene.push('chess-spectate', { matchId: data2.match_id }); scene.push('chess-spectate', { matchId: data2.match_id });
} else { } else {
btn.textContent = 'لا توجد مباراة'; btn.textContent = t('tournament.no_match');
setTimeout(() => { btn.textContent = 'شاهد'; btn.disabled = false; }, 2000); setTimeout(() => { btn.textContent = t('spectate.watch'); btn.disabled = false; }, 2000);
} }
} }
} catch (e) { } catch (e) {
btn.textContent = 'خطأ'; btn.textContent = t('common.error');
setTimeout(() => { btn.textContent = 'شاهد'; btn.disabled = false; }, 2000); setTimeout(() => { btn.textContent = t('spectate.watch'); btn.disabled = false; }, 2000);
} }
}); });
}); });
......
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