@mohasinac/appkit 3.2.3 → 3.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -77,6 +77,10 @@ function useResponsiveDrawer(storageKey) {
|
|
|
77
77
|
setMobileOpen(false);
|
|
78
78
|
});
|
|
79
79
|
}, [isDesktop, storageKey]);
|
|
80
|
+
// Close only the mobile drawer — used on route change so desktop sidebar stays persistent.
|
|
81
|
+
const closeMobile = useCallback(() => {
|
|
82
|
+
startTransition(() => { setMobileOpen(false); });
|
|
83
|
+
}, []);
|
|
80
84
|
const toggle = useCallback(() => {
|
|
81
85
|
startTransition(() => {
|
|
82
86
|
if (isDesktop()) {
|
|
@@ -97,7 +101,7 @@ function useResponsiveDrawer(storageKey) {
|
|
|
97
101
|
registerNav({ open, close, toggle });
|
|
98
102
|
return () => unregisterNav();
|
|
99
103
|
}, [registerNav, unregisterNav, open, close, toggle]);
|
|
100
|
-
return { desktopOpen, mobileOpen, close, toggle };
|
|
104
|
+
return { desktopOpen, mobileOpen, close, closeMobile, toggle };
|
|
101
105
|
}
|
|
102
106
|
/** Filter nav groups by navConfig (enabled toggle) + requiredPermission. */
|
|
103
107
|
function filterGroups(groups, navConfig, permissions) {
|
|
@@ -117,7 +121,8 @@ export function DashboardLayoutClient({ variant, groups, permissions, activeHref
|
|
|
117
121
|
const pathname = usePathname();
|
|
118
122
|
const activeHref = explicitActiveHref ?? pathname ?? "";
|
|
119
123
|
const storageKey = `appkit:sidebar-open:${variant}`;
|
|
120
|
-
const { desktopOpen, mobileOpen, close, toggle } = useResponsiveDrawer(storageKey);
|
|
124
|
+
const { desktopOpen, mobileOpen, close, closeMobile, toggle } = useResponsiveDrawer(storageKey);
|
|
125
|
+
useEffect(() => { closeMobile(); }, [pathname, closeMobile]);
|
|
121
126
|
const { data: settings } = useSiteSettings();
|
|
122
127
|
const navConfig = settings?.navConfig;
|
|
123
128
|
const filteredGroups = filterGroups(groups, navConfig, permissions);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export declare const getHomepageSections: () => Promise<
|
|
1
|
+
export declare const getHomepageSections: () => Promise<import("../../../..").HomepageSectionDocument[]>;
|
|
2
2
|
export declare const getHeroCarouselSlides: () => Promise<never[] | import("../../../..").CarouselSlideDocument[]>;
|
|
3
3
|
/**
|
|
4
4
|
* One parallel fetch returning every piece of data the homepage sections need.
|
|
5
5
|
* Page components call this once; React.cache() deduplicates per request.
|
|
6
6
|
*/
|
|
7
7
|
export declare const getHomepageInitial: () => Promise<{
|
|
8
|
-
sections:
|
|
8
|
+
sections: import("../../../..").HomepageSectionDocument[];
|
|
9
9
|
carouselSlides: never[] | import("../../../..").CarouselSlideDocument[];
|
|
10
10
|
featuredProducts: never[] | import("../../../..").ProductDocument[];
|
|
11
11
|
activeAuctions: never[] | import("../../../..").ProductDocument[];
|
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import { cache } from "react";
|
|
2
|
-
import { homepageSectionsRepository, carouselRepository, productRepository, reviewRepository, blogRepository, eventRepository, categoriesRepository, } from "../../../../repositories";
|
|
2
|
+
import { homepageSectionsRepository, carouselRepository, productRepository, reviewRepository, blogRepository, eventRepository, categoriesRepository, siteSettingsRepository, } from "../../../../repositories";
|
|
3
3
|
import { HOMEPAGE_FEATURED_REVIEWS_LIMIT, HOMEPAGE_RECENT_BLOG_POSTS_LIMIT, } from "../../../shared/features/homepage/config";
|
|
4
|
+
/** Section types that require a feature flag to be enabled to show on the homepage. */
|
|
5
|
+
const SECTION_FEATURE_GATE = {
|
|
6
|
+
auctions: "auctions",
|
|
7
|
+
"pre-orders": "preOrders",
|
|
8
|
+
events: "events",
|
|
9
|
+
"event-raffles": "events",
|
|
10
|
+
"prize-draws": "events",
|
|
11
|
+
"blog-articles": "blog",
|
|
12
|
+
};
|
|
4
13
|
export const getHomepageSections = cache(async () => {
|
|
5
|
-
|
|
14
|
+
const [sections, settings] = await Promise.all([
|
|
15
|
+
homepageSectionsRepository.getEnabledSections().catch(() => []),
|
|
16
|
+
siteSettingsRepository.getSingleton().catch(() => null),
|
|
17
|
+
]);
|
|
18
|
+
const flags = settings?.featureFlags;
|
|
19
|
+
if (!flags)
|
|
20
|
+
return sections;
|
|
21
|
+
return sections.filter((s) => {
|
|
22
|
+
const flagKey = SECTION_FEATURE_GATE[s.type];
|
|
23
|
+
if (!flagKey)
|
|
24
|
+
return true;
|
|
25
|
+
return flags[flagKey] !== false;
|
|
26
|
+
});
|
|
6
27
|
});
|
|
7
28
|
export const getHeroCarouselSlides = cache(async () => {
|
|
8
29
|
return carouselRepository.getActiveSlides().catch(() => []);
|
|
@@ -12,8 +33,9 @@ export const getHeroCarouselSlides = cache(async () => {
|
|
|
12
33
|
* Page components call this once; React.cache() deduplicates per request.
|
|
13
34
|
*/
|
|
14
35
|
export const getHomepageInitial = cache(async () => {
|
|
15
|
-
const [
|
|
36
|
+
const [rawSections, settings, carouselSlides, featuredProducts, activeAuctions, activePreOrders, activeBrands, featuredReviews, recentBlogPosts, activeEvents, featuredCategories,] = await Promise.all([
|
|
16
37
|
homepageSectionsRepository.getEnabledSections().catch(() => []),
|
|
38
|
+
siteSettingsRepository.getSingleton().catch(() => null),
|
|
17
39
|
carouselRepository.getActiveSlides().catch(() => []),
|
|
18
40
|
productRepository.findFeatured().catch(() => []),
|
|
19
41
|
productRepository.findActiveAuctions().catch(() => []),
|
|
@@ -24,6 +46,15 @@ export const getHomepageInitial = cache(async () => {
|
|
|
24
46
|
eventRepository.listActive().catch(() => []),
|
|
25
47
|
categoriesRepository.getFeaturedCategories().catch(() => []),
|
|
26
48
|
]);
|
|
49
|
+
const flags = settings?.featureFlags;
|
|
50
|
+
const sections = flags
|
|
51
|
+
? rawSections.filter((s) => {
|
|
52
|
+
const flagKey = SECTION_FEATURE_GATE[s.type];
|
|
53
|
+
if (!flagKey)
|
|
54
|
+
return true;
|
|
55
|
+
return flags[flagKey] !== false;
|
|
56
|
+
})
|
|
57
|
+
: rawSections;
|
|
27
58
|
return {
|
|
28
59
|
sections,
|
|
29
60
|
carouselSlides,
|
|
@@ -26,6 +26,7 @@ import { SidebarLayout } from "./SidebarLayout";
|
|
|
26
26
|
import { TitleBar } from "./TitleBar";
|
|
27
27
|
import { BackToTop } from "./BackToTop";
|
|
28
28
|
import { useDashboardNav } from "./DashboardNavContext";
|
|
29
|
+
import { usePathname } from "next/navigation";
|
|
29
30
|
// Background defaults consumed by BackgroundRenderer — these are seed values
|
|
30
31
|
// written into siteSettings on first deploy and may be overridden at runtime.
|
|
31
32
|
// audit-hex-tokens-ok: seed defaults for siteSettings.theme.background
|
|
@@ -113,6 +114,8 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
|
|
|
113
114
|
// a single consumer-level QueryProvider is the correct architecture.
|
|
114
115
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
115
116
|
const [searchOpen, setSearchOpen] = useState(false);
|
|
117
|
+
const pathname = usePathname();
|
|
118
|
+
useEffect(() => { setSidebarOpen(false); }, [pathname]);
|
|
116
119
|
const { theme, toggleTheme } = useTheme();
|
|
117
120
|
const { closeNav: closeDashboardNav, hasNav: hasDashboardNav, toggleNav: toggleDashboardNav } = useDashboardNav();
|
|
118
121
|
const { state: bottomActionsState } = useBottomActionsContext();
|