cin-verse / index.html
docto41's picture
Add 2 files
36711f4 verified
<!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">
<!-- Les films seront chargés ici via JavaScript -->
</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>
<!-- Template pour la page de détails du film (caché par défaut) -->
<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">
<!-- Les options de streaming seront ajoutées ici -->
</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>
// Configuration de base
const API_KEY = '3fd2be6f0c70a2a598f084ddfb75487c'; // Clé API TMDB publique pour démo
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() {
// Éléments du DOM
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');
// Charger les films populaires au démarrage
fetchPopularMovies();
// Écouteurs d'événements
loadMoreButton.addEventListener('click', loadMoreMovies);
searchButton.addEventListener('click', searchMovies);
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') searchMovies();
});
// Écouteurs pour les boutons de genre
genreButtons.forEach(button => {
button.addEventListener('click', function() {
currentGenre = this.dataset.id;
currentSearch = '';
currentPage = 1;
sectionTitle.textContent = this.textContent;
fetchMoviesByGenre(currentGenre);
});
});
// Fonction pour charger les films populaires
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>';
}
}
// Fonction pour charger les films par genre
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>';
}
}
// Fonction pour rechercher des films
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>';
}
}
// Fonction pour charger plus de films
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';
}
}
// Fonction pour afficher les films
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');
}
}
// Fonction pour ajouter des films à la grille
function appendMovies(movies) {
movies.forEach(movie => {
const movieCard = document.createElement('div');
movieCard.className = 'movie-card bg-gray-800 rounded-lg overflow-hidden cursor-pointer';
// Vérifier si le film a une affiche
const posterPath = movie.poster_path ?
`${IMAGE_BASE_URL}${movie.poster_path}` :
'https://via.placeholder.com/500x750?text=Affiche+non+disponible';
// Formater la date de sortie
const releaseDate = movie.release_date ?
new Date(movie.release_date).getFullYear() :
'Date inconnue';
// Créer la carte de film
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);
});
}
});
// Fonction pour afficher les détails du film dans une modale
async function showMovieDetails(movieId) {
try {
// Afficher le loader
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>
`;
// Récupérer les détails du film
const movieResponse = await fetch(`https://api.themoviedb.org/3/movie/${movieId}?api_key=3fd2be6f0c70a2a598f084ddfb75487c&language=fr-FR`);
const movieData = await movieResponse.json();
// Récupérer les options de streaming (simulé car l'API watch providers nécessite une clé premium)
// Dans une application réelle, vous utiliseriez: /movie/{movie_id}/watch/providers
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)}` }
];
// Afficher les détails
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>