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

ContentMediaPicker — Optimistic Upload Pattern

components/school-content/ContentMediaPicker.tsx — İçerik görsellerini yönetir.

İki Farklı Medya State

interface NewMediaItem {
  _uid: string;           // Client-side ID
  localUri: string;       // Cihaz local URI
  tempUrl: string | null; // Geçici yükleme URL (null = yükleniyor)
  isUploading: boolean;
}
 
interface ExistingMediaItem {
  id: number;             // API media ID
  url: string;            // CDN URL
  sort: number;
  isDeleting?: boolean;   // Siliniyor işareti
}

Yükleme Stratejisi

Edit mode: Seçilen görsel anında MediaService.uploadMedia() ile yüklenir. Başarılı upload sonrası existingMedia’ya taşınır.

Create mode: Görseller newMediaItems’da bekler. Kaydet butonuna basıldığında content oluşturulur sonra görseller yüklenir.

Ref ile Closure Sorunu Çözme

const newMediaRef = React.useRef(newMediaItems);
React.useEffect(() => { newMediaRef.current = newMediaItems; }, [newMediaItems]);

Async upload callback’lerinde stale closure sorununu önlemek için useRef ile güncel state takibi yapılır.

maxCount Kontrolü

totalCount = existingMedia.length + newMediaItems.length toplamı maxCount’u aşarsa yeni seçim engellenir.