Implement slide deletion and duplication functionality
- Add complete slide deletion with smart confirmation messages - Implement slide duplication that copies layout, content, and notes - Handle edge cases for navigation after deletion/duplication - Add proper slide order management and renumbering - Include comprehensive error handling and user feedback - Support deleting last slide, only slide, and middle slides - Navigate intelligently after operations (to duplicated slide, adjusted position after deletion) - Add improved confirmation dialogs with context-aware messaging - Integrate with existing presentation storage and state management - Replace placeholder TODO implementations with full functionality Features completed: ✅ User can delete slides from presentation ✅ User gets confirmation before slide deletion ✅ Slide order adjusts automatically ✅ User can duplicate existing slides copying layout and content ✅ Smart navigation maintains user context after operations ✅ Robust error handling with proper user feedback 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
79060f0945
commit
4ce9f225a6
@ -35,6 +35,7 @@
|
||||
- [x] User can add presentation notes to slide
|
||||
- [x] User can see miniature preview of slide live while editing
|
||||
- [x] User can save slide (auto-saves presentation)
|
||||
- [x] User can duplicate an existing slide copying it's layout and content.
|
||||
|
||||
### Edit Existing Slide
|
||||
- [x] User can click on existing slide to edit
|
||||
@ -43,6 +44,7 @@
|
||||
- [x] User can exit slide editing mode without saving changes in an obvious way
|
||||
- [x] User can edit presentation notes
|
||||
- [x] Changes auto-save to presentation
|
||||
- [ ] User can edit slide content without preview if desired by clicking inside content slot areas
|
||||
|
||||
### Remove Slide
|
||||
- [ ] User can delete slides from presentation
|
||||
@ -53,3 +55,8 @@
|
||||
- [ ] User can preview individual slides
|
||||
- [ ] User can view slides in presentation mode
|
||||
- [ ] User can navigate between slides in preview
|
||||
|
||||
### Slide Order Management
|
||||
- [ ] User can reorder slides via drag-and-drop
|
||||
- [ ] User can see slide order visually in editor
|
||||
- [ ] Slide order automatically saves when changed
|
||||
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate, Link } from 'react-router-dom';
|
||||
import type { Presentation } from '../../types/presentation';
|
||||
import type { Theme } from '../../types/theme';
|
||||
import { getPresentationById } from '../../utils/presentationStorage';
|
||||
import { getPresentationById, updatePresentation } from '../../utils/presentationStorage';
|
||||
import { getTheme } from '../../themes';
|
||||
import './PresentationEditor.css';
|
||||
|
||||
@ -88,16 +88,47 @@ export const PresentationEditor: React.FC = () => {
|
||||
const duplicateSlide = async (slideIndex: number) => {
|
||||
if (!presentation) return;
|
||||
|
||||
const slideToDuplicate = presentation.slides[slideIndex];
|
||||
if (!slideToDuplicate) return;
|
||||
|
||||
try {
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
|
||||
// TODO: Implement slide duplication
|
||||
console.log('Duplicate slide functionality to be implemented');
|
||||
alert('Slide duplication will be implemented next.');
|
||||
// Create a duplicate slide with new ID
|
||||
const duplicatedSlide = {
|
||||
...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
|
||||
setPresentation(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) {
|
||||
console.error('Error duplicating slide:', err);
|
||||
alert('Failed to duplicate slide');
|
||||
setError(err instanceof Error ? err.message : 'Failed to duplicate slide');
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
@ -106,20 +137,62 @@ export const PresentationEditor: React.FC = () => {
|
||||
const deleteSlide = async (slideIndex: number) => {
|
||||
if (!presentation) return;
|
||||
|
||||
if (!confirm('Are you sure you want to delete this slide?')) {
|
||||
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.`;
|
||||
}
|
||||
|
||||
if (!confirm(confirmMessage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
|
||||
// TODO: Implement slide deletion
|
||||
console.log('Delete slide functionality to be implemented');
|
||||
alert('Slide deletion will be implemented next.');
|
||||
// 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
|
||||
setPresentation(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) {
|
||||
console.error('Error deleting slide:', err);
|
||||
alert('Failed to delete slide');
|
||||
setError(err instanceof Error ? err.message : 'Failed to delete slide');
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user