Skip to content

Commit 939dc8e

Browse files
committed
working things
1 parent b689c92 commit 939dc8e

File tree

4 files changed

+296
-115
lines changed

4 files changed

+296
-115
lines changed

src/context/FavoritesContext.tsx

Lines changed: 112 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,141 @@
1-
import { createContext, useState, useContext, useEffect } from "react";
2-
import { db } from "../config/firebase";
3-
import { doc, updateDoc, onSnapshot, arrayUnion, arrayRemove } from "firebase/firestore";
4-
import { AuthContext } from "./AuthContext";
1+
import { createContext, useState, useEffect, useContext } from 'react';
2+
import { AuthContext } from './AuthContext';
3+
import { doc, onSnapshot, updateDoc, arrayUnion, arrayRemove } from 'firebase/firestore';
4+
import { db } from '../config/firebase';
55

6-
const FavoritesContext = createContext();
6+
// Definir la estructura de una película favorita
7+
interface FavoriteMovie {
8+
id: number;
9+
title: string;
10+
poster_path: string;
11+
vote_average: number;
12+
release_date: string;
13+
overview?: string;
14+
backdrop_path?: string;
15+
}
16+
17+
interface FavoritesContextType {
18+
favorites: FavoriteMovie[];
19+
isLoading: boolean;
20+
addToFavorites: (movie: FavoriteMovie) => Promise<void>;
21+
removeFromFavorites: (movieId: number) => Promise<void>;
22+
isFavorite: (movieId: number) => boolean;
23+
}
24+
25+
export const FavoritesContext = createContext<FavoritesContextType>({
26+
favorites: [],
27+
isLoading: true,
28+
addToFavorites: async () => {},
29+
removeFromFavorites: async () => {},
30+
isFavorite: () => false
31+
});
732

