MovieTok Frontend is a modern, feature-rich web application built with React and Vite. It serves as the client interface for the MovieTok platform β a social movie discovery hub where users can browse films, write reviews, create groups, and share recommendations.
- Browse popular and now playing movies
// Uses TMDB API integration through a custom service const movies = await getPopularMovies(page); const nowPlaying = await getNowPlayingMovies();
- Advanced movie search functionality with filters
// Supports genre filtering through URL parameters const movies = await discoverMovies({ withGenres: selectedGenres, page: currentPage });
- Detailed movie information via TMDB integration
// Fetches comprehensive movie data const details = await getMovieDetails(movieId);
- Local theater showtimes through Finnkino API
// Custom hook for real-time theater data const { showtimes, loading } = useFinnkinoShowTimes();
- Authentication System
// Uses JWT tokens with Context API const AuthContext = createContext(); // Stores tokens securely localStorage.setItem("token", jwt); // Protected route wrapper const PrivateRoute = ({ children }) => { return isLoggedIn ? children : <Navigate to="/login" />; };
- Profile Management
// Custom hook for profile operations const { profile, loading } = useProfile(userId); // Handles user data and preferences const updateProfile = async (data) => { await updateUserProfile(userId, data); };
- Group Management System
// Service for group operations export const createGroup = async (groupData) => { const token = requireToken(); const res = await groupAPI.post("", groupData); return res.data.group; };
- Custom Hook for Group Data
// Real-time group management const { userGroups, groupsLoading } = useUserGroups(userId);
- Member Management
// Handles member operations const addMember = async (groupId, userId) => { await groupAPI.post(`/${groupId}/members`, { userId }); };
- Review System Implementation
// Normalized review structure const normalizeReview = (r) => ({ id: r?.id, movieId: r?.movie_id, rating: Number(r?.rating ?? 0), content: r?.content });
- Interactive Rating System
// Handles review creation with ratings const createReview = async ({ movieId, rating, comment }) => { await api.post("/reviews", { movieId, rating, content: comment }); };
- Favorites Management
// Custom hook for favorites const { favorites, add, remove } = useFavorites(userId, type); // Real-time favorite status tracking const { isFavorite } = useFavoriteStatuses(movieId);
- Watchlist System
// Similar to favorites but with watch status const toggleWatchlist = async (movieId) => { const updated = await updateWatchStatus(movieId); setWatchlist(prev => [...prev, updated]); };
- Universal Modal System
// Reusable modal component const UniversalModal = ({ isOpen, onClose, children }) => { if (!isOpen) return null; return createPortal( <div className="modal-overlay">{children}</div>, document.body ); };
- Notification System
// Auto-dismiss toast notifications const { showToast } = usePopup(); showToast("Operation successful", "success", 3000);
- Responsive Component Design
// Tailwind CSS responsive classes className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
-
Context API for Global State
// Centralized authentication state management const AuthContext = createContext(); export function AuthProvider({ children }) { const [isLoggedIn, setIsLoggedIn] = useState( !!localStorage.getItem("token") ); // ... authentication logic }
-
Custom Hooks Architecture
-
Favorites Management (
useFavorites)const useFavorites = (userId, type) => { const [favorites, setFavorites] = useState([]); // Real-time favorites sync with backend useEffect(() => { getUserFavorites(userId, type) .then(data => setFavorites(data)); }, [userId, type]); // ... CRUD operations };
-
Group Management (
useUserGroups)const useUserGroups = (userId) => { const [userGroups, setUserGroups] = useState([]); // Automatic error handling and loading states const [groupsLoading, setGroupsLoading] = useState(true); const [groupsError, setGroupsError] = useState(null); // ... group synchronization logic };
-
Notification System (
usePopup)const usePopup = () => { const [showPopup, setShowPopup] = useState(false); const [popupMessage, setPopupMessage] = useState(""); // Reusable popup component with type support const PopupComponent = showPopup ? ( <OnsitePopup message={popupMessage} type={popupType} onConfirm={() => setShowPopup(false)} /> ) : null; // ... popup trigger logic };
-
-
Modular API Service Structure
// Separate axios instances for different domains const API_BASE_URL = import.meta.env.VITE_API_BASE_URL; export const api = axios.create({ baseURL: `${API_BASE_URL}/`, }); export const authAPI = axios.create({ baseURL: `${API_BASE_URL}/v1/users`, }); export const groupAPI = axios.create({ baseURL: `${API_BASE_URL}/groups`, });
-
External API Integration
-
TMDB API Service
// Centralized movie data fetching export async function getMovieDetails(id) { const res = await axios.get(`${API_BASE}/tmdb/${id}`); return res.data; } // Genre-based discovery export async function discoverMovies({ withGenres, page }) { const params = new URLSearchParams(); if (withGenres.length > 0) { params.append("with_genres", withGenres.join(",")); } // ... discovery logic }
-
Finnkino Integration
// Real-time theater data const useFinnkinoShowTimes = () => { // Automatic data refresh useEffect(() => { const fetchShowTimes = async () => { const data = await finnkinoApi.getShowTimes(); setShowTimes(data); }; fetchShowTimes(); // Refresh every 5 minutes const interval = setInterval(fetchShowTimes, 300000); return () => clearInterval(interval); }, []); };
-
-
Backend Service Integration
// Normalized data handling const normalizeReview = (r) => ({ id: r?.id, movieId: r?.movie_id, rating: Number(r?.rating ?? 0), // ... data normalization }); // Type-safe API calls export async function createReview({ movieId, rating, comment }) { const token = requireToken(); return api.post("/reviews", { movieId, rating, content: comment }, { headers: { Authorization: `Bearer ${token}` } }); }
- CSS modules for component-specific styling
- Responsive design
- Tailwind CSS integration
- Custom animations and transitions
- Clone the repository
- Install dependencies:
npm install- Set up environment variables:
Create a
.envfile with:
VITE_API_BASE_URL=your_api_base_url- Start the development server:
npm run dev/components- Reusable UI components/context- React Context providers/helpers- Utility functions/hooks- Custom React hooks/pages- Main application pages/routes/services- API service integrations/styles- CSS stylesheets
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production build
- React
- Vite
- Tailwind CSS
- Axios
- React Router
- ESLint
- PostCSS
The application is fully responsive and works seamlessly across:
- Desktop browsers
- Tablets
- Mobile devices
- JWT-based authentication
- Secure API communication
- Protected routes
- XSS protection
This project is licensed under the MIT License - see the LICENSE file for details.