// ==================== I18N TRANSLATIONS ==================== const TRANSLATIONS = { ru: { favorites: "Избранное", history: "История", heroTitle: "Что смотрим сегодня?", heroSubtitle: "Ответь на несколько вопросов — и мы найдём фильм", moodTitle: "Настроение", moodFun: "Весело", moodScary: "Страшно", moodThink: "Подумать", moodRomance: "Романтика", moodDrive: "Драйв", moodComedy: "Комедия", moodSad: "Грустное", moodUnusual: "Что-то необычное", filtersTitle: "Фильтры", resetFilters: "Сбросить фильтры", filterGenre: "Жанр", genreAny: "Любой жанр", genreAction: "Боевик", genreComedy: "Комедия", genreDrama: "Драма", genreScifi: "Фантастика", genreHorror: "Ужасы", genreThriller: "Триллер", genreAdventure: "Приключения", genreFantasy: "Фэнтези", genreMystery: "Детектив", genreRomance: "Романтика", genreAnimation: "Анимация", genreCrime: "Криминал", genreHistory: "История", filterYear: "Год", yearAny: "Любой год", yearBefore1990: "До 1990", filterRating: "Рейтинг", ratingAny: "Любой", filterDuration: "Длительность", durationAny: "Любая", duration90: "До 90 минут", duration120: "До 120 минут", duration150: "До 150 минут", duration150plus: "Более 150 минут", randomMode: "Я НЕ ЗНАЮ, ЧТО ХОЧУ", findMovie: "НАЙТИ ФИЛЬМ", watchNow: "Смотреть", addFavorite: "В избранное", anotherMovie: "Другой фильм", emptyTitle: "Кажется, мы слишком сильно ограничили выбор", emptyText: "Попробуй убрать один из фильтров", back: "Назад", myFavorites: "Мои фильмы ❤️", favoritesEmpty: "Здесь пока пусто", findFirstFilm: "Найдём тебе первый фильм? 🎬", viewingHistory: "История просмотров", historyEmpty: "История пуста", noHistory: "Ты ещё не смотрел фильмы через FILMORA", clearHistory: "Очистить историю", whereToWatch: "Где смотреть", streamingAvailable: "Доступно на платформах" }, en: { favorites: "Favorites", history: "History", heroTitle: "What are we watching tonight?", heroSubtitle: "Answer a few questions and we'll find your perfect movie", moodTitle: "Mood", moodFun: "Fun", moodScary: "Scary", moodThink: "Thoughtful", moodRomance: "Romance", moodDrive: "Action", moodComedy: "Comedy", moodSad: "Sad", moodUnusual: "Something unusual", filtersTitle: "Filters", resetFilters: "Reset filters", filterGenre: "Genre", genreAny: "Any genre", genreAction: "Action", genreComedy: "Comedy", genreDrama: "Drama", genreScifi: "Sci-Fi", genreHorror: "Horror", genreThriller: "Thriller", genreAdventure: "Adventure", genreFantasy: "Fantasy", genreMystery: "Mystery", genreRomance: "Romance", genreAnimation: "Animation", genreCrime: "Crime", genreHistory: "History", filterYear: "Year", yearAny: "Any year", yearBefore1990: "Before 1990", filterRating: "Rating", ratingAny: "Any", filterDuration: "Duration", durationAny: "Any", duration90: "Up to 90 min", duration120: "Up to 120 min", duration150: "Up to 150 min", duration150plus: "Over 150 min", randomMode: "I DON'T KNOW WHAT I WANT", findMovie: "FIND MOVIE", watchNow: "Watch Now", addFavorite: "Add to favorites", anotherMovie: "Another movie", emptyTitle: "Hmm, filters are too strict", emptyText: "Try removing some filters", back: "Back", myFavorites: "My Movies ❤️", favoritesEmpty: "Nothing here yet", findFirstFilm: "Find your first movie? 🎬", viewingHistory: "Viewing History", historyEmpty: "History is empty", noHistory: "You haven't watched any movies through FILMORA yet", clearHistory: "Clear history", whereToWatch: "Where to watch", streamingAvailable: "Available on" }, kk: { favorites: "Таңдаулы", history: "Тарих", heroTitle: "Бүгін не көреміз?", heroSubtitle: "Бірнеше сұраққа жауап бер — біз фильм табамыз", moodTitle: "Көңіл-күй", moodFun: "Көңілді", moodScary: "Қорқынышты", moodThink: "Ойлану", moodRomance: "Романтика", moodDrive: "Драйв", moodComedy: "Комедия", moodSad: "Мұңлы", moodUnusual: "Ерекше нәрсе", filtersTitle: "Сүзгілер", resetFilters: "Сүзгілерді тазалау", filterGenre: "Жанр", genreAny: "Кез келген жанр", genreAction: "Боевик", genreComedy: "Комедия", genreDrama: "Драма", genreScifi: "Фантастика", genreHorror: "Қорқынышты", genreThriller: "Триллер", genreAdventure: "Шытырман", genreFantasy: "Фэнтези", genreMystery: "Детектив", genreRomance: "Романтика", genreAnimation: "Анимация", genreCrime: "Қылмыс", genreHistory: "Тарих", filterYear: "Жыл", yearAny: "Кез келген жыл", yearBefore1990: "1990 дейін", filterRating: "Рейтинг", ratingAny: "Кез келген", filterDuration: "Ұзақтығы", durationAny: "Кез келген", duration90: "90 минутқа дейін", duration120: "120 минутқа дейін", duration150: "150 минутқа дейін", duration150plus: "150 минуттан көп", randomMode: "БІЛМЕЙМІН НЕ ҚАЛАЙМЫН", findMovie: "ФИЛЬМ ТАБУ", watchNow: "Көру", addFavorite: "Таңдаулыға қосу", anotherMovie: "Басқа фильм", emptyTitle: "Сүзгілер тым қатаң", emptyText: "Бір сүзгіні алып таста", back: "Артқа", myFavorites: "Менің фильмдерім ❤️", favoritesEmpty: "Әлі бос", findFirstFilm: "Алғашқы фильмді табайық па? 🎬", viewingHistory: "Көру тарихы", historyEmpty: "Тарих бос", noHistory: "FILMORA арқылы әлі фильм көрмедің", clearHistory: "Тарихты тазалау", whereToWatch: "Қайда көруге", streamingAvailable: "Платформаларда қолжетімді" } }; let currentLang = localStorage.getItem('filmora_lang') || 'ru'; // ==================== MOVIE DATABASE ==================== const MOVIES = [ { id: 1, title: "Побег из Шоушенка", originalTitle: "The Shawshank Redemption", year: 1994, rating: 9.3, duration: 142, genres: ["drama", "crime"], moods: ["think", "sad"], description: "Бухгалтер Энди Дюфрейн обвинён в убийстве собственной жены и её любовника. Оказавшись в тюрьме под названием Шоушенк, он сталкивается с жестокостью и беззаконием.", poster: "https://image.tmdb.org/t/p/w500/q6y0Go1tsGEsmtFryDOJo3dEmqu.jpg", streaming: [ { name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" } ] }, { id: 2, title: "Крёстный отец", originalTitle: "The Godfather", year: 1972, rating: 9.2, duration: 175, genres: ["crime", "drama"], moods: ["think", "drive"], description: "Крёстный отец — драма о мафиозной семье Корлеоне. История о власти, семье и предательстве в мире организованной преступности.", poster: "https://image.tmdb.org/t/p/w500/3bhkrj58Vtu7enYsRolD1fZdja1.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 3, title: "Тёмный рыцарь", originalTitle: "The Dark Knight", year: 2008, rating: 9.0, duration: 152, genres: ["action", "crime", "drama"], moods: ["drive", "think"], description: "Бэтмен поднимает ставки в войне с криминалом. С помощью лейтенанта Джима Гордона и прокурора Харви Дента он намерен очистить улицы от преступности.", poster: "https://image.tmdb.org/t/p/w500/qJ2tW6WMUDux911r6m7haRef0WH.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 4, title: "Начало", originalTitle: "Inception", year: 2010, rating: 8.8, duration: 148, genres: ["scifi", "action", "thriller"], moods: ["think", "drive", "unusual"], description: "Кобб — талантливый вор, лучший в опасном искусстве извлечения секретов подсознания во время сна. Он получает шанс начать всё заново.", poster: "https://image.tmdb.org/t/p/w500/9gk7adHYeDvHkCSEqAvQNLV5Uge.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 5, title: "Интерстеллар", originalTitle: "Interstellar", year: 2014, rating: 8.7, duration: 169, genres: ["scifi", "drama", "adventure"], moods: ["think", "unusual"], description: "Когда засуха и пыльные бури приводят человечество к продовольственному кризису, бывший пилот НАСА Купер отправляется в миссию через червоточину.", poster: "https://image.tmdb.org/t/p/w500/gEU2QniL6E8AHtMYfHM159D5xh.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 6, title: "Криминальное чтиво", originalTitle: "Pulp Fiction", year: 1994, rating: 8.9, duration: 154, genres: ["crime", "thriller"], moods: ["drive", "unusual", "fun"], description: "Два бандита Винсент Вега и Джулс Винфилд обсуждают свои предпочтения в еде и разница между европейской и американской поп-культурой.", poster: "https://image.tmdb.org/t/p/w500/d5iIlFn5s0ImszYzBPb8JPIfbXD.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] }, { id: 7, title: "Бойцовский клуб", originalTitle: "Fight Club", year: 1999, rating: 8.8, duration: 139, genres: ["drama", "thriller"], moods: ["think", "drive", "unusual"], description: "Сотрудник страховой компании страдает хронической бессонницей и отчаянно пытается вырваться из мучительно скучной жизни.", poster: "https://image.tmdb.org/t/p/w500/pB8BM7pdSp6B6Ih7QZ4DrQ3PmJK.jpg", streaming: [{ name: "Rakuten", icon: "🛒", url: "https://rakuten.tv" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 8, title: "Форрест Гамп", originalTitle: "Forrest Gump", year: 1994, rating: 8.8, duration: 142, genres: ["drama", "romance", "comedy"], moods: ["fun", "romance", "sad"], description: "История простого человека с большим сердцем, который становится свидетелем и участником ключевых событий американской истории.", poster: "https://image.tmdb.org/t/p/w500/arw2vcBveWOVZr6pxd9XTd1TdQa.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }] }, { id: 9, title: "Матрица", originalTitle: "The Matrix", year: 1999, rating: 8.7, duration: 136, genres: ["scifi", "action"], moods: ["drive", "think", "unusual"], description: "Хакер Нео узнаёт, что наш мир — это иллюзия, созданная машинами. Он присоединяется к восстанию против машин.", poster: "https://image.tmdb.org/t/p/w500/f89U3ADr1oiB1s9GkdPOEpXUk5H.jpg", streaming: [{ name: "Hulu", icon: "🎬", url: "https://www.hulu.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 10, title: "Хороший, плохой, злой", originalTitle: "The Good, the Bad and the Ugly", year: 1966, rating: 8.8, duration: 161, genres: ["action", "adventure"], moods: ["drive", "fun"], description: "Три охотника за сокровищами конкурируют в поисках конфедеративного золота во время Гражданской войны в США.", poster: "https://image.tmdb.org/t/p/w500/bX2xnavhMYjWDoZp1VM6VnU1xwe.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 11, title: "Властелин колец: Возвращение короля", originalTitle: "The Lord of the Rings: The Return of the King", year: 2003, rating: 9.0, duration: 201, genres: ["fantasy", "adventure", "action"], moods: ["drive", "think"], description: "Фродо и Сэм приближаются к Роковой горе, чтобы уничтожить Кольцо, в то время как Арагорн ведёт битву за Гондор.", poster: "https://image.tmdb.org/t/p/w500/rCzpDGLbOoPwLjy3OAm5NUPOTrC.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 12, title: "Бойцовский клуб", originalTitle: "Fight Club", year: 1999, rating: 8.8, duration: 139, genres: ["drama"], moods: ["think", "unusual"], description: "Офисный работник встречает харизматичного продавца мыла и создаёт подпольный бойцовский клуб.", poster: "https://image.tmdb.org/t/p/w500/pB8BM7pdSp6B6Ih7QZ4DrQ3PmJK.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 13, title: "Звёздные войны: Эпизод V - Империя наносит ответный удар", originalTitle: "Star Wars: Episode V - The Empire Strikes Back", year: 1980, rating: 8.7, duration: 124, genres: ["scifi", "adventure", "fantasy"], moods: ["drive", "fun"], description: "Люк Скайуокер начинает обучение джедая у магистра Йоды, в то время как Дарт Вейдер преследует друзей Люка.", poster: "https://image.tmdb.org/t/p/w500/2l05cFWJacyIsTpsqSgH0wQXe4V.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 14, title: "Один дома", originalTitle: "Home Alone", year: 1990, rating: 7.7, duration: 103, genres: ["comedy", "adventure"], moods: ["fun", "comedy"], description: "Восьмилетний Кевин остаётся один дома на Рождество и должен защитить свой дом от двух грабителей.", poster: "https://image.tmdb.org/t/p/w500/onTSipZ8R3amIkoc8xWrLXl5hV.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 15, title: "Унесённые призраками", originalTitle: "Spirited Away", year: 2001, rating: 8.6, duration: 125, genres: ["animation", "fantasy", "adventure"], moods: ["unusual", "think"], description: "Девочка попадает в таинственный мир духов и должна найти способ освободить себя и своих родителей.", poster: "https://image.tmdb.org/t/p/w500/39wmItIWsg5sZMyRUKGnDbALpd1.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] }, { id: 16, title: "Сияние", originalTitle: "The Shining", year: 1980, rating: 8.4, duration: 146, genres: ["horror", "thriller"], moods: ["scary", "think"], description: "Писатель Джек Торранс становится зимним смотрителем отеля «Оверлук», где происходят сверхъестественные события.", poster: "https://image.tmdb.org/t/p/w500/b6ko0IKC8MdYBBPkkA1aBPLe2yz.jpg", streaming: [{ name: "Rakuten", icon: "🛒", url: "https://rakuten.tv" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 17, title: "Чужой", originalTitle: "Alien", year: 1979, rating: 8.5, duration: 117, genres: ["horror", "scifi"], moods: ["scary", "drive"], description: "Экипаж космического корабля сталкивается с смертоносным инопланетным существом.", poster: "https://image.tmdb.org/t/p/w500/vfrQk5IPloGg1v9Rzbh2Eg3VGyM.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }] }, { id: 18, title: "Титаник", originalTitle: "Titanic", year: 1997, rating: 7.9, duration: 195, genres: ["romance", "drama"], moods: ["romance", "sad"], description: "История любви между аристократкой и художником из бедных слоёв общества на борту обречённого лайнера.", poster: "https://image.tmdb.org/t/p/w500/9xjZS2rlVxm8SFx8kPC3aIGCOYQ.jpg", streaming: [{ name: "Hulu", icon: "🎬", url: "https://www.hulu.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 19, title: "День сурка", originalTitle: "Groundhog Day", year: 1993, rating: 8.0, duration: 101, genres: ["comedy", "romance", "fantasy"], moods: ["fun", "comedy", "romance"], description: "Циничный метеоролог попадает в временную петлю и вынужден проживать один и тот же день снова и снова.", poster: "https://image.tmdb.org/t/p/w500/gCgt1WARPZaXnq5zeJRYrWwFZ2.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 20, title: "Паразиты", originalTitle: "Gisaengchung", year: 2019, rating: 8.5, duration: 132, genres: ["thriller", "drama", "comedy"], moods: ["think", "unusual", "drive"], description: "Бедная семья обманом проникает в богатый дом, выдавая себя за квалифицированных специалистов.", poster: "https://image.tmdb.org/t/p/w500/7IiTTgloJzvGI1TAYymCfbfl3vT.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 21, title: "Джокер", originalTitle: "Joker", year: 2019, rating: 8.4, duration: 122, genres: ["crime", "thriller", "drama"], moods: ["think", "sad", "drive"], description: "История происхождения самого известного злодея вселенной DC — Артура Флека.", poster: "https://image.tmdb.org/t/p/w500/udDclJoHjfjb8EkGsdr7ZKRN44.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 22, title: "Мстители: Финал", originalTitle: "Avengers: Endgame", year: 2019, rating: 8.4, duration: 181, genres: ["action", "adventure", "scifi"], moods: ["drive", "fun"], description: "Мстители собираются в последний раз, чтобы восстановить порядок во вселенной после событий Войны Бесконечности.", poster: "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 23, title: "Ла-Ла Ленд", originalTitle: "La La Land", year: 2016, rating: 8.0, duration: 128, genres: ["romance", "drama", "comedy"], moods: ["romance", "fun", "sad"], description: "История любви между начинающей актрисой и талантливым музыкантом в Лос-Анджелесе.", poster: "https://image.tmdb.org/t/p/w500/uDO8zWDhfWu7x6O0k0006Oe2M7.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 24, title: "Дюна", originalTitle: "Dune", year: 2021, rating: 8.0, duration: 155, genres: ["scifi", "adventure"], moods: ["think", "drive", "unusual"], description: "Пол Атрейдес отправляется на самую опасную планету во Вселенной, чтобы обеспечить будущее своей семьи.", poster: "https://image.tmdb.org/t/p/w500/d5NXSklXo0qyIYkgV94XAgMIckC.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] }, { id: 25, title: "Гарри Поттер и философский камень", originalTitle: "Harry Potter and the Sorcerer's Stone", year: 2001, rating: 7.6, duration: 152, genres: ["fantasy", "adventure"], moods: ["fun", "drive"], description: "Мальчик-сирота узнаёт, что он волшебник, и отправляется в школу магии Хогвартс.", poster: "https://image.tmdb.org/t/p/w500/wuMc08IPKEatf9rnMNXvIDxqP4W.jpg", streaming: [{ name: "Rakuten", icon: "🛒", url: "https://rakuten.tv" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 26, title: "Терминатор 2: Судный день", originalTitle: "Terminator 2: Judgment Day", year: 1991, rating: 8.6, duration: 137, genres: ["action", "scifi"], moods: ["drive", "fun"], description: "Киборг отправляется в прошлое, чтобы защитить будущего лидера сопротивления машин.", poster: "https://image.tmdb.org/t/p/w500/5M0j0B18abtBI5gi2RhfjjurTqb.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }] }, { id: 27, title: "Назад в будущее", originalTitle: "Back to the Future", year: 1985, rating: 8.5, duration: 116, genres: ["scifi", "adventure", "comedy"], moods: ["fun", "drive", "comedy"], description: "Подросток Марти Макфлай случайно отправляется в 1955 год на машине времени.", poster: "https://image.tmdb.org/t/p/w500/fNOH9f9aA7XRTzl1sAd7k1i0qHc.jpg", streaming: [{ name: "Hulu", icon: "🎬", url: "https://www.hulu.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 28, title: "Молчание ягнят", originalTitle: "The Silence of the Lambs", year: 1991, rating: 8.6, duration: 118, genres: ["crime", "thriller", "mystery"], moods: ["scary", "think"], description: "Агент ФБР обращается за помощью к каннибалу Ганнибалу Лектеру, чтобы поймать другого серийного убийцу.", poster: "https://image.tmdb.org/t/p/w500/uS9m8OBk1A8eM9I042bx8XXpqAq.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 29, title: "Спасти рядового Райана", originalTitle: "Saving Private Ryan", year: 1998, rating: 8.6, duration: 169, genres: ["drama", "history", "action"], moods: ["think", "sad", "drive"], description: "Отряд солдат отправляется на поиски парашютиста, чьи три брата погибли в бою.", poster: "https://image.tmdb.org/t/p/w500/uqx37cS8cpHg8U35f9U5IBlrCV3.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 30, title: "Зелёная миля", originalTitle: "The Green Mile", year: 1999, rating: 8.6, duration: 189, genres: ["drama", "fantasy"], moods: ["think", "sad"], description: "История о тюремном охраннике и заключённом с божественным даром.", poster: "https://image.tmdb.org/t/p/w500/velWPhVMQeQKcxggNEU8YmIo51R.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 31, title: "Гладиатор", originalTitle: "Gladiator", year: 2000, rating: 8.5, duration: 155, genres: ["action", "drama", "history"], moods: ["drive", "think"], description: "Римский генерал становится гладиатором и ищет мести за убийство своей семьи.", poster: "https://image.tmdb.org/t/p/w500/ty8TGRuvJLPUmAR1H1nRIsgwvim.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 32, title: "Король Лев", originalTitle: "The Lion King", year: 1994, rating: 8.5, duration: 88, genres: ["animation", "adventure", "drama"], moods: ["fun", "sad"], description: "Лев Симба должен принять свою судьбу и стать королём Прайдленда.", poster: "https://image.tmdb.org/t/p/w500/sKCr78MXSLixwmZ8DyJLrpMsd15.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 33, title: "Вечное сияние чистого разума", originalTitle: "Eternal Sunshine of the Spotless Mind", year: 2004, rating: 8.3, duration: 108, genres: ["romance", "scifi", "drama"], moods: ["romance", "think", "sad"], description: "Пара проходит процедуру удаления воспоминаний о болезненных отношениях.", poster: "https://image.tmdb.org/t/p/w500/5MwkWH9tYHv3m89PXxNulFo7Xug.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] }, { id: 34, title: "Отступники", originalTitle: "The Departed", year: 2006, rating: 8.5, duration: 151, genres: ["crime", "thriller", "drama"], moods: ["drive", "think"], description: "Два крота работают по обе стороны закона в полицейском департаменте Бостона.", poster: "https://image.tmdb.org/t/p/w500/nT97ifVT2J1yMQmeq20Qblg61T.jpg", streaming: [{ name: "Rakuten", icon: "🛒", url: "https://rakuten.tv" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 35, title: "Престиж", originalTitle: "The Prestige", year: 2006, rating: 8.5, duration: 130, genres: ["mystery", "thriller", "drama"], moods: ["think", "unusual"], description: "Два фокусника ведут ожесточённую борьбу, которая приводит к трагическим последствиям.", poster: "https://image.tmdb.org/t/p/w500/tRNlZbgNCNOpLpbPEz5L8G8A0JN.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }] }, { id: 36, title: "Вверх", originalTitle: "Up", year: 2009, rating: 8.3, duration: 96, genres: ["animation", "adventure", "comedy"], moods: ["fun", "comedy", "sad"], description: "78-летний Карл Фредриксен отправляется в приключение на воздушных шарах.", poster: "https://image.tmdb.org/t/p/w500/mFvoEwSfLqbr3N7xzWF8vB5lSj.jpg", streaming: [{ name: "Hulu", icon: "🎬", url: "https://www.hulu.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 37, title: "Тайна Коко", originalTitle: "Coco", year: 2017, rating: 8.4, duration: 105, genres: ["animation", "adventure", "fantasy"], moods: ["fun", "sad"], description: "Мальчик Мигель мечтает стать музыкантом и попадает в страну мёртвых.", poster: "https://image.tmdb.org/t/p/w500/gGEsBPAijhVUFoiNpgZXqRVWJt2.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 38, title: "Джанго освобождённый", originalTitle: "Django Unchained", year: 2012, rating: 8.4, duration: 165, genres: ["action", "drama"], moods: ["drive", "fun"], description: "Освобождённый раб Джанго отправляется спасать свою жену от жестокого владельца плантации.", poster: "https://image.tmdb.org/t/p/w500/7oWY8VDWW7thTzWh3OKYRkWUlD5.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 39, title: "ВАЛЛ·И", originalTitle: "WALL·E", year: 2008, rating: 8.4, duration: 98, genres: ["animation", "scifi", "adventure"], moods: ["fun", "think"], description: "Робот-уборщик на заброшенной Земле влюбляется в робота-разведчика ЕВУ.", poster: "https://image.tmdb.org/t/p/w500/hBnYqza876OMhRJRXxkFz4jjZPt.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 40, title: "Жизнь прекрасна", originalTitle: "La vita è bella", year: 1997, rating: 8.6, duration: 116, genres: ["comedy", "drama"], moods: ["fun", "sad", "think"], description: "Отец использует своё воображение, чтобы защитить сына от ужасов концлагеря.", poster: "https://image.tmdb.org/t/p/w500/74hLDKjD5aGYOotO6esUVaeISa2.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 41, title: "Матрица: Перезагрузка", originalTitle: "The Matrix Reloaded", year: 2003, rating: 7.2, duration: 138, genres: ["action", "scifi"], moods: ["drive", "think"], description: "Нео и его друзья готовятся к войне против машин.", poster: "https://image.tmdb.org/t/p/w500/9TGHDvWrqKBzwDxDodHYXEmOE5J.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 42, title: "Аватар", originalTitle: "Avatar", year: 2009, rating: 7.9, duration: 162, genres: ["scifi", "adventure", "fantasy"], moods: ["drive", "unusual"], description: "Морпех Джейк Салли оказывается на планете Пандора и становится частью народа На'ви.", poster: "https://image.tmdb.org/t/p/w500/6EiRUJpuoeQPghrs3YNktfnqOVh.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] }, { id: 43, title: "Мстители: Война бесконечности", originalTitle: "Avengers: Infinity War", year: 2018, rating: 8.3, duration: 149, genres: ["action", "adventure", "scifi"], moods: ["drive", "fun"], description: "Мстители и их союзники должны остановить безумного титана Таноса.", poster: "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", streaming: [{ name: "Rakuten", icon: "🛒", url: "https://rakuten.tv" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 44, title: "Твоё имя", originalTitle: "Kimi no Na wa", year: 2016, rating: 8.4, duration: 106, genres: ["animation", "romance", "fantasy"], moods: ["romance", "think", "unusual"], description: "Два подростка mysteriously меняются телами и пытаются найти друг друга.", poster: "https://image.tmdb.org/t/p/w500/q719jXXEzOoYaps6babgKnONONX.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }] }, { id: 45, title: "1+1", originalTitle: "Intouchables", year: 2011, rating: 8.5, duration: 112, genres: ["drama", "comedy"], moods: ["fun", "comedy", "think"], description: "Аристократ-инвалид нанимает парня из гетто в качестве сиделки.", poster: "https://image.tmdb.org/t/p/w500/323BP0QQpxYZxhI7nwmANpLHR0u.jpg", streaming: [{ name: "Hulu", icon: "🎬", url: "https://www.hulu.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 46, title: "Хатико: Самый верный друг", originalTitle: "Hachi: A Dog's Tale", year: 2009, rating: 8.1, duration: 93, genres: ["drama"], moods: ["sad", "think"], description: "История о преданной собаке, которая ждёт своего хозяина на вокзале.", poster: "https://image.tmdb.org/t/p/w500/8Vt7mXHRo6bEj8nT5sD7bL8pF0.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 47, title: "Три билборда на границе Эббинга, Миссури", originalTitle: "Three Billboards Outside Ebbing, Missouri", year: 2017, rating: 8.1, duration: 115, genres: ["crime", "drama", "comedy"], moods: ["think", "drive"], description: "Мать убитой дочери требует справедливости через три билборда.", poster: "https://image.tmdb.org/t/p/w500/pZRhqJj0DBy4ghB7g6pG7MG9xW.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 48, title: "Большой Лебовски", originalTitle: "The Big Lebowski", year: 1998, rating: 7.8, duration: 117, genres: ["comedy", "crime"], moods: ["fun", "comedy", "unusual"], description: "Чувака путают с миллионером и втягивают в странную историю.", poster: "https://image.tmdb.org/t/p/w500/d4ftZu4dWypDlVE5p3V0p3e3i4.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 49, title: "Город Бога", originalTitle: "Cidade de Deus", year: 2002, rating: 8.6, duration: 130, genres: ["crime", "drama"], moods: ["drive", "think"], description: "История о жизни в фавелах Рио-де-Жанейро на протяжении нескольких десятилетий.", poster: "https://image.tmdb.org/t/p/w500/k7eYdWvhYQyDYR1p5MjZnJ4n2.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 50, title: "Список Шиндлера", originalTitle: "Schindler's List", year: 1993, rating: 9.0, duration: 195, genres: ["drama", "history"], moods: ["think", "sad"], description: "История Оскара Шиндлера, спасшего более тысячи евреев во время Холокоста.", poster: "https://image.tmdb.org/t/p/w500/sF1U4EUQS8YHUYjNl3pTXMYC4mV.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 51, title: "Пираты Карибского моря: Проклятие Чёрной жемчужины", originalTitle: "Pirates of the Caribbean: The Curse of the Black Pearl", year: 2003, rating: 8.0, duration: 143, genres: ["adventure", "fantasy", "action"], moods: ["fun", "drive", "comedy"], description: "Кузнец Уилл Тёрнер объединяется с эксцентричным пиратом Джеком Воробьём.", poster: "https://image.tmdb.org/t/p/w500/z8onk7LV9Mmw6zKz4hT6pzzvmvl.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] }, { id: 52, title: "Дьявол носит Prada", originalTitle: "The Devil Wears Prada", year: 2006, rating: 7.5, duration: 109, genres: ["comedy", "drama"], moods: ["fun", "comedy"], description: "Молодая девушка становится ассистенткой жестокого редактора модного журнала.", poster: "https://image.tmdb.org/t/p/w500/8916As6Y7bYPVr9pWzuBQQnrTHU.jpg", streaming: [{ name: "Rakuten", icon: "🛒", url: "https://rakuten.tv" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 53, title: "Малхолланд Драйв", originalTitle: "Mulholland Drive", year: 2001, rating: 7.9, duration: 147, genres: ["mystery", "thriller", "drama"], moods: ["think", "unusual", "scary"], description: "Женщина с амнезией и начинающая актриса исследуют тёмные стороны Голливуда.", poster: "https://image.tmdb.org/t/p/w500/tVxGt7uffR6IIbGlQpSP3yJhqqa.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }] }, { id: 54, title: "Семь", originalTitle: "Se7en", year: 1995, rating: 8.6, duration: 127, genres: ["crime", "mystery", "thriller"], moods: ["scary", "think", "drive"], description: "Два детектива ищут серийного убийцу, который наказывает жертв за семь смертных грехов.", poster: "https://image.tmdb.org/t/p/w500/6yoghtyTpznpBik8EngEmJskVUO.jpg", streaming: [{ name: "Hulu", icon: "🎬", url: "https://www.hulu.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 55, title: "Отель «Гранд Будапешт»", originalTitle: "The Grand Budapest Hotel", year: 2014, rating: 8.1, duration: 99, genres: ["comedy", "adventure"], moods: ["fun", "comedy", "unusual"], description: "История о легендарном консьерже Густаве и его друге Zero.", poster: "https://image.tmdb.org/t/p/w500/eWdyYQreja6JGCzqHWXpWHDrrPo.jpg", streaming: [{ name: "Netflix", icon: "🎬", url: "https://www.netflix.com" }, { name: "Kinopoisk", icon: "🎭", url: "https://www.kinopoisk.ru" }] }, { id: 56, title: "Безумный Макс: Дорога ярости", originalTitle: "Mad Max: Fury Road", year: 2015, rating: 7.6, duration: 120, genres: ["action", "adventure", "scifi"], moods: ["drive", "fun"], description: "В постапокалиптической пустоши Макс и Фуриоса бегут от тирана.", poster: "https://image.tmdb.org/t/p/w500/hA2ple9q4qnwxp3hKVNhroipsir.jpg", streaming: [{ name: "HBO Max", icon: "🎬", url: "https://www.hbomax.com" }, { name: "Ivi", icon: "📺", url: "https://www.ivi.ru" }] }, { id: 57, title: "Старикам тут не место", originalTitle: "No Country for Old Men", year: 2007, rating: 8.2, duration: 122, genres: ["crime", "thriller", "drama"], moods: ["think", "scary", "drive"], description: "Охотник находит деньги от наркосделки и становится мишенью психопата.", poster: "https://image.tmdb.org/t/p/w500/bj1v6YKF8yHqA489VFfnQvOJp9n.jpg", streaming: [{ name: "Amazon Prime", icon: "📦", url: "https://www.primevideo.com" }, { name: "Okko", icon: "🎪", url: "https://okko.tv" }] }, { id: 58, title: "Трудно быть богом", originalTitle: "Hard to Be a God", year: 2013, rating: 6.5, duration: 177, genres: ["scifi", "drama"], moods: ["think", "unusual"], description: "Учёный из будущего отправляется на планету, где застряла средневековая цивилизация.", poster: "https://image.tmdb.org/t/p/w500/iR79ieYRZ5fBmXVL7fOe0y7xIJ.jpg", streaming: [{ name: "Disney+", icon: "🏰", url: "https://www.disneyplus.com" }, { name: "Premier", icon: "🎭", url: "https://premier.one" }] }, { id: 59, title: "Одержимость", originalTitle: "Whiplash", year: 2014, rating: 8.5, duration: 106, genres: ["drama"], moods: ["think", "drive"], description: "Молодой барабанщик мечтает стать великим, но сталкивается с жестоким преподавателем.", poster: "https://image.tmdb.org/t/p/w500/7fn624j5lj3xTme2SgiZErnGSwC.jpg", streaming: [{ name: "Apple TV+", icon: "🍎", url: "https://tv.apple.com" }, { name: "More.tv", icon: "📱", url: "https://more.tv" }] }, { id: 60, title: "Криминальное чтиво", originalTitle: "Pulp Fiction", year: 1994, rating: 8.9, duration: 154, genres: ["crime", "thriller"], moods: ["fun", "drive", "unusual"], description: "Несколько переплетающихся историй из криминального мира Лос-Анджелеса.", poster: "https://image.tmdb.org/t/p/w500/d5iIlFn5s0ImszYzBPb8JPIfbXD.jpg", streaming: [{ name: "YouTube", icon: "▶️", url: "https://www.youtube.com/movies" }] } ]; // Genre and mood labels for display const GENRE_LABELS = { action: "Боевик", comedy: "Комедия", drama: "Драма", scifi: "Фантастика", horror: "Ужасы", thriller: "Триллер", adventure: "Приключения", fantasy: "Фэнтези", mystery: "Детектив", romance: "Романтика", animation: "Анимация", crime: "Криминал", history: "История" }; const MOOD_LABELS = { fun: "Весело", scary: "Страшно", think: "Подумать", romance: "Романтика", drive: "Драйв", comedy: "Комедия", sad: "Грустное", unusual: "Что-то необычное" }; // ==================== STATE ==================== let currentMovie = null; let selectedMood = null; let lastFoundMovies = []; // Movies found in current session let favorites = JSON.parse(localStorage.getItem('filmora_favorites')) || []; let history = JSON.parse(localStorage.getItem('filmora_history')) || []; // ==================== DOM ELEMENTS ==================== const navBtns = document.querySelectorAll('.nav-btn'); const backBtns = document.querySelectorAll('.back-btn'); const moodBtns = document.querySelectorAll('.mood-btn'); const findMovieBtn = document.getElementById('findMovie'); const randomModeBtn = document.getElementById('randomMode'); const anotherMovieBtn = document.getElementById('anotherMovie'); const addToFavoritesBtn = document.getElementById('addToFavorites'); const resetFiltersBtn = document.getElementById('resetFilters'); const resetFiltersEmptyBtn = document.getElementById('resetFiltersEmpty'); const clearHistoryBtn = document.getElementById('clearHistory'); const resultSection = document.getElementById('resultSection'); const emptyState = document.getElementById('emptyState'); const loadingState = document.getElementById('loadingState'); const loadingText = document.getElementById('loadingText'); // Filter elements const genreFilter = document.getElementById('genreFilter'); const yearFilter = document.getElementById('yearFilter'); const ratingFilter = document.getElementById('ratingFilter'); const durationFilter = document.getElementById('durationFilter'); // Movie display elements const moviePoster = document.getElementById('moviePoster'); const movieTitle = document.getElementById('movieTitle'); const movieOriginal = document.getElementById('movieOriginal'); const movieYear = document.getElementById('movieYear'); const movieDuration = document.getElementById('movieDuration'); const movieRating = document.getElementById('movieRating'); const movieGenres = document.getElementById('movieGenres'); const movieDescription = document.getElementById('movieDescription'); // ==================== NAVIGATION ==================== function showPage(pageId) { document.querySelectorAll('.page').forEach(page => page.classList.remove('active')); document.getElementById(pageId).classList.add('active'); if (pageId === 'favorites') { renderFavorites(); } else if (pageId === 'history') { renderHistory(); } } navBtns.forEach(btn => { btn.addEventListener('click', () => { const page = btn.dataset.page; showPage(page); }); }); backBtns.forEach(btn => { btn.addEventListener('click', () => { const page = btn.dataset.page; showPage(page); }); }); // ==================== MOOD SELECTION ==================== moodBtns.forEach(btn => { btn.addEventListener('click', () => { const mood = btn.dataset.mood; if (selectedMood === mood) { selectedMood = null; btn.classList.remove('selected'); } else { moodBtns.forEach(b => b.classList.remove('selected')); selectedMood = mood; btn.classList.add('selected'); } }); }); // ==================== FILTER FUNCTIONS ==================== function resetFilters() { selectedMood = null; moodBtns.forEach(btn => btn.classList.remove('selected')); genreFilter.value = 'any'; yearFilter.value = 'any'; ratingFilter.value = 'any'; durationFilter.value = 'any'; } resetFiltersBtn.addEventListener('click', resetFilters); if (resetFiltersEmptyBtn) { resetFiltersEmptyBtn.addEventListener('click', () => { resetFilters(); emptyState.style.display = 'none'; resultSection.classList.remove('show'); }); } // ==================== MOVIE FILTERING ==================== function filterMovies() { let filtered = [...MOVIES]; // Mood filter if (selectedMood) { filtered = filtered.filter(movie => movie.moods.includes(selectedMood)); } // Genre filter if (genreFilter.value !== 'any') { filtered = filtered.filter(movie => movie.genres.includes(genreFilter.value)); } // Year filter if (yearFilter.value !== 'any') { const ranges = { '2020-2026': [2020, 2026], '2010-2019': [2010, 2019], '2000-2009': [2000, 2009], '1990-1999': [1990, 1999], 'before-1990': [0, 1989] }; const [min, max] = ranges[yearFilter.value]; filtered = filtered.filter(movie => movie.year >= min && movie.year <= max); } // Rating filter if (ratingFilter.value !== 'any') { const minRating = parseFloat(ratingFilter.value); filtered = filtered.filter(movie => movie.rating >= minRating); } // Duration filter if (durationFilter.value !== 'any') { if (durationFilter.value === '150+') { filtered = filtered.filter(movie => movie.duration > 150); } else { const maxDuration = parseInt(durationFilter.value); filtered = filtered.filter(movie => movie.duration <= maxDuration); } } // Exclude movies already found in this session filtered = filtered.filter(movie => !lastFoundMovies.includes(movie.id)); return filtered; } // ==================== MOVIE SELECTION & ANIMATION ==================== function getRandomMovie() { const filtered = filterMovies(); if (filtered.length === 0) return null; const randomIndex = Math.floor(Math.random() * filtered.length); return filtered[randomIndex]; } function showLoadingAnimation(callback) { resultSection.classList.remove('show'); emptyState.style.display = 'none'; loadingState.style.display = 'block'; const movieTitles = MOVIES.map(m => m.title); let counter = 0; const maxCounter = 15; const interval = setInterval(() => { const randomTitle = movieTitles[Math.floor(Math.random() * movieTitles.length)]; loadingText.textContent = randomTitle; counter++; if (counter >= maxCounter) { clearInterval(interval); loadingState.style.display = 'none'; callback(); } }, 100); } function displayMovie(movie) { currentMovie = movie; moviePoster.src = movie.poster; movieTitle.textContent = movie.title; movieOriginal.textContent = movie.originalTitle; movieYear.textContent = movie.year; movieDuration.textContent = `${movie.duration} мин`; movieRating.textContent = `⭐ ${movie.rating}/10`; movieGenres.innerHTML = movie.genres.map(g => `${GENRE_LABELS[g]}` ).join(''); movieDescription.textContent = movie.description; // Update streaming info const streamingInfo = document.getElementById('streamingInfo'); if (movie.streaming && movie.streaming.length > 0) { const t = TRANSLATIONS[currentLang]; streamingInfo.innerHTML = `

