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

CRM Galeri DnD Pattern

Kullanılan Kütüphane

@dnd-kit/core + @dnd-kit/sortable — Events ve Achievements edit sayfalarında galeri sıralaması için.

GalleryItem Tipi

interface GalleryItem {
    id: string;             // unique key (media.id string veya temp path)
    type: 'existing' | 'new';
    media?: Media;          // API'den gelen mevcut medya
    tempPath?: string;      // Yeni yüklenen temp dosya path'i
    previewUrl?: string;    // Önizleme URL'i
}

DnD Setup

const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
);
 
// Drag end handler
const handleDragEnd = (event: DragEndEvent) => {
    const { active, over } = event;
    if (active.id !== over?.id) {
        setGalleryItems(items => {
            const oldIndex = items.findIndex(i => i.id === active.id);
            const newIndex = items.findIndex(i => i.id === over!.id);
            return arrayMove(items, oldIndex, newIndex);
        });
    }
};
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
    <SortableContext items={galleryItems.map(i => i.id)} strategy={rectSortingStrategy}>
        {galleryItems.map(item => <SortableGalleryItem key={item.id} item={item} />)}
    </SortableContext>
</DndContext>

SortableGalleryItem

useSortable hook’u ile drag handle ve transform CSS:

const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: item.id });
const style = { transform: CSS.Transform.toString(transform), transition };

GripVertical ikonu drag handle olarak.

Sıralama API’ye Gönderme

Save sırasında mevcut existing itemların yeni sırası:

const sortedMediaIds = galleryItems
    .filter(i => i.type === 'existing' && i.media?.id)
    .map((i, idx) => ({ id: i.media!.id, sort: idx + 1 }));
 
if (sortedMediaIds.length > 0) {
    await MediaService.sort({ role_id: MediaRoleId.EVENTS_ANNOUNCEMENT, items: sortedMediaIds });
}

ImageCropper Entegrasyonu

ImageCropper bileşeni yeni medya ekleme sırasında kullanılır — görsel yüklemeden önce kırpma imkânı.