avada-components-seoon 1.0.26 → 1.0.28
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 +159 -11
- package/dist/components/CrossAppBanner/index.d.ts +1 -34
- package/dist/components/CrossAppBanner/index.d.ts.map +1 -1
- package/dist/components/CrossAppBanner/index.js +83 -144
- package/dist/components/CrossAppBanner/index.js.map +1 -1
- package/dist/components/CrossAppBanner/types.d.ts +1 -8
- package/dist/components/CrossAppBanner/types.d.ts.map +1 -1
- package/dist/hooks/useCheckAppInstalled.d.ts +14 -0
- package/dist/hooks/useCheckAppInstalled.d.ts.map +1 -0
- package/dist/hooks/useCheckAppInstalled.js +35 -0
- package/dist/hooks/useCheckAppInstalled.js.map +1 -0
- package/dist/hooks/useFetchBannerData.d.ts +25 -0
- package/dist/hooks/useFetchBannerData.d.ts.map +1 -0
- package/dist/hooks/useFetchBannerData.js +41 -0
- package/dist/hooks/useFetchBannerData.js.map +1 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -14,6 +14,119 @@ npm install avada-components-seoon
|
|
|
14
14
|
|
|
15
15
|
## Components
|
|
16
16
|
|
|
17
|
+
### CrossAppBanner
|
|
18
|
+
|
|
19
|
+
A smart banner component that promotes other Avada apps to users. It automatically checks installation status and displays the highest priority non-installed app with a beautiful loading state.
|
|
20
|
+
|
|
21
|
+
#### Features
|
|
22
|
+
|
|
23
|
+
- ✨ Automatic installation status checking
|
|
24
|
+
- 🎯 Priority-based app display
|
|
25
|
+
- 💾 Remember dismissed banners per page
|
|
26
|
+
- 🔄 Loading skeleton during data fetching
|
|
27
|
+
- 📱 Responsive design with Shopify Polaris
|
|
28
|
+
- 🎨 Modern UI with smooth animations
|
|
29
|
+
|
|
30
|
+
#### Basic Usage
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { CrossAppBanner } from 'avada-components-seoon';
|
|
34
|
+
|
|
35
|
+
function App() {
|
|
36
|
+
return <CrossAppBanner shopDomain="your-store.myshopify.com" />;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Advanced Usage
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { CrossAppBanner } from 'avada-components-seoon';
|
|
44
|
+
|
|
45
|
+
function App() {
|
|
46
|
+
return (
|
|
47
|
+
<CrossAppBanner
|
|
48
|
+
shopDomain="your-store.myshopify.com"
|
|
49
|
+
clickInstallCallback={() => {
|
|
50
|
+
console.log('User clicked install button');
|
|
51
|
+
// Track analytics, show confirmation, etc.
|
|
52
|
+
}}
|
|
53
|
+
appIds={['avada-seo-suite', 'ai-product-copy', 'seoon-blog']}
|
|
54
|
+
urlJson="https://your-custom-banner-data-url.com/banners.json"
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### Props
|
|
61
|
+
|
|
62
|
+
| Prop | Type | Required | Default | Description |
|
|
63
|
+
| ---------------------- | ------------- | -------- | ----------- | ---------------------------------------------------------------- |
|
|
64
|
+
| `shopDomain` | `string` | Yes | - | The Shopify domain of the store (e.g., 'my-store.myshopify.com') |
|
|
65
|
+
| `clickInstallCallback` | `() => void` | No | - | Callback function triggered when user clicks the install button |
|
|
66
|
+
| `appIds` | `AppIdKeys[]` | No | All apps | Array of app IDs to display in priority order |
|
|
67
|
+
| `urlJson` | `string` | No | Default URL | Custom URL to fetch banner data from |
|
|
68
|
+
|
|
69
|
+
#### Available App IDs
|
|
70
|
+
|
|
71
|
+
You can specify which apps to promote using the `appIds` prop:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// SEOon Suite Apps
|
|
75
|
+
const SEOON_APPS = [
|
|
76
|
+
'avada-seo-suite', // Avada SEO Suite
|
|
77
|
+
'seoon-blog', // SEOon Blog
|
|
78
|
+
'ai-product-copy', // AI Product Copy Writer
|
|
79
|
+
'ap-speed-optimizer', // Speed Optimizer
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
// Other Avada Apps
|
|
83
|
+
const OTHER_APPS = [
|
|
84
|
+
'joy-loyalty', // Joy Loyalty
|
|
85
|
+
'chatty-ai', // Chatty AI
|
|
86
|
+
'gem-pages-landing', // Gem Pages Landing
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
// Example: Only show SEO-related apps
|
|
90
|
+
<CrossAppBanner shopDomain="store.myshopify.com" appIds={['avada-seo-suite', 'ai-product-copy']} />;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### How It Works
|
|
94
|
+
|
|
95
|
+
1. **Priority Check**: The component checks each app in the `appIds` array in order
|
|
96
|
+
2. **Installation Status**: For each app, it verifies if it's already installed on the store
|
|
97
|
+
3. **Display Logic**: Shows the first non-installed, non-dismissed app
|
|
98
|
+
4. **Loading State**: Displays a skeleton loader while fetching data
|
|
99
|
+
5. **Dismissal**: Users can dismiss the banner, and it won't show again on that page
|
|
100
|
+
6. **Persistence**: Dismissed state is saved in localStorage per page
|
|
101
|
+
|
|
102
|
+
#### Styling
|
|
103
|
+
|
|
104
|
+
The component uses Shopify Polaris components and includes default styles. The banner automatically adapts to your Polaris theme.
|
|
105
|
+
|
|
106
|
+
If you need custom styling, you can override the CSS classes:
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
.AC-CrossAppBanner {
|
|
110
|
+
/* Custom styles */
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.AC-CrossAppBanner__Thumbnail {
|
|
114
|
+
/* Customize thumbnail area */
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.AC-CrossAppBanner__Content {
|
|
118
|
+
/* Customize content area */
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.AC-CrossAppBanner__Install {
|
|
122
|
+
/* Customize install button area */
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.AC-CrossAppBanner__Close {
|
|
126
|
+
/* Customize close button */
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
17
130
|
### SeoScore
|
|
18
131
|
|
|
19
132
|
A component for displaying SEO performance metrics and issues for a Shopify store.
|
|
@@ -24,10 +137,9 @@ import { SeoScore } from 'avada-components-seoon';
|
|
|
24
137
|
function App() {
|
|
25
138
|
return (
|
|
26
139
|
<SeoScore
|
|
27
|
-
type="widget"
|
|
140
|
+
type="widget"
|
|
28
141
|
shop={{
|
|
29
142
|
shopifyDomain: 'my-store.myshopify.com',
|
|
30
|
-
// other shop properties...
|
|
31
143
|
}}
|
|
32
144
|
/>
|
|
33
145
|
);
|
|
@@ -36,26 +148,62 @@ function App() {
|
|
|
36
148
|
|
|
37
149
|
#### Props
|
|
38
150
|
|
|
39
|
-
| Prop
|
|
40
|
-
|
|
|
41
|
-
| type | `'widget' \| 'banner'` | No | `'widget'` | Display style of the SEO score |
|
|
42
|
-
| shop | `Shop` | Yes | - | Shop information object |
|
|
151
|
+
| Prop | Type | Required | Default | Description |
|
|
152
|
+
| ------ | ---------------------- | -------- | ---------- | ------------------------------ |
|
|
153
|
+
| `type` | `'widget' \| 'banner'` | No | `'widget'` | Display style of the SEO score |
|
|
154
|
+
| `shop` | `Shop` | Yes | - | Shop information object |
|
|
43
155
|
|
|
44
156
|
## TypeScript Support
|
|
45
157
|
|
|
46
|
-
This package is written in TypeScript and includes type definitions. You'll get
|
|
158
|
+
This package is written in TypeScript and includes full type definitions. You'll get complete type safety when using the components:
|
|
47
159
|
|
|
48
160
|
```tsx
|
|
49
|
-
import {
|
|
161
|
+
import { CrossAppBanner, type CrossAppBannerProps, type AppIdKeys } from 'avada-components-seoon';
|
|
50
162
|
|
|
51
163
|
// Props will be type-checked
|
|
52
|
-
const props:
|
|
53
|
-
|
|
164
|
+
const props: CrossAppBannerProps = {
|
|
165
|
+
shopDomain: 'my-store.myshopify.com',
|
|
166
|
+
appIds: ['avada-seo-suite', 'ai-product-copy'],
|
|
167
|
+
clickInstallCallback: () => console.log('Clicked'),
|
|
54
168
|
};
|
|
55
169
|
|
|
56
170
|
function App() {
|
|
57
|
-
return <
|
|
171
|
+
return <CrossAppBanner {...props} />;
|
|
58
172
|
}
|
|
173
|
+
|
|
174
|
+
// Use type helpers
|
|
175
|
+
const myApps: AppIdKeys[] = ['avada-seo-suite', 'seoon-blog'];
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Examples
|
|
179
|
+
|
|
180
|
+
### Show Only Specific Apps
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
<CrossAppBanner shopDomain="store.myshopify.com" appIds={['avada-seo-suite', 'ai-product-copy']} />
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### With Analytics Tracking
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
<CrossAppBanner
|
|
190
|
+
shopDomain="store.myshopify.com"
|
|
191
|
+
clickInstallCallback={() => {
|
|
192
|
+
// Track to Google Analytics
|
|
193
|
+
gtag('event', 'cross_app_banner_click', {
|
|
194
|
+
app_name: 'cross-promotion',
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Track to custom analytics
|
|
198
|
+
analytics.track('Banner Install Clicked');
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Custom Banner Data Source
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<CrossAppBanner shopDomain="store.myshopify.com" urlJson="https://cdn.example.com/custom-banners.json" />
|
|
59
207
|
```
|
|
60
208
|
|
|
61
209
|
## Contributing
|
|
@@ -1,39 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import './index.scss';
|
|
3
2
|
import { CrossAppBannerProps, CrossAppBannerComponent } from './types';
|
|
4
|
-
|
|
5
|
-
* CrossAppBanner Component
|
|
6
|
-
*
|
|
7
|
-
* A banner component that displays promotional content for other Avada apps.
|
|
8
|
-
* It checks the installation status of specified apps and shows the first non-installed app.
|
|
9
|
-
* Each app can be dismissed independently.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```tsx
|
|
13
|
-
* // Basic usage
|
|
14
|
-
* <CrossAppBanner
|
|
15
|
-
* shopDomain="your-store.myshopify.com"
|
|
16
|
-
* />
|
|
17
|
-
*
|
|
18
|
-
* // With custom callbacks
|
|
19
|
-
* <CrossAppBanner
|
|
20
|
-
* shopDomain="your-store.myshopify.com"
|
|
21
|
-
* clickInstallCallback={() => console.log('Install clicked')}
|
|
22
|
-
* />
|
|
23
|
-
*
|
|
24
|
-
* // With specific apps to check
|
|
25
|
-
* <CrossAppBanner
|
|
26
|
-
* shopDomain="your-store.myshopify.com"
|
|
27
|
-
* appIds={['avada-seo-suite', 'ai-product-copy']}
|
|
28
|
-
* />
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* @param props - Component props
|
|
32
|
-
* @param props.shopDomain - The shop domain to check app installation status
|
|
33
|
-
* @param props.clickInstallCallback - Callback function when user clicks install button
|
|
34
|
-
* @param props.appIds - List of app IDs to check in priority order, current support 'avada-seo-suite', 'seoon-blog', 'ai-product-copy', 'ap-speed-optimizer'
|
|
35
|
-
* @returns JSX.Element | null
|
|
36
|
-
*/
|
|
3
|
+
import './index.scss';
|
|
37
4
|
export declare const CrossAppBanner: CrossAppBannerComponent;
|
|
38
5
|
declare const _default: React.NamedExoticComponent<CrossAppBannerProps>;
|
|
39
6
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/CrossAppBanner/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/CrossAppBanner/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAuBnD,OAAO,EAEL,mBAAmB,EAGnB,uBAAuB,EAIxB,MAAM,SAAS,CAAC;AACjB,OAAO,cAAc,CAAC;AAwGtB,eAAO,MAAM,cAAc,EAAE,uBAoH5B,CAAC;;AAEF,wBAA0C"}
|
|
@@ -1,178 +1,117 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AppProvider, Button, LegacyCard, Text, Thumbnail } from '@shopify/polaris';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
2
|
import React, { useEffect, useState } from 'react';
|
|
4
|
-
import '
|
|
5
|
-
import { listCrossApps, listCrossAppsOutSideSeo } from '../../config/constants';
|
|
6
|
-
import { getAppIdByOrigin, getCheckInstalledProxyUrl, getProxyAccessToken, getUTMParams, } from '../../helpers/getProxyEndPoint';
|
|
7
|
-
import useFetchApi from '../../hooks/api/useFetchApi';
|
|
3
|
+
import { AppProvider, Button, LegacyCard, Text, Thumbnail, SkeletonBodyText, BlockStack, SkeletonDisplayText, } from '@shopify/polaris';
|
|
8
4
|
import { XIcon } from '@shopify/polaris-icons';
|
|
9
|
-
import {
|
|
5
|
+
import { v4 as uuidV4 } from 'uuid';
|
|
6
|
+
import { getAppIdByOrigin, getUTMParams, } from '../../helpers/getProxyEndPoint';
|
|
10
7
|
import { isEmpty } from '../../helpers/isEmpty';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
8
|
+
import useFetchBannerData from '../../hooks/useFetchBannerData';
|
|
9
|
+
import { APP_IDS, APP_ID_KEYS, APP_ID_KEYS_OUT_SIDE_SEO, } from './types';
|
|
10
|
+
import './index.scss';
|
|
11
|
+
import { useCheckAppInstalled } from '../../hooks/useCheckAppInstalled';
|
|
12
|
+
// Helper functions
|
|
13
|
+
const createInitialDismissedState = () => {
|
|
14
|
+
return Object.fromEntries(APP_ID_KEYS.map(key => [key, false]));
|
|
15
|
+
};
|
|
16
|
+
const createInitialInstalledState = () => {
|
|
17
|
+
return Object.fromEntries(Object.values(APP_IDS).map(value => [value, false]));
|
|
18
|
+
};
|
|
19
|
+
const getCurrentPagePath = () => {
|
|
20
|
+
const pathMatch = window.location.href.match(/https?:\/\/[^/]+(\/[^?]+)/);
|
|
21
|
+
return pathMatch ? pathMatch[1] : '';
|
|
22
|
+
};
|
|
23
|
+
const getStorageKey = (appId) => {
|
|
24
|
+
const pagePath = getCurrentPagePath();
|
|
25
|
+
const appOriginId = getAppIdByOrigin(window.location.origin);
|
|
26
|
+
return `cross-app-banner-dismissed-${appOriginId}-${pagePath}-${appId}`;
|
|
27
|
+
};
|
|
28
|
+
const checkIfAppInstalled = (currentAppId, data) => {
|
|
29
|
+
const isSeoOrBlogApp = currentAppId === 'avada-seo-suite' || currentAppId === 'seoon-blog';
|
|
30
|
+
return isSeoOrBlogApp ? data.userType === 'user' : !!data.isInstalled;
|
|
31
|
+
};
|
|
32
|
+
const BannerLoadingSkeleton = () => {
|
|
33
|
+
return (_jsx(AppProvider, { i18n: {}, children: _jsx(LegacyCard, { sectioned: true, children: _jsxs("div", { className: "AC-CrossAppBanner", style: { padding: '4px 0px' }, children: [_jsx("div", { className: "AC-CrossAppBanner__Thumbnail", children: _jsx("div", { style: { width: '40px', height: '40px', background: '#f4f6f8', borderRadius: '8px' } }) }), _jsx("div", { className: "AC-CrossAppBanner__Content", children: _jsxs(BlockStack, { gap: "400", children: [_jsx("div", { style: { width: '160px' }, children: _jsx(SkeletonBodyText, { lines: 1 }) }), _jsx(SkeletonBodyText, { lines: 2 })] }) }), _jsx("div", { className: "AC-CrossAppBanner__Install", children: _jsx(SkeletonDisplayText, { size: "small" }) })] }) }) }));
|
|
34
|
+
};
|
|
35
|
+
const BannerCard = ({ app, appId, isOutsideApp = false, onDismiss, onInstallClick, }) => {
|
|
36
|
+
const handleInstallClick = () => {
|
|
37
|
+
const url = isOutsideApp ? `${app.url}&utm_source=${getUTMParams(window.location.origin)}` : app.url;
|
|
38
|
+
window.open(`${url}&search_id=${uuidV4()}`);
|
|
39
|
+
onInstallClick?.();
|
|
40
|
+
};
|
|
41
|
+
return (_jsx(AppProvider, { i18n: {}, children: _jsx(LegacyCard, { sectioned: true, children: _jsxs("div", { className: "AC-CrossAppBanner", children: [_jsx("div", { className: "AC-CrossAppBanner__Thumbnail", children: _jsx(Thumbnail, { size: "small", source: app.image, alt: "" }) }), _jsxs("div", { className: "AC-CrossAppBanner__Content", children: [_jsx(Text, { variant: "headingMd", as: "strong", children: app.title }), _jsx("br", {}), app.description] }), _jsx("div", { className: "AC-CrossAppBanner__Install", children: _jsx(Button, { onClick: handleInstallClick, children: app.actionLabel }) }), _jsx("div", { className: "AC-CrossAppBanner__Close", children: _jsx(Button, { icon: XIcon, variant: "tertiary", onClick: () => onDismiss(appId) }) })] }) }) }));
|
|
42
|
+
};
|
|
43
|
+
export const CrossAppBanner = ({ shopDomain, clickInstallCallback, appIds = APP_ID_KEYS, urlJson = '', }) => {
|
|
44
|
+
const { bannerData, isLoadingBannerData } = useFetchBannerData({ url: urlJson });
|
|
45
45
|
const [isBannerDismissed, setIsBannerDismissed] = useState(false);
|
|
46
|
-
const [dismissedApps, setDismissedApps] = useState(
|
|
46
|
+
const [dismissedApps, setDismissedApps] = useState(createInitialDismissedState());
|
|
47
47
|
const [currentPriorityIndex, setCurrentPriorityIndex] = useState(0);
|
|
48
|
-
const [installedApps, setInstalledApps] = useState(
|
|
48
|
+
const [installedApps, setInstalledApps] = useState(createInitialInstalledState());
|
|
49
49
|
const [foundNonInstalledApp, setFoundNonInstalledApp] = useState(false);
|
|
50
|
-
// Check if any appIds are from outside SEO apps
|
|
51
50
|
const hasOutsideSeoApps = appIds.some(appId => APP_ID_KEYS_OUT_SIDE_SEO.includes(appId));
|
|
52
|
-
const getCurrentPagePath = () => {
|
|
53
|
-
const url = window.location.href;
|
|
54
|
-
const pathMatch = url.match(/https?:\/\/[^/]+(\/[^?]+)/);
|
|
55
|
-
return pathMatch ? pathMatch[1] : '';
|
|
56
|
-
};
|
|
57
|
-
const getStorageKey = (appId) => {
|
|
58
|
-
const pagePath = getCurrentPagePath();
|
|
59
|
-
const appOriginId = getAppIdByOrigin(window.location.origin);
|
|
60
|
-
return `cross-app-banner-dismissed-${appOriginId}-${pagePath}-${appId}`;
|
|
61
|
-
};
|
|
62
51
|
// Load dismissed apps from localStorage
|
|
63
52
|
useEffect(() => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const storedDismissed = localStorage.getItem(getStorageKey(appId));
|
|
68
|
-
if (storedDismissed === 'true') {
|
|
69
|
-
dismissed[appId] = true;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
setDismissedApps(dismissed);
|
|
73
|
-
};
|
|
74
|
-
loadDismissedApps();
|
|
53
|
+
const dismissed = createInitialDismissedState();
|
|
54
|
+
appIds.forEach(appId => localStorage.getItem(getStorageKey(appId)) === 'true' && (dismissed[appId] = true));
|
|
55
|
+
setDismissedApps(dismissed);
|
|
75
56
|
}, [appIds]);
|
|
76
57
|
// Get current app to check based on priority
|
|
77
58
|
const currentAppId = appIds[currentPriorityIndex];
|
|
78
|
-
const shouldCheckCurrentApp = currentAppId && !foundNonInstalledApp;
|
|
79
|
-
|
|
80
|
-
const {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
'X-SEO-Shop-Domain': shopDomain,
|
|
85
|
-
},
|
|
86
|
-
initLoad: false,
|
|
87
|
-
initLoading: false,
|
|
88
|
-
keepPreviousData: false,
|
|
89
|
-
onSuccess: data => {
|
|
90
|
-
return {
|
|
91
|
-
...data,
|
|
92
|
-
appId: currentAppId,
|
|
93
|
-
};
|
|
94
|
-
},
|
|
59
|
+
const shouldCheckCurrentApp = !!currentAppId && !foundNonInstalledApp;
|
|
60
|
+
const isDismissed = currentAppId ? localStorage.getItem(getStorageKey(currentAppId)) === 'true' : false;
|
|
61
|
+
const { installedData, isCheckingInstalled } = useCheckAppInstalled({
|
|
62
|
+
appId: currentAppId,
|
|
63
|
+
shopDomain,
|
|
64
|
+
shouldCheck: shouldCheckCurrentApp && !isDismissed,
|
|
95
65
|
});
|
|
96
|
-
// Effect to check
|
|
66
|
+
// Effect to handle installation check result
|
|
97
67
|
useEffect(() => {
|
|
98
|
-
if (shouldCheckCurrentApp)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
setCurrentPriorityIndex(prev => prev + 1);
|
|
106
|
-
}
|
|
68
|
+
if (!installedData || !shouldCheckCurrentApp || isDismissed)
|
|
69
|
+
return;
|
|
70
|
+
const isInstalled = checkIfAppInstalled(currentAppId, installedData);
|
|
71
|
+
setInstalledApps(prev => ({ ...prev, [APP_IDS[currentAppId]]: isInstalled }));
|
|
72
|
+
if (isInstalled) {
|
|
73
|
+
setCurrentPriorityIndex(prev => prev + 1);
|
|
74
|
+
return;
|
|
107
75
|
}
|
|
108
|
-
|
|
109
|
-
|
|
76
|
+
setFoundNonInstalledApp(true);
|
|
77
|
+
}, [installedData, currentAppId, shouldCheckCurrentApp, isDismissed]);
|
|
110
78
|
useEffect(() => {
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
const isInstalled = currentAppId === 'avada-seo-suite' || currentAppId === 'seoon-blog'
|
|
114
|
-
? data.userType === 'user'
|
|
115
|
-
: !!data.isInstalled;
|
|
116
|
-
newInstalledApps[APP_IDS[currentAppId]] = isInstalled;
|
|
117
|
-
setInstalledApps(newInstalledApps);
|
|
118
|
-
if (isInstalled) {
|
|
119
|
-
setCurrentPriorityIndex(prev => prev + 1);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
setFoundNonInstalledApp(true);
|
|
123
|
-
}
|
|
79
|
+
if (isDismissed && shouldCheckCurrentApp) {
|
|
80
|
+
setCurrentPriorityIndex(prev => prev + 1);
|
|
124
81
|
}
|
|
125
|
-
}, [
|
|
82
|
+
}, [isDismissed, shouldCheckCurrentApp]);
|
|
126
83
|
const handleDismiss = (appId) => {
|
|
127
84
|
localStorage.setItem(getStorageKey(appId), 'true');
|
|
128
85
|
setIsBannerDismissed(true);
|
|
129
86
|
};
|
|
130
|
-
const checking = loading;
|
|
131
87
|
const getFirstNonInstalledApp = () => {
|
|
132
|
-
if (isBannerDismissed)
|
|
88
|
+
if (isBannerDismissed || isEmpty(bannerData) || isLoadingBannerData)
|
|
133
89
|
return null;
|
|
134
90
|
if (hasOutsideSeoApps) {
|
|
135
91
|
const outsideSeoApp = appIds.find(appKey => APP_ID_KEYS_OUT_SIDE_SEO.includes(appKey) && !dismissedApps[appKey]);
|
|
136
|
-
if (outsideSeoApp) {
|
|
137
|
-
return
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (appIds.length > 0) {
|
|
141
|
-
const priorityApp = appIds.find(appKey => {
|
|
142
|
-
const key = appKey;
|
|
143
|
-
return !installedApps[APP_IDS[key]] && !dismissedApps[key];
|
|
144
|
-
});
|
|
145
|
-
if (priorityApp) {
|
|
146
|
-
return listCrossApps.find(app => APP_IDS[priorityApp] === app.key);
|
|
92
|
+
if (outsideSeoApp && bannerData.appOutSide?.length) {
|
|
93
|
+
return bannerData.appOutSide.find(app => app.key === outsideSeoApp) ?? null;
|
|
147
94
|
}
|
|
148
95
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const appId = Object.entries(APP_IDS).find(([_, value]) => value === app.key)?.[0];
|
|
152
|
-
return (!installedApps[app.key] && !dismissedApps[appId] && appIds.includes(appId));
|
|
96
|
+
const priorityApp = appIds.find((appKey) => {
|
|
97
|
+
return !installedApps[APP_IDS[appKey]] && !dismissedApps[appKey];
|
|
153
98
|
});
|
|
154
|
-
|
|
155
|
-
const appToShow = getFirstNonInstalledApp();
|
|
156
|
-
console.log('%c[Avada]%c Banner SEOon!', 'color: white; background: linear-gradient(90deg, #B7ECF5, #4CC9F0); padding: 2px 6px; border-radius: 4px;', 'color: #333; font-weight: bold;');
|
|
157
|
-
// Skip installation check for outside SEO apps
|
|
158
|
-
if (hasOutsideSeoApps) {
|
|
159
|
-
if (!appToShow || isBannerDismissed)
|
|
99
|
+
if (!priorityApp || !bannerData.appSeoon)
|
|
160
100
|
return null;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
clickInstallCallback();
|
|
166
|
-
}, children: appToShow.actionLabel }) }), _jsx("div", { className: 'AC-CrossAppBanner__Close', children: _jsx(Button, { icon: XIcon, variant: "tertiary", onClick: () => handleDismiss(currentAppIdToShow) }) })] }) }) }));
|
|
101
|
+
return bannerData.appSeoon.find(app => APP_IDS[priorityApp] === app.key) ?? null;
|
|
102
|
+
};
|
|
103
|
+
if (isLoadingBannerData || isCheckingInstalled) {
|
|
104
|
+
return _jsx(BannerLoadingSkeleton, {});
|
|
167
105
|
}
|
|
168
|
-
|
|
106
|
+
const appToShow = getFirstNonInstalledApp();
|
|
107
|
+
if (!appToShow || isBannerDismissed || isEmpty(bannerData)) {
|
|
169
108
|
return null;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
109
|
+
}
|
|
110
|
+
console.log('%c[Avada]%c Banner SEOon!', 'color: white; background: linear-gradient(90deg, #B7ECF5, #4CC9F0); padding: 2px 6px; border-radius: 4px;', 'color: #333; font-weight: bold;');
|
|
111
|
+
const currentAppIdToShow = hasOutsideSeoApps
|
|
112
|
+
? appToShow.key
|
|
113
|
+
: Object.entries(APP_IDS).find(([_, value]) => value === appToShow.key)?.[0];
|
|
114
|
+
return (_jsx(_Fragment, { children: _jsx(BannerCard, { app: appToShow, appId: currentAppIdToShow, isOutsideApp: hasOutsideSeoApps, onDismiss: handleDismiss, onInstallClick: clickInstallCallback }) }));
|
|
176
115
|
};
|
|
177
116
|
export default React.memo(CrossAppBanner);
|
|
178
117
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/CrossAppBanner/index.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/CrossAppBanner/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -42,14 +42,6 @@ export interface CheckInstalledResponse {
|
|
|
42
42
|
userType?: string;
|
|
43
43
|
appId?: AppIdKeys;
|
|
44
44
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Props for the CrossAppBanner component
|
|
47
|
-
* @interface CrossAppBannerProps
|
|
48
|
-
* @property {string} shopDomain - The shop domain to check app installation status
|
|
49
|
-
* @property {() => void} [clickInstallCallback] - Callback function when user clicks install button
|
|
50
|
-
* @property {string} [buttonContent] - Custom content for the install button
|
|
51
|
-
* @property {AppIdKeys[]} [appIds] - List of app IDs to check in priority order
|
|
52
|
-
*/
|
|
53
45
|
export interface CrossAppBannerProps {
|
|
54
46
|
/** The shop domain to check app installation status */
|
|
55
47
|
shopDomain: string;
|
|
@@ -59,6 +51,7 @@ export interface CrossAppBannerProps {
|
|
|
59
51
|
buttonContent?: string;
|
|
60
52
|
/** List of app IDs to check in priority order */
|
|
61
53
|
appIds?: AppIdKeys[];
|
|
54
|
+
urlJson?: string;
|
|
62
55
|
}
|
|
63
56
|
/**
|
|
64
57
|
* CrossAppBanner Component Type
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/CrossAppBanner/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,oBAAoB,CAAC;AACzC,eAAO,MAAM,QAAQ,eAAe,CAAC;AACrC,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,UAAU,cAAc,CAAC;AACtC,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD,eAAO,MAAM,WAAW,UAQvB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,eAAO,MAAM,wBAAwB,UAAuD,CAAC;AAE7F;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,MAAM,GACN,QAAQ,GACR,OAAO,GACP,OAAO,eAAe,GACtB,OAAO,UAAU,GACjB,OAAO,qBAAqB,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,CAQlD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/CrossAppBanner/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,oBAAoB,CAAC;AACzC,eAAO,MAAM,QAAQ,eAAe,CAAC;AACrC,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AAExD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,UAAU,cAAc,CAAC;AACtC,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD,eAAO,MAAM,WAAW,UAQvB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,eAAO,MAAM,wBAAwB,UAAuD,CAAC;AAE7F;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,MAAM,GACN,QAAQ,GACR,OAAO,GACP,OAAO,eAAe,GACtB,OAAO,UAAU,GACjB,OAAO,qBAAqB,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,CAQlD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,uBAAuB,GAAG,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AppIdKeys, CheckInstalledResponse } from '../components/CrossAppBanner/types';
|
|
2
|
+
interface UseCheckAppInstalledParams {
|
|
3
|
+
appId: AppIdKeys;
|
|
4
|
+
shopDomain: string;
|
|
5
|
+
shouldCheck: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface UseCheckAppInstalledReturn {
|
|
8
|
+
installedData: CheckInstalledResponse | undefined;
|
|
9
|
+
isCheckingInstalled: boolean;
|
|
10
|
+
checkInstalledError: unknown;
|
|
11
|
+
}
|
|
12
|
+
export declare const useCheckAppInstalled: ({ appId, shopDomain, shouldCheck, }: UseCheckAppInstalledParams) => UseCheckAppInstalledReturn;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=useCheckAppInstalled.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCheckAppInstalled.d.ts","sourceRoot":"","sources":["../../src/hooks/useCheckAppInstalled.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEvF,UAAU,0BAA0B;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,0BAA0B;IAClC,aAAa,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAClD,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAID,eAAO,MAAM,oBAAoB,GAAI,qCAIlC,0BAA0B,KAAG,0BAgC/B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import useSWR from 'swr';
|
|
2
|
+
import { getCheckInstalledProxyUrl, getProxyAccessToken } from '../helpers/getProxyEndPoint';
|
|
3
|
+
import { fetchAuthenticatedApi } from '../helpers/api';
|
|
4
|
+
const THREE_MINUTES = 1800000;
|
|
5
|
+
export const useCheckAppInstalled = ({ appId, shopDomain, shouldCheck, }) => {
|
|
6
|
+
const swrKey = shouldCheck
|
|
7
|
+
? [
|
|
8
|
+
getCheckInstalledProxyUrl(appId),
|
|
9
|
+
{
|
|
10
|
+
'X-SEO-Access-Token': getProxyAccessToken(appId),
|
|
11
|
+
'X-SEO-Shop-Domain': shopDomain,
|
|
12
|
+
},
|
|
13
|
+
appId,
|
|
14
|
+
]
|
|
15
|
+
: null;
|
|
16
|
+
const fetcher = async ([url, headers]) => {
|
|
17
|
+
const fetchApiInstance = fetchAuthenticatedApi();
|
|
18
|
+
const response = await fetchApiInstance(url, { headers });
|
|
19
|
+
return response.data;
|
|
20
|
+
};
|
|
21
|
+
const { data, isLoading, error } = useSWR(swrKey, fetcher, {
|
|
22
|
+
revalidateOnFocus: false,
|
|
23
|
+
revalidateOnReconnect: false,
|
|
24
|
+
revalidateIfStale: false,
|
|
25
|
+
shouldRetryOnError: false,
|
|
26
|
+
dedupingInterval: THREE_MINUTES,
|
|
27
|
+
focusThrottleInterval: THREE_MINUTES,
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
installedData: data,
|
|
31
|
+
isCheckingInstalled: isLoading,
|
|
32
|
+
checkInstalledError: error,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=useCheckAppInstalled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCheckAppInstalled.js","sourceRoot":"","sources":["../../src/hooks/useCheckAppInstalled.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAevD,MAAM,aAAa,GAAG,OAAO,CAAC;AAE9B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EACnC,KAAK,EACL,UAAU,EACV,WAAW,GACgB,EAA8B,EAAE;IAC3D,MAAM,MAAM,GAAG,WAAW;QACxB,CAAC,CAAC;YACE,yBAAyB,CAAC,KAAK,CAAC;YAChC;gBACE,oBAAoB,EAAE,mBAAmB,CAAC,KAAK,CAAC;gBAChD,mBAAmB,EAAE,UAAU;aAChC;YACD,KAAK;SACN;QACH,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC,GAAG,EAAE,OAAO,CAAmC,EAAE,EAAE;QACzE,MAAM,gBAAgB,GAAG,qBAAqB,EAAE,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,MAAM,CAAyB,MAAM,EAAE,OAAO,EAAE;QACjF,iBAAiB,EAAE,KAAK;QACxB,qBAAqB,EAAE,KAAK;QAC5B,iBAAiB,EAAE,KAAK;QACxB,kBAAkB,EAAE,KAAK;QACzB,gBAAgB,EAAE,aAAa;QAC/B,qBAAqB,EAAE,aAAa;KACrC,CAAC,CAAC;IAEH,OAAO;QACL,aAAa,EAAE,IAAI;QACnB,mBAAmB,EAAE,SAAS;QAC9B,mBAAmB,EAAE,KAAK;KAC3B,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface AppBannerItem {
|
|
2
|
+
title: string;
|
|
3
|
+
description: string;
|
|
4
|
+
image: string;
|
|
5
|
+
url: string;
|
|
6
|
+
actionLabel: string;
|
|
7
|
+
key: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BannerSeoAppData {
|
|
10
|
+
appSeoon: AppBannerItem[];
|
|
11
|
+
appOutSide: AppBannerItem[];
|
|
12
|
+
}
|
|
13
|
+
interface UseFetchBannerDataOptions {
|
|
14
|
+
url?: string;
|
|
15
|
+
initLoad?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface UseFetchBannerDataReturn {
|
|
18
|
+
bannerData: BannerSeoAppData;
|
|
19
|
+
isLoadingBannerData: boolean;
|
|
20
|
+
fetchError: Error | null;
|
|
21
|
+
refetchBannerData: () => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export default function useFetchBannerData({ url, initLoad, }?: UseFetchBannerDataOptions): UseFetchBannerDataReturn;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=useFetchBannerData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFetchBannerData.d.ts","sourceRoot":"","sources":["../../src/hooks/useFetchBannerData.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,UAAU,yBAAyB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,UAAU,EAAE,KAAK,GAAG,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,GAAQ,EACR,QAAe,GAChB,GAAE,yBAA8B,GAAG,wBAAwB,CA2C3D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
export default function useFetchBannerData({ url = '', initLoad = true, } = {}) {
|
|
3
|
+
const [bannerData, setBannerData] = useState({
|
|
4
|
+
appSeoon: [],
|
|
5
|
+
appOutSide: [],
|
|
6
|
+
});
|
|
7
|
+
const [isLoadingBannerData, setIsLoadingBannerData] = useState(initLoad);
|
|
8
|
+
const [fetchError, setFetchError] = useState(null);
|
|
9
|
+
const fetchBannerData = async () => {
|
|
10
|
+
setIsLoadingBannerData(true);
|
|
11
|
+
setFetchError(null);
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch(url);
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
16
|
+
}
|
|
17
|
+
const responseData = await response.json();
|
|
18
|
+
setBannerData(responseData);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
const error = err instanceof Error ? err : new Error('Unknown error occurred');
|
|
22
|
+
setFetchError(error);
|
|
23
|
+
console.error('Error fetching banner SEO app data:', error);
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
setIsLoadingBannerData(false);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (initLoad) {
|
|
31
|
+
fetchBannerData();
|
|
32
|
+
}
|
|
33
|
+
}, [url, initLoad]);
|
|
34
|
+
return {
|
|
35
|
+
bannerData,
|
|
36
|
+
isLoadingBannerData,
|
|
37
|
+
fetchError,
|
|
38
|
+
refetchBannerData: fetchBannerData,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=useFetchBannerData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFetchBannerData.js","sourceRoot":"","sources":["../../src/hooks/useFetchBannerData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA4B5C,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,GAAG,GAAG,EAAE,EACR,QAAQ,GAAG,IAAI,MACc,EAAE;IAC/B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAmB;QAC7D,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;KACK,CAAC,CAAC;IACvB,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAU,QAAQ,CAAC,CAAC;IAClF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEjE,MAAM,eAAe,GAAG,KAAK,IAAmB,EAAE;QAChD,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC7B,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,YAAY,GAAqB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAE7D,aAAa,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC/E,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;gBAAS,CAAC;YACT,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,EAAE,CAAC;YACb,eAAe,EAAE,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEpB,OAAO;QACL,UAAU;QACV,mBAAmB;QACnB,UAAU;QACV,iBAAiB,EAAE,eAAe;KACnC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "avada-components-seoon",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A collection of React components built with Shopify Polaris",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"prepare": "yarn build",
|
|
20
20
|
"build": "tsc && copyfiles -u 1 \"src/**/*.scss\" dist",
|
|
21
21
|
"watch": "tsc --watch",
|
|
22
|
-
"dev": "
|
|
22
|
+
"dev": "vite",
|
|
23
|
+
"dev:build": "nodemon --watch src -e ts,tsx,scss --exec \"yarn build\"",
|
|
23
24
|
"clean": "rm -rf dist",
|
|
24
25
|
"lint": "eslint . --ext .ts,.tsx",
|
|
25
26
|
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"react": "^18.0.0",
|
|
44
45
|
"react-circular-progressbar": "^2.2.0",
|
|
45
46
|
"react-dom": "^18.0.0",
|
|
47
|
+
"swr": "^2.3.6",
|
|
46
48
|
"uuidv4": "6.2.13"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
@@ -53,6 +55,7 @@
|
|
|
53
55
|
"@types/react-redux": "^7.1.34",
|
|
54
56
|
"@typescript-eslint/eslint-plugin": "^8.30.1",
|
|
55
57
|
"@typescript-eslint/parser": "^8.30.1",
|
|
58
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
56
59
|
"autoprefixer": "^10.4.18",
|
|
57
60
|
"concurrently": "^8.2.2",
|
|
58
61
|
"copyfiles": "^2.4.1",
|
|
@@ -68,7 +71,9 @@
|
|
|
68
71
|
"postcss": "^8.4.35",
|
|
69
72
|
"prettier": "^3.5.3",
|
|
70
73
|
"sass": "^1.86.3",
|
|
71
|
-
"typescript": "^5.8.3"
|
|
74
|
+
"typescript": "^5.8.3",
|
|
75
|
+
"vite": "^7.1.12",
|
|
76
|
+
"vite-plugin-dts": "^4.5.4"
|
|
72
77
|
},
|
|
73
78
|
"peerDependencies": {
|
|
74
79
|
"@shopify/polaris": "^13.0.0",
|