@datlv-trustshop/shopify-inapp-components 0.1.9
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.
- package/README.md +141 -0
- package/dist/components/AppList.d.ts +13 -0
- package/dist/components/AppList.js +64 -0
- package/dist/components/ArticleList.d.ts +20 -0
- package/dist/components/ArticleList.js +174 -0
- package/dist/components/ArticleSlide.d.ts +14 -0
- package/dist/components/ArticleSlide.js +151 -0
- package/dist/components/FooterBanner.d.ts +10 -0
- package/dist/components/FooterBanner.js +72 -0
- package/dist/components/GrowApps.d.ts +13 -0
- package/dist/components/GrowApps.js +213 -0
- package/dist/components/ImageLoading.d.ts +15 -0
- package/dist/components/ImageLoading.js +66 -0
- package/dist/components/PartnerList.d.ts +9 -0
- package/dist/components/PartnerList.js +102 -0
- package/dist/components/PopupBanner.d.ts +12 -0
- package/dist/components/PopupBanner.js +100 -0
- package/dist/components/TopBanner.d.ts +14 -0
- package/dist/components/TopBanner.js +31 -0
- package/dist/components/WhatsNew.d.ts +14 -0
- package/dist/components/WhatsNew.js +258 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.js +9 -0
- package/dist/components/inlineStyles.d.ts +110 -0
- package/dist/components/inlineStyles.js +114 -0
- package/dist/components/styles.d.ts +152 -0
- package/dist/components/styles.js +158 -0
- package/dist/core/adapter.d.ts +6 -0
- package/dist/core/adapter.js +301 -0
- package/dist/core/engine.d.ts +33 -0
- package/dist/core/engine.js +176 -0
- package/dist/core/fetcher.d.ts +4 -0
- package/dist/core/fetcher.js +72 -0
- package/dist/core/global-manager.d.ts +99 -0
- package/dist/core/global-manager.js +315 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/useApps.d.ts +3 -0
- package/dist/hooks/useApps.js +18 -0
- package/dist/hooks/useArticles.d.ts +11 -0
- package/dist/hooks/useArticles.js +49 -0
- package/dist/hooks/useBanner.d.ts +5 -0
- package/dist/hooks/useBanner.js +22 -0
- package/dist/hooks/useDashboard.d.ts +11 -0
- package/dist/hooks/useDashboard.js +13 -0
- package/dist/hooks/useGrowApps.d.ts +10 -0
- package/dist/hooks/useGrowApps.js +14 -0
- package/dist/hooks/useTranslations.d.ts +3 -0
- package/dist/hooks/useTranslations.js +9 -0
- package/dist/hooks/useWhatsNew.d.ts +11 -0
- package/dist/hooks/useWhatsNew.js +34 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +16 -0
- package/dist/provider/DashboardProvider.d.ts +36 -0
- package/dist/provider/DashboardProvider.js +184 -0
- package/dist/translations/default.d.ts +2 -0
- package/dist/translations/default.js +27 -0
- package/dist/types/app.d.ts +14 -0
- package/dist/types/app.js +1 -0
- package/dist/types/article.d.ts +14 -0
- package/dist/types/article.js +1 -0
- package/dist/types/banner.d.ts +22 -0
- package/dist/types/banner.js +1 -0
- package/dist/types/dashboard.d.ts +42 -0
- package/dist/types/dashboard.js +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +6 -0
- package/dist/types/partner.d.ts +8 -0
- package/dist/types/partner.js +1 -0
- package/dist/types/product-update.d.ts +23 -0
- package/dist/types/product-update.js +1 -0
- package/dist/types/translations.d.ts +28 -0
- package/dist/types/translations.js +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ArticleItem } from "../types";
|
|
2
|
+
export interface UseArticlesResult {
|
|
3
|
+
articles: ArticleItem[];
|
|
4
|
+
loading: boolean;
|
|
5
|
+
getArticle: (id: string | number) => ArticleItem | undefined;
|
|
6
|
+
getArticlesByCategory: (category: string) => ArticleItem[];
|
|
7
|
+
getLatestArticles: (limit: number) => ArticleItem[];
|
|
8
|
+
}
|
|
9
|
+
export declare function useArticles(limit?: number): UseArticlesResult;
|
|
10
|
+
export declare function useLatestArticles(limit?: number): ArticleItem[];
|
|
11
|
+
export declare function useArticleCategories(): string[];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useDashboardContext } from "../provider/DashboardProvider";
|
|
3
|
+
export function useArticles(limit) {
|
|
4
|
+
const { engine, state } = useDashboardContext();
|
|
5
|
+
const articles = useMemo(() => {
|
|
6
|
+
if (!engine || !state.data)
|
|
7
|
+
return [];
|
|
8
|
+
return engine.getArticles(limit);
|
|
9
|
+
}, [engine, limit, state.data]);
|
|
10
|
+
const getArticle = (id) => {
|
|
11
|
+
return articles.find((article) => article.id === id);
|
|
12
|
+
};
|
|
13
|
+
const getArticlesByCategory = (category) => {
|
|
14
|
+
return articles.filter((article) => article.category === category);
|
|
15
|
+
};
|
|
16
|
+
const getLatestArticles = (limitCount) => {
|
|
17
|
+
const sorted = [...articles].sort((a, b) => {
|
|
18
|
+
const dateA = new Date(a.publishedDate || 0).getTime();
|
|
19
|
+
const dateB = new Date(b.publishedDate || 0).getTime();
|
|
20
|
+
return dateB - dateA;
|
|
21
|
+
});
|
|
22
|
+
return sorted.slice(0, limitCount);
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
articles,
|
|
26
|
+
loading: state.loading,
|
|
27
|
+
getArticle,
|
|
28
|
+
getArticlesByCategory,
|
|
29
|
+
getLatestArticles,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function useLatestArticles(limit = 5) {
|
|
33
|
+
const { articles, getLatestArticles } = useArticles();
|
|
34
|
+
return useMemo(() => {
|
|
35
|
+
return getLatestArticles(limit);
|
|
36
|
+
}, [articles, limit]);
|
|
37
|
+
}
|
|
38
|
+
export function useArticleCategories() {
|
|
39
|
+
const { articles } = useArticles();
|
|
40
|
+
return useMemo(() => {
|
|
41
|
+
const categories = new Set();
|
|
42
|
+
articles.forEach((article) => {
|
|
43
|
+
if (article.category) {
|
|
44
|
+
categories.add(article.category);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return Array.from(categories);
|
|
48
|
+
}, [articles]);
|
|
49
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BannerItem, BannerType } from "../types";
|
|
2
|
+
export declare function useBanners(type?: BannerType): BannerItem[];
|
|
3
|
+
export declare function useTopBanner(): BannerItem | null;
|
|
4
|
+
export declare function usePopupBanner(): BannerItem | null;
|
|
5
|
+
export declare function useFooterBanner(): BannerItem | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useDashboardContext } from "../provider/DashboardProvider";
|
|
3
|
+
export function useBanners(type) {
|
|
4
|
+
const { engine, state } = useDashboardContext();
|
|
5
|
+
return useMemo(() => {
|
|
6
|
+
if (!engine || !state.data)
|
|
7
|
+
return [];
|
|
8
|
+
return engine.getBanners(type);
|
|
9
|
+
}, [engine, type, state.data]);
|
|
10
|
+
}
|
|
11
|
+
export function useTopBanner() {
|
|
12
|
+
const banners = useBanners("top_banner");
|
|
13
|
+
return banners[0] || null;
|
|
14
|
+
}
|
|
15
|
+
export function usePopupBanner() {
|
|
16
|
+
const banners = useBanners("popup");
|
|
17
|
+
return banners[0] || null;
|
|
18
|
+
}
|
|
19
|
+
export function useFooterBanner() {
|
|
20
|
+
const banners = useBanners("footer_banner");
|
|
21
|
+
return banners[0] || null;
|
|
22
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DashboardData } from "../types";
|
|
2
|
+
export interface UseDashboardResult {
|
|
3
|
+
data: DashboardData | null;
|
|
4
|
+
loading: boolean;
|
|
5
|
+
error: Error | null;
|
|
6
|
+
refresh: () => Promise<void>;
|
|
7
|
+
isInitialized: boolean;
|
|
8
|
+
lastFetch: Date | null;
|
|
9
|
+
locale: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function useDashboard(): UseDashboardResult;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useDashboardContext } from "../provider/DashboardProvider";
|
|
2
|
+
export function useDashboard() {
|
|
3
|
+
const { state, refresh, isInitialized, locale } = useDashboardContext();
|
|
4
|
+
return {
|
|
5
|
+
data: state.data,
|
|
6
|
+
loading: state.loading,
|
|
7
|
+
error: state.error,
|
|
8
|
+
refresh,
|
|
9
|
+
isInitialized,
|
|
10
|
+
lastFetch: state.lastFetch,
|
|
11
|
+
locale,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to access grow apps data from the dashboard context
|
|
3
|
+
* @returns Object containing grow apps array and loading/error states
|
|
4
|
+
*/
|
|
5
|
+
export declare function useGrowApps(): {
|
|
6
|
+
apps: import("..").GrowApp[];
|
|
7
|
+
loading: boolean;
|
|
8
|
+
error: Error | null;
|
|
9
|
+
isEmpty: boolean;
|
|
10
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useDashboard } from "./useDashboard";
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access grow apps data from the dashboard context
|
|
4
|
+
* @returns Object containing grow apps array and loading/error states
|
|
5
|
+
*/
|
|
6
|
+
export function useGrowApps() {
|
|
7
|
+
const { data, loading, error } = useDashboard();
|
|
8
|
+
return {
|
|
9
|
+
apps: data?.grow_apps || [],
|
|
10
|
+
loading,
|
|
11
|
+
error,
|
|
12
|
+
isEmpty: !data?.grow_apps || data.grow_apps.length === 0,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useDashboardContext } from '../provider/DashboardProvider';
|
|
2
|
+
export function useTranslations() {
|
|
3
|
+
const context = useDashboardContext();
|
|
4
|
+
return context.translations;
|
|
5
|
+
}
|
|
6
|
+
export function useTranslation(key) {
|
|
7
|
+
const translations = useTranslations();
|
|
8
|
+
return translations[key];
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ProductUpdateItem } from "../types";
|
|
2
|
+
export interface UseWhatsNewResult {
|
|
3
|
+
updates: ProductUpdateItem[];
|
|
4
|
+
loading: boolean;
|
|
5
|
+
getUpdate: (id: string | number) => ProductUpdateItem | undefined;
|
|
6
|
+
getUpdatesByType: (type: "major" | "minor" | "patch") => ProductUpdateItem[];
|
|
7
|
+
getLatestUpdate: () => ProductUpdateItem | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function useWhatsNew(limit?: number): UseWhatsNewResult;
|
|
10
|
+
export declare function useLatestUpdate(): ProductUpdateItem | null;
|
|
11
|
+
export declare function useMajorUpdates(): ProductUpdateItem[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useDashboardContext } from "../provider/DashboardProvider";
|
|
3
|
+
export function useWhatsNew(limit) {
|
|
4
|
+
const { engine, state } = useDashboardContext();
|
|
5
|
+
const updates = useMemo(() => {
|
|
6
|
+
if (!engine || !state.data)
|
|
7
|
+
return [];
|
|
8
|
+
return engine.getWhatsNew(limit);
|
|
9
|
+
}, [engine, limit, state.data]);
|
|
10
|
+
const getUpdate = (id) => {
|
|
11
|
+
return updates.find((update) => update.id === id);
|
|
12
|
+
};
|
|
13
|
+
const getUpdatesByType = (type) => {
|
|
14
|
+
return updates.filter((update) => update.type === type);
|
|
15
|
+
};
|
|
16
|
+
const getLatestUpdate = () => {
|
|
17
|
+
return updates[0] || null;
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
updates,
|
|
21
|
+
loading: state.loading,
|
|
22
|
+
getUpdate,
|
|
23
|
+
getUpdatesByType,
|
|
24
|
+
getLatestUpdate,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function useLatestUpdate() {
|
|
28
|
+
const { updates } = useWhatsNew(1);
|
|
29
|
+
return updates[0] || null;
|
|
30
|
+
}
|
|
31
|
+
export function useMajorUpdates() {
|
|
32
|
+
const { getUpdatesByType } = useWhatsNew();
|
|
33
|
+
return getUpdatesByType("major");
|
|
34
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { DashboardEngine } from "./core/engine";
|
|
2
|
+
export { GlobalDashboardManager } from "./core/global-manager";
|
|
3
|
+
export { adaptDashboardData, adaptBanner, adaptApp, adaptArticle, adaptProductUpdate, } from "./core/adapter";
|
|
4
|
+
export { fetchDashboard, clearCache, getCacheSize } from "./core/fetcher";
|
|
5
|
+
export * from "./types";
|
|
6
|
+
export { DashboardProvider, DashboardContext, useDashboardContext, } from "./provider/DashboardProvider";
|
|
7
|
+
export type { DashboardProviderProps, DashboardContextValue, } from "./provider/DashboardProvider";
|
|
8
|
+
export * from "./hooks";
|
|
9
|
+
export * from "./components";
|
|
10
|
+
export type { SDKTranslations } from './types/translations';
|
|
11
|
+
export { defaultTranslations } from './translations/default';
|
|
12
|
+
export { useTranslations, useTranslation } from './hooks/useTranslations';
|
|
13
|
+
import { DashboardEngine } from "./core/engine";
|
|
14
|
+
declare const _default: {
|
|
15
|
+
DashboardEngine: typeof DashboardEngine;
|
|
16
|
+
DashboardProvider: import("react").FC<import("./provider/DashboardProvider").DashboardProviderProps>;
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { DashboardEngine } from "./core/engine";
|
|
2
|
+
export { GlobalDashboardManager } from "./core/global-manager";
|
|
3
|
+
export { adaptDashboardData, adaptBanner, adaptApp, adaptArticle, adaptProductUpdate, } from "./core/adapter";
|
|
4
|
+
export { fetchDashboard, clearCache, getCacheSize } from "./core/fetcher";
|
|
5
|
+
export * from "./types";
|
|
6
|
+
export { DashboardProvider, DashboardContext, useDashboardContext, } from "./provider/DashboardProvider";
|
|
7
|
+
export * from "./hooks";
|
|
8
|
+
export * from "./components";
|
|
9
|
+
export { defaultTranslations } from './translations/default';
|
|
10
|
+
export { useTranslations, useTranslation } from './hooks/useTranslations';
|
|
11
|
+
import { DashboardEngine } from "./core/engine";
|
|
12
|
+
import { DashboardProvider } from "./provider/DashboardProvider";
|
|
13
|
+
export default {
|
|
14
|
+
DashboardEngine,
|
|
15
|
+
DashboardProvider,
|
|
16
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
import { DashboardEngine } from "../core/engine";
|
|
3
|
+
import { DashboardData, DashboardConfig, DashboardState } from "../types";
|
|
4
|
+
import { SDKTranslations } from "../types/translations";
|
|
5
|
+
export interface DashboardContextValue {
|
|
6
|
+
engine: DashboardEngine;
|
|
7
|
+
state: DashboardState;
|
|
8
|
+
refresh: () => Promise<void>;
|
|
9
|
+
isInitialized: boolean;
|
|
10
|
+
locale: string;
|
|
11
|
+
translations: Required<SDKTranslations>;
|
|
12
|
+
}
|
|
13
|
+
export declare const DashboardContext: React.Context<DashboardContextValue | null>;
|
|
14
|
+
export declare const useDashboardContext: () => DashboardContextValue;
|
|
15
|
+
export interface DashboardProviderProps {
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
config: DashboardConfig;
|
|
18
|
+
locale?: string;
|
|
19
|
+
translations?: SDKTranslations;
|
|
20
|
+
autoInit?: boolean;
|
|
21
|
+
autoRefreshOnLocaleChange?: boolean;
|
|
22
|
+
onError?: (error: Error) => void;
|
|
23
|
+
onLoad?: (data: DashboardData) => void;
|
|
24
|
+
onLocaleChange?: (newLocale: string, oldLocale: string) => void;
|
|
25
|
+
onFallbackUsed?: (requested: string, actual: string) => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* DashboardProvider - Lightweight provider that connects to the global manager
|
|
29
|
+
*
|
|
30
|
+
* Multiple providers can be used throughout the app and they will all share:
|
|
31
|
+
* - The same engine instance
|
|
32
|
+
* - The same data/cache
|
|
33
|
+
* - The same locale state
|
|
34
|
+
* - Deduplicated API calls
|
|
35
|
+
*/
|
|
36
|
+
export declare const DashboardProvider: React.FC<DashboardProviderProps>;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { createContext, useEffect, useState, useCallback, useMemo, useRef, } from "react";
|
|
3
|
+
import { GlobalDashboardManager } from "../core/global-manager";
|
|
4
|
+
import { defaultTranslations } from "../translations/default";
|
|
5
|
+
export const DashboardContext = createContext(null);
|
|
6
|
+
export const useDashboardContext = () => {
|
|
7
|
+
const context = React.useContext(DashboardContext);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error('useDashboardContext must be used within a DashboardProvider');
|
|
10
|
+
}
|
|
11
|
+
return context;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* DashboardProvider - Lightweight provider that connects to the global manager
|
|
15
|
+
*
|
|
16
|
+
* Multiple providers can be used throughout the app and they will all share:
|
|
17
|
+
* - The same engine instance
|
|
18
|
+
* - The same data/cache
|
|
19
|
+
* - The same locale state
|
|
20
|
+
* - Deduplicated API calls
|
|
21
|
+
*/
|
|
22
|
+
export const DashboardProvider = ({ children, config, locale, translations, autoInit = true, autoRefreshOnLocaleChange = true, onError, onLoad, onLocaleChange, onFallbackUsed, }) => {
|
|
23
|
+
const [state, setState] = useState({
|
|
24
|
+
data: null,
|
|
25
|
+
loading: false,
|
|
26
|
+
error: null,
|
|
27
|
+
lastFetch: null,
|
|
28
|
+
});
|
|
29
|
+
// Generate unique ID for this provider instance
|
|
30
|
+
const providerIdRef = useRef(`provider-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`);
|
|
31
|
+
// Track if we've called onLoad for this data
|
|
32
|
+
const lastDataRef = useRef(null);
|
|
33
|
+
const lastLocaleRef = useRef(locale || config.locale || "en");
|
|
34
|
+
// Get the global manager
|
|
35
|
+
const manager = useMemo(() => GlobalDashboardManager.getInstance(), []);
|
|
36
|
+
// Create config with current locale
|
|
37
|
+
const currentConfig = useMemo(() => ({
|
|
38
|
+
...config,
|
|
39
|
+
locale: locale || config.locale || "en",
|
|
40
|
+
}), [config, locale]);
|
|
41
|
+
// Register this provider
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const providerId = providerIdRef.current;
|
|
44
|
+
manager.registerProvider(providerId, currentConfig);
|
|
45
|
+
return () => {
|
|
46
|
+
manager.unregisterProvider(providerId);
|
|
47
|
+
};
|
|
48
|
+
}, [manager, currentConfig]);
|
|
49
|
+
// Subscribe to global state changes
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const providerId = providerIdRef.current;
|
|
52
|
+
const unsubscribe = manager.subscribe(providerId, (globalState) => {
|
|
53
|
+
setState(globalState);
|
|
54
|
+
// Handle callbacks
|
|
55
|
+
if (globalState.data && globalState.data !== lastDataRef.current) {
|
|
56
|
+
lastDataRef.current = globalState.data;
|
|
57
|
+
// Check for fallback usage
|
|
58
|
+
if (globalState.data.fallback_used && onFallbackUsed) {
|
|
59
|
+
onFallbackUsed(globalState.data.requested_locale || locale || "en", globalState.data.locale || "en");
|
|
60
|
+
}
|
|
61
|
+
if (onLoad) {
|
|
62
|
+
onLoad(globalState.data);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (globalState.error && onError) {
|
|
66
|
+
onError(globalState.error);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return unsubscribe;
|
|
70
|
+
}, [manager, locale, onError, onLoad, onFallbackUsed]);
|
|
71
|
+
// Handle locale changes
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (!locale)
|
|
74
|
+
return;
|
|
75
|
+
const currentLocale = manager.getCurrentLocale();
|
|
76
|
+
if (currentLocale !== locale) {
|
|
77
|
+
const oldLocale = lastLocaleRef.current;
|
|
78
|
+
lastLocaleRef.current = locale;
|
|
79
|
+
if (autoRefreshOnLocaleChange) {
|
|
80
|
+
manager.setLocale(locale).catch((error) => {
|
|
81
|
+
console.error('Failed to set locale:', error);
|
|
82
|
+
if (onError) {
|
|
83
|
+
onError(error instanceof Error ? error : new Error('Failed to set locale'));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Just update config without refresh
|
|
89
|
+
const engine = manager.getEngine();
|
|
90
|
+
if (engine) {
|
|
91
|
+
engine.updateLocale(locale);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (onLocaleChange) {
|
|
95
|
+
onLocaleChange(locale, oldLocale);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}, [locale, manager, autoRefreshOnLocaleChange, onLocaleChange, onError]);
|
|
99
|
+
// Auto-init on mount if requested
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (autoInit && !manager.isInitialized()) {
|
|
102
|
+
manager.init(currentConfig).catch((error) => {
|
|
103
|
+
console.error("Failed to auto-initialize dashboard:", error);
|
|
104
|
+
if (onError) {
|
|
105
|
+
onError(error instanceof Error
|
|
106
|
+
? error
|
|
107
|
+
: new Error("Failed to initialize dashboard"));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}, [autoInit, manager, currentConfig, onError]);
|
|
112
|
+
// Create refresh function
|
|
113
|
+
const refresh = useCallback(async () => {
|
|
114
|
+
try {
|
|
115
|
+
await manager.refresh();
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error("Failed to refresh dashboard:", error);
|
|
119
|
+
if (onError) {
|
|
120
|
+
onError(error instanceof Error
|
|
121
|
+
? error
|
|
122
|
+
: new Error("Failed to refresh dashboard"));
|
|
123
|
+
}
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}, [manager, onError]);
|
|
127
|
+
// Merge translations with defaults
|
|
128
|
+
const mergedTranslations = useMemo(() => {
|
|
129
|
+
if (!translations)
|
|
130
|
+
return defaultTranslations;
|
|
131
|
+
return {
|
|
132
|
+
whatsNew: {
|
|
133
|
+
...defaultTranslations.whatsNew,
|
|
134
|
+
...translations.whatsNew,
|
|
135
|
+
tabs: {
|
|
136
|
+
...defaultTranslations.whatsNew.tabs,
|
|
137
|
+
...translations.whatsNew?.tabs,
|
|
138
|
+
},
|
|
139
|
+
buttonViewAll: {
|
|
140
|
+
...defaultTranslations.whatsNew.buttonViewAll,
|
|
141
|
+
...translations.whatsNew?.buttonViewAll,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
growApps: {
|
|
145
|
+
...defaultTranslations.growApps,
|
|
146
|
+
...translations.growApps,
|
|
147
|
+
},
|
|
148
|
+
banner: {
|
|
149
|
+
...defaultTranslations.banner,
|
|
150
|
+
...translations.banner,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}, [translations]);
|
|
154
|
+
// Get engine from manager (might be null initially)
|
|
155
|
+
const engine = manager.getEngine();
|
|
156
|
+
// Create stable context value
|
|
157
|
+
const contextValue = useMemo(() => {
|
|
158
|
+
if (!engine)
|
|
159
|
+
return null;
|
|
160
|
+
return {
|
|
161
|
+
engine,
|
|
162
|
+
state,
|
|
163
|
+
refresh,
|
|
164
|
+
isInitialized: manager.isInitialized(),
|
|
165
|
+
locale: manager.getCurrentLocale(),
|
|
166
|
+
translations: mergedTranslations,
|
|
167
|
+
};
|
|
168
|
+
}, [engine, state, refresh, manager, mergedTranslations]);
|
|
169
|
+
// If engine not ready yet, we can still render children
|
|
170
|
+
// This allows components to mount even if engine isn't initialized
|
|
171
|
+
if (!contextValue) {
|
|
172
|
+
// Create a placeholder context that will update once engine is ready
|
|
173
|
+
const placeholderContext = {
|
|
174
|
+
engine: null, // Will be replaced when ready
|
|
175
|
+
state,
|
|
176
|
+
refresh,
|
|
177
|
+
isInitialized: false,
|
|
178
|
+
locale: manager.getCurrentLocale(),
|
|
179
|
+
translations: mergedTranslations,
|
|
180
|
+
};
|
|
181
|
+
return (_jsx(DashboardContext.Provider, { value: placeholderContext, children: children }));
|
|
182
|
+
}
|
|
183
|
+
return (_jsx(DashboardContext.Provider, { value: contextValue, children: children }));
|
|
184
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const defaultTranslations = {
|
|
2
|
+
whatsNew: {
|
|
3
|
+
title: "What's New",
|
|
4
|
+
tabs: {
|
|
5
|
+
article: "Articles",
|
|
6
|
+
productUpdate: "Product Updates",
|
|
7
|
+
},
|
|
8
|
+
buttonViewAll: {
|
|
9
|
+
article: "View all articles",
|
|
10
|
+
productUpdate: "View all updates",
|
|
11
|
+
},
|
|
12
|
+
noData: "No updates available",
|
|
13
|
+
},
|
|
14
|
+
growApps: {
|
|
15
|
+
title: "Grow faster with apps",
|
|
16
|
+
subtitle: "Discover powerful apps to enhance your store and boost your business",
|
|
17
|
+
exploreApps: "Explore apps",
|
|
18
|
+
install: "Install",
|
|
19
|
+
installed: "Installed",
|
|
20
|
+
dismiss: "Dismiss",
|
|
21
|
+
noData: "No apps available",
|
|
22
|
+
},
|
|
23
|
+
banner: {
|
|
24
|
+
learnMore: "Learn more",
|
|
25
|
+
dismiss: "Dismiss",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type AppGroup = "grow_faster" | "integration" | "marketing" | "analytics" | "other";
|
|
2
|
+
export interface AppItem {
|
|
3
|
+
id: string | number;
|
|
4
|
+
key: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
link: string;
|
|
9
|
+
group: AppGroup;
|
|
10
|
+
rating?: number;
|
|
11
|
+
installs?: number;
|
|
12
|
+
price?: string;
|
|
13
|
+
featured?: boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ArticleItem {
|
|
2
|
+
id: string | number;
|
|
3
|
+
title: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
content?: string;
|
|
6
|
+
thumbnail?: string;
|
|
7
|
+
imageUrl?: string;
|
|
8
|
+
link: string;
|
|
9
|
+
author?: string;
|
|
10
|
+
publishedDate?: string;
|
|
11
|
+
category?: string;
|
|
12
|
+
readTime?: number;
|
|
13
|
+
tags?: string[];
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type BannerType = "popup" | "top_banner" | "footer_banner";
|
|
2
|
+
export type OpenType = "new_tab" | "same_tab";
|
|
3
|
+
export interface BannerStyle {
|
|
4
|
+
backgroundColor?: string;
|
|
5
|
+
textColor?: string;
|
|
6
|
+
buttonColor?: string;
|
|
7
|
+
buttonTextColor?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BannerItem {
|
|
10
|
+
id: string | number;
|
|
11
|
+
type: BannerType;
|
|
12
|
+
title: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
image?: string;
|
|
15
|
+
icon?: string;
|
|
16
|
+
link: string;
|
|
17
|
+
linkText?: string;
|
|
18
|
+
openType: OpenType;
|
|
19
|
+
style?: BannerStyle;
|
|
20
|
+
priority?: number;
|
|
21
|
+
isActive?: boolean;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BannerItem } from "./banner";
|
|
2
|
+
import { AppItem, AppGroup } from "./app";
|
|
3
|
+
import { ArticleItem } from "./article";
|
|
4
|
+
import { ProductUpdateItem } from "./product-update";
|
|
5
|
+
import { PartnerItem } from "./partner";
|
|
6
|
+
export interface GrowApp {
|
|
7
|
+
id: string | number;
|
|
8
|
+
title: string;
|
|
9
|
+
content: string;
|
|
10
|
+
icon_url?: string;
|
|
11
|
+
imageUrl?: string;
|
|
12
|
+
button_text?: string;
|
|
13
|
+
button_get_app?: string;
|
|
14
|
+
app_url?: string;
|
|
15
|
+
get_app?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface DashboardData {
|
|
18
|
+
locale?: string;
|
|
19
|
+
requested_locale?: string;
|
|
20
|
+
fallback_used?: boolean;
|
|
21
|
+
banners: BannerItem[];
|
|
22
|
+
apps: Record<AppGroup, AppItem[]>;
|
|
23
|
+
articles: ArticleItem[];
|
|
24
|
+
whatsNew: ProductUpdateItem[];
|
|
25
|
+
grow_apps?: GrowApp[];
|
|
26
|
+
grow_apps_display_limit?: number;
|
|
27
|
+
partner_list?: PartnerItem[];
|
|
28
|
+
}
|
|
29
|
+
export interface DashboardConfig {
|
|
30
|
+
apiUrl: string;
|
|
31
|
+
locale?: string;
|
|
32
|
+
cacheTime?: number;
|
|
33
|
+
retryAttempts?: number;
|
|
34
|
+
retryDelay?: number;
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
export interface DashboardState {
|
|
38
|
+
data: DashboardData | null;
|
|
39
|
+
loading: boolean;
|
|
40
|
+
error: Error | null;
|
|
41
|
+
lastFetch: Date | null;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ProductUpdateItem {
|
|
2
|
+
id: string | number;
|
|
3
|
+
title: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
releaseDate?: string;
|
|
7
|
+
date_time?: string;
|
|
8
|
+
features?: string[];
|
|
9
|
+
improvements?: string[];
|
|
10
|
+
fixes?: string[];
|
|
11
|
+
link?: string;
|
|
12
|
+
imageUrl?: string;
|
|
13
|
+
image_url?: string;
|
|
14
|
+
type?: "major" | "minor" | "patch";
|
|
15
|
+
position?: number;
|
|
16
|
+
button_try_it_now?: string;
|
|
17
|
+
button_try_url?: string;
|
|
18
|
+
button_learn_more?: string;
|
|
19
|
+
button_learn_url?: string;
|
|
20
|
+
content?: {
|
|
21
|
+
text?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|