Skip to content

Eğitmen ve Kurs Yönetimi (Instructor Engine)

Kurs oluşturma sihirbazı, müfredat (Section/Lesson), Bunny CDN streaming, performans paneli ve manuel ödeme talebi.

Coursio’da eğitmenler kurs oluşturur, müfredat ve içerik yönetir, gelir/öğrenci istatistiklerini görür ve biriken bakiyeyi çeker. Bu sayfa Kurs Oluşturma Sihirbazı, Müfredat ve İçerik (Section/Lesson, Bunny CDN), Eğitmen Performans Paneli (Recharts ile analiz) ve Manuel Ödeme Talebi akışını açıklar.

Dosya: app/routes/instructor.create.tsx

Eğitmen yeni kurs oluşturmak için adım adım sihirbaz kullanır.

Adımİçerik
1Kurs türü seçimi: “Kurs” (video dersler, sınavlar) veya “Pratik Testi” (şu an devre dışı).
2Kurs başlığı: Metin alanı (max 60 karakter); en az 5 karakter gerekli.
3Kategori: CATEGORIES listesinden ana/alt kategori seçimi; seçim zorunlu.
4Zaman taahhüdü: “0-2 saat”, “2-4 saat”, “5+ saat” (opsiyonel).
  1. Slug üretimi: Başlıktan generateSlug(title) ile URL dostu slug; çakışmayı önlemek için rastgele 5 karakter eklenir: slug-xxxxx.
  2. GraphQL mutation: createCourse(title, slug, category) çağrılır.
  3. Yönlendirme: Başarılıysa eğitmen Hedefler (Goals) sayfasına yönlendirilir:
    /{lang}/instructor/course/{slug}/manage/goals.

Kurs oluşturulduktan sonra CourseEditSidebar ile adım adım tamamlanır:

  • Planlama: Hedefler (goals), Kurs Yapısı (course-structure), Kurulum & Test (setup).
  • İçerik: Filming & Editing (filming), Müfredat (curriculum), Altyazılar (captions).
  • Yayın: Landing sayfası (landing), Fiyatlandırma (pricing).

Tamamlanma durumu: goals → learningOutcomes; curriculum → sectionCount/lessonCount; landing → başlık, açıklama, thumbnail, kategori; pricing → fiyat.

Bölüm (Section) ve Ders (Lesson) Hiyerarşisi

Section titled “Bölüm (Section) ve Ders (Lesson) Hiyerarşisi”

Veritabanı:

  • sections: id, course_id, title, order, created_at. Her bölüm bir kursa aittir.
  • lessons: id, section_id, title, bunny_video_id, order, is_preview, duration. Her ders bir bölüme aittir; video varsa bunny_video_id dolu.

Aynı section altında quiz ve coding exercise tabloları da vardır (quizzes, coding_exercisessection_id); müfredat sayfasında bölüm içinde dersler, quiz’ler ve egzersizler birlikte listelenir.

Dosya: app/routes/instructor.course.$slug.manage.curriculum.tsx

  • Bölüm ekleme/düzenleme/silme, sürükle-bırak sıralama (Accordion + order).
  • Ders ekleme: başlık, video yükleme (Bunny), önizleme (isPreview), kaynaklar (lesson_resources).
  • Video yükleme: Bunny Stream API (presigned URL veya upload endpoint) ile yükleme; bunnyVideoId derse kaydedilir.
  • Bunny işlem durumu: fetchBunnyVideoStatus(libraryId, videoId, apiKey) ile status/length çekilir; getBunnyVideoStatusKind ile “processing” | “ready” | “error” gösterilir (lib/bunny-video-status.ts).

Video İçeriklerinin Bunny CDN Üzerinden Streaming Mantığı

Section titled “Video İçeriklerinin Bunny CDN Üzerinden Streaming Mantığı”

Yükleme (eğitmen tarafı):

  • Curriculum sayfasında derse video seçilir; Bunny Stream Library’ye yükleme yapılır (BUNNY_LIBRARY_ID, BUNNY_API_KEY).
  • Ders kaydına dönen Bunny Video ID (bunnyVideoId) yazılır.

İzleme (öğrenci tarafı):

Dosya: app/lib/video-security.tsgenerateSignedVideoUrl(videoId, libraryId, securityKey, expirationSeconds)

  • Amaç: Doğrudan indirme ve yetkisiz erişimi engellemek için imzalı URL kullanılır.
  • Algoritma: tokenData = securityKey + videoId + expires → SHA-256 hash → query: token=...&expires=....
  • URL formatı: https://iframe.mediadelivery.net/embed/{libraryId}/{videoId}?token={hash}&expires={expires}.
  • Ortam değişkenleri: BUNNY_LIBRARY_ID, BUNNY_VIDEO_SECURITY_KEY (Pull Zone Remote Auth Key).

Öğrenci sayfası: app/routes/learn.$slug.tsx loader’da müfredat çekilir; her ders için generateSignedVideoUrl ile signedVideoUrl hesaplanır; oynatıcıda bu URL kullanılır. Kayıt/enrollment kontrolü loader’da yapılır.

Bunny durum kodları (lib/bunny-video-status.ts): 0=Queued, 1=Processing, 2=Encoding → “İşleniyor”; 3=Finished, 4=Resolution finished → “Hazır”; 5=Failed, 8=PresignedUploadFailed → “Hata”.

