diff --git a/src/blog/Blog.tsx b/src/blog/Blog.tsx
index 19f79e9..3b3e4f3 100644
--- a/src/blog/Blog.tsx
+++ b/src/blog/Blog.tsx
@@ -15,6 +15,32 @@ import Profile from './components/Profile';
import { useArticles } from './providers/Article';
import { useAuth } from './providers/Author';
import { View, useViewRouter } from "./types/views";
+import { ArticleModel } from "./types/models";
+import { ArticleViewProps, ArticleEditorProps } from "./types/props";
+
+function HomeView({ currentUser, open_login, open_profile, open_create, articles, openArticle }: any) {
+ return (
+ <>
+
+ {!currentUser ? (
+
+ ) : (
+ <>
+
+
+ >
+ )}
+
+
+
+
+ >
+ );
+}
export default function Blog(props: { disableCustomTheme?: boolean }) {
const { articles, loading, error } = useArticles();
@@ -27,72 +53,86 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
const {
goBack,
- openLogin,
- openRegister,
- openProfile,
- openCreate,
- openEditor,
+ navigateToChildren,
openArticle,
} = useViewRouter(setUI);
+ type RouterContext = {
+ ui: any;
+ articles: ArticleModel[];
+ currentUser: any;
+ openArticle: (index: number) => void;
+ };
+
+ type ViewComponentEntry
= {
+ component: React.ComponentType
;
+ extraProps?: (ctx: RouterContext) => Partial
;
+ };
+
+ const VIEW_COMPONENTS: Record> = {
+ home: {
+ component: HomeView,
+ },
+
+ login: {
+ component: Login,
+ },
+
+ register: {
+ component: Register,
+ },
+
+ profile: {
+ component: Profile,
+ },
+
+ article: {
+ component: ArticleView,
+ extraProps: ({ ui, articles }) => ({
+ article: articles[ui.selectedArticle!],
+ }) satisfies Partial,
+ },
+
+ editor: {
+ component: ArticleEditor,
+ extraProps: ({ ui, articles }) => ({
+ article: ui.selectedArticle !== null ? articles[ui.selectedArticle] : null,
+ }) satisfies Partial,
+ },
+
+ create: {
+ component: ArticleEditor,
+ extraProps: () => ({
+ article: null,
+ }) satisfies Partial,
+ },
+ };
+
+
const renderView = () => {
- switch (ui.view) {
- case "login":
- return goBack(ui.view)} onRegister={openRegister} />;
+ const entry = VIEW_COMPONENTS[ui.view];
+ const ViewComponent = entry.component;
- case "register":
- return goBack(ui.view)} />;
+ const childNav = navigateToChildren(ui.view);
- case "profile":
- return goBack(ui.view)} />;
+ const ctx: RouterContext = {
+ ui,
+ articles,
+ currentUser,
- case "article":
- return (
- goBack(ui.view)}
- onEdit={openEditor}
- />
- );
+ openArticle,
+ };
- case "editor":
- return (
- goBack(ui.view)}
- />
- );
+ const extraProps = entry.extraProps ? entry.extraProps(ctx) : {};
- case "create":
- return (
- goBack(ui.view)}
- />
- );
-
- default:
- return (
- <>
-
- {!currentUser ? (
-
- ) : (
- <>
-
-
- >
- )}
-
-
-
-
- >
- );
- }
+ return (
+ goBack(ui.view)}
+ {...extraProps}
+ />
+ );
};
if (loading) {
diff --git a/src/blog/components/Article/ArticleView.tsx b/src/blog/components/Article/ArticleView.tsx
index 0823822..47b2a24 100644
--- a/src/blog/components/Article/ArticleView.tsx
+++ b/src/blog/components/Article/ArticleView.tsx
@@ -5,7 +5,7 @@ import { styled } from '@mui/material/styles';
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
import EditRoundedIcon from '@mui/icons-material/EditRounded';
import { ArticleMeta } from "../ArticleMeta";
-import { ArticleProps } from '../../types/props';
+import { ArticleViewProps } from '../../types/props';
import {useAuth} from "../../providers/Author";
const ArticleContainer = styled(Box)(({ theme }) => ({
@@ -28,10 +28,12 @@ const CoverImage = styled('img')({
export default function ArticleView({
article,
onBack,
- onEdit,
-}: ArticleProps) {
+ open_editor,
+}: ArticleViewProps) {
const { currentUser } = useAuth();
+ const onEdit = open_editor;
+
return (
Promise; // optional async callback
}
-export interface ArticleProps {
+export interface ArticleViewProps {
article: ArticleModel;
onBack: () => void;
- onEdit: () => void;
+ open_editor?: () => void; // optional because home → article must still work
}
+
export interface ArticleEditorProps {
article?: ArticleModel | null;
onBack: () => void;
diff --git a/src/blog/types/views.ts b/src/blog/types/views.ts
index d805787..b36c3de 100644
--- a/src/blog/types/views.ts
+++ b/src/blog/types/views.ts
@@ -1,4 +1,3 @@
-// types.ts
export type View =
| "home"
| "login"
@@ -40,17 +39,16 @@ export const VIEW_TREE: Record = {
},
};
-export function useViewRouter(setUI: React.Dispatch) {
+export function useViewRouter(setUI: any) {
const navigate = (view: View) => {
setUI((prev: any) => ({ ...prev, view }));
window.scrollTo({ top: 0, behavior: "smooth" });
};
- const goBack = (currentView: View) => {
- const parent = VIEW_TREE[currentView].parent;
- if (parent) {
- setUI((prev: any) => ({ ...prev, view: parent }));
- }
+ // auto back logic from parent
+ const goBack = (view: View) => {
+ const parent = VIEW_TREE[view].parent;
+ if (parent) navigate(parent);
};
const openArticle = (i: number) => {
@@ -58,14 +56,17 @@ export function useViewRouter(setUI: React.Dispatch) {
window.scrollTo({ top: 0, behavior: "smooth" });
};
- return {
- navigate,
- goBack,
- openLogin: () => navigate("login"),
- openRegister: () => navigate("register"),
- openProfile: () => navigate("profile"),
- openCreate: () => navigate("create"),
- openEditor: () => navigate("editor"),
- openArticle,
+ // auto child navigators from children[]
+ const navigateToChildren = (view: View) => {
+ const node = VIEW_TREE[view];
+ const funcs: Record void> = {};
+
+ node.children?.forEach((child) => {
+ funcs[`open_${child}`] = () => navigate(child);
+ });
+
+ return funcs;
};
+
+ return { navigate, goBack, openArticle, navigateToChildren };
}