feat: add modals to Cancel and Publish buttons in Editor
This commit is contained in:
BIN
public/derek.jpg
Normal file
BIN
public/derek.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 544 KiB |
@@ -230,4 +230,53 @@ form {
|
|||||||
width: 350px !important;
|
width: 350px !important;
|
||||||
margin: 0 auto !important;
|
margin: 0 auto !important;
|
||||||
contain: layout;
|
contain: layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enhanced visual styling with shadows */
|
||||||
|
/* PostCard component shadows */
|
||||||
|
.k-card {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.k-card:hover {
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Campfire theme shadow for cards */
|
||||||
|
.k-card {
|
||||||
|
box-shadow: 0 2px 8px rgba(237, 189, 125, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.k-card:hover {
|
||||||
|
box-shadow: 0 4px 16px rgba(237, 189, 125, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PanelBar component shadow */
|
||||||
|
.k-panelbar {
|
||||||
|
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Campfire theme shadow for PanelBar */
|
||||||
|
.k-panelbar {
|
||||||
|
box-shadow: 2px 0 12px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button component shadows */
|
||||||
|
.k-button {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.k-button:hover {
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Campfire theme shadow for buttons */
|
||||||
|
.k-button {
|
||||||
|
box-shadow: 0 2px 8px rgba(237, 189, 125, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.k-button:hover {
|
||||||
|
box-shadow: 0 4px 16px rgba(237, 189, 125, 0.3);
|
||||||
}
|
}
|
@@ -52,9 +52,35 @@ const CampfireAppBar = ({ isLoggedIn, onLogin, onDrawerToggle }) => {
|
|||||||
<AppBarSpacer style={{ width: 20 }} />
|
<AppBarSpacer style={{ width: 20 }} />
|
||||||
|
|
||||||
{isLoggedIn ? (
|
{isLoggedIn ? (
|
||||||
<Button look="flat" onClick={handleLogout}>
|
<>
|
||||||
Logout
|
<Button look="flat" onClick={handleLogout}>
|
||||||
</Button>
|
Logout
|
||||||
|
</Button>
|
||||||
|
<Avatar
|
||||||
|
rounded="full"
|
||||||
|
type="image"
|
||||||
|
style={{
|
||||||
|
marginLeft: "8px",
|
||||||
|
width: "48px !important",
|
||||||
|
height: "48px !important",
|
||||||
|
minWidth: "48px",
|
||||||
|
maxWidth: "48px",
|
||||||
|
minHeight: "48px",
|
||||||
|
maxHeight: "48px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/derek.jpg"
|
||||||
|
alt="Derek Seitz"
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
border: "2px solid #edbd7d",
|
||||||
|
borderRadius: "50%"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Avatar>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Link to="/login">
|
<Link to="/login">
|
||||||
<Button look="flat">Login</Button>
|
<Button look="flat">Login</Button>
|
||||||
|
50
src/components/Editor/UI/CancelModal.jsx
Normal file
50
src/components/Editor/UI/CancelModal.jsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// CancelModal.jsx
|
||||||
|
// Confirmation modal for canceling post editing
|
||||||
|
import React from 'react';
|
||||||
|
import { Dialog, DialogActionsBar } from '@progress/kendo-react-dialogs';
|
||||||
|
import { Button } from '@progress/kendo-react-buttons';
|
||||||
|
|
||||||
|
const CancelModal = ({ isVisible, onClose, onConfirm, hasUnsavedChanges }) => {
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
title="Cancel Editing"
|
||||||
|
onClose={onClose}
|
||||||
|
minWidth={400}
|
||||||
|
width={500}
|
||||||
|
style={{ borderRadius: '8px' }}
|
||||||
|
>
|
||||||
|
<div style={{ padding: '20px' }}>
|
||||||
|
{hasUnsavedChanges ? (
|
||||||
|
<>
|
||||||
|
<p style={{ margin: '0 0 16px 0', fontSize: '16px' }}>
|
||||||
|
You have unsaved changes.
|
||||||
|
</p>
|
||||||
|
<p style={{ margin: '0', fontSize: '14px', color: '#666' }}>
|
||||||
|
Are you sure you want to cancel? All unsaved changes will be lost.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<p style={{ margin: '0', fontSize: '16px' }}>
|
||||||
|
Are you sure you want to cancel editing?
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<DialogActionsBar>
|
||||||
|
<Button onClick={onClose}>
|
||||||
|
Continue Editing
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={onConfirm}
|
||||||
|
themeColor="primary"
|
||||||
|
look="outline"
|
||||||
|
>
|
||||||
|
{hasUnsavedChanges ? 'Discard Changes' : 'Cancel'}
|
||||||
|
</Button>
|
||||||
|
</DialogActionsBar>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CancelModal;
|
51
src/components/Editor/UI/PublishModal.jsx
Normal file
51
src/components/Editor/UI/PublishModal.jsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// PublishModal.jsx
|
||||||
|
// Confirmation modal for publishing posts
|
||||||
|
import React from 'react';
|
||||||
|
import { Dialog, DialogActionsBar } from '@progress/kendo-react-dialogs';
|
||||||
|
import { Button } from '@progress/kendo-react-buttons';
|
||||||
|
|
||||||
|
const PublishModal = ({ isVisible, onClose, onConfirm, postTitle }) => {
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
title="Publish Post"
|
||||||
|
onClose={onClose}
|
||||||
|
minWidth={400}
|
||||||
|
width={500}
|
||||||
|
style={{ borderRadius: '8px' }}
|
||||||
|
>
|
||||||
|
<div style={{ padding: '20px' }}>
|
||||||
|
<p style={{ margin: '0 0 16px 0', fontSize: '16px' }}>
|
||||||
|
Are you sure you want to publish this post?
|
||||||
|
</p>
|
||||||
|
{postTitle && (
|
||||||
|
<p style={{
|
||||||
|
margin: '0 0 16px 0',
|
||||||
|
fontSize: '14px',
|
||||||
|
fontStyle: 'italic',
|
||||||
|
color: '#666'
|
||||||
|
}}>
|
||||||
|
"{postTitle}"
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<p style={{ margin: '0', fontSize: '14px', color: '#666' }}>
|
||||||
|
This will make the post visible to your readers.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<DialogActionsBar>
|
||||||
|
<Button onClick={onClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={onConfirm}
|
||||||
|
themeColor="primary"
|
||||||
|
>
|
||||||
|
Publish Post
|
||||||
|
</Button>
|
||||||
|
</DialogActionsBar>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PublishModal;
|
@@ -1,15 +1,18 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
import { Button } from '@progress/kendo-react-buttons';
|
import { Button } from '@progress/kendo-react-buttons';
|
||||||
import { marked } from 'marked';
|
import { marked } from 'marked';
|
||||||
import MetadataEditor from '../components/Editor/MetadataEditor';
|
import MetadataEditor from '../components/Editor/MetadataEditor';
|
||||||
import WysiwygEditor from '../components/Editor/WysiwygEditor';
|
import WysiwygEditor from '../components/Editor/WysiwygEditor';
|
||||||
import MarkdownEditor from '../components/Editor/MarkdownEditor';
|
import MarkdownEditor from '../components/Editor/MarkdownEditor';
|
||||||
import EditorModeToggle from '../components/Editor/custom/EditorModeToggle';
|
import EditorModeToggle from '../components/Editor/custom/EditorModeToggle';
|
||||||
|
import PublishModal from '../components/Editor/UI/PublishModal';
|
||||||
|
import CancelModal from '../components/Editor/UI/CancelModal';
|
||||||
import { getPostBySlug } from '../data/postsCache';
|
import { getPostBySlug } from '../data/postsCache';
|
||||||
|
|
||||||
const EditorPage = React.forwardRef((props, ref) => {
|
const EditorPage = React.forwardRef((props, ref) => {
|
||||||
const { slug } = useParams();
|
const { slug } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
const [postData, setPostData] = useState(null);
|
const [postData, setPostData] = useState(null);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
@@ -22,6 +25,11 @@ const EditorPage = React.forwardRef((props, ref) => {
|
|||||||
{}
|
{}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Modal state management
|
||||||
|
const [showPublishModal, setShowPublishModal] = useState(false);
|
||||||
|
const [showCancelModal, setShowCancelModal] = useState(false);
|
||||||
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadPostData = async () => {
|
const loadPostData = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@@ -60,18 +68,31 @@ const EditorPage = React.forwardRef((props, ref) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handlePublish = () => {
|
const handlePublish = () => {
|
||||||
console.log('Publish clicked', { postData });
|
setShowPublishModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePublishConfirm = () => {
|
||||||
|
console.log('Publish confirmed', { postData });
|
||||||
|
setShowPublishModal(false);
|
||||||
// Demo functionality - would save and publish the post
|
// Demo functionality - would save and publish the post
|
||||||
|
navigate('/dashboard');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveDraft = () => {
|
const handleSaveDraft = () => {
|
||||||
console.log('Save Draft clicked', { postData });
|
console.log('Save Draft clicked', { postData });
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
// Demo functionality - would save as draft
|
// Demo functionality - would save as draft
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
console.log('Cancel clicked');
|
setShowCancelModal(true);
|
||||||
// Demo functionality - would navigate back to dashboard
|
};
|
||||||
|
|
||||||
|
const handleCancelConfirm = () => {
|
||||||
|
console.log('Cancel confirmed');
|
||||||
|
setShowCancelModal(false);
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
|
navigate('/dashboard');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Editor mode toggle handler
|
// Editor mode toggle handler
|
||||||
@@ -95,6 +116,13 @@ const EditorPage = React.forwardRef((props, ref) => {
|
|||||||
// Markdown change handler
|
// Markdown change handler
|
||||||
const handleMarkdownChange = (event) => {
|
const handleMarkdownChange = (event) => {
|
||||||
setMarkdownContent(event.target.value);
|
setMarkdownContent(event.target.value);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Content change handler for WYSIWYG editor
|
||||||
|
const handleContentChange = (newContent) => {
|
||||||
|
setContent(newContent);
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Splitter change handler
|
// Splitter change handler
|
||||||
@@ -119,7 +147,7 @@ const EditorPage = React.forwardRef((props, ref) => {
|
|||||||
{editMode === 'html' ? (
|
{editMode === 'html' ? (
|
||||||
<WysiwygEditor
|
<WysiwygEditor
|
||||||
content={content}
|
content={content}
|
||||||
onContentChange={setContent}
|
onContentChange={handleContentChange}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<MarkdownEditor
|
<MarkdownEditor
|
||||||
@@ -148,6 +176,21 @@ const EditorPage = React.forwardRef((props, ref) => {
|
|||||||
Publish
|
Publish
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Confirmation Modals */}
|
||||||
|
<PublishModal
|
||||||
|
isVisible={showPublishModal}
|
||||||
|
onClose={() => setShowPublishModal(false)}
|
||||||
|
onConfirm={handlePublishConfirm}
|
||||||
|
postTitle={postData?.title}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CancelModal
|
||||||
|
isVisible={showCancelModal}
|
||||||
|
onClose={() => setShowCancelModal(false)}
|
||||||
|
onConfirm={handleCancelConfirm}
|
||||||
|
hasUnsavedChanges={hasUnsavedChanges}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user