bep40 commited on
Commit
d25db91
·
verified ·
1 Parent(s): 3d237b1

Upload static/match_detail.js

Browse files
Files changed (1) hide show
  1. static/match_detail.js +121 -167
static/match_detail.js CHANGED
@@ -1,19 +1,14 @@
1
  // === VNEWS — Match Detail UI ===
2
- // Fetches & renders match detail (preview, lineups, H2H, stats) from bongda.com.vn
3
- // Loaded after app_v2.js; extends the match overlay with a "Chi tiết" tab.
4
 
5
  (function(){
6
- // Inject styles
7
- if(document.getElementById('match-detail-css')) return;
8
- const s = document.createElement('style');
9
- s.id = 'match-detail-css';
10
- s.textContent = `
11
- .md-loading{display:flex;align-items:center;justify-content:center;padding:30px;color:#888;font-size:12px;flex-direction:column;gap:8px}
12
- .md-spinner{width:24px;height:24px;border:3px solid #333;border-top-color:#5cb87a;border-radius:50%;animation:md-spin .8s linear infinite}
13
- @keyframes md-spin{to{transform:rotate(360deg)}}
14
- .md-section{margin-bottom:16px}
15
- .md-section-title{font-size:13px;font-weight:800;color:#5cb87a;margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid #2a2a2a;display:flex;align-items:center;gap:6px}
16
- .md-preview-text{font-size:13px;color:#ccc;line-height:1.6;white-space:pre-wrap;background:#1a1a1a;border-radius:8px;padding:12px;border-left:3px solid #2d8659}
17
  .md-lineups{display:grid;grid-template-columns:1fr 1fr;gap:12px}
18
  .md-team-box{background:#1a2a1f;border:1px solid #2a3a2a;border-radius:8px;padding:10px}
19
  .md-team-name{font-size:13px;font-weight:800;color:#5cb87a;margin-bottom:4px;text-align:center}
@@ -28,227 +23,186 @@
28
  .md-h2h-home{text-align:right;flex:1}
29
  .md-h2h-away{text-align:left;flex:1}
30
  .md-h2h-score{font-size:13px;font-weight:800;color:#f0c040;min-width:40px;text-align:center}
31
- .md-h2h-live{color:#e74c3c;font-size:9px;font-weight:700}
32
- .md-no-data{color:#777;font-size:12px;padding:20px;text-align:center;line-height:1.6}
33
- .md-preview-container{font-size:13px;color:#ccc;line-height.6}
34
- .md-preview-container img{max-width:100%;border-radius:6px;margin:8px 0}
35
- .md-preview-container p{margin-bottom:8px}
36
- .md-preview-container h2,.md-preview-container h3{color:#eee;margin:12px 0 6px}
37
- .md-lineups-container,.md-h2h-container,.md-stats-container{font-size:12px;color:#ccc}
38
- .md-lineups-container table,.md-h2h-container table,.md-stats-container table{width:100%;border-collapse:collapse}
39
- .md-lineups-container td,.md-h2h-container td,.md-stats-container td{padding:4px 6px;border-bottom:1px solid #1a1a1a}
40
- .md-lineups-container tr:hover,.md-h2h-container tr:hover{background:#1a2a1f}
41
  `;
42
  document.head.appendChild(s);
43
 
44
- function esc(s){return String(s||'').replace(/[&<>"']/g,m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]))}
 
 
 
 
 
 
 
45
 
46
- // Store original loadMatchTab
47
- const _origLoadMatchTab = window.loadMatchTab;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
- // Override loadMatchTab to handle detail tab
 
50
  window.loadMatchTab = async function(tab){
51
  if(tab === 'detail'){
52
  document.querySelectorAll('.mo-tab').forEach(t=>t.classList.remove('active'));
53
  document.querySelectorAll('.mo-tab').forEach(t=>{
54
- if(t.textContent.includes('Chi tiết') || t.textContent.includes('Detail')) t.classList.add('active');
55
  });
56
  const el = document.getElementById('mo-body');
57
  if(!el) return;
58
- el.innerHTML = '<div class="md-loading"><div class="md-spinner"></div>Đang tải chi tiết trận đấu...</div>';
 
 
 
 
 
 
 
59
  try{
60
- const eventId = window._currentEventId;
61
- if(!eventId){
62
- // Try to extract from overlay title or page
63
- el.innerHTML = '<div class="md-no-data">⚠️ Không tìm thấy mã trận đấu.<br><small>Vui lòng đóng và mở lại từ danh sách livescore.</small></div>';
64
- return;
65
- }
66
  const r = await fetch(`/api/match/${eventId}/detail`);
67
- if(!r.ok){ throw new Error('HTTP ' + r.status); }
68
  const d = await r.json();
 
69
  renderMatchDetail(el, d);
70
  }catch(e){
71
- console.error('Match detail error:', e);
72
- el.innerHTML = '<div class="md-no-data">⚠️ Lỗi tải chi tiết: ' + esc(e.message) + '<br><small>Vui lòng thử lại sau hoặc chuyển sang tab "Diễn biến".</small></div>';
73
  }
74
  } else {
75
- _origLoadMatchTab(tab);
76
  }
77
  };
78
 
79
  function renderMatchDetail(el, data){
80
  let h = '';
81
 
82
- // === 1. Preview / Commentaries ===
83
  if(data.commentaries_html && data.commentaries_html.length > 10){
84
- h += '<div class="md-section">';
85
- h += '<div class="md-section-title">📋 Thông tin trận đấu</div>';
86
- let cleanHtml = data.commentaries_html
87
  .replace(/<script[^>]*>.*?<\/script>/gi, '')
88
  .replace(/<iframe[^>]*>.*?<\/iframe>/gi, '')
89
  .replace(/<ins[^>]*>.*?<\/ins>/gi, '')
90
- .replace(/<style[^>]*>.*?<\/style>/gi, '')
91
  .replace(/style="[^"]*display:\s*none[^"]*"/gi, 'style="display:none"');
92
- h += '<div class="md-preview-container">' + cleanHtml + '</div>';
93
- h += '</div>';
94
  } else if(data.preview_text && data.preview_text.length > 0){
95
- h += '<div class="md-section">';
96
- h += '<div class="md-section-title">📋 Thông tin trận đấu</div>';
97
- h += '<div class="md-preview-text">' + data.preview_text.map(t=>esc(t)).join('\n\n') + '</div>';
98
- h += '</div>';
99
  }
100
 
101
- // === 2. Lineups ===
102
  if(data.lineups_html && data.lineups_html.length > 10){
103
- h += '<div class="md-section">';
104
- h += '<div class="md-section-title"> Đội hình</div>';
105
- let cleanLineups = data.lineups_html
106
- .replace(/<script[^>]*>.*?<\/script>/gi, '')
107
- .replace(/<iframe[^>]*>.*?<\/iframe>/gi, '')
108
- .replace(/<ins[^>]*>.*?<\/ins>/gi, '')
109
- .replace(/<style[^>]*>.*?<\/style>/gi, '');
110
- h += '<div class="md-lineups-container">' + cleanLineups + '</div>';
111
- h += '</div>';
112
  } else if(data.lineups && (data.lineups.home_players || data.lineups.away_players)){
113
- h += '<div class="md-section">';
114
- h += '<div class="md-section-title">⚽ Đội hình</div>';
115
- h += renderLineups(data.lineups);
116
- h += '</div>';
117
  }
118
 
119
- // === 3. Head-to-Head ===
120
  if(data.h2h_html && data.h2h_html.length > 10){
121
- h += '<div class="md-section">';
122
- h += '<div class="md-section-title">🔄 Đối đầu (H2H)</div>';
123
- let cleanH2h = data.h2h_html
124
- .replace(/<script[^>]*>.*?<\/script>/gi, '')
125
- .replace(/<iframe[^>]*>.*?<\/iframe>/gi, '')
126
- .replace(/<style[^>]*>.*?<\/style>/gi, '');
127
- h += '<div class="md-h2h-container">' + cleanH2h + '</div>';
128
- h += '</div>';
129
  } else if(data.h2h && data.h2h.length > 0){
130
- h += '<div class="md-section">';
131
- h += '<div class="md-section-title">🔄 Đối đầu (H2H)</div>';
132
- h += renderH2H(data.h2h);
133
- h += '</div>';
134
  }
135
 
136
- // === 4. Match Stats ===
137
  if(data.stats_html && data.stats_html.length > 10){
138
- h += '<div class="md-section">';
139
- h += '<div class="md-section-title">📊 Thống </div>';
140
- let cleanStats = data.stats_html
141
- .replace(/<script[^>]*>.*?<\/script>/gi, '')
142
- .replace(/<iframe[^>]*>.*?<\/iframe>/gi, '')
143
- .replace(/<style[^>]*>.*?<\/style>/gi, '');
144
- h += '<div class="md-stats-container">' + cleanStats + '</div>';
145
- h += '</div>';
146
  }
147
 
148
- // === 5. Match Info ===
149
  if(data.info && Object.keys(data.info).length > 0){
150
- h += '<div class="md-section">';
151
- h += '<div class="md-section-title">📍 Thông tin</div>';
152
  h += '<div style="font-size:12px;color:#ccc;line-height:1.8;padding:8px;background:#1a1a1a;border-radius:8px">';
153
- if(data.info.date) h += '<div>📅 Ngày: <b>' + esc(data.info.date) + '</b></div>';
154
- if(data.info.time) h += '<div>🕐 Giờ: <b>' + esc(data.info.time) + '</b></div>';
155
- if(data.info.stadium) h += '<div>🏟 Sân: <b>' + esc(data.info.stadium) + '</b></div>';
156
- if(data.info.referee) h += '<div>👨‍⚖️ Trọng tài: <b>' + esc(data.info.referee) + '</b></div>';
157
  h += '</div></div>';
158
  }
159
 
160
  if(!h){
161
- h = '<div class="md-no-data">Chưa có chi tiết cho trận đấu này.<br><small style="color:#666">Dữ liệu sẽ cập nhật khi giải khởi tranh hoặc trận đấu bắt đầu.</small><br><br><button onclick="window.loadMatchTab(\'comm\')" style="background:#2d8659;border:0;color:#fff;padding:8px 16px;border-radius:8px;font-size:11px;cursor:pointer">Xem Diễn biến</button></div>';
162
  }
163
 
164
  el.innerHTML = h;
165
  el.querySelectorAll('a').forEach(a=>a.addEventListener('click', e=>e.preventDefault()));
166
  }
167
 
168
- function renderLineups(lineups){
169
- let h = '<div class="md-lineups">';
170
- h += '<div class="md-team-box">';
171
- h += '<div class="md-team-name">' + esc(lineups.home_team || 'Đội nhà') + '</div>';
172
- if(lineups.home_formation) h += '<div class="md-formation">Đội hình: ' + esc(lineups.home_formation) + '</div>';
173
- h += '<ul class="md-player-list">';
174
- (lineups.home_players || []).forEach((p,i)=>{
175
- h += '<li class="md-player-item"><span class="md-player-no">' + (i+1) + '</span>' + esc(p) + '</li>';
176
- });
177
- h += '</ul>';
178
- if(lineups.home_subs && lineups.home_subs.length > 0){
179
- h += '<div class="md-subs-title">🔄 Dự bị:</div>';
180
- (lineups.home_subs || []).forEach(p=>{
181
- h += '<div style="font-size:10px;color:#888;padding:2px 0">' + esc(p) + '</div>';
182
- });
183
- }
184
- h += '</div>';
185
- h += '<div class="md-team-box">';
186
- h += '<div class="md-team-name">' + esc(lineups.away_team || 'Đội khách') + '</div>';
187
- if(lineups.away_formation) h += '<div class="md-formation">Đội hình: ' + esc(lineups.away_formation) + '</div>';
188
- h += '<ul class="md-player-list">';
189
- (lineups.away_players || []).forEach((p,i)=>{
190
- h += '<li class="md-player-item"><span class="md-player-no">' + (i+1) + '</span>' + esc(p) + '</li>';
191
- });
192
- h += '</ul>';
193
- if(lineups.away_subs && lineups.away_subs.length > 0){
194
- h += '<div class="md-subs-title">🔄 Dự bị:</div>';
195
- (lineups.away_subs || []).forEach(p=>{
196
- h += '<div style="font-size:10px;color:#888;padding:2px 0">' + esc(p) + '</div>';
197
- });
198
- }
199
- h += '</div>';
200
- h += '</div>';
201
  return h;
202
  }
203
 
204
  function renderH2H(matches){
205
- let h = '';
206
  matches.forEach(m=>{
207
- const isLive = m.status === 'live';
208
- h += '<div class="md-h2h-item">';
209
- h += '<span class="md-h2h-date">' + esc(m.date || '') + '</span>';
210
- h += '<span class="md-h2h-teams">';
211
- h += '<span class="md-h2h-home">' + esc(m.home || '') + '</span>';
212
- h += '<span class="md-h2h-score">' + esc(m.score || 'vs') + '</span>';
213
- h += '<span class="md-h2h-away">' + esc(m.away || '') + '</span>';
214
- h += '</span>';
215
- if(isLive) h += '<span class="md-h2h-live">LIVE</span>';
216
- h += '</div>';
217
  });
218
  return h;
219
  }
220
 
221
- // Add the "Chi tiết" tab to the match overlay
222
  function injectDetailTab(){
223
- const check = setInterval(()=>{
224
- const tabsContainer = document.querySelector('.mo-tabs');
225
- if(tabsContainer && !document.querySelector('.mo-tab-detail')){
226
- const existing = document.querySelector('.mo-tab-detail');
227
- if(existing) existing.remove();
228
- const detailTab = document.createElement('span');
229
- detailTab.className = 'mo-tab mo-tab-detail';
230
- detailTab.textContent = '📋 Chi tiết';
231
- detailTab.onclick = ()=>window.loadMatchTab('detail');
232
- // Insert as first tab
233
- tabsContainer.insertBefore(detailTab, tabsContainer.firstChild);
234
- clearInterval(check);
235
- }
236
- }, 500);
237
- setTimeout(()=>clearInterval(check), 30000);
238
  }
239
 
240
- // Override openMatch to inject detail tab
241
- const _origOpenMatch = window.openMatch;
242
- if(_origOpenMatch){
243
- window.openMatch = function(id){
244
- _origOpenMatch(id);
245
- setTimeout(injectDetailTab, 300);
246
- };
247
- }
 
 
 
 
248
 
249
- if(document.readyState === 'loading'){
250
- document.addEventListener('DOMContentLoaded', ()=>setTimeout(injectDetailTab, 1000));
251
- } else {
252
- setTimeout(injectDetailTab, 1000);
253
- }
254
  })();
 
1
  // === VNEWS — Match Detail UI ===
2
+ // Renders match detail (preview, lineups, H2H) in the match overlay
3
+ // Auto-extracts event_id from the clicked match element
4
 
5
  (function(){
6
+ if(document.getElementById('md-css')) return;
7
+ const s=document.createElement('style'); s.id='md-css';
8
+ s.textContent=`
9
+ .md-sec{margin-bottom:16px}
10
+ .md-sec-title{font-size:13px;font-weight:800;color:#5cb87a;margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid #2a2a2a;display:flex;align-items:center;gap:6px}
11
+ .md-preview-text{font-size:13px;color:#ccc;line-height:1.6;background:#1a1a1a;border-radius:8px;padding:12px;border-left:3px solid #2d8659;max-height:300px;overflow-y:auto}
 
 
 
 
 
12
  .md-lineups{display:grid;grid-template-columns:1fr 1fr;gap:12px}
13
  .md-team-box{background:#1a2a1f;border:1px solid #2a3a2a;border-radius:8px;padding:10px}
14
  .md-team-name{font-size:13px;font-weight:800;color:#5cb87a;margin-bottom:4px;text-align:center}
 
23
  .md-h2h-home{text-align:right;flex:1}
24
  .md-h2h-away{text-align:left;flex:1}
25
  .md-h2h-score{font-size:13px;font-weight:800;color:#f0c040;min-width:40px;text-align:center}
26
+ .md-no-data{color:#777;font-size:12px;padding:20px;text-align:center}
27
+ .md-err{color:#e74c3c;font-size:12px;padding:20px;text-align:center}
 
 
 
 
 
 
 
 
28
  `;
29
  document.head.appendChild(s);
30
 
31
+ // Override openMatch to store event_id properly
32
+ const _origOpenMatch = window.openMatch;
33
+ window.openMatch = function(id){
34
+ if(id) window._currentEventId = id;
35
+ if(_origOpenMatch) _origOpenMatch(id);
36
+ // Inject detail tab after overlay opens
37
+ setTimeout(injectDetailTab, 200);
38
+ };
39
 
40
+ // Also intercept match clicks from livescore to capture event_id
41
+ function interceptMatchClick(e){
42
+ const md = e.target.closest('.match-detail');
43
+ if(!md){
44
+ // Try parent
45
+ const md2 = e.target.closest('[class*="match"]');
46
+ if(!md2) return;
47
+ }
48
+ // Find event_id from the link
49
+ const link = (md||e.target).querySelector('.status a, a[href*="tran-dau"]');
50
+ if(link){
51
+ const href = link.getAttribute('href') || '';
52
+ const m = href.match(/\/tran-dau\/(\d+)\//);
53
+ if(m) window._currentEventId = m[1];
54
+ }
55
+ }
56
 
57
+ // Override loadMatchTab
58
+ const _origLoadMatchTab = window.loadMatchTab;
59
  window.loadMatchTab = async function(tab){
60
  if(tab === 'detail'){
61
  document.querySelectorAll('.mo-tab').forEach(t=>t.classList.remove('active'));
62
  document.querySelectorAll('.mo-tab').forEach(t=>{
63
+ if(t.textContent.includes('Chi tiết') || t.textContent.includes('📋')) t.classList.add('active');
64
  });
65
  const el = document.getElementById('mo-body');
66
  if(!el) return;
67
+ el.innerHTML = '<div class="md-no-data">Đang tải chi tiết trận đấu...</div>';
68
+
69
+ const eventId = window._currentEventId;
70
+ if(!eventId){
71
+ el.innerHTML = '<div class="md-err">⚠️ Không tìm thấy mã trận đấu.<br><small>Hãy click vào một trận đấu cụ thể từ danh sách livescore.</small></div>';
72
+ return;
73
+ }
74
+
75
  try{
 
 
 
 
 
 
76
  const r = await fetch(`/api/match/${eventId}/detail`);
77
+ if(!r.ok) throw new Error('API error ' + r.status);
78
  const d = await r.json();
79
+ if(d.error) throw new Error(d.error);
80
  renderMatchDetail(el, d);
81
  }catch(e){
82
+ el.innerHTML = '<div class="md-err">⚠️ Lỗi tải chi tiết: ' + esc(e.message) + '<br><small>Event ID: ' + esc(String(eventId)) + '</small></div>';
 
83
  }
84
  } else {
85
+ if(_origLoadMatchTab) _origLoadMatchTab(tab);
86
  }
87
  };
88
 
89
  function renderMatchDetail(el, data){
90
  let h = '';
91
 
92
+ // 1. Preview / Commentaries
93
  if(data.commentaries_html && data.commentaries_html.length > 10){
94
+ h += '<div class="md-sec"><div class="md-sec-title">📋 Thông tin trận đấu</div>';
95
+ let clean = data.commentaries_html
 
96
  .replace(/<script[^>]*>.*?<\/script>/gi, '')
97
  .replace(/<iframe[^>]*>.*?<\/iframe>/gi, '')
98
  .replace(/<ins[^>]*>.*?<\/ins>/gi, '')
 
99
  .replace(/style="[^"]*display:\s*none[^"]*"/gi, 'style="display:none"');
100
+ h += '<div class="md-preview-text">' + clean + '</div></div>';
 
101
  } else if(data.preview_text && data.preview_text.length > 0){
102
+ h += '<div class="md-sec"><div class="md-sec-title">📋 Thông tin trận đấu</div>';
103
+ h += '<div class="md-preview-text">' + data.preview_text.map(t=>esc(t)).join('<br><br>') + '</div></div>';
 
 
104
  }
105
 
106
+ // 2. Lineups
107
  if(data.lineups_html && data.lineups_html.length > 10){
108
+ h += '<div class="md-sec"><div class="md-sec-title">⚽ Đội hình</div>';
109
+ h += '<div>' + data.lineups_html.replace(/<script[^>]*>.*?<\/script>/gi,'').replace(/<iframe[^>]*>.*?<\/iframe>/gi,'') + '</div></div>';
 
 
 
 
 
 
 
110
  } else if(data.lineups && (data.lineups.home_players || data.lineups.away_players)){
111
+ h += '<div class="md-sec"><div class="md-sec-title">⚽ Đội hình</div>';
112
+ h += renderLineups(data.lineups) + '</div>';
 
 
113
  }
114
 
115
+ // 3. H2H
116
  if(data.h2h_html && data.h2h_html.length > 10){
117
+ h += '<div class="md-sec"><div class="md-sec-title">🔄 Đối đầu (H2H)</div>';
118
+ h += '<div>' + data.h2h_html.replace(/<script[^>]*>.*?<\/script>/gi,'').replace(/<iframe[^>]*>.*?<\/iframe>/gi,'') + '</div></div>';
 
 
 
 
 
 
119
  } else if(data.h2h && data.h2h.length > 0){
120
+ h += '<div class="md-sec"><div class="md-sec-title">🔄 Đối đầu (H2H)</div>';
121
+ h += renderH2H(data.h2h) + '</div>';
 
 
122
  }
123
 
124
+ // 4. Stats
125
  if(data.stats_html && data.stats_html.length > 10){
126
+ h += '<div class="md-sec"><div class="md-sec-title">📊 Thống kê</div>';
127
+ h += '<div>' + data.stats_html.replace(/<script[^>]*>.*?<\/script>/gi,'').replace(/<iframe[^>]*>.*?<\/iframe>/gi,'') + '</div></div>';
 
 
 
 
 
 
128
  }
129
 
130
+ // 5. Info
131
  if(data.info && Object.keys(data.info).length > 0){
132
+ h += '<div class="md-sec"><div class="md-sec-title">📍 Thông tin</div>';
 
133
  h += '<div style="font-size:12px;color:#ccc;line-height:1.8;padding:8px;background:#1a1a1a;border-radius:8px">';
134
+ if(data.info.date) h += '<div>📅 Ngày: <b>'+esc(data.info.date)+'</b></div>';
135
+ if(data.info.time) h += '<div>🕐 Giờ: <b>'+esc(data.info.time)+'</b></div>';
136
+ if(data.info.stadium) h += '<div>🏟 Sân: <b>'+esc(data.info.stadium)+'</b></div>';
137
+ if(data.info.referee) h += '<div>👨‍⚖️ Trọng tài: <b>'+esc(data.info.referee)+'</b></div>';
138
  h += '</div></div>';
139
  }
140
 
141
  if(!h){
142
+ h = '<div class="md-no-data">Chưa có chi tiết cho trận đấu này.<br><small style="color:#666">Dữ liệu sẽ cập nhật khi giải khởi tranh hoặc trận đấu bắt đầu.</small></div>';
143
  }
144
 
145
  el.innerHTML = h;
146
  el.querySelectorAll('a').forEach(a=>a.addEventListener('click', e=>e.preventDefault()));
147
  }
148
 
149
+ function renderLineups(l){
150
+ let h='<div class="md-lineups">';
151
+ h+='<div class="md-team-box"><div class="md-team-name">'+esc(l.home_team||'Đội nhà')+'</div>';
152
+ if(l.formation) h+='<div class="md-formation">'+esc(l.formation)+'</div>';
153
+ h+='<ul class="md-player-list">';
154
+ (l.home_players||[]).forEach((p,i)=>{h+='<li class="md-player-item"><span class="md-player-no">'+(i+1)+'</span>'+esc(p)+'</li>';});
155
+ h+='</ul>';
156
+ if(l.home_subs&&l.home_subs.length){h+='<div class="md-subs-title">Dự bị:</div>';(l.home_subs||[]).forEach(p=>{h+='<div style="font-size:10px;color:#888">'+esc(p)+'</div>';});}
157
+ h+='</div>';
158
+ h+='<div class="md-team-box"><div class="md-team-name">'+esc(l.away_team||'Đội khách')+'</div>';
159
+ if(l.away_formation) h+='<div class="md-formation">'+esc(l.away_formation)+'</div>';
160
+ h+='<ul class="md-player-list">';
161
+ (l.away_players||[]).forEach((p,i)=>{h+='<li class="md-player-item"><span class="md-player-no">'+(i+1)+'</span>'+esc(p)+'</li>';});
162
+ h+='</ul>';
163
+ if(l.away_subs&&l.away_subs.length){h+='<div class="md-subs-title">Dự bị:</div>';(l.away_subs||[]).forEach(p=>{h+='<div style="font-size:10px;color:#888">'+esc(p)+'</div>';});}
164
+ h+='</div></div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  return h;
166
  }
167
 
168
  function renderH2H(matches){
169
+ let h='';
170
  matches.forEach(m=>{
171
+ h+='<div class="md-h2h-item">';
172
+ h+='<span class="md-h2h-date">'+esc(m.date||'')+'</span>';
173
+ h+='<span class="md-h2h-teams"><span class="md-h2h-home">'+esc(m.home||'')+'</span>';
174
+ h+='<span class="md-h2h-score">'+esc(m.score||'vs')+'</span>';
175
+ h+='<span class="md-h2h-away">'+esc(m.away||'')+'</span></span>';
176
+ h+='</div>';
 
 
 
 
177
  });
178
  return h;
179
  }
180
 
 
181
  function injectDetailTab(){
182
+ const tabs = document.querySelector('.mo-tabs');
183
+ if(!tabs || document.querySelector('.mo-tab-detail')) return;
184
+ const d = document.createElement('span');
185
+ d.className = 'mo-tab mo-tab-detail';
186
+ d.textContent = '📋 Chi tiết';
187
+ d.onclick = ()=>window.loadMatchTab('detail');
188
+ // Insert as first tab
189
+ tabs.insertBefore(d, tabs.firstChild);
 
 
 
 
 
 
 
190
  }
191
 
192
+ // Intercept clicks in livescore to capture event_id
193
+ document.addEventListener('click', function(e){
194
+ const md = e.target.closest('.match-detail');
195
+ if(md){
196
+ const link = md.querySelector('.status a, a[href*="tran-dau"]');
197
+ if(link){
198
+ const href = link.getAttribute('href') || '';
199
+ const m = href.match(/\/tran-dau\/(\d+)\//);
200
+ if(m){ window._currentEventId = m[1]; }
201
+ }
202
+ }
203
+ }, true);
204
 
205
+ // Also inject on DOM ready
206
+ if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',()=>setTimeout(injectDetailTab,1000));
207
+ else setTimeout(injectDetailTab,1000);
 
 
208
  })();