URL handling both on navigation and when directly calling URL.
directly calling only works for Article ID
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import CssBaseline from '@mui/material/CssBaseline';
|
import CssBaseline from '@mui/material/CssBaseline';
|
||||||
import Container from '@mui/material/Container';
|
import Container from '@mui/material/Container';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
@@ -15,10 +16,17 @@ import Profile from './components/Profile';
|
|||||||
import { useArticles } from './providers/Article';
|
import { useArticles } from './providers/Article';
|
||||||
import { useAuth } from './providers/Author';
|
import { useAuth } from './providers/Author';
|
||||||
import { View, useViewRouter } from "./types/views";
|
import { View, useViewRouter } from "./types/views";
|
||||||
import { ArticlesModel } from "./types/models";
|
import { ArticleModel, ArticlesModel } from "./types/models";
|
||||||
import { ArticleViewProps, ArticleEditorProps } from "./types/props";
|
import { ArticleViewProps, ArticleEditorProps } from "./types/props";
|
||||||
|
|
||||||
function HomeView({ currentUser, open_login, open_profile, open_create, articles, openArticle }: any) {
|
function HomeView({
|
||||||
|
currentUser,
|
||||||
|
open_login,
|
||||||
|
open_profile,
|
||||||
|
open_create,
|
||||||
|
articles,
|
||||||
|
openArticle
|
||||||
|
}: any) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ display: "flex", justifyContent: "flex-end", mb: 2, gap: 1 }}>
|
<Box sx={{ display: "flex", justifyContent: "flex-end", mb: 2, gap: 1 }}>
|
||||||
@@ -47,10 +55,29 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
|
|||||||
const { currentUser } = useAuth();
|
const { currentUser } = useAuth();
|
||||||
|
|
||||||
const [ui, setUI] = React.useState({
|
const [ui, setUI] = React.useState({
|
||||||
selectedArticle: null as number | null,
|
selectedArticle: null as ArticleModel | null,
|
||||||
view: "home" as View,
|
view: "home" as View,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loading) return;
|
||||||
|
|
||||||
|
const path = window.location.pathname;
|
||||||
|
const parts = path.split('/').filter(Boolean);
|
||||||
|
|
||||||
|
if (parts[0] === 'articles' && parts[1]) {
|
||||||
|
const id = parts[1];
|
||||||
|
const article = articles.readById(id);
|
||||||
|
|
||||||
|
if (article) {
|
||||||
|
setUI({
|
||||||
|
selectedArticle: article,
|
||||||
|
view: 'article',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [loading]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
goBack,
|
goBack,
|
||||||
navigateToChildren,
|
navigateToChildren,
|
||||||
@@ -61,7 +88,7 @@ export default function Blog(props: { disableCustomTheme?: boolean }) {
|
|||||||
ui: any;
|
ui: any;
|
||||||
articles: ArticlesModel;
|
articles: ArticlesModel;
|
||||||
currentUser: any;
|
currentUser: any;
|
||||||
openArticle: (index: number) => void;
|
openArticle: (article: ArticleModel) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ViewComponentEntry<P> = {
|
type ViewComponentEntry<P> = {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import {ArticleModel} from "./models";
|
||||||
|
|
||||||
export type View =
|
export type View =
|
||||||
| "home"
|
| "home"
|
||||||
| "login"
|
| "login"
|
||||||
@@ -39,9 +41,31 @@ export const VIEW_TREE: Record<View, ViewNode> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const VIEW_URL: Record<View, (ui?: any) => string> = {
|
||||||
|
home: () => "/",
|
||||||
|
login: () => "/login",
|
||||||
|
register: () => "/register",
|
||||||
|
profile: () => "/profile",
|
||||||
|
create: () => "/create",
|
||||||
|
article: (ui) => `/articles/${ui.selectedArticle._id ?? ""}`,
|
||||||
|
editor: (ui) => `/articles/${ui.selectedArticle._id ?? ""}/edit`,
|
||||||
|
};
|
||||||
|
|
||||||
export function useViewRouter(setUI: any) {
|
export function useViewRouter(setUI: any) {
|
||||||
const navigate = (view: View) => {
|
const navigate = (
|
||||||
setUI((prev: any) => ({ ...prev, view }));
|
view: View,
|
||||||
|
nextState?: any
|
||||||
|
) => {
|
||||||
|
setUI((prev: any) => {
|
||||||
|
const newState = { ...prev, ...nextState, view };
|
||||||
|
|
||||||
|
// update URL
|
||||||
|
const url = VIEW_URL[view](newState);
|
||||||
|
window.history.pushState(newState, "", url);
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,8 +75,19 @@ export function useViewRouter(setUI: any) {
|
|||||||
if (parent) navigate(parent);
|
if (parent) navigate(parent);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openArticle = (i: number) => {
|
const openArticle = (article: ArticleModel) => {
|
||||||
setUI({ selectedArticle: i, view: "article" });
|
setUI((prev: any) => {
|
||||||
|
const newState = {
|
||||||
|
...prev,
|
||||||
|
selectedArticle: article,
|
||||||
|
view: "article",
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = `/articles/${article._id}`;
|
||||||
|
window.history.pushState(newState, "", url);
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user