Thanks to visit codestin.com
Credit goes to github.com

Skip to content

gegyhamdani/movie-list

Repository files navigation

Movie List App

A modern, accessible movie list application built with React 19, TypeScript, and Redux Toolkit that consumes the OMDB API (Open Movie Database).

Features

  • Real-time Movie Search - Search movies with debounced input (500ms delay)
  • Custom Infinite Scroll - No external plugins, uses IntersectionObserver API
  • Movie Details Modal - Click any movie card to view complete details
  • Poster Preview Modal - Click movie poster to view full-size image
  • Fully Responsive - Mobile-first design with Tailwind CSS v4
  • WCAG AA Compliant - Meets accessibility standards (4.5:1 contrast ratio)
  • Optimized Performance - React.memo, useCallback, custom hooks
  • Modern UI/UX - Dark theme with smooth transitions

Tech Stack

  • React 19.2.0 - Latest React with TypeScript
  • TypeScript 5.9.3 - Strict mode enabled (zero any types)
  • Redux Toolkit - State management with async thunks
  • Vite 7.2.7 - Lightning-fast build tool
  • Tailwind CSS v4 - Utility-first styling
  • Axios - HTTP client with singleton pattern
  • Vitest - Unit testing framework
  • Happy-DOM - Fast DOM implementation for tests

Prerequisites

  • Node.js - v20 or higher recommended
  • npm or yarn or pnpm
  • OMDB API Key - Get free key from omdbapi.com

Installation

# Clone repository
git clone <repository-url>
cd movie-list

# Install dependencies
npm install

# Create .env file
echo "VITE_OMDB_API_KEY=faf7e5bb" > .env
echo "VITE_OMDB_API_URL=http://www.omdbapi.com" >> .env

Running the App

Development Mode

npm run dev

Open http://localhost:5173 in your browser.

Production Build

# Build for production
npm run build

# Preview production build
npm run preview

Running Tests

# Run tests
npm test

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage

Project Structure

src/
├── components/
│   ├── commons/          # Feature-specific components
│   │   ├── error-boundary/
│   │   ├── error-message/
│   │   ├── loading-spinner/
│   │   ├── movie-card/
│   │   ├── movie-grid/
│   │   ├── movie-detail-modal/  # Feature modal
│   │   └── poster-modal/        # Feature modal
│   └── ui/               # Base/reusable UI components
│       ├── button/
│       ├── input/
│       ├── modal/        # Generic modal (supports variants)
│       └── search-box/
├── constants/
│   ├── apiConfig.ts     # API endpoints & config
│   └── appConfig.ts     # App-wide constants
├── hooks/
│   ├── use-debounce/    # Debounce hook (500ms)
│   ├── use-infinite-scroll/  # Custom infinite scroll
│   └── use-modal/       # Modal state management
├── libs/
│   └── axiosInstance.ts # Axios singleton instance
├── services/
│   └── movie-api/       # OMDB API service layer
│       ├── movieApi.ts
│       └── movieApi.types.ts
├── store/               # Redux store
│   ├── hooks.ts         # Typed Redux hooks
│   ├── index.ts         # Store configuration
│   └── slices/
│       └── movieSlice.ts
├── types/
│   ├── api.types.ts
│   └── movie.types.ts
├── App.tsx              # Main app component
└── main.tsx             # Entry point

Core Features Implementation

1. Movie Search with Debouncing

  • Uses custom useDebounce hook (500ms delay)
  • Minimum 2 characters required for search
  • Clears previous results when query changes

2. Infinite Scroll (No Plugin)

  • Custom implementation using IntersectionObserver API
  • Only activates when search results > 5 items
  • Threshold: 200px from bottom
  • Shows loading spinner during fetch

3. Movie Detail Modal

  • Fetches complete movie data by IMDB ID
  • Displays: plot, cast, director, ratings, awards, runtime
  • Loading state with skeleton
  • Error state with retry button
  • Keyboard accessible (ESC to close)

4. Poster Image Preview

  • Click poster thumbnail to open full-size modal
  • Loading state during image fetch
  • Error state for failed images
  • Close with backdrop click or ESC key

5. Redux State Management

{
  movies: {
    searchResults: Movie[],
    currentMovie: MovieDetail | null,
    searchQuery: string,
    currentPage: number,
    totalResults: number,
    isLoading: boolean,
    isLoadingMore: boolean,
    isLoadingDetail: boolean,
    error: string | null,
    hasMore: boolean
  }
}

6. Custom Hooks

  • useDebounce - Delays value updates to reduce API calls
  • useInfiniteScroll - Detects scroll position with IntersectionObserver
  • useModal - Manages modal state, body scroll lock, ESC key handling

Accessibility Features

  • WCAG AA compliant color contrast ratios (min 4.5:1)
  • Keyboard navigation support (Tab, Enter, ESC)
  • Proper ARIA labels on all interactive elements
  • Semantic HTML elements (button, nav, main)

Environment Variables

Variable Description Default
VITE_OMDB_API_KEY OMDB API key faf7e5bb
VITE_OMDB_API_URL OMDB API base URL http://www.omdbapi.com

Testing

Tests are written using:

  • Vitest - Test runner
  • @testing-library/react - Component testing utilities
  • @testing-library/user-event - User interaction simulation
  • happy-dom - Fast DOM environment
# Run all tests
npm test

# Watch mode
npm run test:watch

# Coverage report
npm run test:coverage

Build & Deployment

# Production build
npm run build

# Output: dist/ folder ready for deployment

The build is optimized with:

  • Code splitting
  • Tree shaking
  • Minification
  • Asset optimization

API Documentation

OMDB API

  • Base URL: http://www.omdbapi.com
  • Documentation: omdbapi.com
  • Rate Limit: 1000 requests/day (free tier)

Endpoints Used

// Search movies
GET /?apikey={key}&s={query}&page={page}

// Get movie details
GET /?apikey={key}&i={imdbID}

License

MIT License - feel free to use this project for learning purposes.

Credits

  • Movie data from OMDB API
  • Built with using React & TypeScript

Made with React 19 • TypeScript • Redux Toolkit • Tailwind CSS v4

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages