cleaner view for Blog
This commit is contained in:
@@ -21,136 +21,74 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
|
|||||||
const { articles, loading, error } = useArticles();
|
const { articles, loading, error } = useArticles();
|
||||||
const { currentUser } = useAuth();
|
const { currentUser } = useAuth();
|
||||||
|
|
||||||
const [selectedArticle, setSelectedArticle] = React.useState<number | null>(null);
|
const [ui, setUI] = React.useState({
|
||||||
const [showLogin, setShowLogin] = React.useState(false);
|
selectedArticle: null as number | null,
|
||||||
const [showRegister, setShowRegister] = React.useState(false);
|
view: "home" as View,
|
||||||
const [showProfile, setShowProfile] = React.useState(false);
|
});
|
||||||
const [showEditor, setShowEditor] = React.useState(false);
|
const show = (view: View) => {
|
||||||
|
setUI(prev => ({ ...prev, view }));
|
||||||
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
|
};
|
||||||
|
const openLogin = () => show("login");
|
||||||
|
const openRegister = () => show("register");
|
||||||
|
const openProfile = () => show("profile");
|
||||||
|
const openEditor = () => show("editor");
|
||||||
|
|
||||||
const handleSelectArticle = (index: number) => {
|
const openArticle = (index: number) => {
|
||||||
setSelectedArticle(index);
|
setUI({ selectedArticle: index, view: "article" });
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
};
|
|
||||||
const handleShowLogin = () => {
|
|
||||||
setShowLogin(true);
|
|
||||||
setShowRegister(false);
|
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
||||||
};
|
|
||||||
const handleShowRegister = () => {
|
|
||||||
setShowRegister(true);
|
|
||||||
setShowLogin(false);
|
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
||||||
};
|
|
||||||
const handleHideAuth = () => {
|
|
||||||
setShowLogin(false);
|
|
||||||
setShowRegister(false);
|
|
||||||
};
|
|
||||||
const handleShowProfile = () => {
|
|
||||||
setShowProfile(true);
|
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
||||||
};
|
|
||||||
const handleHideProfile = () => {
|
|
||||||
setShowProfile(false);
|
|
||||||
};
|
|
||||||
const handleShowEditor = () => {
|
|
||||||
setShowEditor(true);
|
|
||||||
};
|
|
||||||
const handleHideEditor = () => {
|
|
||||||
setShowEditor(false);
|
|
||||||
};
|
|
||||||
const handleArticleViewBack = () => setSelectedArticle(null);
|
|
||||||
const handleArticleEditorBack = () => {
|
|
||||||
handleHideEditor()
|
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// derive a single source of truth for view
|
const goHome = () => setUI({ selectedArticle: null, view: "home" });
|
||||||
const view: View = React.useMemo(() => {
|
|
||||||
if (selectedArticle !== null && !showEditor) return 'article';
|
|
||||||
if (showRegister) return 'register';
|
|
||||||
if (showLogin) return 'login';
|
|
||||||
if (showProfile) return 'profile';
|
|
||||||
if (showEditor) return 'editor';
|
|
||||||
return 'home';
|
|
||||||
}, [selectedArticle, showLogin, showRegister, showProfile, showEditor]);
|
|
||||||
|
|
||||||
// render function keeps JSX tidy
|
|
||||||
const renderView = () => {
|
const renderView = () => {
|
||||||
switch (view) {
|
switch (ui.view) {
|
||||||
case 'register':
|
case "login":
|
||||||
return <Register onBack={handleHideAuth} />;
|
return <Login onBack={goHome} onRegister={openRegister} />;
|
||||||
case 'login':
|
|
||||||
|
case "register":
|
||||||
|
return <Register onBack={goHome} />;
|
||||||
|
|
||||||
|
case "profile":
|
||||||
|
return <Profile onBack={goHome} />;
|
||||||
|
|
||||||
|
case "article":
|
||||||
return (
|
return (
|
||||||
<Login
|
<ArticleView
|
||||||
onBack={handleHideAuth}
|
article={articles[ui.selectedArticle!]}
|
||||||
onRegister={() => {
|
onBack={goHome}
|
||||||
handleShowRegister();
|
onEdit={openEditor}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'profile':
|
|
||||||
|
case "editor":
|
||||||
return (
|
return (
|
||||||
<Profile
|
<ArticleEditor
|
||||||
onBack={handleHideProfile}
|
article={ui.selectedArticle !== null ? articles[ui.selectedArticle] : null}
|
||||||
|
onBack={goHome}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'article':
|
|
||||||
if (selectedArticle == null || !articles[selectedArticle]) return null;
|
|
||||||
return <ArticleView
|
|
||||||
article={articles[selectedArticle]}
|
|
||||||
onBack={handleArticleViewBack}
|
|
||||||
onEdit={handleShowEditor}
|
|
||||||
/>;
|
|
||||||
case 'editor':
|
|
||||||
if (selectedArticle == null || !articles[selectedArticle])
|
|
||||||
return <ArticleEditor
|
|
||||||
onBack={handleArticleEditorBack}
|
|
||||||
/>
|
|
||||||
return <ArticleEditor
|
|
||||||
article={articles[selectedArticle] || null}
|
|
||||||
onBack={handleArticleEditorBack}
|
|
||||||
/>
|
|
||||||
case 'home':
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end', mb: 2, gap: 1 }}>
|
<Box sx={{ display: "flex", justifyContent: "flex-end", mb: 2, gap: 1 }}>
|
||||||
{!currentUser ? (
|
{!currentUser ? (
|
||||||
<>
|
<Button variant="outlined" onClick={openLogin}>Login</Button>
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={handleShowLogin}
|
|
||||||
>
|
|
||||||
Login
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button variant="outlined" onClick={openProfile}>
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={handleShowProfile}
|
|
||||||
>
|
|
||||||
{currentUser.username}
|
{currentUser.username}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button variant="contained" onClick={openEditor}>
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={handleShowEditor}
|
|
||||||
>
|
|
||||||
New Article
|
New Article
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<MainContent articles={articles} onSelectArticle={handleSelectArticle} />
|
<MainContent articles={articles} onSelectArticle={openArticle} />
|
||||||
<Latest
|
<Latest articles={articles} onSelectArticle={openArticle} />
|
||||||
articles={articles}
|
|
||||||
onSelectArticle={handleSelectArticle}
|
|
||||||
onLoadMore={async () => {}}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -210,13 +148,13 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
my: 4,
|
my: 4,
|
||||||
gap: 4,
|
gap: 4,
|
||||||
pb: view === 'home' ? 24 : 0,
|
pb: ui.view === 'home' ? 24 : 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{renderView()}
|
{renderView()}
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
{view === 'home' && (
|
{ui.view === 'home' && (
|
||||||
<Box
|
<Box
|
||||||
component="footer"
|
component="footer"
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export interface ArticleProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ArticleEditorProps {
|
export interface ArticleEditorProps {
|
||||||
article?: ArticleModel;
|
article?: ArticleModel | null;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user