PluginProbe
Extendify / 3.1.0
Extendify v3.1.0
3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 0.7.0 All 126 releases
extendify / src / HelpCenter / hooks / useRouter.js

useRouter.js in Extendify 3.1.0, at src/HelpCenter/hooks/useRouter.js

116 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { routes as aiRoutes } from '@help-center/pages/AIChat';
2 import { routes as dashRoutes } from '@help-center/pages/Dashboard';
3 import { routes as kbRoutes } from '@help-center/pages/KnowledgeBase';
4 import { routes as tourRoutes } from '@help-center/pages/Tours';
5 import { safeParseJson } from '@shared/lib/parsing';
6 import { useActivityStore } from '@shared/state/activity';
7 import apiFetch from '@wordpress/api-fetch';
8 import { useCallback, useEffect } from '@wordpress/element';
9 import { create } from 'zustand';
10 import { createJSONStorage, devtools, persist } from 'zustand/middleware';
11
12 const pages = [...dashRoutes, ...kbRoutes, ...tourRoutes, ...aiRoutes];
13
14 const initialState = {
15 history: [],
16 viewedPages: [],
17 current: null,
18 };
19
20 const state = (set, get) => ({
21 ...initialState,
22 // initialize the state with default values
23 ...(safeParseJson(window.extHelpCenterData.userData.routerData)?.state ?? {}),
24 goBack: () => {
25 if (get().history.length < 2) return;
26 const nextPage = get().history[1];
27 useActivityStore.getState().incrementActivity(`hc-${nextPage.slug}-back`);
28 set((state) => ({
29 history: state.history.slice(1),
30 current: nextPage,
31 }));
32 },
33 setCurrent: (page) => {
34 if (!page) return;
35 // If history is the same, dont add (they pressed the same button)
36 if (get().history[0]?.slug === page.slug) return;
37 const state = get();
38 const lastViewedAt = new Date().toISOString();
39 const firstViewedAt = lastViewedAt;
40 const visited = state.viewedPages.find((a) => a.slug === page.slug);
41 const viewedPages = [
42 // Remove the page if it's already in the list
43 ...state.viewedPages.filter((a) => a.slug !== page.slug),
44 // Either add the page or update the count
45 visited
46 ? { ...visited, count: Number(visited.count) + 1, lastViewedAt }
47 : {
48 slug: page.slug,
49 firstViewedAt,
50 lastViewedAt,
51 count: 1,
52 },
53 ];
54 // Persist the detailed history to the server (don't wait for response)
55 apiFetch({
56 path: '/extendify/v1/help-center/router-data',
57 method: 'POST',
58 data: { state: { viewedPages } },
59 });
60
61 set({
62 history: [page, ...state.history].filter(Boolean),
63 current: page,
64 viewedPages,
65 });
66 },
67 reset: () => set({ ...initialState }),
68 });
69
70 const useRouterState = create(
71 persist(devtools(state, { name: 'Extendify Help Center Router' }), {
72 name: `extendify-help-center-router-${window.extSharedData.siteId}`,
73 storage: createJSONStorage(() => sessionStorage),
74 partialize: ({ history, current }) => {
75 // remove the component from the current page
76 return { history, current: { ...current, component: null } };
77 },
78 }),
79 );
80
81 export const useRouter = () => {
82 const { current, setCurrent, history, goBack, reset } = useRouterState();
83 const Component =
84 current?.component ??
85 pages.find((a) => a.slug === current?.slug)?.component ??
86 (() => null);
87
88 useEffect(() => {
89 if (current) return;
90 setCurrent(pages[0]);
91 }, [current, setCurrent]);
92 return {
93 current,
94 CurrentPage: useCallback(
95 () => (
96 <section aria-live="polite" className="h-full">
97 {/* Announce to SR on change */}
98 <h1 className="sr-only">{current?.title}</h1>
99 <Component />
100 </section>
101 ),
102 [current],
103 ),
104 navigateTo: (slug) => {
105 const page = pages.find((a) => a.slug === slug);
106 if (!page) return setCurrent(pages[0]);
107
108 useActivityStore.getState().incrementActivity(`hc-${page.slug}`);
109 setCurrent(page);
110 },
111 goBack,
112 history,
113 reset,
114 };
115 };
116