CakhiaTV - Trang Trực Tiếp Bóng Đá Cà Khịa Tivi Top 01 VN

  • Tất cả
  • Trực tiếp
  • Hot
  • Nay
  • Mai
Xem thêm trận đấu
HLV Liam Rosenior nổi giận sau trận thua Brighton

Sau trận thua gây tranh cãi trước Brighton, HLV Liam Rosenior không giấu nổi sự ...

CakhiaTV là nền tảng trực tiếp bóng đá hàng đầu, cung cấp trải nghiệm theo dõi trận đấu liền mạch, hạn chế gián đoạn và tối ưu hiển thị. Với hệ thống nội dung bao phủ các giải đấu lớn trên toàn cầu, đặc biệt là Ngoại Hạng Anh, nền tảng đảm bảo người dùng tiếp cận đầy đủ các trận cầu quan trọng với chất lượng hình ảnh sắc nét và tốc độ ổn định. Nhờ định hướng công nghệ rõ ràng, Cakhia TV đang từng bước nâng cao tiêu chuẩn xem bóng đá trực tuyến tại thị trường Việt Nam.

Nguồn gốc tên gọi “Cakhia TV”

Tên gọi CakhiaTV xuất phát từ cách nói dân dã “cà khịa” trong tiếng Việt – một thuật ngữ phổ biến trong cộng đồng mạng, mang sắc thái hài hước, tranh luận, đối đáp sôi động. Việc lựa chọn tên này phản ánh rõ định vị thương hiệu:

  • Gắn liền với văn hóa bóng đá – nơi cảm xúc, tranh luận và tương tác luôn hiện hữu
  • Tạo cảm giác gần gũi, trẻ trung và dễ nhận diện với người dùng Việt
  • Nhấn mạnh yếu tố tương tác cộng đồng thay vì chỉ xem nội dung thụ động

Việc bổ sung “TV” phía sau giúp định hình rõ đây là một nền tảng phát nội dung dạng truyền hình số.

Nguồn gốc tên gọi CakhiaTV trong cộng đồng
Nguồn gốc tên gọi CakhiaTV trong cộng đồng

Định hướng phát triển chiến lược của Cakhia TV

CakhiaTV định hướng trở thành nền tảng xem bóng đá trực tuyến hàng đầu thông qua việc cung cấp các giải đấu lớn với chất lượng ổn định, tốc độ truyền tải nhanh và trải nghiệm liền mạch. Đồng thời, nền tảng mở rộng sang hệ sinh thái thể thao – giải trí, tích hợp nội dung đa dạng và tương tác cộng đồng nhằm gia tăng giá trị người dùng. 

Trọng tâm phát triển nằm ở việc ứng dụng công nghệ, đặc biệt là AI, để cá nhân hóa trải nghiệm, đồng thời từng bước mở rộng sang thị trường Đông Nam Á, hướng tới xây dựng một thương hiệu truyền thông số mang tầm khu vực.

CakhiaTV: Hướng dẫn truy cập và xem bóng đá trực tiếp nhanh chóng

Để trải nghiệm các trận bóng đá trực tiếp trên Cakhia, người dùng có thể thực hiện theo các bước đơn giản và tối ưu sau:

Truy cập nền tảng:

  • Cách 1: Sử dụng công cụ tìm kiếm Google, nhập từ khóa “cakhiatv” và lựa chọn kết quả dẫn đến trang chính thức.
  • Cách 2: Truy cập trực tiếp vào địa chỉ chính thức: https://cakhiaz.info/ thông qua trình duyệt web.

Theo dõi trận đấu trực tiếp:
Ngay tại giao diện trang chủ, hệ thống hiển thị danh sách các trận đấu nổi bật, kèm theo thời gian thi đấu và thông tin giải đấu. Người dùng chỉ cần lựa chọn trận đấu mong muốn để truy cập vào giao diện xem trực tiếp bóng đá, nơi cung cấp hình ảnh chất lượng cao, âm thanh rõ nétđường truyền ổn định.

