Add runtime filter, kid-friendly toggle, surprise me, and re-roll
- Runtime quick-select buttons (Any/90m/2h/2.5h) filter movies by length - Kid-friendly toggle forces PG-13 max and boosts Family/Animation genres - Surprise Me picks a random mood prompt from 20 curated options - Show Me More re-rolls same mood excluding already-shown movies - Re-roll appends new results to the existing search history entry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+91
-3
@@ -3,6 +3,34 @@
|
||||
const API = '';
|
||||
let currentUser = null;
|
||||
let selectedUserIds = [];
|
||||
let maxRuntime = null;
|
||||
let kidFriendly = false;
|
||||
let shownMovieIds = [];
|
||||
let lastMood = '';
|
||||
let currentHistoryId = null;
|
||||
|
||||
const SURPRISE_PROMPTS = [
|
||||
"pizza night with the kids",
|
||||
"something scary but not too gory",
|
||||
"light fun movie after a hard week",
|
||||
"80s action classic",
|
||||
"mind-bending sci-fi",
|
||||
"feel-good comedy",
|
||||
"epic adventure",
|
||||
"rainy Sunday afternoon",
|
||||
"date night romance",
|
||||
"underrated hidden gem",
|
||||
"visually stunning cinematography",
|
||||
"based on a true story",
|
||||
"twisty thriller with a great ending",
|
||||
"nostalgic 90s vibes",
|
||||
"animated movie for all ages",
|
||||
"something weird and quirky",
|
||||
"inspiring sports movie",
|
||||
"cozy mystery",
|
||||
"space exploration",
|
||||
"laugh out loud comedy",
|
||||
];
|
||||
|
||||
// --- Auth ---
|
||||
|
||||
@@ -90,10 +118,18 @@ function toggleUser(userId, pill) {
|
||||
|
||||
// --- Mood / Recommendations ---
|
||||
|
||||
async function findMovies() {
|
||||
async function findMovies(excludeIds = []) {
|
||||
const mood = document.getElementById('mood-input').value.trim();
|
||||
if (!mood) return;
|
||||
|
||||
// Track mood for re-roll; reset shown IDs if mood changed
|
||||
const isReroll = excludeIds.length > 0;
|
||||
if (mood !== lastMood) {
|
||||
shownMovieIds = [];
|
||||
currentHistoryId = null;
|
||||
lastMood = mood;
|
||||
}
|
||||
|
||||
document.getElementById('empty-state').classList.add('hidden');
|
||||
document.getElementById('results').classList.add('hidden');
|
||||
document.getElementById('error-state').classList.add('hidden');
|
||||
@@ -101,10 +137,19 @@ async function findMovies() {
|
||||
|
||||
try {
|
||||
const additionalIds = selectedUserIds.filter(id => id !== currentUser.id);
|
||||
const payload = {
|
||||
mood,
|
||||
additional_user_ids: additionalIds,
|
||||
exclude_ids: excludeIds,
|
||||
kid_friendly: kidFriendly,
|
||||
};
|
||||
if (maxRuntime) payload.max_runtime = maxRuntime;
|
||||
if (isReroll && currentHistoryId) payload.history_id = currentHistoryId;
|
||||
|
||||
const res = await fetch(`${API}/api/mood`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ mood, additional_user_ids: additionalIds })
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
@@ -113,6 +158,17 @@ async function findMovies() {
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
// Track shown movie IDs and history ID for re-roll
|
||||
if (data.recommendations) {
|
||||
data.recommendations.forEach(r => {
|
||||
if (!shownMovieIds.includes(r.jellyfin_id)) {
|
||||
shownMovieIds.push(r.jellyfin_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (data.meta && data.meta.history_id) {
|
||||
currentHistoryId = data.meta.history_id;
|
||||
}
|
||||
renderResults(data);
|
||||
loadHistory();
|
||||
} catch (err) {
|
||||
@@ -293,7 +349,7 @@ document.getElementById('login-form').addEventListener('submit', async (e) => {
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('find-btn').addEventListener('click', findMovies);
|
||||
document.getElementById('find-btn').addEventListener('click', () => findMovies());
|
||||
document.getElementById('mood-input').addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') findMovies();
|
||||
});
|
||||
@@ -305,5 +361,37 @@ document.getElementById('show-history-btn').addEventListener('click', () => {
|
||||
loadHistory();
|
||||
});
|
||||
|
||||
// Runtime filter buttons
|
||||
document.querySelectorAll('.runtime-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.runtime-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
maxRuntime = btn.dataset.runtime ? parseInt(btn.dataset.runtime) : null;
|
||||
});
|
||||
});
|
||||
|
||||
// Kid-friendly toggle
|
||||
document.getElementById('kid-friendly-btn').addEventListener('click', () => {
|
||||
kidFriendly = !kidFriendly;
|
||||
const btn = document.getElementById('kid-friendly-btn');
|
||||
if (kidFriendly) {
|
||||
btn.classList.add('active');
|
||||
} else {
|
||||
btn.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Surprise me
|
||||
document.getElementById('surprise-btn').addEventListener('click', () => {
|
||||
const prompt = SURPRISE_PROMPTS[Math.floor(Math.random() * SURPRISE_PROMPTS.length)];
|
||||
document.getElementById('mood-input').value = prompt;
|
||||
findMovies();
|
||||
});
|
||||
|
||||
// Re-roll
|
||||
document.getElementById('reroll-btn').addEventListener('click', () => {
|
||||
findMovies(shownMovieIds);
|
||||
});
|
||||
|
||||
// --- Init ---
|
||||
checkAuth();
|
||||
|
||||
Reference in New Issue
Block a user