mirror of
				https://github.com/aykhans/slash-e.git
				synced 2025-10-31 00:49:59 +00:00 
			
		
		
		
	feat: add last visited path
This commit is contained in:
		| @@ -18,8 +18,8 @@ const Header: React.FC = () => { | |||||||
|   const [showAboutDialog, setShowAboutDialog] = useState<boolean>(false); |   const [showAboutDialog, setShowAboutDialog] = useState<boolean>(false); | ||||||
|   const profile = workspaceStore.profile; |   const profile = workspaceStore.profile; | ||||||
|   const isAdmin = currentUser.role === Role.ADMIN; |   const isAdmin = currentUser.role === Role.ADMIN; | ||||||
|   const shouldShowRouterSwitch = location.pathname === "/" || location.pathname === "/collections"; |   const shouldShowRouterSwitch = location.pathname === "/shortcuts" || location.pathname === "/collections"; | ||||||
|   const selectedSection = location.pathname === "/" ? "Shortcuts" : location.pathname === "/collections" ? "Collections" : "Memos"; |   const selectedSection = location.pathname === "/shortcuts" ? "Shortcuts" : location.pathname === "/collections" ? "Collections" : ""; | ||||||
|  |  | ||||||
|   const handleSignOutButtonClick = async () => { |   const handleSignOutButtonClick = async () => { | ||||||
|     await authServiceClient.signOut({}); |     await authServiceClient.signOut({}); | ||||||
| @@ -55,7 +55,7 @@ const Header: React.FC = () => { | |||||||
|                     <> |                     <> | ||||||
|                       <Link |                       <Link | ||||||
|                         className="w-full px-2 flex flex-row justify-start items-center text-left dark:text-gray-400 leading-8 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-800 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:opacity-60" |                         className="w-full px-2 flex flex-row justify-start items-center text-left dark:text-gray-400 leading-8 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-800 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:opacity-60" | ||||||
|                         to="/" |                         to="/shortcuts" | ||||||
|                         unstable_viewTransition |                         unstable_viewTransition | ||||||
|                       > |                       > | ||||||
|                         <Icon.SquareSlash className="w-5 h-auto mr-2 opacity-70" /> Shortcuts |                         <Icon.SquareSlash className="w-5 h-auto mr-2 opacity-70" /> Shortcuts | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import { Button, Input } from "@mui/joy"; | import { Button, Input } from "@mui/joy"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||||
|  | import useLocalStorage from "react-use/lib/useLocalStorage"; | ||||||
| import CollectionView from "@/components/CollectionView"; | import CollectionView from "@/components/CollectionView"; | ||||||
| import CreateCollectionDrawer from "@/components/CreateCollectionDrawer"; | import CreateCollectionDrawer from "@/components/CreateCollectionDrawer"; | ||||||
| import FilterView from "@/components/FilterView"; | import FilterView from "@/components/FilterView"; | ||||||
| @@ -14,6 +15,7 @@ interface State { | |||||||
|  |  | ||||||
| const CollectionDashboard: React.FC = () => { | const CollectionDashboard: React.FC = () => { | ||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|  |   const [, setLastVisited] = useLocalStorage<string>("lastVisited", "/shortcuts"); | ||||||
|   const loadingState = useLoading(); |   const loadingState = useLoading(); | ||||||
|   const shortcutStore = useShortcutStore(); |   const shortcutStore = useShortcutStore(); | ||||||
|   const collectionStore = useCollectionStore(); |   const collectionStore = useCollectionStore(); | ||||||
| @@ -30,6 +32,7 @@ const CollectionDashboard: React.FC = () => { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|  |     setLastVisited("/collections"); | ||||||
|     Promise.all([shortcutStore.fetchShortcutList(), collectionStore.fetchCollectionList()]).finally(() => { |     Promise.all([shortcutStore.fetchShortcutList(), collectionStore.fetchCollectionList()]).finally(() => { | ||||||
|       loadingState.setFinish(); |       loadingState.setFinish(); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -1,92 +1,20 @@ | |||||||
| import { Button, Input } from "@mui/joy"; | import { useEffect } from "react"; | ||||||
| import { useEffect, useState } from "react"; | import useLocalStorage from "react-use/lib/useLocalStorage"; | ||||||
| import { useTranslation } from "react-i18next"; | import useNavigateTo from "@/hooks/useNavigateTo"; | ||||||
| import CreateShortcutDrawer from "@/components/CreateShortcutDrawer"; |  | ||||||
| import FilterView from "@/components/FilterView"; |  | ||||||
| import Icon from "@/components/Icon"; |  | ||||||
| import ShortcutsContainer from "@/components/ShortcutsContainer"; |  | ||||||
| import ShortcutsNavigator from "@/components/ShortcutsNavigator"; |  | ||||||
| import ViewSetting from "@/components/ViewSetting"; |  | ||||||
| import useLoading from "@/hooks/useLoading"; |  | ||||||
| import { useShortcutStore, useUserStore, useViewStore } from "@/stores"; |  | ||||||
| import { getFilteredShortcutList, getOrderedShortcutList } from "@/stores/view"; |  | ||||||
|  |  | ||||||
| interface State { |  | ||||||
|   showCreateShortcutDrawer: boolean; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const Home: React.FC = () => { | const Home: React.FC = () => { | ||||||
|   const { t } = useTranslation(); |   const [lastVisited] = useLocalStorage<string>("lastVisited", "/shortcuts"); | ||||||
|   const loadingState = useLoading(); |   const navigateTo = useNavigateTo(); | ||||||
|   const currentUser = useUserStore().getCurrentUser(); |  | ||||||
|   const shortcutStore = useShortcutStore(); |  | ||||||
|   const viewStore = useViewStore(); |  | ||||||
|   const shortcutList = shortcutStore.getShortcutList(); |  | ||||||
|   const [state, setState] = useState<State>({ |  | ||||||
|     showCreateShortcutDrawer: false, |  | ||||||
|   }); |  | ||||||
|   const filter = viewStore.filter; |  | ||||||
|   const filteredShortcutList = getFilteredShortcutList(shortcutList, filter, currentUser); |  | ||||||
|   const orderedShortcutList = getOrderedShortcutList(filteredShortcutList, viewStore.order); |  | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     Promise.all([shortcutStore.fetchShortcutList()]).finally(() => { |     if (lastVisited === "/shortcuts" || lastVisited === "/collections") { | ||||||
|       loadingState.setFinish(); |       navigateTo(lastVisited); | ||||||
|     }); |     } else { | ||||||
|  |       navigateTo("/shortcuts"); | ||||||
|  |     } | ||||||
|   }, []); |   }, []); | ||||||
|  |  | ||||||
|   const setShowCreateShortcutDrawer = (show: boolean) => { |   return <></>; | ||||||
|     setState({ |  | ||||||
|       ...state, |  | ||||||
|       showCreateShortcutDrawer: show, |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   return ( |  | ||||||
|     <> |  | ||||||
|       <div className="mx-auto max-w-8xl w-full px-4 sm:px-6 md:px-12 pt-4 pb-6 flex flex-col justify-start items-start"> |  | ||||||
|         <ShortcutsNavigator /> |  | ||||||
|         <div className="w-full flex flex-row justify-between items-center mb-4"> |  | ||||||
|           <div className="flex flex-row justify-start items-center"> |  | ||||||
|             <Input |  | ||||||
|               className="w-32 mr-2" |  | ||||||
|               type="text" |  | ||||||
|               size="sm" |  | ||||||
|               placeholder={t("common.search")} |  | ||||||
|               startDecorator={<Icon.Search className="w-4 h-auto" />} |  | ||||||
|               endDecorator={<ViewSetting />} |  | ||||||
|               value={filter.search} |  | ||||||
|               onChange={(e) => viewStore.setFilter({ search: e.target.value })} |  | ||||||
|             /> |  | ||||||
|           </div> |  | ||||||
|           <div className="flex flex-row justify-end items-center"> |  | ||||||
|             <Button className="hover:shadow" variant="soft" size="sm" onClick={() => setShowCreateShortcutDrawer(true)}> |  | ||||||
|               <Icon.Plus className="w-5 h-auto" /> |  | ||||||
|               <span className="ml-0.5">{t("common.create")}</span> |  | ||||||
|             </Button> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|         <FilterView /> |  | ||||||
|         {loadingState.isLoading ? ( |  | ||||||
|           <div className="py-12 w-full flex flex-row justify-center items-center opacity-80 dark:text-gray-500"> |  | ||||||
|             <Icon.Loader className="mr-2 w-5 h-auto animate-spin" /> |  | ||||||
|             {t("common.loading")} |  | ||||||
|           </div> |  | ||||||
|         ) : orderedShortcutList.length === 0 ? ( |  | ||||||
|           <div className="py-16 w-full flex flex-col justify-center items-center text-gray-400"> |  | ||||||
|             <Icon.PackageOpen className="w-16 h-auto" strokeWidth="1" /> |  | ||||||
|             <p className="mt-4">No shortcuts found.</p> |  | ||||||
|           </div> |  | ||||||
|         ) : ( |  | ||||||
|           <ShortcutsContainer shortcutList={orderedShortcutList} /> |  | ||||||
|         )} |  | ||||||
|       </div> |  | ||||||
|  |  | ||||||
|       {state.showCreateShortcutDrawer && ( |  | ||||||
|         <CreateShortcutDrawer onClose={() => setShowCreateShortcutDrawer(false)} onConfirm={() => setShowCreateShortcutDrawer(false)} /> |  | ||||||
|       )} |  | ||||||
|     </> |  | ||||||
|   ); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export default Home; | export default Home; | ||||||
|   | |||||||
							
								
								
									
										95
									
								
								frontend/web/src/pages/ShortcutDashboard.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								frontend/web/src/pages/ShortcutDashboard.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | |||||||
|  | import { Button, Input } from "@mui/joy"; | ||||||
|  | import { useEffect, useState } from "react"; | ||||||
|  | import { useTranslation } from "react-i18next"; | ||||||
|  | import useLocalStorage from "react-use/lib/useLocalStorage"; | ||||||
|  | import CreateShortcutDrawer from "@/components/CreateShortcutDrawer"; | ||||||
|  | import FilterView from "@/components/FilterView"; | ||||||
|  | import Icon from "@/components/Icon"; | ||||||
|  | import ShortcutsContainer from "@/components/ShortcutsContainer"; | ||||||
|  | import ShortcutsNavigator from "@/components/ShortcutsNavigator"; | ||||||
|  | import ViewSetting from "@/components/ViewSetting"; | ||||||
|  | import useLoading from "@/hooks/useLoading"; | ||||||
|  | import { useShortcutStore, useUserStore, useViewStore } from "@/stores"; | ||||||
|  | import { getFilteredShortcutList, getOrderedShortcutList } from "@/stores/view"; | ||||||
|  |  | ||||||
|  | interface State { | ||||||
|  |   showCreateShortcutDrawer: boolean; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const ShortcutDashboard: React.FC = () => { | ||||||
|  |   const { t } = useTranslation(); | ||||||
|  |   const [, setLastVisited] = useLocalStorage<string>("lastVisited", "/shortcuts"); | ||||||
|  |   const loadingState = useLoading(); | ||||||
|  |   const currentUser = useUserStore().getCurrentUser(); | ||||||
|  |   const shortcutStore = useShortcutStore(); | ||||||
|  |   const viewStore = useViewStore(); | ||||||
|  |   const shortcutList = shortcutStore.getShortcutList(); | ||||||
|  |   const [state, setState] = useState<State>({ | ||||||
|  |     showCreateShortcutDrawer: false, | ||||||
|  |   }); | ||||||
|  |   const filter = viewStore.filter; | ||||||
|  |   const filteredShortcutList = getFilteredShortcutList(shortcutList, filter, currentUser); | ||||||
|  |   const orderedShortcutList = getOrderedShortcutList(filteredShortcutList, viewStore.order); | ||||||
|  |  | ||||||
|  |   useEffect(() => { | ||||||
|  |     setLastVisited("/shortcuts"); | ||||||
|  |     Promise.all([shortcutStore.fetchShortcutList()]).finally(() => { | ||||||
|  |       loadingState.setFinish(); | ||||||
|  |     }); | ||||||
|  |   }, []); | ||||||
|  |  | ||||||
|  |   const setShowCreateShortcutDrawer = (show: boolean) => { | ||||||
|  |     setState({ | ||||||
|  |       ...state, | ||||||
|  |       showCreateShortcutDrawer: show, | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       <div className="mx-auto max-w-8xl w-full px-4 sm:px-6 md:px-12 pt-4 pb-6 flex flex-col justify-start items-start"> | ||||||
|  |         <ShortcutsNavigator /> | ||||||
|  |         <div className="w-full flex flex-row justify-between items-center mb-4"> | ||||||
|  |           <div className="flex flex-row justify-start items-center"> | ||||||
|  |             <Input | ||||||
|  |               className="w-32 mr-2" | ||||||
|  |               type="text" | ||||||
|  |               size="sm" | ||||||
|  |               placeholder={t("common.search")} | ||||||
|  |               startDecorator={<Icon.Search className="w-4 h-auto" />} | ||||||
|  |               endDecorator={<ViewSetting />} | ||||||
|  |               value={filter.search} | ||||||
|  |               onChange={(e) => viewStore.setFilter({ search: e.target.value })} | ||||||
|  |             /> | ||||||
|  |           </div> | ||||||
|  |           <div className="flex flex-row justify-end items-center"> | ||||||
|  |             <Button className="hover:shadow" variant="soft" size="sm" onClick={() => setShowCreateShortcutDrawer(true)}> | ||||||
|  |               <Icon.Plus className="w-5 h-auto" /> | ||||||
|  |               <span className="ml-0.5">{t("common.create")}</span> | ||||||
|  |             </Button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |         <FilterView /> | ||||||
|  |         {loadingState.isLoading ? ( | ||||||
|  |           <div className="py-12 w-full flex flex-row justify-center items-center opacity-80 dark:text-gray-500"> | ||||||
|  |             <Icon.Loader className="mr-2 w-5 h-auto animate-spin" /> | ||||||
|  |             {t("common.loading")} | ||||||
|  |           </div> | ||||||
|  |         ) : orderedShortcutList.length === 0 ? ( | ||||||
|  |           <div className="py-16 w-full flex flex-col justify-center items-center text-gray-400"> | ||||||
|  |             <Icon.PackageOpen className="w-16 h-auto" strokeWidth="1" /> | ||||||
|  |             <p className="mt-4">No shortcuts found.</p> | ||||||
|  |           </div> | ||||||
|  |         ) : ( | ||||||
|  |           <ShortcutsContainer shortcutList={orderedShortcutList} /> | ||||||
|  |         )} | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |       {state.showCreateShortcutDrawer && ( | ||||||
|  |         <CreateShortcutDrawer onClose={() => setShowCreateShortcutDrawer(false)} onConfirm={() => setShowCreateShortcutDrawer(false)} /> | ||||||
|  |       )} | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default ShortcutDashboard; | ||||||
| @@ -5,6 +5,7 @@ import CollectionDashboard from "@/pages/CollectionDashboard"; | |||||||
| import CollectionSpace from "@/pages/CollectionSpace"; | import CollectionSpace from "@/pages/CollectionSpace"; | ||||||
| import Home from "@/pages/Home"; | import Home from "@/pages/Home"; | ||||||
| import NotFound from "@/pages/NotFound"; | import NotFound from "@/pages/NotFound"; | ||||||
|  | import ShortcutDashboard from "@/pages/ShortcutDashboard"; | ||||||
| import ShortcutDetail from "@/pages/ShortcutDetail"; | import ShortcutDetail from "@/pages/ShortcutDetail"; | ||||||
| import ShortcutSpace from "@/pages/ShortcutSpace"; | import ShortcutSpace from "@/pages/ShortcutSpace"; | ||||||
| import SignIn from "@/pages/SignIn"; | import SignIn from "@/pages/SignIn"; | ||||||
| @@ -34,6 +35,10 @@ const router = createBrowserRouter([ | |||||||
|             path: "/", |             path: "/", | ||||||
|             element: <Home />, |             element: <Home />, | ||||||
|           }, |           }, | ||||||
|  |           { | ||||||
|  |             path: "/shortcuts", | ||||||
|  |             element: <ShortcutDashboard />, | ||||||
|  |           }, | ||||||
|           { |           { | ||||||
|             path: "/collections", |             path: "/collections", | ||||||
|             element: <CollectionDashboard />, |             element: <CollectionDashboard />, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Steven
					Steven