Hướng dẫn truy cập và xem bóng đá trên CakhiaTV
Hướng dẫn truy cập và xem bóng đá trên CakhiaTV

Với quy trình truy cập đơn giản và tối ưu, người dùng có thể nhanh chóng tiếp cận nội dung và hòa mình vào không khí sôi động của các trận cầu cùng cộng đồng người hâm mộ trên Cakhia TV.

CakhiaTV và hệ sinh thái tính năng phục vụ người hâm mộ bóng đá

Cà Khịa TV không chỉ phát sóng trực tiếp bóng đá mà còn phát triển hệ sinh thái nội dung toàn diện, giúp người dùng theo dõi, cập nhật, phân tích và tương tác trận đấu một cách đầy đủ và chuyên sâu hơn.

Trực tiếp bóng đá với trải nghiệm xem ổn định

Đây là tính năng cốt lõi làm nên giá trị của CakhiaTV. Nền tảng cung cấp các trận bóng đá trực tiếp từ nhiều giải đấu lớn nhỏ, với ưu tiên rõ ràng về chất lượng truyền tải, độ ổn định của đường truyền và khả năng hiển thị trên nhiều thiết bị. 

Lợi ích lớn nhất đối với người dùng nằm ở khả năng tiếp cận trận đấu theo thời gian thực mà không phải phụ thuộc vào quá nhiều nguồn khác nhau. Khi chất lượng hình ảnh được duy trì tốt và độ trễ được kiểm soát, trải nghiệm theo dõi trận đấu trở nên liền mạch hơn, đặc biệt trong những thời điểm quan trọng như bàn thắng, VAR hay các tình huống quyết định.

Tin tức bóng đá giúp người dùng cập nhật nhanh và có chọn lọc

Bên cạnh nội dung trực tiếp, CakhiaTV cung cấp tin tức bóng đá chọn lọc, bao gồm chuyển nhượng, phong độ và diễn biến bên lề. Tính năng này giúp người dùng tiết kiệm thời gian, tiếp cận nguồn tin đáng tin cậy và có góc nhìn đầy đủ trước và sau trận đấu.

Lịch thi đấu hỗ trợ chủ động theo dõi giải đấu

Tính năng lịch thi đấu mang ý nghĩa thực dụng rất rõ ràng. Thay vì phải tra cứu riêng lẻ theo từng giải hoặc từng đội bóng, người dùng có thể theo dõi lịch theo ngày, theo giải đấu hoặc theo cặp đấu cụ thể. 

Giao diện lịch thi đấu giúp theo dõi trận đấu dễ dàng
Giao diện lịch thi đấu giúp theo dõi trận đấu dễ dàng

Lợi ích lớn nhất là khả năng chủ động sắp xếp thời gian và không bỏ lỡ các trận cầu quan trọng. Với những người theo dõi nhiều giải đấu cùng lúc trên CakhiaTV, đây là công cụ giúp tối ưu hành vi sử dụng, giảm thao tác và tăng tính tiện lợi trong quá trình tiếp cận nội dung.

Bảng xếp hạng cung cấp góc nhìn hệ thống về cục diện giải đấu

Bảng xếp hạng giúp người dùng nắm bức tranh tổng thể giải đấu thông qua dữ liệu cập nhật liên tục về điểm số, hiệu số và vị thế đội bóng. Đây không chỉ là công cụ tra cứu mà còn hỗ trợ phân tích cục diện, dự đoán xu hướng cạnh tranh và đánh giá triển vọng mùa giải.

Kết quả bóng đá hôm nay giúp nắm bắt nhanh diễn biến toàn cục

Tính năng kết quả bóng đá hôm nay giúp người dùng nhanh chóng nắm bắt tỷ số, bàn thắng, thẻ phạt và diễn biến chính mà không cần xem trực tiếp. Giá trị cốt lõi nằm ở khả năng cập nhật toàn cảnh bóng đá trong thời gian ngắn, phù hợp với người ưu tiên tốc độ nhưng vẫn muốn theo sát diễn biến bóng đá trên CakhiaTV.