Layout: app/routes/instructor.performance.tsx — InstructorSidebar + <Outlet />.
Varsayılan yönlendirme: instructor.performance._index.tsx/{lang}/instructor/performance/students.

Dosya: app/routes/instructor.performance.students.tsx

  • Loader: getInstructorStudents(db, userId) ile son öğrenciler, tüm satın alanlar, iade edilenler, abonelik izleyicileri ve satın alım özeti (subscription, direct, organic, affiliate) alınır.
  • Metrik kartları: Toplam satın alım, aktif öğrenci sayısı, iade edilen sayısı, abonelik izleyicisi sayısı.
  • Sekmeler: Tüm öğrenciler, satın alanlar, iade edilenler, abonelik.
  • Tablo: Öğrenci adı, kurs, satın alma tarihi, satın alma türü (badge). Recharts kullanılmaz; istatistikler kart ve tablo ile sunulur.

Gelir Analizi ve Recharts — Reviews / İzlenme Trendleri

Section titled “Gelir Analizi ve Recharts — Reviews / İzlenme Trendleri”

Dosya: app/components/instructor/PerformanceReviewsCharts.tsx

  • Veri: watchTrends (tarih bazlı toplam / abonelik / satın alım izlenme süreleri) ve courseAnalytics (kurs bazlı trendler).
  • Recharts: Dinamik import ile yüklenir (import("recharts")). Kullanılan bileşenler: LineChart, Line, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer.
  • Grafikler:
    • Çizgi grafiği: Tarih başına toplam / abonelik / satın alım izlenme dakikaları (watchTrends).
    • Çubuk grafiği: Günlük izlenme dakikaları.
  • Filtreler: Dönem (1 hafta, 1 ay, 3 ay, 6 ay); kurs seçimi (courseAnalytics üzerinden).

Bu bileşen instructor.performance.reviews sayfasında kullanılır; eğitmen burada izlenme trendlerini ve dolaylı olarak ilgili gelir/etkileşim analizini görür.

Manuel Ödeme Talebi: Biriken Bakiyeyi Çekme Süreci

Section titled “Manuel Ödeme Talebi: Biriken Bakiyeyi Çekme Süreci”

Dosya: app/routes/instructor.payouts.tsx

  • Loader: getInstructorBalance, getInstructorPayoutRequests, getUserById, getInstructorEarnings, getInstructorSubscriptionWatchByCourse ile bakiye, talep listesi, kullanıcı ödeme ayarları, kazançlar ve abonelik izlenme verileri alınır.
  • Stripe Connect: onboarding=success query parametresi ile dönüldüğünde isConnectOnboardingCompleted ve payoutMethod güncellenir.
  • Toplam bakiye (kurs satışları + affiliate + abonelik payları).
  • Son kazançlar listesi (earnings): satış türü badge’i (organik, direkt, affiliate, paket, abonelik), tutar, tarih.
  1. Tutar girişi: Minimum çekim tutarı kontrolü (TR ve Stripe Connect için farklı mesajlar).
  2. Aylık limit: Varsa limit aşılmışsa uyarı.
  3. TR (Türkiye): manualPayoutDetails (IBAN/Payoneer) dolu olmalı; değilse “Önce bilgileri kaydedin” uyarısı ve ayarlar açılır.
  4. Stripe Connect: isConnectOnboardingCompleted veya stripeConnectId / payout bilgisi dolu olmalı; değilse ödeme bilgisi güncelleme yönlendirmesi.
  5. Mutation: requestPayout(amount: Float!) GraphQL mutation’ı çağrılır; başarılıysa payout_requests tablosuna kayıt eklenir (status: pending).
  6. Liste: Önceki talepler tabloda gösterilir; durum: pending, processing, completed, rejected.

Admin panelinde bu talepler onaylanır; Stripe Connect için processPayoutTransfer, TR için manuel havale/EFT sonrası durum “completed” yapılır (bkz. Türkiye (TR) Özel Payout Akışı ve Stripe Connect Akışı).

KonuAçıklama
Kurs sihirbazıinstructor.create.tsx — 4 adım (tür, başlık, kategori, zaman); createCourse mutation → manage/goals’a yönlendirme.
MüfredatSection/Lesson (ve quiz, coding exercise) hiyerarşisi; curriculum sayfasında CRUD ve sıralama.
VideoBunny CDN: yükleme → bunnyVideoId; izleme → generateSignedVideoUrl ile imzalı embed URL.
PerformansÖğrenci istatistikleri (performance/students); Recharts ile izlenme trendleri (performance/reviews).
Manuel ödemeinstructor.payouts: bakiye, requestPayout mutation, TR/Stripe Connect koşulları ve talep listesi.

Detaylı ödeme akışları için Stripe Connect, TR Payout ve Checkout & Webhooks sayfalarına bakın.

  • app/routes/instructor.create.tsx — Kurs oluşturma sihirbazı.
  • app/routes/instructor.payouts.tsx — Eğitmen ödemeler ve payout talebi.
  • app/routes/instructor.course.$slug.manage.curriculum.tsx — Müfredat ve video yükleme (Bunny).
  • app/routes/instructor.course.$slug.manage.*.tsx — Goals, setup, filming, landing, pricing.
  • app/lib/bunny-video-status.ts — Bunny video durumu; fetchBunnyVideoStatus, getBunnyVideoStatusKind.
  • app/lib/video-security.ts — generateSignedVideoUrl.
  • app/routes/api.lesson-resource-upload.ts — Ders kaynağı yükleme.