diff --git a/src/blog/Blog.tsx b/src/blog/Blog.tsx
index 575aa4e..563ed96 100644
--- a/src/blog/Blog.tsx
+++ b/src/blog/Blog.tsx
@@ -6,6 +6,7 @@ import Button from '@mui/material/Button';
import AppTheme from '../shared-theme/AppTheme';
import MainContent from './components/MainContent';
import ArticleView from './components/Article/ArticleView';
+import ArticleEditor from './components/Article/ArticleEditor';
import Latest from './components/Latest';
import Footer from './components/Footer';
import Login from './components/Login';
@@ -14,7 +15,7 @@ import Profile from './components/Profile';
import { useArticles } from './providers/Article';
import { useAuth } from './providers/Author';
-type View = 'home' | 'login' | 'register' | 'article' | 'profile';
+type View = 'home' | 'login' | 'register' | 'article' | 'profile' | 'editor';
export default function Blog(props: { disableCustomTheme?: boolean }) {
const { articles, loading, error } = useArticles();
@@ -24,6 +25,7 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
const [showLogin, setShowLogin] = React.useState(false);
const [showRegister, setShowRegister] = React.useState(false);
const [showProfile, setShowProfile] = React.useState(false);
+ const [showEditor, setShowEditor] = React.useState(false);
const handleSelectArticle = (index: number) => {
setSelectedArticle(index);
@@ -53,6 +55,13 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
const handleHideProfile = () => {
setShowProfile(false);
};
+ const handleShowEditor = () => {
+ console.log("handleShowEditor")
+ setShowEditor(true);
+ };
+ const handleHideEditor = () => {
+ setShowEditor(false);
+ };
// derive a single source of truth for view
const view: View = React.useMemo(() => {
@@ -60,8 +69,9 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
if (showRegister) return 'register';
if (showLogin) return 'login';
if (showProfile) return 'profile';
+ if (showEditor) return 'editor';
return 'home';
- }, [selectedArticle, showLogin, showRegister, showProfile]);
+ }, [selectedArticle, showLogin, showRegister, showProfile, showEditor]);
// render function keeps JSX tidy
const renderView = () => {
@@ -86,6 +96,8 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
case 'article':
if (selectedArticle == null || !articles[selectedArticle]) return null;
return ;
+ case 'editor':
+ return
case 'home':
default:
return (
@@ -110,6 +122,13 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
>
{currentUser.username}
+
>
)}
diff --git a/src/blog/components/Article/ArticleEditor.tsx b/src/blog/components/Article/ArticleEditor.tsx
new file mode 100644
index 0000000..a53cac4
--- /dev/null
+++ b/src/blog/components/Article/ArticleEditor.tsx
@@ -0,0 +1,139 @@
+import * as React from 'react';
+import { Box, Typography, Divider, IconButton, Chip, TextField, Button } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
+import { ArticleMeta } from "../ArticleMeta";
+import { ArticleEditorProps } from '../../types/props';
+import ReactMarkdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
+
+const ArticleContainer = styled(Box)(({ theme }) => ({
+ maxWidth: '800px',
+ margin: '0 auto',
+ padding: theme.spacing(4),
+ [theme.breakpoints.down('sm')]: {
+ padding: theme.spacing(2),
+ },
+}));
+
+const CoverImage = styled('img')({
+ width: '100%',
+ height: 'auto',
+ borderRadius: '12px',
+ marginTop: '16px',
+ marginBottom: '24px',
+});
+
+export default function ArticleView({
+ article,
+ onBack,
+ author,
+}: ArticleEditorProps) {
+
+ const [title, setTitle] = React.useState(article?.title ?? "");
+ const [description, setDescription] = React.useState(article?.description ?? "");
+ const [tag, setTag] = React.useState(article?.tag ?? "");
+ const [img, setImg] = React.useState(article?.img ?? "");
+ const [content, setContent] = React.useState(article?.content ?? "");
+
+ return (
+
+ {/* BACK BUTTON */}
+
+
+
+
+ {/* TAG */}
+ setTag(e.target.value)}
+ sx={{ mb: 2 }}
+ />
+
+ {/* TITLE */}
+ setTitle(e.target.value)}
+ sx={{ mb: 3 }}
+ />
+
+
+
+ {/* COVER IMAGE URL */}
+ setImg(e.target.value)}
+ sx={{ mb: 2 }}
+ />
+
+ {/* COVER IMAGE PREVIEW */}
+ {img && }
+
+ {/* MARKDOWN EDITOR */}
+
+ Content
+
+ setContent(e.target.value)}
+ sx={{
+ '& textarea': {
+ fontFamily: 'monospace',
+ lineHeight: 1.6,
+ },
+ }}
+ />
+
+ {/* LIVE PREVIEW */}
+
+ Preview
+
+
+
+ {content}
+
+
+
+ {/* ACTIONS */}
+
+
+
+
+
+ );
+}
diff --git a/src/blog/types/props.ts b/src/blog/types/props.ts
index 5f3567a..2e43e3e 100644
--- a/src/blog/types/props.ts
+++ b/src/blog/types/props.ts
@@ -1,4 +1,4 @@
-import { ArticleModel } from "./models";
+import {ArticleModel, AuthorModel} from "./models";
import {styled} from "@mui/material/styles";
import Card from "@mui/material/Card";
@@ -13,6 +13,12 @@ export interface ArticleProps {
onBack: () => void;
}
+export interface ArticleEditorProps {
+ article: ArticleModel;
+ onBack: () => void;
+ author: AuthorModel;
+}
+
export interface ArticleMetaProps {
article: ArticleModel;
}