Highlight bóng đá tối ưu hóa trải nghiệm xem lại

Tính năng highlight bóng đá cho phép người dùng xem nhanh các tình huống nổi bật như bàn thắng hay pha bóng quan trọng mà không cần theo dõi toàn bộ trận đấu. Đây là giải pháp hiệu quả cho người dùng có quỹ thời gian hạn chế, giúp tối ưu thời gian tiếp cận nội dung mà vẫn đảm bảo trải nghiệm cảm xúc, đồng thời đáp ứng linh hoạt nhiều nhu cầu xem khác nhau.

Livescore cung cấp dữ liệu theo thời gian thực

Livescore giúp người dùng cập nhật nhanh tỷ số, đội hình và diễn biến trận đấu theo thời gian thực khi không thể xem trực tiếp. Tính năng này tăng tính tức thời, cho phép theo dõi nhịp trận liên tục mà không cần chuyển đổi nhiều nguồn.

Nhận định bóng đá chuyên sâu nâng cao chất lượng tiếp cận thông tin

Tính năng nhận định bóng đá chuyên sâu trên CakhiaTV không chỉ cung cấp nội dung mà còn giúp lý giải trận đấu thông qua phân tích phong độ, chiến thuật và lực lượng. Nhờ đó, người dùng hiểu sâu hơn về diễn biến, nâng cao tư duy phân tích và tăng mức độ gắn bó lâu dài với nền tảng.

Phân tích chuyên sâu về nhận định bóng đá và chiến thuật
Phân tích chuyên sâu về nhận định bóng đá và chiến thuật

Thông tin tỷ lệ kèo đấu như một lớp dữ liệu tham khảo bổ sung

Nền tảng bổ sung thông tin tỷ lệ kèo như một nguồn tham khảo, giúp người dùng nắm bắt cách đánh giá trận đấu từ góc nhìn chuyên môn. Giá trị cốt lõi nằm ở việc cung cấp dữ liệu thống kê và dự báo, hỗ trợ phân tích cục diện, mức độ chênh lệch và các yếu tố ảnh hưởng đến trận đấu.

CakhiaTV được định vị như một nền tảng nội dung thể thao đa lớp thay vì chỉ xem bóng đá. Dưới sự dẫn dắt của CEO Huy Nguyễn (cakhiaz.info), hệ thống phát triển từ trực tiếp, cập nhật thông tin đến phân tích và cá nhân hóa, tạo giá trị dài hạn và thúc đẩy người dùng quay lại thường xuyên.

Lý do lựa chọn CakhiaTV: Nền tảng xem bóng đá toàn diện và tối ưu trải nghiệm

Cakhia TV được định vị như một nền tảng trực tiếp bóng đá toàn diện, không chỉ đáp ứng nhu cầu xem trận đấu mà còn mở rộng sang hệ sinh thái nội dung thể thao đa chiều. Dưới góc nhìn phân tích, có thể tổng hợp những lý do chính khiến người dùng lựa chọn nền tảng như sau:

1. Trải nghiệm xem bóng đá trực tiếp ổn định và liền mạch

CakhiaTV tập trung tối ưu chất lượng hình ảnh, đường truyền và độ trễ thấp. Điều này đảm bảo người dùng có thể theo dõi các trận đấu theo thời gian thực mà không bị gián đoạn, đặc biệt trong các thời điểm quan trọng như bàn thắng hoặc tình huống quyết định.

2. Hệ sinh thái nội dung bóng đá toàn diện và tích hợp

Khác với các nền tảng chỉ phát sóng, CakhiaTV tích hợp nhiều lớp nội dung:

  • Tin tức bóng đá được cập nhật liên tục, đảm bảo tính kịp thời và chính xác
  • Lịch thi đấu hỗ trợ người dùng chủ động theo dõi và sắp xếp thời gian
  • Bảng xếp hạng phản ánh rõ nét cục diện và diễn biến của giải đấu
  • Kết quả và highlight phục vụ nhu cầu xem nhanh
