import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import type { Presentation, Slide } from '../types/presentation.ts'; import { updatePresentation } from '../utils/presentationStorage.ts'; import { loggers } from '../utils/logger.ts'; interface UseSlideOperationsProps { presentation: Presentation | null; presentationId: string; onPresentationUpdate: (presentation: Presentation) => void; onError: (error: string) => void; confirmDelete: (message: string) => Promise; } export const useSlideOperations = ({ presentation, presentationId, onPresentationUpdate, onError, confirmDelete }: UseSlideOperationsProps) => { const navigate = useNavigate(); const [saving, setSaving] = useState(false); const duplicateSlide = async (slideIndex: number) => { if (!presentation) return; const slideToDuplicate = presentation.slides[slideIndex]; if (!slideToDuplicate) return; try { setSaving(true); onError(''); // Create a duplicate slide with new ID const duplicatedSlide: Slide = { ...slideToDuplicate, id: `slide_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, order: slideIndex + 1 // Insert right after the original }; // Create updated presentation with the duplicated slide const updatedPresentation = { ...presentation }; const newSlides = [...presentation.slides]; // Insert the duplicated slide after the original newSlides.splice(slideIndex + 1, 0, duplicatedSlide); // Update slide order for all slides after the insertion point newSlides.forEach((slide, index) => { slide.order = index; }); updatedPresentation.slides = newSlides; // Save the updated presentation await updatePresentation(updatedPresentation); // Update local state onPresentationUpdate(updatedPresentation); // Navigate to the duplicated slide const newSlideNumber = slideIndex + 2; // +2 because we inserted after and slide numbers are 1-based navigate(`/presentations/${presentationId}/edit/slides/${newSlideNumber}`); } catch (err) { loggers.presentation.error('Failed to duplicate slide', err instanceof Error ? err : new Error(String(err))); onError(err instanceof Error ? err.message : 'Failed to duplicate slide'); } finally { setSaving(false); } }; const deleteSlide = async (slideIndex: number) => { if (!presentation) return; const slideToDelete = presentation.slides[slideIndex]; if (!slideToDelete) return; const slideNumber = slideIndex + 1; const totalSlides = presentation.slides.length; let confirmMessage = `Are you sure you want to delete slide ${slideNumber}?`; if (totalSlides === 1) { confirmMessage = `Are you sure you want to delete the only slide in this presentation? The presentation will be empty after deletion.`; } else { confirmMessage += ` This will remove the slide and renumber all subsequent slides. This action cannot be undone.`; } const confirmed = await confirmDelete(confirmMessage); if (!confirmed) { return; } try { setSaving(true); onError(''); // Create updated presentation with the slide removed const updatedPresentation = { ...presentation }; updatedPresentation.slides = presentation.slides.filter((_, index) => index !== slideIndex); // Update slide order for remaining slides updatedPresentation.slides.forEach((slide, index) => { slide.order = index; }); // Save the updated presentation await updatePresentation(updatedPresentation); // Update local state onPresentationUpdate(updatedPresentation); // Handle navigation after deletion const totalSlides = updatedPresentation.slides.length; if (totalSlides === 0) { // No slides left, stay on editor main view navigate(`/presentations/${presentationId}/edit`); } else { // Navigate to appropriate slide let newSlideIndex = slideIndex; if (slideIndex >= totalSlides) { // If we deleted the last slide, go to the new last slide newSlideIndex = totalSlides - 1; } // Navigate to the adjusted slide number const slideNumber = newSlideIndex + 1; navigate(`/presentations/${presentationId}/edit/slides/${slideNumber}`); } } catch (err) { loggers.presentation.error('Failed to delete slide', err instanceof Error ? err : new Error(String(err))); onError(err instanceof Error ? err.message : 'Failed to delete slide'); } finally { setSaving(false); } }; const reorderSlides = async (fromIndex: number, toIndex: number) => { if (!presentation || fromIndex === toIndex) return; try { setSaving(true); onError(''); // Create updated presentation with reordered slides const updatedPresentation = { ...presentation }; const newSlides = [...presentation.slides]; // Remove the slide from its current position const [movedSlide] = newSlides.splice(fromIndex, 1); // Insert it at the new position newSlides.splice(toIndex, 0, movedSlide); // Update slide order for all slides newSlides.forEach((slide, index) => { slide.order = index; }); updatedPresentation.slides = newSlides; // Save the updated presentation await updatePresentation(updatedPresentation); // Update local state onPresentationUpdate(updatedPresentation); } catch (err) { loggers.presentation.error('Failed to reorder slides', err instanceof Error ? err : new Error(String(err))); onError(err instanceof Error ? err.message : 'Failed to reorder slides'); } finally { setSaving(false); } }; return { duplicateSlide, deleteSlide, reorderSlides, saving }; };