${t.whereToWatch}

${movie.streaming.map(s => ` ${s.icon} ${s.name} `).join('')}
`; streamingInfo.style.display = 'block'; } else { streamingInfo.style.display = 'none'; } // Update watch button const watchBtn = document.getElementById('watchButton'); if (movie.streaming && movie.streaming.length > 0) { watchBtn.href = movie.streaming[0].url; watchBtn.style.display = 'flex'; } else { watchBtn.href = '#'; watchBtn.style.display = 'none'; } // Update favorite button state const isFavorite = favorites.some(f => f.id === movie.id); addToFavoritesBtn.classList.toggle('active', isFavorite); addToFavoritesBtn.querySelector('span:first-child').textContent = isFavorite ? '❤️' : '♡'; resultSection.classList.add('show'); } function findMovie() { showLoadingAnimation(() => { const movie = getRandomMovie(); if (!movie) { resultSection.classList.remove('show'); emptyState.style.display = 'block'; return; } lastFoundMovies.push(movie.id); // Add to history const historyEntry = { ...movie, date: new Date().toISOString() }; history.unshift(historyEntry); if (history.length > 50) history.pop(); // Keep max 50 entries localStorage.setItem('filmora_history', JSON.stringify(history)); displayMovie(movie); }); } findMovieBtn.addEventListener('click', findMovie); anotherMovieBtn.addEventListener('click', () => { findMovie(); }); // ==================== FAVORITES ==================== addToFavoritesBtn.addEventListener('click', () => { if (!currentMovie) return; const index = favorites.findIndex(f => f.id === currentMovie.id); if (index === -1) { favorites.unshift(currentMovie); addToFavoritesBtn.classList.add('active'); addToFavoritesBtn.querySelector('span:first-child').textContent = '❤️'; } else { favorites.splice(index, 1); addToFavoritesBtn.classList.remove('active'); addToFavoritesBtn.querySelector('span:first-child').textContent = '♡'; } localStorage.setItem('filmora_favorites', JSON.stringify(favorites)); }); function renderFavorites() { const grid = document.getElementById('favoritesGrid'); const empty = document.getElementById('emptyFavorites'); if (favorites.length === 0) { grid.innerHTML = ''; empty.style.display = 'block'; return; } empty.style.display = 'none'; grid.innerHTML = favorites.map(movie => `
${movie.title}

