# Değerlendirme ve Puanlama Sistemi (Reviews API) Dokümantasyonu

Bu doküman, `reviews` uygulaması tarafından sağlanan API endpoint'lerinin frontend tarafında nasıl kullanılacağını açıklar. Bu sistem polimorfik bir yapıdadır, yani sadece ürünler için değil, ileride eklenebilecek diğer modüller (Blog, Satıcı vb.) için de kullanılabilir.

## 1. Genel Bilgiler

*   **Base URL:** `/api/v1/reviews/`
*   **Authentication:** Oy verme işlemi (`POST`) için kullanıcının giriş yapmış olması (Token ile) gerekir. Listeleme (`GET`) işlemi herkese açıktır.

## 2. Ürün Verisinde Puanlama Bilgisi

Ürünleri listelediğinizde (`/api/v1/products/`) veya detayını çektiğinizde (`/api/v1/products/<slug>/`), ürün objesi artık şu iki alanı içerir:

*   **`average_rating` (Float):** Ürünün ortalama puanı (1.0 - 5.0 arası). Hiç oy yoksa `0.0` döner.
*   **`rating_count` (Integer):** Toplam kaç kişinin oy verdiği.

**Örnek Ürün Objesi:**
```json
{
    "id": 15,
    "title": "Örnek Ürün",
    "price": 100.0,
    "average_rating": 4.5,  // <-- Ortalama Puan
    "rating_count": 12,     // <-- Oy Sayısı
    "images": "/media/uploads/products/example.avif",
    ...
}
```
Bu bilgileri ürün kartlarında yıldız göstermek için kullanabilirsiniz.

---

## 3. API Endpoint'leri

### 3.1. Oy Verme ve Yorum Yapma

Kullanıcının bir nesneye (örneğin bir ürüne) puan vermesini ve isteğe bağlı olarak yorum yapmasını sağlar. Bir kullanıcı aynı nesneye sadece bir kez oy verebilir; ikinci istekte mevcut oy güncellenir.

*   **URL:** `/api/v1/reviews/rate/`
*   **Method:** `POST`
*   **Permission:** `IsAuthenticated` (Header'da `Authorization: Bearer <token>` olmalı)

#### İstek (Request) Body Parametreleri:

| Parametre    | Tip     | Zorunlu | Açıklama                                                                 |
| :---         | :---    | :---    | :---                                                                     |
| `model_name` | String  | Evet    | Oylanacak nesnenin model adı. Örn: `"product"`                           |
| `object_id`  | Integer | Evet    | Oylanacak nesnenin ID'si. Örn: `15`                                      |
| `score`      | Integer | Evet    | 1 ile 5 arasında bir tam sayı.                                           |
| `comment`    | String  | Hayır   | Kullanıcının yorumu.                                                     |

#### Örnek İstek (JSON):

```json
{
  "model_name": "product",
  "object_id": 15,
  "score": 5,
  "comment": "Ürün beklediğimden çok daha kaliteli çıktı, tavsiye ederim."
}
```

#### Başarılı Yanıt (201 Created veya 200 OK):

```json
{
  "id": 42,
  "score": 5,
  "comment": "Ürün beklediğimden çok daha kaliteli çıktı, tavsiye ederim.",
  "user": "kullanici_adi",
  "created_at": "2023-10-27T10:00:00Z",
  "model_name": "product",
  "object_id": 15
}
```

#### Hata Yanıtları:

*   **400 Bad Request:** Eksik parametre veya geçersiz puan (1-5 dışı).
*   **401 Unauthorized:** Giriş yapılmamış.
*   **404 Not Found:** Belirtilen model veya ID bulunamadı.

---

### 3.2. Değerlendirmeleri Listeleme

Belirli bir nesneye ait tüm yorumları ve puanları listeler. Genellikle ürün detay sayfasının altındaki "Yorumlar" sekmesinde kullanılır.

*   **URL:** `/api/v1/reviews/list/`
*   **Method:** `GET`
*   **Permission:** `AllowAny` (Herkes erişebilir)

#### Query Parametreleri:

| Parametre | Zorunlu | Açıklama                                       |
| :---      | :---    | :---                                           |
| `model`   | Evet    | Listelenecek nesnenin model adı. Örn: `product`|
| `id`      | Evet    | Listelenecek nesnenin ID'si.                   |

#### Örnek İstek:

`GET /api/v1/reviews/list/?model=product&id=15`

#### Başarılı Yanıt (200 OK):

```json
[
  {
    "id": 42,
    "score": 5,
    "comment": "Harika ürün!",
    "user": "ahmet123",
    "created_at": "2023-10-27T10:00:00Z",
    "model_name": "product",
    "object_id": 15
  },
  {
    "id": 43,
    "score": 4,
    "comment": "Kargo biraz geç geldi ama ürün güzel.",
    "user": "ayse_yilmaz",
    "created_at": "2023-10-26T14:30:00Z",
    "model_name": "product",
    "object_id": 15
  }
]
```

---

## 4. Frontend Entegrasyon Senaryosu (React Örneği)

Bir ürün detay sayfasında (Product Detail Page) yapılması gerekenler:

1.  **Ürün Bilgisini Çek:** `/api/v1/products/<slug>/` endpoint'inden ürünü çekin. Gelen `average_rating` ve `rating_count` ile sayfanın üst kısmında yıldızları gösterin.
2.  **Yorumları Çek:** Ürün ID'sini kullanarak `/api/v1/reviews/list/?model=product&id=<id>` endpoint'inden yorumları çekin ve aşağıda listeleyin.

```javascript
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function ProductDetail({ slug }) {
  const [product, setProduct] = useState(null);
  const [reviews, setReviews] = useState([]);

  useEffect(() => {
    async function fetchData() {
      // 1. Ürün detayını çek
      const prodRes = await axios.get(`/api/v1/products/${slug}/`);
      setProduct(prodRes.data);

      // 2. Ürünün yorumlarını çek (prodRes.data.id kullanarak)
      const reviewRes = await axios.get(`/api/v1/reviews/list/`, {
        params: { model: 'product', id: prodRes.data.id }
      });
      setReviews(reviewRes.data);
    }
    fetchData();
  }, [slug]);

  if (!product) return <div>Yükleniyor...</div>;

  return (
    <div>
      <h1>{product.title}</h1>
      
      {/* Özet Puan Gösterimi */}
      <div className="rating-summary">
        <span>Ortalama Puan: {product.average_rating} / 5</span>
        <span>({product.rating_count} değerlendirme)</span>
      </div>

      {/* ... Ürün detayları ... */}

      {/* Yorumlar Listesi */}
      <div className="reviews-section">
        <h3>Yorumlar</h3>
        {reviews.map(review => (
          <div key={review.id} className="review-card">
            <strong>{review.user}</strong> - <span>{review.score} Yıldız</span>
            <p>{review.comment}</p>
          </div>
        ))}
      </div>
    </div>
  );
}
```

## 5. Notlar

*   **Resim Yolları:** API'den dönen resim yolları `/media/...` şeklinde olabilir. Frontend tarafında base URL'i (`http://localhost:8000` veya canlı sunucu adresi) başına eklemeniz gerekebilir.