Hệ sinh thái nội dung bóng đá đa dạng trên CakhiaTV
Hệ sinh thái nội dung bóng đá đa dạng trên CakhiaTV

Điều này giúp người dùng tập trung tiếp cận thông tin trên một nền tảng CakhiaTV duy nhất, hạn chế việc phải phân tán sang nhiều nguồn khác nhau.

3. Cập nhật dữ liệu và diễn biến theo thời gian thực

Các tính năng như livescore cho phép theo dõi tỷ số, diễn biến và dữ liệu trận đấu ngay cả khi không xem trực tiếp. Đây là yếu tố quan trọng giúp duy trì kết nối liên tục với trận đấu trong mọi hoàn cảnh.

4. Nội dung phân tích chuyên sâu

CakhiaTV cung cấp các bài nhận định bóng đá dựa trên phong độ, chiến thuật và lực lượng. Điều này giúp người dùng không chỉ xem mà còn hiểu trận đấu ở cấp độ phân tích, nâng cao trải nghiệm và kiến thức.

5. Tăng cường ứng dụng công nghệ để nâng cao trải nghiệm người dùng

Các trọng tâm cốt lõi gồm:

  • Tối ưu tốc độ tải và khả năng vận hành trên đa thiết bị
  • Ứng dụng công nghệ để cá nhân hóa nội dung hiển thị
  • Tăng cường mức độ tương tác giữa người dùng và hệ thống nội dung
Công nghệ tối ưu hóa UI/UX trên nền tảng
Công nghệ tối ưu hóa UI/UX trên nền tảng

Nhờ đó, trải nghiệm sử dụng trở nên linh hoạt và phù hợp với nhiều nhóm người dùng.

6. Định hướng phát triển có chiến lược rõ ràng và tầm nhìn dài hạn

Dưới sự dẫn dắt của CEO Huy Nguyễn, CakhiaTV không chỉ dừng lại ở thị trường nội địa mà còn hướng tới mở rộng khu vực. Hướng phát triển gồm các điều sau:

  • Nâng cao chất lượng công nghệ
  • Mở rộng hệ sinh thái nội dung
  • Xây dựng thương hiệu truyền thông số bền vững

Lời kết

Tổng thể, CakhiaTV không chỉ là một nền tảng trực tiếp bóng đá mà còn là một hệ sinh thái nội dung được xây dựng có chiến lược, kết hợp giữa công nghệ, dữ liệu và trải nghiệm người dùng. Với định hướng phát triển rõ ràng, nền tảng đang từng bước nâng cao tiêu chuẩn tiếp cận bóng đá trực tuyến, đồng thời tạo ra giá trị bền vững cho người dùng trong dài hạn.

