Proje: Okul.com.tr CRM · Hub: Okul.com.tr CRM — Conventions

GenericListPage Bileşeni

src/components/common/GenericListPage.tsx

Props

interface GenericListPageProps<T> {
    data: { items: T[]; loading: boolean; error: string | null; totalItems: number; }
    columns: Column[];
    selectedColumns?: Column[];
    sort: SortState;
    search?: string;
    currentPage: number;
    pageCount: number;
    lastPage?: number;
    appliedFilters: Record<string, string>;
    displayFilters?: DisplayFilter[];
    filters?: GenericFilter[];
    isFilterSidebarOpen?: boolean;
    permissions?: ActionPermissions;
    viewRoute?: string;     // Detail sayfası route'u
    addRoute?: string;      // Yeni kayıt oluşturma route'u
    onSearch: (value: string) => void;
    onPageChange: (page: number) => void;
    onPageCountChange: (count: number) => void;
    onSort: (sort: SortState) => void;
    onFilterChange?: (filters: GenericFilter[]) => void;
    onFilterApply?: () => void;
    onFilterReset?: () => void;
    onFilterRemove?: (name: string) => void;
    onOpenFilterSidebar?: () => void;
    onCloseFilterSidebar?: () => void;
    onEdit: (item: T) => void;
    onDelete: (item: T) => void;
    onDuplicate?: (item: T) => void;
    onRowClick?: (item: T) => void;
    customActions?: (item: T) => React.ReactNode;
    emptyStateMessage?: string;
    title: string;
    description?: string;
}

Column Tanımı

interface Column {
    key: string;    // data property key
    label: string;  // başlık
    sortable?: boolean;
    render?: (value: any, item: T) => React.ReactNode;
}

Tarih Formatı

isDateString() ile ISO tarih string’leri tespit edilir ve formatDate() ile formatlanır — render fonksiyonu olmadan bile.

Sıralama İkonu

  • Sıralanmamış sortable kolon: ArrowUpDown (gri)
  • Aktif ASC: ArrowUp (primary renk)
  • Aktif DESC: ArrowDown (primary renk)

ActionPermissions ile Görünürlük

interface ActionPermissions {
    add?: string;
    edit?: string;
    delete?: string;
}

Permission yoksa action her zaman gösterilir. Permission varsa hasPermission() ile kontrol edilir.

Performance

GenericTable React.memo ile wrap edilmiş — sadece data/sort/columns değişince yeniden render eder. Parent’taki state değişiklikleri (filter sidebar açık/kapalı vb.) tabloyu yeniden render ettirmez.

customActions Kullanımı

customActions={(item) => (
    <Button size="sm" onClick={() => handleSpecialAction(item)}>
        Özel İşlem
    </Button>
)}