Proje Detayları

Önemli Not: Bu projede kullanılacak OMDB API gibi harici API'ler genellikle bir API anahtarı (API Key) gerektirir. OMDB API için buradan ücretsiz bir API anahtarı almanız gerekecektir. Aldığınız anahtarı JavaScript kodunuzda belirtilen yere eklemelisiniz.

Adım Adım Geliştirme

Bu bölümde, film veritabanı uygulamasını adım adım nasıl geliştirebileceğinizi öğreneceksiniz. Her adımda, ilgili kod parçalarını ve açıklamalarını bulacaksınız.

Adım 1: Proje Yapısını Oluşturma

İlk olarak, projemiz için gerekli dosyaları oluşturalım:

  • index.html - Ana HTML dosyası
  • style.css - CSS stil dosyası
  • script.js - JavaScript kod dosyası
index.html
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Film Veritabanı</title>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
    <div class="movie-db-app">
        <div class="movie-header">
            <h2>Film Veritabanı</h2>
            <div class="search-bar">
                <input type="text" id="movieSearchInput" placeholder="Film adı girin...">
                <button id="searchButton"><i class="fas fa-search"></i></button>
            </div>
        </div>
        
        <div class="movie-results" id="movieResults">
            <div class="loading-indicator" id="loadingIndicator" style="display: none;">Yükleniyor...</div>
            <div class="error-message" id="errorMessage" style="display: none;">Bir hata oluştu veya film bulunamadı.</div>
            <div class="movie-grid" id="movieGrid">
                <!-- Film kartları buraya dinamik olarak eklenecek -->
            </div>
        </div>
        
        <!-- Film Detay Modalı -->
        <div id="movieDetailModal" class="movie-detail-modal">
            <div class="modal-detail-content">
                <span class="close-detail-btn" id="closeDetailBtn">×</span>
                <img src="" alt="Film Posteri" class="modal-poster" id="modalPoster">
                <div class="modal-info">
                    <h2 class="modal-title" id="modalTitle"></h2>
                    <div class="modal-meta">
                        <span id="modalYear"></span>
                        <span id="modalRated"></span>
                        <span id="modalRuntime"></span>
                    </div>
                    <p class="modal-plot" id="modalPlot"></p>
                    <div class="modal-details">
                        <p><strong>Yönetmen:</strong> <span id="modalDirector"></span></p>
                        <p><strong>Yazar:</strong> <span id="modalWriter"></span></p>
                        <p><strong>Oyuncular:</strong> <span id="modalActors"></span></p>
                        <p><strong>Tür:</strong> <span id="modalGenre"></span></p>
                        <p><strong>IMDb Puanı:</strong> <span id="modalImdbRating"></span></p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>
style.css
/* Genel Stiller */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f0f2f5;
    color: #333;
    line-height: 1.6;
    padding: 20px;
}

/* Film Veritabanı Uygulaması Stilleri */
.movie-db-app {
    max-width: 1200px;
    margin: 0 auto;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0,0,0,0.1);
    overflow: hidden;
}

.movie-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px 20px;
    background-color: #4caf50;
    color: white;
}

.movie-header h2 {
    margin: 0;
    font-size: 1.5rem;
}

.search-bar {
    display: flex;
    align-items: center;
    background-color: white;
    border-radius: 4px;
    padding: 5px 10px;
    width: 50%;
    max-width: 400px;
}

.search-bar input {
    border: none;
    outline: none;
    padding: 5px;
    font-size: 1rem;
    flex: 1;
}

.search-bar button {
    background: none;
    border: none;
    color: #4caf50;
    font-size: 1.2rem;
    cursor: pointer;
    margin-left: 5px;
}

.movie-results {
    padding: 30px;
    background-color: #f9f9f9;
    border-top: none;
    min-height: 400px;
}

.movie-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
}

.movie-card {
    background-color: #fff;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    cursor: pointer;
    transition: transform 0.3s, box-shadow 0.3s;
}

.movie-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 15px rgba(0,0,0,0.15);
}

.movie-poster {
    width: 100%;
    height: 300px;
    object-fit: cover;
    display: block;
    background-color: #eee; /* Poster yüklenene kadar */
}

.movie-info {
    padding: 15px;
}

.movie-title {
    font-size: 1.1rem;
    font-weight: bold;
    margin-bottom: 5px;
    color: #333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.movie-year {
    font-size: 0.9rem;
    color: #666;
}

.loading-indicator {
    text-align: center;
    padding: 50px;
    font-size: 1.2rem;
    color: #666;
}