` } } function showLoading() { if (matchesContainer) { matchesContainer.innerHTML = `
` } } function renderMatches(matches) { if (!matchesContainer) return; if (!matches || matches.length === 0) { matchesContainer.innerHTML = '
Không có trận đấu nào.
'; return } itemsToShow = ITEMS_TO_SHOW; matchesContainer.innerHTML = matches.map(match => renderMatchCard(match)).join(''); filterMatches(activeFilter) } function renderMatchCard(match) { const matchId = match.id || ''; const homeTeam = match.home_info?.name || match.home_name || 'Team A'; const awayTeam = match.away_info?.name || match.away_name || 'Team B'; const homeLogo = match.home_info?.logo || match.home_logo || ''; const awayLogo = match.away_info?.logo || match.away_logo || ''; const competitionName = match.competition?.name || match.competition_name || 'Competition'; const competitionLogo = match.competition?.logo || match.competition_logo || ''; // Normalize match time field (avoid mismatch between match_time / matchTime / kick_off_timestamp) const matchTime = Number( match.match_time ?? match.matchTime ?? match.kick_off_timestamp ?? match.kickoff_timestamp ?? Math.floor(Date.now() / 1000) ); const matchDatetime = formatMatchDatetime(matchTime); const matchDay = formatMatchDay(matchTime); const homeScore = match.full_time_home_score || 0; const awayScore = match.full_time_away_score || 0; const statusId = Number(match.status_id ?? 0); // const statusText = getStatusText(match); const isLive = [2, 3, 4, 5, 6, 7].includes(statusId); const isUpcoming = statusId === 1; const isFinished = statusId === 8; const filterClasses = getFilterClasses(match); // console.log("filterClasses", filterClasses, { matchId, matchTime }); const halfTimeHome = match.haft_time_home_score || 0; const halfTimeAway = match.haft_time_away_score || 0; const halfTimeScore = `${halfTimeHome} - ${halfTimeAway}`; const corners = (match.home_corners || 0) + (match.away_corners || 0); const yellowCards = (match.home_yellow_cards || 0) + (match.away_yellow_cards || 0); const matchUrl = generateMatchUrl(match); const gradientIdPrefix = isUpcoming ? `yellow_${matchId}` : `green_${matchId}`; const isDarkTheme = document.getElementById('cakhia-plugin-container')?.classList.contains('theme-dark') || document.querySelector('.cakhia-plugin-container')?.classList.contains('theme-dark'); const themeSuffix = isDarkTheme ? '-dark' : ''; let bgImage = `bg-match-live${themeSuffix}.png`; if (isUpcoming) { bgImage = `bg-match${themeSuffix}.png` } else if (isFinished) { bgImage = `bg-match${themeSuffix}.png` } else if (isLive != '' ) { bgImage = `bg-match-live${themeSuffix}.png` } return `
     
