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>
)}Related
- liste-sayfasi-pattern — useListFilters ile entegrasyon
- permission-sistemi — ActionPermissions detayları