Skip to main content

Overview

The MediaItem interface represents a media item (movie, TV series, or episode) in the ScreenPulse application. It is used throughout the application for search results, favorites, and media details.

Import

import { MediaItem } from 'src/app/shared/models/movie.model';

Interface Definition

export interface MediaItem {
  _id?: string;
  title: string;
  year: string;
  imdbID: string;
  type: string;
  poster: string;
  description?: string;
  user?: string;
  createdAt?: string;
  updatedAt?: string;
}

Fields

_id
string
Unique identifier for the media item in the database. Generated by MongoDB when a favorite is saved. Not present in OMDB API responses.
title
string
required
The title of the media item (movie, series, or episode name)
year
string
required
The release year of the media item
imdbID
string
required
The unique IMDb identifier (e.g., ‘tt1375666’ for Inception)
type
string
required
The media type. Valid values: 'movie', 'series', or 'episode'
poster
string
required
URL to the poster image for the media item
description
string
User-added description or notes about the media item. Only present for favorites.
user
string
User ID of the owner. Only present for favorites stored in the database.
createdAt
string
ISO 8601 timestamp when the favorite was created. Generated by the server.
updatedAt
string
ISO 8601 timestamp when the favorite was last updated. Generated by the server.

Usage Examples

Creating a MediaItem from Search Results

import { MediaItem } from 'src/app/shared/models/movie.model';
import { OmdbService } from 'src/app/shared/services/omdb/omdb.service';

// Search results from OMDB API
omdbService.fetchMediaItems('Inception', 'movie', '2010', 1)
  .subscribe(response => {
    if (response.Response === 'True' && response.Search) {
      const mediaItems: MediaItem[] = response.Search;
      
      mediaItems.forEach(item => {
        console.log('Title:', item.title);
        console.log('Year:', item.year);
        console.log('IMDb ID:', item.imdbID);
        console.log('Type:', item.type);
        console.log('Poster:', item.poster);
        // Note: _id, description, user, createdAt, updatedAt are not present
      });
    }
  });

Adding to Favorites

import { MediaItem } from 'src/app/shared/models/movie.model';
import { FavoritesService } from 'src/app/shared/services/favorites/favorites.service';

const mediaItem: MediaItem = {
  title: 'Inception',
  year: '2010',
  imdbID: 'tt1375666',
  type: 'movie',
  poster: 'https://m.media-amazon.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg',
  description: 'A masterpiece of cinema' // Optional user note
};

favoritesService.addToFavorites(mediaItem).subscribe({
  next: (savedItem) => {
    // Server adds additional fields
    console.log('Favorite ID:', savedItem._id);
    console.log('Created at:', savedItem.createdAt);
    console.log('Updated at:', savedItem.updatedAt);
    console.log('User ID:', savedItem.user);
  }
});

Displaying Favorites

import { Component, OnInit } from '@angular/core';
import { MediaItem } from 'src/app/shared/models/movie.model';
import { FavoritesService } from 'src/app/shared/services/favorites/favorites.service';

@Component({
  selector: 'app-favorites-list',
  template: `
    <div *ngFor="let favorite of favorites">
      <img [src]="favorite.poster" [alt]="favorite.title">
      <h3>{{ favorite.title }} ({{ favorite.year }})</h3>
      <p>Type: {{ favorite.type }}</p>
      <p *ngIf="favorite.description">{{ favorite.description }}</p>
      <small>Added: {{ favorite.createdAt | date }}</small>
    </div>
  `
})
export class FavoritesListComponent implements OnInit {
  favorites: MediaItem[] = [];

  constructor(private favoritesService: FavoritesService) {}

  ngOnInit() {
    this.favoritesService.getFavorites(1, 10).subscribe({
      next: (response) => {
        this.favorites = response.favorites;
      }
    });
  }
}

Updating a Favorite

import { MediaItem } from 'src/app/shared/models/movie.model';
import { FavoritesService } from 'src/app/shared/services/favorites/favorites.service';

const favorite: MediaItem = {
  _id: '507f1f77bcf86cd799439011',
  title: 'Inception',
  year: '2010',
  imdbID: 'tt1375666',
  type: 'movie',
  poster: 'https://example.com/poster.jpg',
  description: 'Updated: Must watch again!' // New description
};

favoritesService.updateFavorite(favorite).subscribe({
  next: (updated) => {
    console.log('Updated description:', updated.description);
    console.log('Updated at:', updated.updatedAt);
  }
});

Type Guards

Check if MediaItem is a Favorite

function isFavorite(item: MediaItem): boolean {
  return item._id !== undefined && item._id !== null;
}

const searchResult: MediaItem = {
  title: 'Inception',
  year: '2010',
  imdbID: 'tt1375666',
  type: 'movie',
  poster: 'https://example.com/poster.jpg'
};

console.log(isFavorite(searchResult)); // false

const favorite: MediaItem = {
  _id: '507f1f77bcf86cd799439011',
  title: 'Inception',
  year: '2010',
  imdbID: 'tt1375666',
  type: 'movie',
  poster: 'https://example.com/poster.jpg',
  user: '507f191e810c19729de860ea'
};

console.log(isFavorite(favorite)); // true

Field Usage by Context

OMDB Search Results

When receiving search results from OMDB API:
  • ✅ Present: title, year, imdbID, type, poster
  • ❌ Not present: _id, description, user, createdAt, updatedAt

Creating a Favorite (Request)

When sending to addToFavorites():
  • ✅ Required: title, year, imdbID, type, poster
  • ✅ Optional: description
  • ❌ Ignored: _id, user, createdAt, updatedAt (generated by server)

Favorite from Database (Response)

When receiving from getFavorites() or addToFavorites():
  • ✅ Present: All fields
  • ✅ Server-generated: _id, user, createdAt, updatedAt

Updating a Favorite (Request)

When sending to updateFavorite():
  • ✅ Required: _id, description (only description is updated)
  • ✅ Present but not modified: title, year, imdbID, type, poster

Validation Example

function validateMediaItem(item: Partial<MediaItem>): string[] {
  const errors: string[] = [];

  if (!item.title || item.title.trim() === '') {
    errors.push('Title is required');
  }

  if (!item.year || !/^\d{4}$/.test(item.year)) {
    errors.push('Valid year is required');
  }

  if (!item.imdbID || !item.imdbID.startsWith('tt')) {
    errors.push('Valid IMDb ID is required');
  }

  if (!item.type || !['movie', 'series', 'episode'].includes(item.type)) {
    errors.push('Type must be movie, series, or episode');
  }

  if (!item.poster || !item.poster.startsWith('http')) {
    errors.push('Valid poster URL is required');
  }

  return errors;
}

const item: MediaItem = {
  title: 'Inception',
  year: '2010',
  imdbID: 'tt1375666',
  type: 'movie',
  poster: 'https://example.com/poster.jpg'
};

const errors = validateMediaItem(item);
if (errors.length === 0) {
  console.log('Valid media item');
} else {
  console.error('Validation errors:', errors);
}

Build docs developers (and LLMs) love