PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.7
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.7
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / src / admin / Render.js

Render.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.7, at src/admin/Render.js

205 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useCallback, useEffect, useState } from "@wordpress/element";
2 import { Toaster, toast } from "react-hot-toast";
3 import Header from "./components/layout/Header";
4 import "./style.scss";
5 import useGetOptions from "./hooks/getOptions";
6 import BlockPage from "./pages/blocks";
7 import QuickStart from "./pages/quick-start";
8 import Modules from "./pages/modules";
9 import SavedTemplate from "./pages/saved-template";
10 import "./editor.scss";
11 import LightToPro from "./pages/lite-to-pro";
12 import AboutUs from "./pages/about-us";
13 import SetupWizard from "./setup-wizard";
14 import "./setup-wizard/setup-wizard.scss";
15 import Settings from "./pages/Settings/Settings";
16 import Integrations from "./pages/integrations";
17
18 // Inject Crisp chat script
19 const initCrispChat = () => {
20 if (window.$crisp) {
21 return;
22 }
23 window.$crisp = [];
24 window.CRISP_WEBSITE_ID = "3770a55e-947f-424d-87b8-d93a86f2cd7b";
25 (function () {
26 const d = document;
27 const s = d.createElement("script");
28 s.src = "https://client.crisp.chat/l.js";
29 s.async = 1;
30 d.getElementsByTagName("head")[0].appendChild(s);
31 })();
32 };
33
34 const options = sp_pcp_block_settings.getOptions;
35 const modules = sp_pcp_block_settings?.modulesOptions;
36 const integrations = sp_pcp_block_settings?.integrationOptions;
37
38 const Render = () => {
39 const hashValue = window.location.hash.replace("#", "").split("=")[0];
40
41 const [blocksSettings, setBlocksSettings] = useState(options);
42 const [modulesOptions, setModulesOptions] = useState(modules);
43 const [integrationOptions, setIntegrationOptions] = useState(integrations);
44
45 const [page, setPage] = useState(hashValue ? hashValue : "quick-start");
46
47 // Store menu references in state to avoid unnecessary re-renders
48 const [menuRefs, setMenuRefs] = useState({ postMenu: null, allItems: null });
49
50 // Update menu references when needed
51 useEffect(() => {
52 const postMenu = document.querySelector("#menu-posts-sp_post_carousel .wp-submenu");
53 const allItems = postMenu?.querySelectorAll("li") || [];
54 setMenuRefs({ postMenu, allItems });
55 }, []);
56
57 // Stable callback for menu click handling
58 const postMenuAction = useCallback((e) => {
59 const currentItem = e.target.closest("li");
60 menuRefs.allItems?.forEach((element) => {
61 element.classList.remove("current");
62 });
63 currentItem?.classList.add("current");
64
65 setTimeout(() => {
66 setPage(window.location.hash.replace("#", ""));
67 }, 0);
68 }, [menuRefs.allItems]);
69
70 useEffect(() => {
71 // Extract base page name from page value (e.g., "settings" from "settings=advanced")
72 const basePageName = page.includes("=") ? page.split("=")[0] : page;
73 const pageLink = ["blocks", "savedTemplate", "settings", "lite-vs-pro"].includes(basePageName) ? basePageName : "pcp_help";
74
75 if (menuRefs.postMenu) {
76 const blocksMenuLi = menuRefs.postMenu.querySelector(`a[href$="${pageLink}"]`)?.closest("li");
77
78 if (blocksMenuLi) {
79 menuRefs.allItems?.forEach((element) => {
80 element.classList.remove("current");
81 });
82 blocksMenuLi.classList.add("current");
83 }
84 }
85
86 const recommendedPage = document.querySelector(".spspc-recommended-page");
87
88 if ("our-plugins" === page && recommendedPage) {
89 recommendedPage.style.display = "block";
90 }
91
92 if (menuRefs.postMenu) {
93 menuRefs.postMenu.addEventListener("click", postMenuAction);
94 }
95
96 return () => {
97 if (menuRefs.postMenu) {
98 menuRefs.postMenu.removeEventListener("click", postMenuAction);
99 }
100 };
101 }, [page, menuRefs.postMenu, menuRefs.allItems, postMenuAction]);
102
103 // Initialize Crisp chat
104 useEffect(() => {
105 initCrispChat();
106 }, []);
107
108 // Update hash when page changes (for pages with tab parameters like settings=advanced)
109 useEffect(() => {
110 if (page && page.includes("=")) {
111 window.location.hash = `#${page}`;
112 }
113 }, [page]);
114
115 const successMes = useGetOptions(blocksSettings, modulesOptions, integrationOptions);
116
117 const notify = (message, type = "success") => {
118 if (type === "success") {
119 toast.success(message, { style: { marginTop: "20px" } });
120 } else if (type === "error") {
121 toast.error(message, { style: { marginTop: "20px" } });
122 } else {
123 toast(message, { style: { marginTop: "20px" } });
124 }
125 };
126
127 const blockShowHideHandler = (block_name, type = "block-option") => {
128 const notifyChange = (name, currentValue, kind = "block") => {
129 if (successMes) {
130 notify(`The ${kind} has been ${currentValue ? "disabled" : "enabled"}`);
131 }
132 };
133
134 if (type === "block-option") {
135 const newData = blocksSettings?.map((item) =>
136 item.block_name === block_name ? { ...item, show: !item.show } : item
137 );
138 const findCurrentBlock = blocksSettings.find((block) => block.block_name === block_name);
139 notifyChange(block_name, findCurrentBlock?.show, "block");
140 setBlocksSettings(newData);
141 }
142
143 if (type === "modules-option") {
144 const moduleData = modulesOptions?.map((item) => {
145 return item.module_name === block_name ? { ...item, show: !item.show } : item;
146 });
147 const findCurrentModule = modulesOptions.find((item) => item.module_name === block_name);
148 notifyChange(block_name, findCurrentModule?.show, "module");
149 setModulesOptions(moduleData);
150 }
151
152 if (type === "integration-option") {
153 const integrationData = integrationOptions?.map((item) => {
154 return item.name === block_name ? { ...item, show: !item.show } : item;
155 });
156 const findCurrentIntegration = integrationOptions.find((item) => item.name === block_name);
157 notifyChange(block_name, findCurrentIntegration?.show, "integration");
158 setIntegrationOptions(integrationData);
159 }
160 };
161
162 const enabledSavedTemplate = modulesOptions?.some((item) => item.module_name === "saved-template" && item.show);
163
164 if (page === "setupwizard") {
165 return <SetupWizard
166 blocksSettings={blocksSettings}
167 modulesOptions={modulesOptions}
168 blockShowHideHandler={blockShowHideHandler}
169 />;
170 }
171
172 return (
173 <>
174 <Header setPage={setPage} page={page} modulesOptions={modulesOptions} />
175
176 <div className="sp-pcp-blocks-setting-wrapper">
177 {(page === "quick-start" || "" === page) && <QuickStart blocksSettings={blocksSettings} blockShowHideHandler={blockShowHideHandler} setPageAndHash={setPage} modulesOptions={modulesOptions} />}
178 {page === "blocks" && (
179 <BlockPage blocksSettings={blocksSettings} blockShowHideHandler={blockShowHideHandler} />
180 )}
181 {page === "modules" && (
182 <Modules modulesOptions={modulesOptions} blockShowHideHandler={blockShowHideHandler} />
183 )}
184 {page === "lite-vs-pro" && <LightToPro />}
185 {page === "about-us" && <AboutUs />}
186 {( page === "savedTemplate" && enabledSavedTemplate ) && <SavedTemplate />}
187 {page === "integrations" && <Integrations
188 integrationOptions={integrationOptions}
189 blockShowHideHandler={blockShowHideHandler}
190 />}
191 {(page === "settings" || page?.startsWith("settings=")) && (
192 <Settings
193 setPage={setPage}
194 initialTab={page?.includes("=") ? page.split("=")[1] : undefined}
195 />
196 )}
197 </div>
198
199 <Toaster position="top-right" reverseOrder={false} />
200 </>
201 );
202 };
203
204 export default Render;
205