Skip to content

Commit b118fe0

Browse files
committed
Add fav movie page
1 parent 10c7a16 commit b118fe0

File tree

1 file changed

+325
-0
lines changed

1 file changed

+325
-0
lines changed

Web_app/pages/Favorite_Movie.py

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
import streamlit as st
2+
import requests
3+
import time
4+
from datetime import datetime
5+
import json
6+
7+
# Initialize session state for favorites
8+
if "favorites" not in st.session_state:
9+
st.session_state.favorites = set()
10+
11+
# TMDB API Configuration
12+
API_KEY = "Imdb_api_key"
13+
BASE_URL = "https://api.themoviedb.org/3"
14+
15+
16+
def fetch_movies(list_type="trending"):
17+
"""Fetch movies from TMDB API"""
18+
if list_type == "trending":
19+
url = f"{BASE_URL}/trending/movie/week?api_key={API_KEY}"
20+
else:
21+
url = f"{BASE_URL}/movie/popular?api_key={API_KEY}"
22+
23+
try:
24+
response = requests.get(url)
25+
return response.json()["results"] if response.status_code == 200 else []
26+
except:
27+
st.error("Failed to fetch movies")
28+
return []
29+
30+
31+
# Page Configuration
32+
st.set_page_config(page_title="Movie Collection", page_icon="🎬", layout="wide")
33+
34+
# Custom CSS for the new compact design
35+
st.markdown(
36+
"""
37+
<style>
38+
/* General Styles */
39+
[data-testid="stAppViewContainer"] {
40+
background: #1a1d29;
41+
color: #ffffff;
42+
}
43+
44+
.movie-list-container {
45+
padding: 10px;
46+
background: #1a1d29;
47+
}
48+
49+
/* Compact Movie Card */
50+
.movie-card {
51+
background: #242836;
52+
border-radius: 8px;
53+
height: 90px;
54+
margin: 8px 0;
55+
display: flex;
56+
overflow: hidden;
57+
transition: transform 0.2s, box-shadow 0.2s;
58+
position: relative;
59+
}
60+
61+
.movie-card:hover {
62+
transform: translateX(5px);
63+
box-shadow: -4px 4px 12px rgba(0, 0, 0, 0.2);
64+
}
65+
66+
/* Poster Style */
67+
.poster-container {
68+
width: 60px;
69+
height: 90px;
70+
flex-shrink: 0;
71+
}
72+
73+
.movie-poster {
74+
width: 100%;
75+
height: 100%;
76+
object-fit: cover;
77+
}
78+
79+
/* Movie Info */
80+
.movie-info {
81+
padding: 8px 12px;
82+
flex-grow: 1;
83+
display: flex;
84+
flex-direction: column;
85+
justify-content: space-between;
86+
}
87+
88+
.movie-title {
89+
font-size: 0.95rem;
90+
font-weight: 600;
91+
color: #ffffff;
92+
margin-bottom: 4px;
93+
white-space: nowrap;
94+
overflow: hidden;
95+
text-overflow: ellipsis;
96+
}
97+
98+
.movie-meta {
99+
font-size: 0.8rem;
100+
color: #a0a0a0;
101+
display: flex;
102+
align-items: center;
103+
gap: 12px;
104+
}
105+
106+
/* Rating Badge */
107+
.rating {
108+
background: #ffd700;
109+
color: #000000;
110+
padding: 2px 6px;
111+
border-radius: 4px;
112+
font-weight: 600;
113+
font-size: 0.75rem;
114+
}
115+
116+
/* Action Buttons */
117+
.action-buttons {
118+
position: absolute;
119+
right: 12px;
120+
top: 50%;
121+
transform: translateY(-50%);
122+
display: flex;
123+
gap: 8px;
124+
}
125+
126+
.btn {
127+
padding: 6px 12px;
128+
border-radius: 4px;
129+
border: none;
130+
cursor: pointer;
131+
font-size: 0.75rem;
132+
transition: all 0.2s;
133+
text-decoration: none;
134+
}
135+
136+
.btn-favorite {
137+
background: none;
138+
border: none;
139+
padding: 4px;
140+
cursor: pointer;
141+
transition: transform 0.2s;
142+
}
143+
144+
.btn-favorite:hover {
145+
transform: scale(1.2);
146+
}
147+
148+
.btn-share {
149+
background: #4267B2;
150+
color: white;
151+
}
152+
153+
.btn-share:hover {
154+
background: #365899;
155+
}
156+
157+
/* Filter Section */
158+
.filter-section {
159+
background: #242836;
160+
padding: 16px;
161+
border-radius: 8px;
162+
margin: 16px 0;
163+
}
164+
165+
/* Custom Checkbox Style */
166+
.stCheckbox {
167+
color: white !important;
168+
}
169+
170+
/* Custom Select Box Style */
171+
.stSelectbox {
172+
background: #242836;
173+
color: white !important;
174+
}
175+
176+
/* Header Styling */
177+
.main-header {
178+
text-align: center;
179+
color: #ffffff;
180+
padding: 20px 0;
181+
background: linear-gradient(90deg, #1a1d29 0%, #242836 100%);
182+
border-radius: 8px;
183+
margin-bottom: 20px;
184+
}
185+
186+
/* Empty State */
187+
.empty-state {
188+
text-align: center;
189+
padding: 40px;
190+
color: #a0a0a0;
191+
}
192+
</style>
193+
""",
194+
unsafe_allow_html=True,
195+
)
196+
197+
# Header
198+
st.markdown(
199+
"""
200+
<div class="main-header">
201+
<h1>🎬 Movie Collection</h1>
202+
<p style="color: #a0a0a0;">Discover and collect your favorite movies</p>
203+
</div>
204+
""",
205+
unsafe_allow_html=True,
206+
)
207+
208+
# Filter Section
209+
col1, col2, col3 = st.columns([1, 1, 1])
210+
with col1:
211+
show_favorites = st.checkbox("Show Favorites", key="show_favorites")
212+
with col2:
213+
sort_by = st.selectbox(
214+
"Sort by", ["Rating", "Release Date", "Title"], key="sort_by"
215+
)
216+
with col3:
217+
list_type = st.selectbox("List Type", ["Trending", "Popular"], key="list_type")
218+
219+
# Fetch and process movies
220+
movies = fetch_movies(list_type.lower())
221+
222+
# Filter favorites if needed
223+
if show_favorites:
224+
movies = [m for m in movies if m["id"] in st.session_state.favorites]
225+
226+
# Sort movies
227+
if sort_by == "Rating":
228+
movies.sort(key=lambda x: x["vote_average"], reverse=True)
229+
elif sort_by == "Release Date":
230+
movies.sort(key=lambda x: x["release_date"], reverse=True)
231+
else:
232+
movies.sort(key=lambda x: x["title"])
233+
234+
# Display movies
235+
if not movies:
236+
st.markdown(
237+
"""
238+
<div class="empty-state">
239+
<h3>No movies found</h3>
240+
<p>Try adjusting your filters or check back later for new movies.</p>
241+
</div>
242+
""",
243+
unsafe_allow_html=True,
244+
)
245+
else:
246+
for movie in movies:
247+
# Create columns for layout
248+
movie_id = movie["id"]
249+
is_favorite = movie_id in st.session_state.favorites
250+
251+
# Movie card HTML
252+
st.markdown(
253+
f"""
254+
<div class="movie-card">
255+
<div class="poster-container">
256+
<img class="movie-poster"
257+
src="https://image.tmdb.org/t/p/w92{movie['poster_path']}"
258+
alt="{movie['title']}"/>
259+
</div>
260+
<div class="movie-info">
261+
<div>
262+
<div class="movie-title">{movie['title']}</div>
263+
<div class="movie-meta">
264+
<span>{movie['release_date'][:4]}</span>
265+
<span class="rating">★ {movie['vote_average']:.1f}</span>
266+
</div>
267+
</div>
268+
</div>
269+
<div class="action-buttons">
270+
{'❤️' if is_favorite else '🤍'}
271+
<button class="btn-share" onclick="shareMovie('{movie['title']}')">Share</button>
272+
</div>
273+
</div>
274+
""",
275+
unsafe_allow_html=True,
276+
)
277+
278+
# Toggle favorite button
279+
if st.button(
280+
f"{'Remove from' if is_favorite else 'Add to'} Favorites",
281+
key=f"toggle_{movie_id}",
282+
):
283+
if is_favorite:
284+
st.session_state.favorites.remove(movie_id)
285+
else:
286+
st.session_state.favorites.add(movie_id)
287+
st.experimental_rerun()
288+
289+
# JavaScript for interactivity
290+
st.markdown(
291+
"""
292+
<script>
293+
function handleFavorite(movieId) {
294+
// Find and click the hidden toggle button
295+
document.querySelector(`button[key="toggle_${movieId}"]`).click();
296+
}
297+
298+
function shareMovie(title) {
299+
const url = encodeURIComponent(window.location.href);
300+
const text = encodeURIComponent(`Check out "${title}" on Movie Collection!`);
301+
302+
// Twitter share
303+
const twitterUrl = `https://twitter.com/intent/tweet?text=${text}&url=${url}`;
304+
305+
// LinkedIn share
306+
const linkedinUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}&title=${text}`;
307+
308+
// Instagram doesn't support direct web-sharing, open Instagram website instead
309+
const instaUrl = "https://www.instagram.com/";
310+
311+
const options = `
312+
<button onclick="window.open('${twitterUrl}', '_blank')">Twitter</button>
313+
<button onclick="window.open('${linkedinUrl}', '_blank')">LinkedIn</button>
314+
<button onclick="window.open('${instaUrl}', '_blank')">Instagram</button>
315+
`;
316+
317+
const popup = document.createElement("div");
318+
popup.innerHTML = options;
319+
document.body.appendChild(popup);
320+
}
321+
</script>
322+
<script>
323+
""",
324+
unsafe_allow_html=True,
325+
)

0 commit comments

Comments
 (0)