.error-message {
    text-align: center;
    padding: 50px;
    font-size: 1.2rem;
    color: #f44336;
}

.movie-detail-modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgba(0,0,0,0.7);
}

.modal-detail-content {
    background-color: #fefefe;
    margin: 5% auto;
    padding: 30px;
    border: 1px solid #888;
    width: 90%;
    max-width: 800px;
    border-radius: 8px;
    position: relative;
    display: flex;
    gap: 30px;
    box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}

.close-detail-btn {
    color: #aaa;
    position: absolute;
    top: 15px;
    right: 25px;
    font-size: 32px;
    font-weight: bold;
    cursor: pointer;
}

.close-detail-btn:hover,
.close-detail-btn:focus {
    color: black;
    text-decoration: none;
}

.modal-poster {
    width: 300px;
    height: auto;
    max-height: 450px;
    object-fit: cover;
    border-radius: 5px;
    background-color: #eee; /* Poster yüklenene kadar */
}

.modal-info {
    flex: 1;
}

.modal-title {
    font-size: 2rem;
    margin-bottom: 15px;
    color: #333;
}

.modal-meta {
    font-size: 0.9rem;
    color: #666;
    margin-bottom: 15px;
}

.modal-meta span {
    margin-right: 15px;
}

.modal-plot {
    margin-bottom: 20px;
    line-height: 1.6;
}

.modal-details {
    font-size: 0.9rem;
}

.modal-details p {
    margin-bottom: 8px;
}

.modal-details strong {
    color: #333;
}

/* Responsive Tasarım */
@media (max-width: 768px) {
    .movie-grid {
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    }
    
    .movie-poster {
        height: 225px;
    }
    
    .modal-detail-content {
        flex-direction: column;
        align-items: center;
        text-align: center;
        width: 95%;
        margin: 10% auto;
    }
    
    .modal-poster {
        width: 80%;
        max-width: 250px;
        margin-bottom: 20px;
    }
    
    .search-bar {
        width: 70%;
    }
}

@media (max-width: 480px) {
    .movie-grid {
        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    }
    
    .movie-poster {
        height: 180px;
    }
    
    .movie-header {
        flex-direction: column;
        align-items: stretch;
        padding: 10px;
    }
    
    .movie-header h2 {
        margin-bottom: 10px;
        text-align: center;
    }
    
    .search-bar {
        width: 100%;
    }
    
    .modal-title {
        font-size: 1.5rem;
    }
}

Adım 2: JavaScript Kodunu Yazma

Şimdi, uygulamanın işlevselliğini sağlayacak JavaScript kodunu yazalım:

script.js
// DOM elementlerini seçme
const movieSearchInput = document.getElementById('movieSearchInput');
const searchButton = document.getElementById('searchButton');
const movieGrid = document.getElementById('movieGrid');
const loadingIndicator = document.getElementById('loadingIndicator');
const errorMessage = document.getElementById('errorMessage');
const movieDetailModal = document.getElementById('movieDetailModal');
const closeDetailBtn = document.getElementById('closeDetailBtn');
const modalPoster = document.getElementById('modalPoster');
const modalTitle = document.getElementById('modalTitle');
const modalYear = document.getElementById('modalYear');
const modalRated = document.getElementById('modalRated');
const modalRuntime = document.getElementById('modalRuntime');
const modalPlot = document.getElementById('modalPlot');
const modalDirector = document.getElementById('modalDirector');
const modalWriter = document.getElementById('modalWriter');
const modalActors = document.getElementById('modalActors');
const modalGenre = document.getElementById('modalGenre');
const modalImdbRating = document.getElementById('modalImdbRating');

// API Bilgileri
const API_KEY = 'YOUR_OMDB_API_KEY'; // Kendi OMDB API anahtarınızı buraya girin
const API_URL = `https://www.omdbapi.com/?apikey=${API_KEY}`;

// Olay Dinleyicileri
document.addEventListener('DOMContentLoaded', () => {
    // Arama butonu tıklama olayı
    searchButton.addEventListener('click', searchMovies);
    
    // Enter tuşu ile arama
    movieSearchInput.addEventListener('keypress', (event) => {
        if (event.key === 'Enter') {
            searchMovies();
        }
    });
    
    // Film kartına tıklama olayı (event delegation)
    movieGrid.addEventListener('click', (event) => {
        const movieCard = event.target.closest('.movie-card');
        if (movieCard) {
            const imdbID = movieCard.dataset.imdbid;
            fetchMovieDetails(imdbID);
        }
    });
    
    // Detay modalı kapatma butonu
    closeDetailBtn.addEventListener('click', closeDetailModal);
    
    // Modal dışına tıklama olayı
    window.addEventListener('click', (event) => {
        if (event.target === movieDetailModal) {
            closeDetailModal();
        }
    });
});