8-
export function FavoritesProvider({ children }) {
9-
const [favorites, setFavorites] = useState([]);
33+
export const useFavorites = () => useContext(FavoritesContext);
34+
35+
export const FavoritesProvider = ({ children }: { children: React.ReactNode }) => {
36+
const [favorites, setFavorites] = useState<FavoriteMovie[]>([]);
37+
const [isLoading, setIsLoading] = useState(true);
1038
const { user } = useContext(AuthContext);
1139

12-
// Sincronizar favoritos con Firestore cuando cambia el usuario
40+
// Escuchar cambios en los favoritos del usuario
1341
useEffect(() => {
1442
if (!user) {
1543
setFavorites([]);
44+
setIsLoading(false);
1645
return;
1746
}
1847

19-
const userDocRef = doc(db, "users", user.uid);
20-
const unsubscribe = onSnapshot(userDocRef, (snapshot) => {
21-
if (snapshot.exists() && snapshot.data().favorites) {
22-
setFavorites(snapshot.data().favorites);
48+
setIsLoading(true);
49+
const userRef = doc(db, 'users', user.uid);
50+
51+
// Suscripción en tiempo real a los cambios en favoritos
52+
const unsubscribe = onSnapshot(userRef, (docSnap) => {
53+
if (docSnap.exists()) {
54+
const userData = docSnap.data();
55+
56+
// Verificar que favorites existe y es un array
57+
if (userData.favorites && Array.isArray(userData.favorites)) {
58+
// Eliminar posibles duplicados basados en ID
59+
const uniqueFavorites = Array.from(
60+
new Map(userData.favorites.map((movie: FavoriteMovie) => [movie.id, movie]))
61+
.values()
62+
);
63+
64+
setFavorites(uniqueFavorites);
65+
} else {
66+
setFavorites([]);
67+
}
2368
} else {
2469
setFavorites([]);
2570
}
71+
setIsLoading(false);
72+
}, (error) => {
73+
console.error("Error al obtener favoritos:", error);
74+
setIsLoading(false);
2675
});
2776

2877
return () => unsubscribe();
2978
}, [user]);
3079

31-
async function addFavorite(movie) {
32-
// Verificar si la película ya está en favoritos para evitar duplicados
33-
if (!favorites.some(fav => fav.id === movie.id) && user) {
34-
const userDocRef = doc(db, "users", user.uid);
35-
try {
36-
await updateDoc(userDocRef, {
37-
favorites: arrayUnion(movie)
38-
});
39-
} catch (error) {
40-
console.error("Error al añadir a favoritos:", error);
41-
}
80+
// Añadir película a favoritos
81+
const addToFavorites = async (movie: FavoriteMovie) => {
82+
if (!user) return;
83+
84+
// Verificar que la película no está ya en favoritos
85+
if (isFavorite(movie.id)) {
86+
console.log("La película ya está en favoritos");
87+
return;
4288
}
43-
}
89+
90+
try {
91+
const userRef = doc(db, 'users', user.uid);
92+
93+
// Actualizar Firestore
94+
await updateDoc(userRef, {
95+
favorites: arrayUnion(movie)
96+
});
97+
98+
} catch (error) {
99+
console.error("Error al añadir a favoritos:", error);
100+
}
101+
};
44102

45-
async function removeFavorite(movieId) {
46-
if (user) {
47-
const movieToRemove = favorites.find(movie => movie.id === movieId);
103+
// Eliminar película de favoritos
104+
const removeFromFavorites = async (movieId: number) => {
105+
if (!user) return;
106+
107+
try {
108+
const userRef = doc(db, 'users', user.uid);
109+
110+
// Encontrar la película exacta a eliminar
111+
const movieToRemove = favorites.find(fav => fav.id === movieId);
112+
48113
if (movieToRemove) {
49-
const userDocRef = doc(db, "users", user.uid);
50-
try {
51-
await updateDoc(userDocRef, {
52-
favorites: arrayRemove(movieToRemove)
53-
});
54-
} catch (error) {
55-
console.error("Error al eliminar de favoritos:", error);
56-
}
114+
// Eliminar usando arrayRemove
115+
await updateDoc(userRef, {
116+
favorites: arrayRemove(movieToRemove)
117+
});
57118
}
119+
120+
} catch (error) {
121+
console.error("Error al eliminar de favoritos:", error);
58122
}
59-
}
123+
};
60124

61-
const isFavorite = (movieId) => favorites.some(movie => movie.id === movieId);
125+
// Verificar si una película está en favoritos
126+
const isFavorite = (movieId: number): boolean => {
127+
return favorites.some(movie => movie.id === movieId);
128+
};
62129

63130
return (
64-
<FavoritesContext.Provider value={{ favorites, addFavorite, removeFavorite, isFavorite }}>
131+
<FavoritesContext.Provider value={{
132+
favorites,
133+
isLoading,
134+
addToFavorites,
135+
removeFromFavorites,
136+
isFavorite
137+
}}>
65138
{children}
66139
</FavoritesContext.Provider>
67140
);
68-
}
69-
70-
export function useFavorites() {
71-
return useContext(FavoritesContext);
72-
}
141+
};

src/pages/MovieContent.tsx

Lines changed: 2 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ interface MovieContentProps {
88
cast: Cast[];
99
videos: Video[];
1010
similarMovies: SimilarMovie[];
11+
activeTab: string;
1112
}
1213

13-
export default function MovieContent({ movie, cast, videos, similarMovies }: MovieContentProps) {
14-
const [activeTab, setActiveTab] = useState('overview');
14+
export default function MovieContent({ movie, cast, videos, similarMovies, activeTab }: MovieContentProps) {
1515
const navigate = useNavigate();
1616

1717
const createTrailerModal = (videoKey: string) => {
@@ -59,69 +59,6 @@ export default function MovieContent({ movie, cast, videos, similarMovies }: Mov
5959
return (
6060
<div className="container mx-auto p-4">
6161
<div className="bg-gray-800 rounded-lg p-6 md:p-8 mt-4">
62-
{/* Tabs */}
63-
<div className="mb-6 border-b border-gray-700">
64-
<div className="flex space-x-6 overflow-x-auto pb-1">
65-
<button
66-
onClick={() => setActiveTab('overview')}
67-
className={`py-3 font-medium relative ${
68-
activeTab === 'overview'
69-
? 'text-white'
70-
: 'text-gray-400 hover:text-gray-300'
71-
}`}
72-
>
73-
Sinopsis
74-
{activeTab === 'overview' && (
75-
<span className="absolute bottom-0 left-0 w-full h-0.5 bg-red-600"></span>
76-
)}
77-
</button>
78-
79-
<button
80-
onClick={() => setActiveTab('cast')}
81-
className={`py-3 font-medium relative ${
82-
activeTab === 'cast'
83-
? 'text-white'
84-
: 'text-gray-400 hover:text-gray-300'
85-
}`}
86-
>
87-
Reparto
88-
{activeTab === 'cast' && (
89-
<span className="absolute bottom-0 left-0 w-full h-0.5 bg-red-600"></span>
90-
)}
91-
</button>
92-
93-
{videos.length > 0 && (
94-
<button
95-
onClick={() => setActiveTab('videos')}
96-
className={`py-3 font-medium relative ${
97-
activeTab === 'videos'
98-
? 'text-white'
99-
: 'text-gray-400 hover:text-gray-300'
100-
}`}
101-
>
102-
Videos
103-
{activeTab === 'videos' && (
104-
<span className="absolute bottom-0 left-0 w-full h-0.5 bg-red-600"></span>
105-
)}
106-
</button>
107-
)}
108-
109-
<button
110-
onClick={() => setActiveTab('reviews')}
111-
className={`py-3 font-medium relative ${
112-
activeTab === 'reviews'
113-
? 'text-white'
114-
: 'text-gray-400 hover:text-gray-300'
115-
}`}
116-
>
117-
Reseñas
118-
{activeTab === 'reviews' && (
119-
<span className="absolute bottom-0 left-0 w-full h-0.5 bg-red-600"></span>
120-
)}
121-
</button>
122-
</div>
123-
</div>
124-
12562
{/* Tab content */}
12663
<div className="min-h-[200px]">
12764
{/* Overview tab */}

src/pages/MovieDetails.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ export default function MovieDetails() {
5353
const [similarMovies, setSimilarMovies] = useState<SimilarMovie[]>([]);
5454
const [isLoading, setIsLoading] = useState(true);
5555
const [error, setError] = useState<string | null>(null);
56+
// Estado para controlar la pestaña activa
57+
const [activeTab, setActiveTab] = useState('overview');
5658

5759
// Get favorites functions from context
5860
const { addFavorite, removeFavorite, isFavorite } = useFavorites();
@@ -102,6 +104,8 @@ export default function MovieDetails() {
102104

103105
if (id) {
104106
fetchMovieData();
107+
// Restablecer la pestaña activa cuando cambia la película
108+
setActiveTab('overview');
105109
}
106110
}, [id, TMDB_API_KEY]);
107111

@@ -176,13 +180,16 @@ export default function MovieDetails() {
176180
videos={videos}
177181
handleFavoriteToggle={handleFavoriteToggle}
178182
isFavorited={isFavorited}
183+
activeTab={activeTab}
184+
setActiveTab={setActiveTab}
179185
/>
180186

181187
<MovieContent
182188
movie={movie}
183189
cast={cast}
184190
videos={videos}
185191
similarMovies={similarMovies}
192+
activeTab={activeTab}
186193
/>
187194

188195
{/* Back to top button */}

0 commit comments

Comments
 (0)