Proje: Okul B2B App · Hub: Okul B2B App — Domain

School Comments API (Customer-Scoped)

Customer\SchoolCommentController — kurumsal kullanıcıların yetkili okullarına bırakılan yorumları listeleme ve cevaplama.

Endpoints

MethodPathAmaç
GET/customer/school-commentsParent yorum listesi (paginated)
GET/customer/school-comments/{id}Tek yorum detayı
GET/customer/school-comments/statisticsOkul bazlı sayım (şu an kullanılmıyor)
POST/customer/school-comments/{id}/replyCevap oluştur/güncelle/sil

Liste: query parametreleri

  • page, per_page — sayfalama
  • sort-created_at (default), id, comment_rate, status, school_id ve negatif tersleri
  • filter[school_id] — tek okul
  • filter[school_ids][] — çoklu
  • filter[search] — serbest metin (comment, commenter_name/email, school name, user email/name içinde)
  • filter[comment_rate] — 1–5
  • includes[]school, reply, user, userType

Önemli davranışlar

  • Sadece parent yorumlar döner: Repository whereNull('replied_id') hardcoded. Liste asla cevap satırı içermez.
  • Sadece onaylı yorumlar: status=1 filtresi uygulanıyor. Admin pending/rejected yorumları customer görmez.
  • reply nested: include[]=reply ile customer’ın yazdığı cevap parent yorumun içinde reply objesi olarak gelir; cevap yoksa null.
  • Erişim: accessibleSchoolIdsCustomerUserService::getContentAccessSchoolIds() üzerinden sadece kullanıcının yetkili olduğu okulların yorumları listelenir.

Cevap yazma

POST /customer/school-comments/{id}/reply body:

{ "comment": "Teşekkürler, geri bildiriminiz alındı." }
  • comment string, max 2000 karakter.
  • Boş/null → mevcut reply varsa silinir, yoksa no-op.
  • Aynı okula yetkili BAŞKA customer user mevcut reply’ı güncelleyebilir (bilinçli tasarım — müşteri temsilcisi değişiminde ekip cevap düzenleyebilsin diye).
  • Parent onaylanmamışsa (status=0 veya reject_stage != null) 422 döner.

Response shape — SchoolCommentResource (Customer)

{
  "id": 12345,
  "school_id": 5,
  "commenter_name": "Ayşe Yılmaz",
  "commenter_email": "...",
  "replied_id": null,                // parent için null
  "comment": "Olumlu yorumu...",
  "comment_negative": "Geliştirilebilir yanı...",
  "comment_rate": 4,
  "do_recommend": true,
  "status": true,
  "created_at": "2026-04-10T10:30:00Z",
  "school": { "id": 5, "name": "..." },
  "user_type": { "id": 5, "item_value": "Veli" },
  "user": { "id": 10, "name": "..." },
  "reply": {                        // include=reply ile gelir, yoksa null
    "id": 12346,
    "replied_id": 12345,
    "comment": "Teşekkürler...",
    "created_at": "2026-04-11T09:15:00Z"
  }
}

comment_rate 1–5 yıldız. comment olumlu, comment_negative eleştiri metni — frontend’te ayrı “Olumlu” / “Geliştirilebilir” bloklarında gösterilir.

Mobil tarafı

  • Servis: services/SchoolCommentsService.tsgetList, getById, reply, deleteReply.
  • Tip: types/schoolComment.tsSchoolComment, SchoolCommentFilters, ReplyStatusFilter.
  • Ekran: app/school-comments/index.tsx — liste + inline detay modali (KeyboardAvoidingView pattern).

”Bekleyen” filtresi — client-side

Backend has_reply filtresi yok. include[]=reply ile parent listesi çekilir, frontend c.reply == null check’i ile bekleyenleri ayırır. Çok sayıda yorum olan okullarda sayfa başına cevaplı/cevapsız oranı bozulabilir; gerekirse backend’e filter eklenir.