// Film arama fonksiyonu
async function searchMovies() {
    const searchTerm = movieSearchInput.value.trim();
    
    if (searchTerm === '') {
        showError('Lütfen bir film adı girin.');
        return;
    }
    
    // Önceki sonuçları temizle ve yükleme göstergesini göster
    clearResults();
    showLoading();
    
    try {
        // API'ye istek gönder
        const response = await fetch(`${API_URL}&s=${searchTerm}`);
        const data = await response.json();
        
        // Yükleme göstergesini gizle
        hideLoading();
        
        // Sonuçları kontrol et
        if (data.Response === 'True') {
            displayMovies(data.Search);
        } else {
            showError(data.Error || 'Film bulunamadı.');
        }
    } catch (error) {
        hideLoading();
        showError('API isteği sırasında bir hata oluştu.');
        console.error('Arama hatası:', error);
    }
}

// Filmleri gösterme fonksiyonu
function displayMovies(movies) {
    movieGrid.innerHTML = ''; // Önceki filmleri temizle
    
    movies.forEach(movie => {
        const movieCard = document.createElement('div');
        movieCard.className = 'movie-card';
        movieCard.dataset.imdbid = movie.imdbID;
        
        // Poster yoksa varsayılan bir resim kullan
        const posterUrl = movie.Poster === 'N/A' ? 'https://via.placeholder.com/200x300/cccccc/ffffff?text=Poster+Yok' : movie.Poster;
        
        movieCard.innerHTML = `
            
            
                ${movie.Title}
                ${movie.Year}
            
        `;
        movieGrid.appendChild(movieCard);
    });
}

// Film detaylarını getirme fonksiyonu
async function fetchMovieDetails(imdbID) {
    showLoading(); // Detaylar yüklenirken gösterge
    
    try {
        // API'ye detay isteği gönder
        const response = await fetch(`${API_URL}&i=${imdbID}&plot=full`);
        const movieDetails = await response.json();
        
        hideLoading();
        
        if (movieDetails.Response === 'True') {
            displayMovieDetails(movieDetails);
        } else {
            showError('Film detayları alınamadı.');
        }
    } catch (error) {
        hideLoading();
        showError('Film detayları alınırken bir hata oluştu.');
        console.error('Detay hatası:', error);
    }
}

// Film detaylarını modalda gösterme fonksiyonu
function displayMovieDetails(details) {
    modalPoster.src = details.Poster === 'N/A' ? 'https://via.placeholder.com/300x450/cccccc/ffffff?text=Poster+Yok' : details.Poster;
    modalTitle.textContent = details.Title;
    modalYear.textContent = details.Year;
    modalRated.textContent = details.Rated;
    modalRuntime.textContent = details.Runtime;
    modalPlot.textContent = details.Plot;
    modalDirector.textContent = details.Director;
    modalWriter.textContent = details.Writer;
    modalActors.textContent = details.Actors;
    modalGenre.textContent = details.Genre;
    modalImdbRating.textContent = details.imdbRating;
    
    // Modalı göster
    movieDetailModal.style.display = 'block';
}

// Detay modalını kapatma fonksiyonu
function closeDetailModal() {
    movieDetailModal.style.display = 'none';
}

// Yükleme göstergesini gösterme fonksiyonu
function showLoading() {
    loadingIndicator.style.display = 'block';
    errorMessage.style.display = 'none';
}

// Yükleme göstergesini gizleme fonksiyonu
function hideLoading() {
    loadingIndicator.style.display = 'none';
}

// Hata mesajını gösterme fonksiyonu
function showError(message) {
    errorMessage.textContent = message;
    errorMessage.style.display = 'block';
    movieGrid.innerHTML = ''; // Hata durumunda film gridini temizle
}

// Sonuçları temizleme fonksiyonu
function clearResults() {
    movieGrid.innerHTML = '';
    errorMessage.style.display = 'none';
}

Adım 3: Uygulamayı Test Etme

