proekt-filmora-movie-night-r/script.js

1503 lines
60 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ==================== 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: "Очистить историю",
removeFavorite: "Удалить из избранного",
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",
removeFavorite: "Remove from favorites",
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: "Тарихты тазалау",
removeFavorite: "Таңдаулыдан жою",
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 =>
`<span class="genre-tag">${GENRE_LABELS[g]}</span>`
).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 = `
<h4>${t.whereToWatch}</h4>
<div class="streaming-services">
${movie.streaming.map(s => `
<a href="${s.url}" target="_blank" rel="noopener" class="streaming-service">
<span class="icon">${s.icon}</span>
<span>${s.name}</span>
</a>
`).join('')}
</div>
`;
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';
const t = TRANSLATIONS[currentLang];
grid.innerHTML = favorites.map(movie => `
<div class="movie-item" data-id="${movie.id}">
<img src="${movie.poster}" alt="${movie.title}" class="movie-item-poster">
<div class="movie-item-info">
<h3 class="movie-item-title">${movie.title}</h3>
<div class="movie-item-meta">
<span>${movie.year}</span>
<span class="movie-item-rating">⭐ ${movie.rating}</span>
</div>
<button class="remove-btn" data-id="${movie.id}">${t.removeFavorite || 'Удалить'}</button>
</div>
</div>
`).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';
const t = TRANSLATIONS[currentLang];
grid.innerHTML = history.map((movie, index) => {
const date = new Date(movie.date).toLocaleDateString(currentLang === 'kk' ? 'kk-KZ' : currentLang === 'en' ? 'en-US' : 'ru-RU', {
day: 'numeric',
month: 'short',
year: 'numeric'
});
return `
<div class="movie-item" data-index="${index}">
<img src="${movie.poster}" alt="${movie.title}" class="movie-item-poster">
<div class="movie-item-info">
<h3 class="movie-item-title">${movie.title}</h3>
<div class="movie-item-meta">
<span>${date}</span>
<span class="movie-item-rating">⭐ ${movie.rating}</span>
</div>
</div>
</div>
`;
}).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');
});