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

Data Flow — API’den UI’a Veri Akışı

Genel Akış

API (api.okul.com.tr)
    ↓ HTTP (utils/ApiClient.ts)
    ↓ [x-consumer-key + x-cid + Authorization headers]
Services (services/)
    ↓ TypeScript interfaces ile tip dönüşümü
Contexts (contexts/)
    ↓ React Context + useState/useCallback
Screen Components (app/(tabs)/)
    ↓ useCompany(), useSchool() hooks
UI render

Context Hiyerarşisi

_layout.tsx içinde iç içe geçmiş Context Provider’lar:

ThemeProvider
  └── CompanyProvider          ← Firma seçimi ve verisi
       └── TermsGuard          ← Kullanım şartları kontrolü
            └── SchoolProvider ← Okul seçimi ve verisi
                 └── NotificationProvider
                      └── Ekranlar

Kritik State Akışı: Firma → Okul → İçerik

  1. CompanyProvider: Giriş sonrası /customer/me/firms çağrısı → firma listesi yüklenir → tek firma varsa otomatik seçilir, birden fazla varsa CompanySelectionScreen gösterilir
  2. apiClient.setCustomerId(companyId) → tüm sonraki isteklere x-cid header’ı eklenir
  3. SchoolProvider: Seçili firmadan okullar yüklenir → tek okul varsa otomatik seçilir
  4. apiClient.setSchoolId(schoolId) (varsa) → lead/galeri filtresi
  5. Ekranlar useSchool().selectedSchool ve useCompany().company üzerinden veri okur

Auth State Akışı

app launch
  → AuthService.isAuthenticatedAsync()    ← expo-secure-store'dan token okur
  → token varsa: MainApp → AuthenticatedApp
  → token yoksa: AuthFlow (login ekranı)
  
login
  → AuthService.loginWithEmail() / verifyOTP()
  → apiClient.setAuthToken(token)          ← tüm isteklere Authorization header eklenir
  → setIsAuthenticated(true)               ← _layout.tsx state güncellemesi
  → CompanyProvider mount edilir
  
logout
  → AuthService.logout()                   ← fire-and-forget pattern (hızlı UI tepkisi)
  → notifyLogout() event → _layout setIsAuthenticated(false)
  → AsyncStorage + SecureStorage temizlenir

Cache Stratejisi

ApiClient 5 dakika TTL ile GET isteklerini cache’ler (max 100 kayıt). Cache anahtarı: url + headers kombinasyonu. getLeads(bypassCache: true) ile cache atlanabilir.