Şimdi uygulamanızı test etme zamanı! Aşağıdaki adımları izleyin:

  1. JavaScript kodundaki YOUR_OMDB_API_KEY kısmını kendi OMDB API anahtarınızla değiştirin.
  2. Tüm dosyaları (index.htmlstyle.cssscript.js) aynı klasöre kaydedin.
  3. HTML dosyasını bir web tarayıcısında açın.
  4. Arama kutusuna bir film adı girin (örneğin, "Batman", "Inception") ve arama butonuna tıklayın veya Enter tuşuna basın.
  5. Yükleme göstergesinin göründüğünü ve ardından film sonuçlarının listelendiğini doğrulayın.
  6. Bir film kartına tıklayarak detay modalının açıldığını ve film bilgilerinin doğru yüklendiğini kontrol edin.
  7. Detay modalını kapatma butonuna veya modal dışına tıklayarak kapatın.
  8. Geçersiz bir arama terimi girerek veya API anahtarı olmadan hata mesajlarının doğru gösterildiğini test edin.

İpucu: Tarayıcınızın geliştirici araçlarını (genellikle F12 tuşu ile açılır) kullanarak API isteklerini ve yanıtlarını inceleyebilir, JavaScript hatalarını ayıklayabilirsiniz.

Projeyi Geliştirme

Temel film veritabanı uygulamasını başarıyla oluşturduktan sonra, aşağıdaki özelliklerle projenizi geliştirebilirsiniz:

1. Sayfalama (Pagination)

Arama sonuçları çok fazlaysa, sonuçları sayfalara bölerek gösterin. API genellikle sayfalama parametreleri sunar (örneğin, OMDB API'de page parametresi).

2. Filtreleme (Yıl, Tür vb.)

Arama sonuçlarını yıla veya türe göre filtreleme seçenekleri ekleyin. API'nin desteklediği filtreleme parametrelerini kullanabilirsiniz.

3. Favori Filmler

Kullanıcıların beğendikleri filmleri favorilerine ekleyebilmesini ve favori listesini görüntüleyebilmesini sağlayın. Bu bilgiyi LocalStorage kullanarak saklayabilirsiniz.

4. Daha Fazla Detay

Film detay modalına daha fazla bilgi ekleyin (örneğin, ödüller, gişe hasılatı, Rotten Tomatoes puanı vb.). API'nin sağladığı ek verileri kullanın.

5. Gelişmiş Arama

Kullanıcıların sadece başlığa göre değil, oyuncuya, yönetmene veya yıla göre de arama yapabilmesini sağlayın.

6. Farklı API Kullanımı

OMDB API yerine The Movie Database (TMDb) gibi daha kapsamlı başka bir film API'si kullanmayı deneyin.

Geliştirme Zorlukları

Film veritabanı uygulamanızı daha da geliştirmek için aşağıdaki zorlukları deneyebilirsiniz:

  1. Otomatik Tamamlama: Arama kutusuna yazarken olası film başlıklarını öneren bir otomatik tamamlama özelliği ekleyin.
  2. Benzer Filmler: Film detay sayfasında seçili filme benzer filmleri önerin.
  3. Fragman Gösterme: Film detay modalına filmin fragmanını (örneğin, YouTube'dan) ekleyin.
  4. Çevrimdışı Kullanım: Service Worker kullanarak uygulamanın çevrimdışı çalışabilmesini sağlayın (en azından daha önce görüntülenen verilerle).
  5. Kullanıcı Yorumları/Puanlama: Kullanıcıların filmlere yorum yapabilmesini ve puan verebilmesini sağlayan bir sistem ekleyin (bu genellikle sunucu tarafı kodlama gerektirir).

Sonuç ve Öğrenilen Dersler

Bu projede, JavaScript kullanarak harici bir API ile etkileşim kuran bir film veritabanı uygulaması geliştirdik. Bu süreçte şunları öğrendik:

  • Fetch API kullanarak harici API'lerden veri çekmeyi
  • Async/Await ile eşzamansız işlemleri yönetmeyi
  • JSON verilerini işlemeyi
  • API yanıtlarına göre dinamik olarak DOM'u güncellemeyi
  • Arama, listeleme ve detay gösterme işlevselliği oluşturmayı
  • Modal pencereler kullanmayı
  • Hata yönetimi ve yükleme durumlarını ele almayı

Bu proje, API'lerle çalışma ve modern JavaScript tekniklerini kullanarak dinamik web uygulamaları oluşturma konusunda önemli bir pratik deneyim sunmuştur. Öğrendiğiniz beceriler, çeşitli web servisleriyle entegre olan daha karmaşık uygulamalar geliştirmenize olanak tanır.