cin / index.html
docto41's picture
Add 3 files
a52bb2d verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tableau de Bord Cinéma</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.movie-card:hover .movie-overlay {
opacity: 1;
}
.movie-overlay {
transition: opacity 0.3s ease;
}
.skeleton {
animation: pulse 2s infinite ease-in-out;
}
@keyframes pulse {
0%, 100% { opacity: 0.6; }
50% { opacity: 0.3; }
}
.server-btn {
transition: all 0.3s ease;
}
.server-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.player-container {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
z-index: 1000;
justify-content: center;
align-items: center;
}
.player-wrapper {
width: 80%;
max-width: 1200px;
position: relative;
}
.close-player {
position: absolute;
top: -40px;
right: 0;
color: white;
font-size: 24px;
cursor: pointer;
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="flex justify-between items-center mb-10">
<div>
<h1 class="text-3xl font-bold text-indigo-400">CinéDashboard</h1>
<p class="text-gray-400">Votre tableau de bord cinématographique</p>
</div>
<div class="flex items-center space-x-4">
<div class="relative">
<input type="text" placeholder="Rechercher un film..." class="bg-gray-800 rounded-full py-2 px-4 pl-10 focus:outline-none focus:ring-2 focus:ring-indigo-500 w-64">
<i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
</div>
<div class="h-10 w-10 rounded-full bg-indigo-600 flex items-center justify-center">
<i class="fas fa-user"></i>
</div>
</div>
</header>
<!-- Stats -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-10">
<div class="bg-gray-800 rounded-lg p-6 flex items-center">
<div class="bg-indigo-600 p-3 rounded-full mr-4">
<i class="fas fa-film text-white"></i>
</div>
<div>
<p class="text-gray-400">Films chargés</p>
<h3 class="text-2xl font-bold" id="movies-count">0</h3>
</div>
</div>
<div class="bg-gray-800 rounded-lg p-6 flex items-center">
<div class="bg-purple-600 p-3 rounded-full mr-4">
<i class="fas fa-star text-white"></i>
</div>
<div>
<p class="text-gray-400">Note moyenne</p>
<h3 class="text-2xl font-bold" id="avg-rating">0</h3>
</div>
</div>
<div class="bg-gray-800 rounded-lg p-6 flex items-center">
<div class="bg-green-600 p-3 rounded-full mr-4">
<i class="fas fa-calendar text-white"></i>
</div>
<div>
<p class="text-gray-400">Dernière MAJ</p>
<h3 class="text-2xl font-bold" id="last-update">Aujourd'hui</h3>
</div>
</div>
<div class="bg-gray-800 rounded-lg p-6 flex items-center">
<div class="bg-red-600 p-3 rounded-full mr-4">
<i class="fas fa-fire text-white"></i>
</div>
<div>
<p class="text-gray-400">Tendance</p>
<h3 class="text-2xl font-bold" id="trending">0</h3>
</div>
</div>
</div>
<!-- Filters -->
<div class="flex flex-wrap items-center justify-between mb-8 bg-gray-800 p-4 rounded-lg">
<div class="flex space-x-4 mb-4 md:mb-0">
<button class="bg-indigo-600 hover:bg-indigo-700 px-4 py-2 rounded-lg transition" id="filter-popular">
Populaires
</button>
<button class="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded-lg transition" id="filter-top">
Top Rated
</button>
<button class="bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded-lg transition" id="filter-upcoming">
Prochainement
</button>
</div>
<div class="flex items-center">
<label for="year-filter" class="mr-2 text-gray-400">Année:</label>
<select id="year-filter" class="bg-gray-700 rounded px-3 py-2 focus:outline-none">
<option value="all">Toutes</option>
<!-- Years will be populated by JS -->
</select>
</div>
</div>
<!-- Movies Grid -->
<div class="mb-10">
<h2 class="text-2xl font-bold mb-6 flex items-center">
<i class="fas fa-fire text-red-500 mr-2"></i>
<span id="section-title">Films populaires</span>
</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6" id="movies-grid">
<!-- Skeleton loading -->
<div class="skeleton bg-gray-800 rounded-lg h-96"></div>
<div class="skeleton bg-gray-800 rounded-lg h-96"></div>
<div class="skeleton bg-gray-800 rounded-lg h-96"></div>
<div class="skeleton bg-gray-800 rounded-lg h-96"></div>
<div class="skeleton bg-gray-800 rounded-lg h-96"></div>
</div>
<div class="flex justify-center mt-8">
<button id="load-more" class="bg-indigo-600 hover:bg-indigo-700 px-6 py-3 rounded-lg transition font-medium">
Charger plus de films
</button>
</div>
</div>
<!-- Player Container (hidden by default) -->
<div class="player-container" id="player-container">
<div class="player-wrapper">
<div class="close-player" id="close-player">
<i class="fas fa-times"></i>
</div>
<iframe id="movie-player" width="100%" height="600" frameborder="0" allowfullscreen></iframe>
</div>
</div>
<!-- Footer -->
<footer class="border-t border-gray-800 pt-6 mt-10">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<h2 class="text-xl font-bold text-indigo-400">CinéDashboard</h2>
<p class="text-gray-400">Powered by TMDb API</p>
</div>
<div class="flex space-x-6">
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-twitter"></i></a>
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-facebook"></i></a>
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-instagram"></i></a>
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-github"></i></a>
</div>
</div>
<p class="text-center text-gray-500 mt-6 text-sm">© 2023 CinéDashboard. Tous droits réservés.</p>
</footer>
</div>
<script>
// Configuration
const API_KEY = 'fb437b10727a5a4eb8d9134e29c82ae0';
const BASE_URL = 'https://api.themoviedb.org/3';
const STREAMING_SERVERS = {
'server1': { name: 'Serveur Premium', icon: 'fas fa-bolt', color: 'bg-purple-600' },
'server2': { name: 'Serveur Rapide', icon: 'fas fa-tachometer-alt', color: 'bg-blue-600' },
'server3': { name: 'Serveur HD', icon: 'fas fa-high-definition', color: 'bg-green-600' },
'server4': { name: 'Serveur Backup', icon: 'fas fa-shield-alt', color: 'bg-yellow-600' }
};
let currentPage = 1;
let currentFilter = 'popular';
let currentYear = 'all';
let isLoading = false;
// DOM Elements
const moviesGrid = document.getElementById('movies-grid');
const loadMoreBtn = document.getElementById('load-more');
const moviesCount = document.getElementById('movies-count');
const avgRating = document.getElementById('avg-rating');
const lastUpdate = document.getElementById('last-update');
const trending = document.getElementById('trending');
const sectionTitle = document.getElementById('section-title');
const yearFilter = document.getElementById('year-filter');
const playerContainer = document.getElementById('player-container');
const moviePlayer = document.getElementById('movie-player');
const closePlayer = document.getElementById('close-player');
// Filter buttons
const filterPopular = document.getElementById('filter-popular');
const filterTop = document.getElementById('filter-top');
const filterUpcoming = document.getElementById('filter-upcoming');
// Initialize
document.addEventListener('DOMContentLoaded', () => {
// Set current date
const today = new Date();
lastUpdate.textContent = today.toLocaleDateString('fr-FR');
// Populate year filter
populateYearFilter();
// Load initial movies
loadMovies();
// Event listeners
loadMoreBtn.addEventListener('click', loadMoreMovies);
filterPopular.addEventListener('click', () => {
changeFilter('popular', 'Films populaires');
});
filterTop.addEventListener('click', () => {
changeFilter('top_rated', 'Top Rated');
});
filterUpcoming.addEventListener('click', () => {
changeFilter('upcoming', 'Prochainement');
});
yearFilter.addEventListener('change', (e) => {
currentYear = e.target.value;
currentPage = 1;
moviesGrid.innerHTML = createSkeletons(5);
loadMovies();
});
// Player events
closePlayer.addEventListener('click', () => {
playerContainer.style.display = 'none';
moviePlayer.src = '';
});
});
// Functions
function populateYearFilter() {
const currentYear = new Date().getFullYear();
for (let year = currentYear; year >= 2000; year--) {
const option = document.createElement('option');
option.value = year;
option.textContent = year;
yearFilter.appendChild(option);
}
}
function changeFilter(filter, title) {
currentFilter = filter;
currentPage = 1;
sectionTitle.textContent = title;
// Update active button
document.querySelectorAll('#filters button').forEach(btn => {
btn.classList.remove('bg-indigo-600', 'hover:bg-indigo-700');
btn.classList.add('bg-gray-700', 'hover:bg-gray-600');
});
event.target.classList.remove('bg-gray-700', 'hover:bg-gray-600');
event.target.classList.add('bg-indigo-600', 'hover:bg-indigo-700');
// Clear and reload movies
moviesGrid.innerHTML = createSkeletons(5);
loadMovies();
}
function createSkeletons(count) {
let skeletons = '';
for (let i = 0; i < count; i++) {
skeletons += `<div class="skeleton bg-gray-800 rounded-lg h-96"></div>`;
}
return skeletons;
}
async function loadMovies() {
if (isLoading) return;
isLoading = true;
loadMoreBtn.disabled = true;
loadMoreBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Chargement...';
try {
let url = `${BASE_URL}/movie/${currentFilter}?api_key=${API_KEY}&page=${currentPage}&language=fr-FR`;
if (currentYear !== 'all') {
url += `&primary_release_year=${currentYear}`;
}
const response = await fetch(url);
const data = await response.json();
if (currentPage === 1) {
moviesGrid.innerHTML = '';
// Update stats
moviesCount.textContent = data.total_results;
trending.textContent = data.total_results > 1000 ? 'Élevée' : 'Moyenne';
}
displayMovies(data.results);
// Calculate average rating
if (currentPage === 1) {
const ratings = data.results.map(movie => movie.vote_average);
const average = (ratings.reduce((a, b) => a + b, 0) / ratings.length).toFixed(1);
avgRating.textContent = average;
}
currentPage++;
// Hide load more button if we've reached the end
if (currentPage > data.total_pages) {
loadMoreBtn.style.display = 'none';
} else {
loadMoreBtn.style.display = 'flex';
}
} catch (error) {
console.error('Error fetching movies:', error);
moviesGrid.innerHTML = `
<div class="col-span-full text-center py-10">
<i class="fas fa-exclamation-triangle text-red-500 text-4xl mb-4"></i>
<h3 class="text-xl font-bold">Erreur de chargement</h3>
<p class="text-gray-400">Impossible de charger les films. Veuillez réessayer.</p>
</div>
`;
} finally {
isLoading = false;
loadMoreBtn.disabled = false;
loadMoreBtn.innerHTML = 'Charger plus de films';
}
}
function loadMoreMovies() {
loadMovies();
}
function displayMovies(movies) {
movies.forEach(movie => {
const movieCard = document.createElement('div');
movieCard.className = 'movie-card bg-gray-800 rounded-lg overflow-hidden shadow-lg hover:shadow-xl transition relative';
movieCard.innerHTML = `
<div class="relative h-80 overflow-hidden">
<img
src="${movie.poster_path ? `https://image.tmdb.org/t/p/w500${movie.poster_path}` : 'https://via.placeholder.com/500x750?text=No+Image'}"
alt="${movie.title}"
class="w-full h-full object-cover"
onerror="this.src='https://via.placeholder.com/500x750?text=No+Image'"
>
<div class="movie-overlay absolute inset-0 bg-black bg-opacity-70 opacity-0 flex flex-col justify-between p-4">
<div class="flex justify-between items-start">
<span class="bg-indigo-600 text-white text-xs font-bold px-2 py-1 rounded">
${movie.release_date ? movie.release_date.split('-')[0] : 'N/A'}
</span>
<span class="bg-yellow-500 text-gray-900 text-xs font-bold px-2 py-1 rounded flex items-center">
<i class="fas fa-star mr-1"></i> ${movie.vote_average.toFixed(1)}
</span>
</div>
<div>
<p class="text-sm text-gray-300 line-clamp-3">${movie.overview || 'Aucune description disponible.'}</p>
</div>
<div class="flex flex-col space-y-2">
<!-- Play button -->
<button class="play-btn bg-red-600 hover:bg-red-700 text-white px-3 py-2 rounded font-medium transition flex items-center justify-center w-full" data-movie-id="${movie.id}">
<i class="fas fa-play mr-2"></i> Regarder maintenant
</button>
<!-- Watch later button -->
<button class="watch-later-btn bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-2 rounded font-medium transition flex items-center justify-center w-full">
<i class="fas fa-clock mr-2"></i> À regarder plus tard
</button>
<!-- Details button -->
<a href="https://www.themoviedb.org/movie/${movie.id}" target="_blank" class="bg-white text-gray-900 hover:bg-gray-200 px-3 py-2 rounded text-sm font-medium transition flex items-center justify-center">
<i class="fas fa-info-circle mr-2"></i> Détails
</a>
</div>
</div>
</div>
<div class="p-4">
<h3 class="font-bold text-lg mb-1 truncate">${movie.title}</h3>
<div class="flex justify-between items-center text-gray-400 text-sm">
<span>${movie.genre_ids.length ? 'Genre' : 'Pas de genre'}</span>
<span class="flex items-center">
<i class="fas fa-heart text-red-500 mr-1"></i> ${movie.popularity.toFixed(0)}
</span>
</div>
</div>
`;
moviesGrid.appendChild(movieCard);
// Add event listener to the play button
const playBtn = movieCard.querySelector('.play-btn');
playBtn.addEventListener('click', () => showStreamingOptions(movie));
});
}
function showStreamingOptions(movie) {
// Create modal for server selection
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-gray-800 rounded-lg p-6 w-full max-w-md">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">Choisissez un serveur</h3>
<button class="close-modal text-gray-400 hover:text-white">
<i class="fas fa-times"></i>
</button>
</div>
<p class="text-gray-400 mb-4">Sélectionnez un serveur pour regarder "${movie.title}"</p>
<div class="grid grid-cols-2 gap-3 mb-4" id="server-buttons">
${Object.entries(STREAMING_SERVERS).map(([key, server]) => `
<button class="server-btn ${server.color} hover:${server.color.replace('600', '700')} text-white px-4 py-3 rounded-lg transition flex flex-col items-center" data-server="${key}">
<i class="${server.icon} text-xl mb-1"></i>
<span>${server.name}</span>
</button>
`).join('')}
</div>
<div class="bg-gray-700 rounded-lg p-4 hidden" id="quality-options">
<h4 class="font-medium mb-2">Qualité disponible :</h4>
<div class="flex space-x-2">
<button class="quality-btn bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded" data-quality="1080">1080p</button>
<button class="quality-btn bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded" data-quality="720">720p</button>
<button class="quality-btn bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded" data-quality="480">480p</button>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
// Close modal
const closeModal = modal.querySelector('.close-modal');
closeModal.addEventListener('click', () => {
document.body.removeChild(modal);
});
// Server selection
const serverButtons = modal.querySelectorAll('.server-btn');
const qualityOptions = modal.querySelector('#quality-options');
serverButtons.forEach(btn => {
btn.addEventListener('click', () => {
// Highlight selected server
serverButtons.forEach(b => b.classList.remove('ring-2', 'ring-white'));
btn.classList.add('ring-2', 'ring-white');
// Show quality options
qualityOptions.classList.remove('hidden');
// When quality is selected
const qualityBtns = qualityOptions.querySelectorAll('.quality-btn');
qualityBtns.forEach(qBtn => {
qBtn.addEventListener('click', () => {
const quality = qBtn.dataset.quality;
playMovie(movie, btn.dataset.server, quality);
document.body.removeChild(modal);
});
});
});
});
}
function playMovie(movie, server, quality) {
// Generate a streaming URL based on movie ID, server and quality
// Note: This is a simulation - in a real app, you would need actual streaming URLs
const streamingUrl = `https://example-stream-provider.com/player?movie_id=${movie.id}&server=${server}&quality=${quality}`;
// Show player container
playerContainer.style.display = 'flex';
// Set iframe source
moviePlayer.src = streamingUrl;
// Update stats (simulate view count)
const moviesCountEl = document.getElementById('movies-count');
moviesCountEl.textContent = parseInt(moviesCountEl.textContent) + 1;
// Add to recently watched in localStorage
const watched = JSON.parse(localStorage.getItem('recentlyWatched') || '[]');
watched.unshift({
id: movie.id,
title: movie.title,
poster: movie.poster_path ? `https://image.tmdb.org/t/p/w200${movie.poster_path}` : null,
date: new Date().toISOString()
});
localStorage.setItem('recentlyWatched', JSON.stringify(watched.slice(0, 10)));
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=docto41/cin" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>