| <!DOCTYPE html> |
| <html lang="fr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>CinéVerse - Films populaires</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 { |
| transition: transform 0.3s ease, box-shadow 0.3s ease; |
| } |
| .movie-card:hover { |
| transform: scale(1.05); |
| box-shadow: 0 10px 25px rgba(220, 38, 38, 0.3); |
| } |
| .scroll-container { |
| height: calc(100vh - 200px); |
| overflow-y: auto; |
| } |
| .scroll-container::-webkit-scrollbar { |
| width: 8px; |
| } |
| .scroll-container::-webkit-scrollbar-track { |
| background: #1a202c; |
| } |
| .scroll-container::-webkit-scrollbar-thumb { |
| background: #e53e3e; |
| border-radius: 4px; |
| } |
| .loading-spinner { |
| animation: spin 1s linear infinite; |
| } |
| @keyframes spin { |
| 0% { transform: rotate(0deg); } |
| 100% { transform: rotate(360deg); } |
| } |
| .streaming-option { |
| transition: all 0.3s ease; |
| } |
| .streaming-option:hover { |
| transform: translateY(-5px); |
| box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1); |
| } |
| </style> |
| </head> |
| <body class="bg-gray-900 text-white"> |
| <header class="bg-black py-6 shadow-lg sticky top-0 z-50"> |
| <div class="container mx-auto px-4"> |
| <div class="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0"> |
| <div class="flex items-center space-x-2"> |
| <i class="fas fa-film text-3xl text-red-500"></i> |
| <h1 class="text-2xl font-bold">CinéVerse</h1> |
| </div> |
| <div class="relative w-full md:w-1/3"> |
| <input type="text" id="searchInput" placeholder="Rechercher un film..." class="w-full bg-gray-800 rounded-full py-2 px-4 text-white focus:outline-none focus:ring-2 focus:ring-red-500"> |
| <button id="searchButton" class="absolute right-3 top-2 text-gray-400 hover:text-white"> |
| <i class="fas fa-search"></i> |
| </button> |
| </div> |
| <div class="flex space-x-4"> |
| <button class="bg-red-600 hover:bg-red-700 px-4 py-2 rounded-md font-medium"> |
| <i class="fas fa-user mr-2"></i>Connexion |
| </button> |
| </div> |
| </div> |
| </div> |
| </header> |
|
|
| <main class="container mx-auto px-4 py-8"> |
| <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8 space-y-4 md:space-y-0"> |
| <h2 class="text-2xl font-bold" id="sectionTitle">Films populaires</h2> |
| <div class="flex flex-wrap gap-2"> |
| <button class="genre-btn bg-red-600 hover:bg-red-700 px-4 py-2 rounded-md" data-id="28">Action</button> |
| <button class="genre-btn bg-red-600 hover:bg-red-700 px-4 py-2 rounded-md" data-id="35">Comédie</button> |
| <button class="genre-btn bg-red-600 hover:bg-red-700 px-4 py-2 rounded-md" data-id="18">Drame</button> |
| <button class="genre-btn bg-red-600 hover:bg-red-700 px-4 py-2 rounded-md" data-id="27">Horreur</button> |
| <button class="genre-btn bg-red-600 hover:bg-red-700 px-4 py-2 rounded-md" data-id="10749">Romance</button> |
| </div> |
| </div> |
|
|
| <div id="loading" class="flex justify-center items-center py-20"> |
| <i class="fas fa-spinner loading-spinner text-4xl text-red-500"></i> |
| </div> |
|
|
| <div class="scroll-container hidden" id="moviesContainer"> |
| <div id="moviesGrid" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-6"> |
| |
| </div> |
| <div class="flex justify-center mt-8 mb-4"> |
| <button id="loadMore" class="bg-red-600 hover:bg-red-700 px-6 py-3 rounded-md font-medium hidden"> |
| Charger plus de films |
| </button> |
| </div> |
| </div> |
| </main> |
|
|
| |
| <div id="movieDetailsTemplate" class="hidden fixed inset-0 bg-black bg-opacity-90 z-50 overflow-y-auto"> |
| <div class="container mx-auto px-4 py-12"> |
| <button onclick="closeMovieDetails()" class="absolute top-4 right-4 text-3xl text-white hover:text-red-500"> |
| <i class="fas fa-times"></i> |
| </button> |
| |
| <div class="flex flex-col lg:flex-row gap-8"> |
| <div class="lg:w-1/3"> |
| <img id="detailPoster" src="" alt="Affiche du film" class="w-full rounded-lg shadow-xl"> |
| </div> |
| |
| <div class="lg:w-2/3"> |
| <h1 id="detailTitle" class="text-3xl font-bold mb-2"></h1> |
| <div class="flex items-center space-x-4 mb-4"> |
| <span id="detailYear" class="text-gray-400"></span> |
| <span id="detailRuntime" class="text-gray-400"></span> |
| <span id="detailRating" class="flex items-center text-yellow-400"> |
| <i class="fas fa-star mr-1"></i> |
| <span></span> |
| </span> |
| </div> |
| |
| <p id="detailOverview" class="text-lg mb-6"></p> |
| |
| <div class="mb-8"> |
| <h2 class="text-xl font-semibold mb-4">Où regarder</h2> |
| <div id="streamingOptions" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4"> |
| |
| </div> |
| <p class="text-gray-400 mt-4 text-sm">* Les liens pointent vers des plateformes légales de streaming</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <footer class="bg-black py-8 mt-12"> |
| <div class="container mx-auto px-4"> |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> |
| <div> |
| <h3 class="text-xl font-bold mb-4">CinéVerse</h3> |
| <p class="text-gray-400">Votre destination pour découvrir les meilleurs films et où les regarder légalement.</p> |
| </div> |
| <div> |
| <h4 class="text-lg font-semibold mb-4">Liens utiles</h4> |
| <ul class="space-y-2 text-gray-400"> |
| <li><a href="#" class="hover:text-red-500">À propos</a></li> |
| <li><a href="#" class="hover:text-red-500">Contact</a></li> |
| <li><a href="#" class="hover:text-red-500">Politique de confidentialité</a></li> |
| </ul> |
| </div> |
| <div> |
| <h4 class="text-lg font-semibold mb-4">Plateformes</h4> |
| <ul class="space-y-2 text-gray-400"> |
| <li><a href="https://www.netflix.com" target="_blank" class="hover:text-red-500">Netflix</a></li> |
| <li><a href="https://www.primevideo.com" target="_blank" class="hover:text-red-500">Amazon Prime</a></li> |
| <li><a href="https://www.disneyplus.com" target="_blank" class="hover:text-red-500">Disney+</a></li> |
| </ul> |
| </div> |
| <div> |
| <h4 class="text-lg font-semibold mb-4">Réseaux sociaux</h4> |
| <div class="flex space-x-4"> |
| <a href="#" class="text-gray-400 hover:text-red-500 text-xl"><i class="fab fa-facebook"></i></a> |
| <a href="#" class="text-gray-400 hover:text-red-500 text-xl"><i class="fab fa-twitter"></i></a> |
| <a href="#" class="text-gray-400 hover:text-red-500 text-xl"><i class="fab fa-instagram"></i></a> |
| </div> |
| </div> |
| </div> |
| <div class="border-t border-gray-800 mt-8 pt-6 text-center text-gray-400"> |
| <p>Ce site utilise l'API TMDB mais n'est pas affilié à TMDB.</p> |
| <p class="mt-2">Les films présentés sont protégés par des droits d'auteur.</p> |
| </div> |
| </div> |
| </footer> |
|
|
| <script> |
| |
| const API_KEY = '3fd2be6f0c70a2a598f084ddfb75487c'; |
| const BASE_URL = 'https://api.themoviedb.org/3'; |
| const IMAGE_BASE_URL = 'https://image.tmdb.org/t/p/w500'; |
| const FRENCH_LANGUAGE = 'fr-FR'; |
| |
| let currentPage = 1; |
| let currentGenre = ''; |
| let currentSearch = ''; |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const moviesGrid = document.getElementById('moviesGrid'); |
| const loadingElement = document.getElementById('loading'); |
| const moviesContainer = document.getElementById('moviesContainer'); |
| const loadMoreButton = document.getElementById('loadMore'); |
| const searchInput = document.getElementById('searchInput'); |
| const searchButton = document.getElementById('searchButton'); |
| const sectionTitle = document.getElementById('sectionTitle'); |
| const genreButtons = document.querySelectorAll('.genre-btn'); |
| |
| |
| fetchPopularMovies(); |
| |
| |
| loadMoreButton.addEventListener('click', loadMoreMovies); |
| searchButton.addEventListener('click', searchMovies); |
| searchInput.addEventListener('keypress', function(e) { |
| if (e.key === 'Enter') searchMovies(); |
| }); |
| |
| |
| genreButtons.forEach(button => { |
| button.addEventListener('click', function() { |
| currentGenre = this.dataset.id; |
| currentSearch = ''; |
| currentPage = 1; |
| sectionTitle.textContent = this.textContent; |
| fetchMoviesByGenre(currentGenre); |
| }); |
| }); |
| |
| |
| async function fetchPopularMovies() { |
| try { |
| const response = await fetch(`${BASE_URL}/movie/popular?api_key=${API_KEY}&language=${FRENCH_LANGUAGE}&page=${currentPage}`); |
| const data = await response.json(); |
| displayMovies(data.results); |
| } catch (error) { |
| console.error('Erreur:', error); |
| loadingElement.innerHTML = '<p class="text-red-500">Erreur lors du chargement des films. Veuillez réessayer.</p>'; |
| } |
| } |
| |
| |
| async function fetchMoviesByGenre(genreId) { |
| try { |
| loadingElement.classList.remove('hidden'); |
| moviesContainer.classList.add('hidden'); |
| loadMoreButton.classList.add('hidden'); |
| moviesGrid.innerHTML = ''; |
| |
| const response = await fetch(`${BASE_URL}/discover/movie?api_key=${API_KEY}&language=${FRENCH_LANGUAGE}&sort_by=popularity.desc&page=${currentPage}&with_genres=${genreId}`); |
| const data = await response.json(); |
| displayMovies(data.results); |
| } catch (error) { |
| console.error('Erreur:', error); |
| loadingElement.innerHTML = '<p class="text-red-500">Erreur lors du chargement des films. Veuillez réessayer.</p>'; |
| } |
| } |
| |
| |
| async function searchMovies() { |
| const query = searchInput.value.trim(); |
| if (query === '') return; |
| |
| currentSearch = query; |
| currentGenre = ''; |
| currentPage = 1; |
| sectionTitle.textContent = `Résultats pour "${query}"`; |
| |
| try { |
| loadingElement.classList.remove('hidden'); |
| moviesContainer.classList.add('hidden'); |
| loadMoreButton.classList.add('hidden'); |
| moviesGrid.innerHTML = ''; |
| |
| const response = await fetch(`${BASE_URL}/search/movie?api_key=${API_KEY}&language=${FRENCH_LANGUAGE}&query=${encodeURIComponent(query)}&page=${currentPage}`); |
| const data = await response.json(); |
| displayMovies(data.results); |
| } catch (error) { |
| console.error('Erreur:', error); |
| loadingElement.innerHTML = '<p class="text-red-500">Erreur lors de la recherche. Veuillez réessayer.</p>'; |
| } |
| } |
| |
| |
| async function loadMoreMovies() { |
| currentPage++; |
| try { |
| loadMoreButton.disabled = true; |
| loadMoreButton.innerHTML = '<i class="fas fa-spinner loading-spinner mr-2"></i> Chargement...'; |
| |
| let response; |
| if (currentSearch) { |
| response = await fetch(`${BASE_URL}/search/movie?api_key=${API_KEY}&language=${FRENCH_LANGUAGE}&query=${encodeURIComponent(currentSearch)}&page=${currentPage}`); |
| } else if (currentGenre) { |
| response = await fetch(`${BASE_URL}/discover/movie?api_key=${API_KEY}&language=${FRENCH_LANGUAGE}&sort_by=popularity.desc&page=${currentPage}&with_genres=${currentGenre}`); |
| } else { |
| response = await fetch(`${BASE_URL}/movie/popular?api_key=${API_KEY}&language=${FRENCH_LANGUAGE}&page=${currentPage}`); |
| } |
| |
| const data = await response.json(); |
| appendMovies(data.results); |
| |
| loadMoreButton.disabled = false; |
| loadMoreButton.innerHTML = 'Charger plus de films'; |
| } catch (error) { |
| console.error('Erreur:', error); |
| loadMoreButton.innerHTML = 'Erreur - Réessayer'; |
| } |
| } |
| |
| |
| function displayMovies(movies) { |
| if (movies.length === 0) { |
| loadingElement.innerHTML = '<p class="text-red-500">Aucun film trouvé.</p>'; |
| return; |
| } |
| |
| moviesGrid.innerHTML = ''; |
| appendMovies(movies); |
| |
| loadingElement.classList.add('hidden'); |
| moviesContainer.classList.remove('hidden'); |
| |
| if (movies.length >= 20) { |
| loadMoreButton.classList.remove('hidden'); |
| } else { |
| loadMoreButton.classList.add('hidden'); |
| } |
| } |
| |
| |
| function appendMovies(movies) { |
| movies.forEach(movie => { |
| const movieCard = document.createElement('div'); |
| movieCard.className = 'movie-card bg-gray-800 rounded-lg overflow-hidden cursor-pointer'; |
| |
| |
| const posterPath = movie.poster_path ? |
| `${IMAGE_BASE_URL}${movie.poster_path}` : |
| 'https://via.placeholder.com/500x750?text=Affiche+non+disponible'; |
| |
| |
| const releaseDate = movie.release_date ? |
| new Date(movie.release_date).getFullYear() : |
| 'Date inconnue'; |
| |
| |
| movieCard.innerHTML = ` |
| <div onclick="showMovieDetails(${movie.id})"> |
| <img src="${posterPath}" alt="${movie.title}" class="w-full h-64 sm:h-80 object-cover"> |
| <div class="p-4"> |
| <h3 class="font-bold truncate">${movie.title}</h3> |
| <div class="flex justify-between items-center mt-2 text-sm text-gray-400"> |
| <span>${releaseDate}</span> |
| <span class="flex items-center"> |
| <i class="fas fa-star text-yellow-400 mr-1"></i> |
| ${movie.vote_average ? movie.vote_average.toFixed(1) : 'N/A'} |
| </span> |
| </div> |
| </div> |
| </div> |
| `; |
| moviesGrid.appendChild(movieCard); |
| }); |
| } |
| }); |
| |
| |
| async function showMovieDetails(movieId) { |
| try { |
| |
| const detailsTemplate = document.getElementById('movieDetailsTemplate'); |
| detailsTemplate.classList.remove('hidden'); |
| detailsTemplate.innerHTML = ` |
| <div class="flex justify-center items-center h-full"> |
| <i class="fas fa-spinner loading-spinner text-4xl text-red-500"></i> |
| </div> |
| `; |
| |
| |
| const movieResponse = await fetch(`https://api.themoviedb.org/3/movie/${movieId}?api_key=3fd2be6f0c70a2a598f084ddfb75487c&language=fr-FR`); |
| const movieData = await movieResponse.json(); |
| |
| |
| |
| const streamingOptions = [ |
| { provider_name: "Netflix", logo_path: "/9A1JSVmSxsyaBK4SUFsYVqbAYfW.jpg", link: `https://www.netflix.com/search?q=${encodeURIComponent(movieData.title)}` }, |
| { provider_name: "Amazon Prime", logo_path: "/5NyLm42TmCqCMOZFvH4fcoSNKEW.jpg", link: `https://www.primevideo.com/search/ref=atv_nb_sr?phrase=${encodeURIComponent(movieData.title)}` }, |
| { provider_name: "Disney+", logo_path: "/drg0fW8CQ5icOq2PZ3mzAfpXvDF.jpg", link: `https://www.disneyplus.com/fr-fr/search?q=${encodeURIComponent(movieData.title)}` }, |
| { provider_name: "Canal+", logo_path: "/sVBEF7q7LqjHAWSnKwDbzmr2EMY.jpg", link: `https://www.canalplus.com/recherche/?q=${encodeURIComponent(movieData.title)}` } |
| ]; |
| |
| |
| detailsTemplate.innerHTML = ` |
| <div class="container mx-auto px-4 py-12"> |
| <button onclick="closeMovieDetails()" class="absolute top-4 right-4 text-3xl text-white hover:text-red-500"> |
| <i class="fas fa-times"></i> |
| </button> |
| |
| <div class="flex flex-col lg:flex-row gap-8"> |
| <div class="lg:w-1/3"> |
| <img id="detailPoster" src="${movieData.poster_path ? 'https://image.tmdb.org/t/p/w500' + movieData.poster_path : 'https://via.placeholder.com/500x750?text=Affiche+non+disponible'}" alt="${movieData.title}" class="w-full rounded-lg shadow-xl"> |
| </div> |
| |
| <div class="lg:w-2/3"> |
| <h1 id="detailTitle" class="text-3xl font-bold mb-2">${movieData.title}</h1> |
| <div class="flex items-center space-x-4 mb-4"> |
| <span id="detailYear" class="text-gray-400"> |
| </html> |