${competitionName}
${matchDatetime}
${homeTeam}
${homeTeam}
${( () => { const statusText = getMatchStatusDisplay(match); let isRelive = false; if(statusText != ''){ isRelive = true; } const shouldReduceSize = match.status_id !== 1; const block = shouldReduceSize ? 'style="display:block"' : 'style="display:none"'; const none = shouldReduceSize ? 'style="display:none"' : 'style="display:block"'; return `VS ${escapeHtml(statusText)}
${homeScore} - ${awayScore}
`; } )()}
${awayTeam}
${awayTeam}
` } function renderStatusBadge(statusText, gradientIdPrefix, isUpcoming) { return '' } function renderCommentators(match) { const commentators = match.commentator_info || []; const matchId = match.id || ''; if (!commentators || commentators.length === 0) { return `
BLV: TV
` } let matchSlug = match.slug || ''; if (!matchSlug) { const homeTeam = match.home_info?.name || match.home_name || 'home'; const awayTeam = match.away_info?.name || match.away_name || 'away'; const homeSlug = createSlug(homeTeam); const awaySlug = createSlug(awayTeam); matchSlug = `${homeSlug}-vs-${awaySlug}`; let datetimeSuffix = ''; if (match.matchTime && match.matchTime > 0) { const matchTimestamp = match.matchTime * 1000; const matchDate = new Date(matchTimestamp); const hours = matchDate.getHours(); const minutes = matchDate.getMinutes(); const day = matchDate.getDate(); const month = matchDate.getMonth() + 1; const year = matchDate.getFullYear(); const timeStr = String(hours).padStart(2, '0') + String(minutes).padStart(2, '0'); const dayStr = String(day).padStart(2, '0'); const monthStr = String(month).padStart(2, '0'); datetimeSuffix = `-vao-luc-${timeStr}-${dayStr}-${monthStr}-${year}`; matchSlug = `${matchSlug}${datetimeSuffix}` } } const generateCommentatorUrl = (commentator) => { const commentatorSlug = commentator.slug || ''; if (matchSlug && commentatorSlug) { const urlPath = `/truc-tiep/${matchSlug}/`; const queryParam = `?blv=${encodeURIComponent(commentatorSlug)}`; return `${window.location.origin}${urlPath}${queryParam}` } return `${window.location.origin}/truc-tiep/` } ; if (commentators.length === 1) { const commentator = commentators[0]; const commentatorName = commentator.full_name || 'Unknown'; const commentatorAvatar = commentator.avatar || ''; const commentatorSlug = commentator.slug || ''; const commentatorUrl = generateCommentatorUrl(commentator); return `` } const generateSlidesHtml = (commentatorsList) => { return commentatorsList.map( (commentator, index) => { const commentatorName = commentator.full_name || 'Unknown'; const commentatorAvatar = commentator.avatar || ''; const commentatorSlug = commentator.slug || ''; const commentatorUrl = generateCommentatorUrl(commentator); return `` } ).join('') }; if (commentators.length > 1) { const shuffled = [...commentators].sort(() => 0.5 - Math.random()); return generateSlidesHtml(shuffled); } return generateSlidesHtml(commentators); } function randomCommentators(match){ const commentators = match.commentator_info || []; const matchId = match.id || ''; let matchSlug = match.slug || ''; if (!matchSlug) { const homeTeam = match.home_info?.name || match.home_name || 'home'; const awayTeam = match.away_info?.name || match.away_name || 'away'; const homeSlug = createSlug(homeTeam); const awaySlug = createSlug(awayTeam); matchSlug = `${homeSlug}-vs-${awaySlug}`; let datetimeSuffix = ''; if (match.match_time && match.match_time > 0) { const matchTimestamp = match.match_time * 1000; const matchDate = new Date(matchTimestamp); const hours = matchDate.getHours(); const minutes = matchDate.getMinutes(); const day = matchDate.getDate(); const month = matchDate.getMonth() + 1; const year = matchDate.getFullYear(); const timeStr = String(hours).padStart(2, '0') + String(minutes).padStart(2, '0'); const dayStr = String(day).padStart(2, '0'); const monthStr = String(month).padStart(2, '0'); datetimeSuffix = `-vao-luc-${timeStr}-${dayStr}-${monthStr}-${year}`; matchSlug = `${matchSlug}${datetimeSuffix}` } } const generateCommentatorUrl = (commentator) => { const commentatorSlug = commentator.slug || ''; if (matchSlug && commentatorSlug) { return `${window.location.origin}/truc-tiep/${matchSlug}/?blv=${encodeURIComponent(commentatorSlug)}`; } return `${window.location.origin}/truc-tiep/`; }; if (commentators.length > 0) { const randomIndex = Math.floor(Math.random() * commentators.length); const randomCommentator = commentators[randomIndex]; return generateCommentatorUrl(randomCommentator); } return `${window.location.origin}/truc-tiep/`; } function renderHexagonAvatar(avatar, matchId, slug) { const clipId = `hexagonClip_${matchId}_${slug}`; const defaultLogo = getPluginUrl() + 'assets/img/logo_default.webp'; const avatarUrl = avatar || defaultLogo; return `` } function getFilterClasses(match) { const statusId = match.status_id || 0; const isLive = [2, 3, 4, 5, 6, 7].includes(statusId); const isHot = match.is_hot; const matchTime = match.match_time || 0; const now = Math.floor(Date.now() / 1000); const timezoneOffset = 0; const todayStart = Math.floor(new Date().setHours(0, 0, 0, 0) / 1000) - (timezoneOffset * 3600); const todayEnd = todayStart + 86400; const tomorrowStart = todayEnd; const tomorrowEnd = tomorrowStart + 86400; const isToday = matchTime >= todayStart && matchTime = tomorrowStart && matchTime 0) { const currentTime = Math.floor(Date.now() / 1000); const elapsedSeconds = currentTime - kickOffTimestamp; const elapsedMinutes = Math.floor(elapsedSeconds / 60) + 1; if (statusId === 2) { // First Half: 0' -> 45+' if (elapsedMinutes > 45) { statusText += ": 45+'"; } else { statusText += `: ${elapsedMinutes}'`; } } else if (statusId === 4) { // Second Half: 45' -> 90+' const adjustedTime = elapsedMinutes + 45; if (adjustedTime > 90) { statusText += ": 90+'"; } else { statusText += `: ${adjustedTime}'`; } } } return statusText; // Default: return status text } function getMatchStatusText(status) { switch (status) { case 1: return 'H1'; case 3: return 'H2'; case -10: return 'Hủy'; case -11: return 'TBD'; case -12: return 'Chấm dứt'; case -13: return 'Gián đoạn'; case -14: return 'Hoãn'; default: return 'TBD'; } } function formatMatchDatetime(timestamp) { const date = new Date(timestamp * 1000); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const month = String(date.getMonth() + 1).padStart(2, '0'); return `${hours}:${minutes} ${day}-${month}` } function formatMatchDay(timestamp) { const date = new Date(timestamp * 1000); const day = String(date.getDate()).padStart(2, '0'); const month = String(date.getMonth() + 1).padStart(2, '0');; const year = date.getFullYear(); return `${day}/${month}/${year}`; } function generateMatchUrl(match) { if (match.slug) { const urlPath = `/truc-tiep/${match.slug}/`; return `${window.location.origin}${urlPath}` } const homeTeam = match.home_info?.name || match.home_name || 'home'; const awayTeam = match.away_info?.name || match.away_name || 'away'; const homeSlug = createSlug(homeTeam); const awaySlug = createSlug(awayTeam); const teamSlug = `${homeSlug}-vs-${awaySlug}`; let datetimeSuffix = ''; if (match.match_time && match.match_time > 0) { const matchDate = new Date(match.match_time * 1000); const timeStr = String(matchDate.getHours()).padStart(2, '0') + String(matchDate.getMinutes()).padStart(2, '0'); const day = String(matchDate.getDate()).padStart(2, '0'); const month = String(matchDate.getMonth() + 1).padStart(2, '0'); const year = matchDate.getFullYear(); datetimeSuffix = `-vao-luc-${timeStr}-${day}-${month}-${year}` } if (teamSlug) { const urlPath = `/truc-tiep/${teamSlug}${datetimeSuffix}/`; return `${window.location.origin}${urlPath}` } return `${window.location.origin}/truc-tiep/` } function createSlug(str) { return str.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/đ/g, 'd').replace(/[^a-z0-9\s-]/g, '').trim().replace(/\s+/g, '-').replace(/-+/g, '-') } function getPluginUrl() { if (typeof window.cakhiaMatch1 !== 'undefined' && window.cakhiaMatch1.plugin_url) { return window.cakhiaMatch1.plugin_url } const scripts = document.querySelectorAll('script[src*="match-1.js"]'); for (let script of scripts) { const src = script.src; const match = src.match(/(.*\/plugins\/[^\/]+\/)/); if (match) { return match[1] } } const cakhiaScripts = document.querySelectorAll('script[src*="cakhia"]'); for (let script of cakhiaScripts) { const src = script.src; const match = src.match(/(.*\/plugins\/[^\/]+\/)/); if (match) { return match[1] } } return '/wp-content/plugins/cakhia/' } function updateStats() { const stats = { all: allMatches.length, live: 0, hot: 0, today: 0, tomorrow: 0 }; const now = Math.floor(Date.now() / 1000); const timezoneOffset = 0; const todayStart = Math.floor(new Date().setHours(0, 0, 0, 0) / 1000) - (timezoneOffset * 3600); const todayEnd = todayStart + 86400; const tomorrowStart = todayEnd; const tomorrowEnd = tomorrowStart + 86400; allMatches.forEach(match => { const matchTime = match.match_time || 0; const statusId = match.status_id || 0; // Trực tiếp = đang chơi (status 2,3,4,5,6,7) if ([2, 3, 4, 5, 6, 7].includes(statusId)) { stats.live++; } if (match.is_hot) { stats.hot++; } if (matchTime >= todayStart && matchTime = tomorrowStart && matchTime { const filter = tab.getAttribute('data-filter'); const spans = tab.querySelector('span[amount]'); const badge = spans.length >= 2 ? spans[1] : null; // Recompute filter classes on existing DOM nodes (useful when match data is updated without full re-render) function refreshFilterClassesFromData(matches) { const mapById = new Map((matches || []).map(m => [String(m.id ?? ''), m])); document.querySelectorAll('.match-item[data-match-id]').forEach(card => { const matchId = card.getAttribute('data-match-id'); const match = mapById.get(String(matchId)); if (!match) return; card.classList.remove('match-filter-all', 'match-filter-live', 'match-filter-hot', 'match-filter-today', 'match-filter-tomorrow'); const classes = getFilterClasses(match).split(/\s+/).filter(Boolean); classes.forEach(c => card.classList.add(c)); }); } if (stats[filter] !== undefined) { const count = stats[filter]; if (count === 0) { spans.setAttribute('amount', 0); } else { spans.setAttribute('amount', count); } } } ) } function filterMatches(type) { activeFilter = type; const cards = document.querySelectorAll('.match-item'); let visibleCount = 0; let shownCount = 0; cards.forEach(card => { let matchesFilter = !1; switch (type) { case 'all': matchesFilter = card.classList.contains('match-filter-all'); break; case 'live': matchesFilter = card.classList.contains('match-filter-live'); break; case 'hot': matchesFilter = card.classList.contains('match-filter-hot'); break; case 'today': matchesFilter = card.classList.contains('match-filter-today'); break; case 'tomorrow': matchesFilter = card.classList.contains('match-filter-tomorrow'); break } if (matchesFilter) { visibleCount++; if (shownCount = totalVisibleItems) { paginationContainer.innerHTML = ''; paginationContainer.style.display = 'none'; return } paginationContainer.style.display = ''; paginationContainer.className = 'mt-3 flex justify-center lg:mt-6'; const btnText = 'Xem thêm'; const iconPath = ''; paginationContainer.innerHTML = `Xem thêm trận đấu`; const btn = document.querySelector('#cakhia-pagination-btn'); if (btn) { const newBtn = btn.cloneNode(!0); btn.parentNode.replaceChild(newBtn, btn); newBtn.addEventListener('click', (e) => { e.preventDefault(); itemsToShow += ITEMS_TO_SHOW; filterMatches(activeFilter) } ) } } function updateActiveTab(type) { filterTabs.forEach(tab => { tab.classList.remove('active'); } ); const activeTab = document.querySelector(`.filter-tab-match[data-filter="${type}"]`); if (activeTab) { activeTab.classList.add('active'); } } function setupEventListeners() { filterTabs.forEach(tab => { tab.addEventListener('click', (e) => { e.preventDefault(); const filterType = tab.getAttribute('data-filter'); if (filterType) { itemsToShow = ITEMS_TO_SHOW; filterMatches(filterType) } } ) } ) } function escapeHtml(value) { if (value === null || value === undefined) { return ''; } const stringValue = String(value); return stringValue.replace(/[&"']/g, (char) => { switch (char) { case '&': return '&'; case '': return '>'; case '"': return '"'; case '\'': return '''; default: return char; } }); } async function init() { console.log('Init started, checking for preloaded data...'); showLoading(); setupEventListeners(); if (window.cakhiaMatchDataPreloaded && Array.isArray(window.cakhiaMatchDataPreloaded)) { console.log('Using preloaded data, count:', window.cakhiaMatchDataPreloaded.length); allMatches = window.cakhiaMatchDataPreloaded; renderMatches(allMatches); updateStats() } else if (window.cakhiaMatchDataPromise) { console.log('Waiting for promise to resolve...'); try { const data = await window.cakhiaMatchDataPromise; if (data && Array.isArray(data)) { console.log('Promise resolved, using data, count:', data.length); allMatches = data; renderMatches(allMatches); updateStats() } else { console.log('Promise resolved but no data, fetching again'); fetchMatches() } } catch (error) { console.error('Preloaded promise failed, fetching again:', error); fetchMatches() } } else { console.log('No preload found, fetching normally'); fetchMatches() } setInterval(fetchMatches, 30000) } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init) } else { init() } } )();