CinePlex/js/providers.js

179 lines
6.7 KiB
JavaScript
Raw Normal View History

2025-07-25 23:57:03 +02:00
import { fetchTMDB } from './api.js';
import { state } from './state.js';
import { _, showNotification } from './utils.js';
import { renderGrid } from './ui.js';
let currentProviderId = null;
let currentPage = 1;
let totalPages = 1;
export async function getAvailableProviders(type, region) {
try {
const url = `watch/providers/${type}`;
const providers = await fetchTMDB(url, { watch_region: region });
return providers.results || [];
} catch (error) {
console.error(`Error fetching ${type} providers for region ${region}:`, error);
return [];
}
}
export async function fetchAllProviders(region) {
const [movieProviders, tvProviders] = await Promise.all([
getAvailableProviders('movie', region),
getAvailableProviders('tv', region)
]);
const allProvidersMap = new Map();
[...movieProviders, ...tvProviders].forEach(provider => {
allProvidersMap.set(provider.provider_id, provider);
});
return Array.from(allProvidersMap.values()).sort((a, b) => a.provider_name.localeCompare(b.provider_name));
}
export async function getRegions() {
try {
const regions = await fetchTMDB('watch/providers/regions');
return regions.results || [];
} catch (error) {
console.error('Error fetching regions:', error);
return [];
}
}
export function resetProvidersView() {
const providersSection = document.getElementById('providers-section');
if (!providersSection) return;
const grid = document.getElementById('providers-grid');
const itemsContainer = document.getElementById('provider-items-container');
const titleElement = document.querySelector('#providers-section .section-title');
const backButton = document.getElementById('back-to-providers');
if (grid) grid.style.display = 'grid';
if (itemsContainer) itemsContainer.style.display = 'none';
if (titleElement) titleElement.textContent = _('navProviders');
if (backButton) backButton.style.display = 'none';
}
export async function backToProviders() {
resetProvidersView();
const providers = await fetchAllProviders(state.settings.watchRegion);
renderProviders(providers);
}
export function renderProviders(providers) {
const grid = document.getElementById('providers-grid');
if (!grid) return;
grid.style.display = 'grid';
if (providers.length === 0) {
grid.innerHTML = `<div class="empty-state"><i class="fas fa-tv"></i><p>${_('noProvidersFound')}</p></div>`;
return;
}
const availableProviderIds = new Set(state.localSeries.flatMap(s => s.titulos).map(t => t.provider_id));
const providersHtml = providers.map(provider => {
const isAvailable = availableProviderIds.has(provider.provider_id);
return `
<div class="provider-card ${isAvailable ? 'available' : ''}" data-provider-id="${provider.provider_id}" data-provider-name="${provider.provider_name}">
<img src="https://image.tmdb.org/t/p/w200${provider.logo_path}" alt="${provider.provider_name}" class="provider-logo">
<div class="provider-tooltip">${provider.provider_name}</div>
</div>
`;
}).join('');
grid.innerHTML = providersHtml;
gsap.fromTo(".provider-card",
{ scale: 0.5, opacity: 0 },
{
duration: 0.5,
scale: 1,
opacity: 1,
delay: 0.2,
stagger: 0.08,
ease: "back.out(1.7)",
force3D: true
}
);
}
export async function getProviderItems(providerId, page = 1) {
try {
const watchRegion = state.settings.watchRegion || 'US';
const language = state.settings.language || 'en-US';
const params = {
with_watch_providers: providerId,
watch_region: watchRegion,
page: page,
language: language
};
const moviesResponse = await fetchTMDB('discover/movie', params);
const seriesResponse = await fetchTMDB('discover/tv', params);
const movies = moviesResponse.results.map(item => ({ ...item, media_type: 'movie' }));
const series = seriesResponse.results.map(item => ({ ...item, media_type: 'tv' }));
const items = [...movies, ...series].sort((a, b) => b.popularity - a.popularity);
const total_pages = Math.max(moviesResponse.total_pages, seriesResponse.total_pages);
return { success: true, items, total_pages };
} catch (error) {
showNotification(`${_('couldNotLoadContent')}: ${error.message}`, 'error');
return { success: false, items: [], total_pages: 0 };
}
}
export async function loadProviderContent(providerId, providerName, page = 1) {
currentProviderId = providerId;
currentPage = page;
const itemsContainer = document.getElementById('provider-items-container');
const providersGrid = document.getElementById('providers-grid');
const itemsGrid = document.getElementById('provider-items');
const paginationControls = document.getElementById('pagination-controls');
const pageNumberSpan = document.getElementById('page-number');
const prevButton = document.getElementById('prev-page');
const nextButton = document.getElementById('next-page');
const sectionTitle = document.querySelector('#providers-section .section-title');
const backButton = document.getElementById('back-to-providers');
providersGrid.style.display = 'none';
itemsContainer.style.display = 'block';
backButton.style.display = 'block';
if (sectionTitle) sectionTitle.textContent = providerName;
itemsGrid.innerHTML = `<div class="col-12 text-center mt-5"><div class="spinner" style="position: static; margin: auto; display: block;"></div></div>`;
paginationControls.style.display = 'none';
const { success, items, total_pages } = await getProviderItems(providerId, page);
if (success) {
totalPages = total_pages;
renderGrid(items, false, 'provider-items');
if (totalPages > 1) {
paginationControls.style.display = 'flex';
pageNumberSpan.textContent = `${_('page')} ${currentPage} / ${totalPages}`;
prevButton.disabled = currentPage === 1;
nextButton.disabled = currentPage >= totalPages;
}
} else {
itemsGrid.innerHTML = `<div class="empty-state"><i class="fas fa-exclamation-triangle"></i><p>${_('couldNotLoadContent')}</p></div>`;
}
}
export function changeProviderPage(direction) {
const newPage = currentPage + direction;
if (newPage > 0 && newPage <= totalPages && currentProviderId) {
const providerName = document.querySelector('#providers-section .section-title').textContent;
loadProviderContent(currentProviderId, providerName, newPage);
}
}