${movie.title}

${movie.year} ⭐ ${movie.rating}
`).join(''); // Add click handlers for movie items (show in main view) grid.querySelectorAll('.movie-item').forEach(item => { item.addEventListener('click', (e) => { if (e.target.classList.contains('remove-btn')) return; const id = parseInt(item.dataset.id); const movie = MOVIES.find(m => m.id === id); if (movie) { showPage('home'); displayMovie(movie); } }); }); // Add click handlers for remove buttons grid.querySelectorAll('.remove-btn').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const id = parseInt(btn.dataset.id); favorites = favorites.filter(f => f.id !== id); localStorage.setItem('filmora_favorites', JSON.stringify(favorites)); renderFavorites(); }); }); } // ==================== HISTORY ==================== function renderHistory() { const grid = document.getElementById('historyGrid'); const empty = document.getElementById('emptyHistory'); const clearBtn = document.getElementById('clearHistory'); if (history.length === 0) { grid.innerHTML = ''; empty.style.display = 'block'; clearBtn.style.display = 'none'; return; } empty.style.display = 'none'; clearBtn.style.display = 'block'; grid.innerHTML = history.map((movie, index) => { const date = new Date(movie.date).toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' }); return `
${movie.title}

${movie.title}

${date} ⭐ ${movie.rating}
`; }).join(''); // Add click handlers grid.querySelectorAll('.movie-item').forEach(item => { item.addEventListener('click', () => { const index = parseInt(item.dataset.index); const movie = history[index]; showPage('home'); displayMovie(movie); }); }); } clearHistoryBtn.addEventListener('click', () => { if (confirm('Вы уверены, что хотите очистить историю?')) { history = []; localStorage.setItem('filmora_history', JSON.stringify(history)); renderHistory(); } }); // ==================== RANDOM MODE ==================== randomModeBtn.addEventListener('click', () => { // Set random filters const moods = ['fun', 'scary', 'think', 'romance', 'drive', 'comedy', 'sad', 'unusual']; const genres = ['any', 'action', 'comedy', 'drama', 'scifi', 'horror', 'thriller', 'adventure', 'fantasy', 'mystery', 'romance', 'animation', 'crime']; const years = ['any', '2020-2026', '2010-2019', '2000-2009', '1990-1999', 'before-1990']; const ratings = ['any', '6', '7', '8', '8.5']; const durations = ['any', '90', '120', '150', '150+']; // Random mood (50% chance) selectedMood = Math.random() > 0.5 ? moods[Math.floor(Math.random() * moods.length)] : null; moodBtns.forEach(btn => { btn.classList.toggle('selected', btn.dataset.mood === selectedMood); }); // Random filters genreFilter.value = genres[Math.floor(Math.random() * genres.length)]; yearFilter.value = years[Math.floor(Math.random() * years.length)]; ratingFilter.value = ratings[Math.floor(Math.random() * ratings.length)]; durationFilter.value = durations[Math.floor(Math.random() * durations.length)]; // Find movie findMovie(); }); // ==================== I18N FUNCTION ==================== function updateTexts() { const t = TRANSLATIONS[currentLang]; // Update all elements with data-i18n attribute document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.dataset.i18n; if (t[key]) { // Only update if text is different to avoid unnecessary DOM changes if (el.textContent !== t[key]) { el.textContent = t[key]; } } }); // Update genre labels in select const genreSelect = document.getElementById('genreFilter'); const genreMap = { any: 'genreAny', action: 'genreAction', comedy: 'genreComedy', drama: 'genreDrama', scifi: 'genreScifi', horror: 'genreHorror', thriller: 'genreThriller', adventure: 'genreAdventure', fantasy: 'genreFantasy', mystery: 'genreMystery', romance: 'genreRomance', animation: 'genreAnimation', crime: 'genreCrime', history: 'genreHistory' }; Object.entries(genreMap).forEach(([value, key]) => { const option = genreSelect.querySelector(`option[value="${value}"]`); if (option && t[key]) { option.textContent = t[key]; } }); // Update duration labels const durationSelect = document.getElementById('durationFilter'); const durationMap = { any: 'durationAny', 90: 'duration90', 120: 'duration120', 150: 'duration150', '150+': 'duration150plus' }; Object.entries(durationMap).forEach(([value, key]) => { const option = durationSelect.querySelector(`option[value="${value}"]`); if (option && t[key]) { option.textContent = t[key]; } }); // Save language localStorage.setItem('filmora_lang', currentLang); document.documentElement.lang = currentLang; } // Language switcher const langBtns = document.querySelectorAll('.lang-btn'); langBtns.forEach(btn => { btn.addEventListener('click', () => { const lang = btn.dataset.lang; currentLang = lang; // Update active state langBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); updateTexts(); }); // Set initial active state if (btn.dataset.lang === currentLang) { btn.classList.add('active'); } }); // ==================== INITIALIZATION ==================== document.addEventListener('DOMContentLoaded', () => { updateTexts(); showPage('home'); });