@foxpixel/react 0.2.0 → 0.2.1
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/dist/index.d.mts +49 -26
- package/dist/index.d.ts +49 -26
- package/dist/index.js +379 -200
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +359 -181
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/context/FoxPixelContext.tsx
|
|
2
|
-
import { createContext, useContext, useMemo } from "react";
|
|
2
|
+
import React, { createContext, useContext, useMemo } from "react";
|
|
3
3
|
|
|
4
4
|
// src/client/http.ts
|
|
5
5
|
import axios from "axios";
|
|
@@ -111,15 +111,21 @@ var FoxPixelHttpClient = class {
|
|
|
111
111
|
|
|
112
112
|
// src/context/FoxPixelContext.tsx
|
|
113
113
|
import { jsx } from "react/jsx-runtime";
|
|
114
|
+
if (!React || typeof React.useMemo !== "function") {
|
|
115
|
+
throw new Error(
|
|
116
|
+
'@foxpixel/react: React is not available. Ensure your app uses a single React instance and the SDK is not bundled with a different React. In Next.js use transpilePackages: ["@foxpixel/react"] and ensure react/react-dom resolve to one module (see next.config.js).'
|
|
117
|
+
);
|
|
118
|
+
}
|
|
114
119
|
var FoxPixelContext = createContext(null);
|
|
115
|
-
function FoxPixelProvider({ children, config = {} }) {
|
|
120
|
+
function FoxPixelProvider({ children, config = {}, queryClient }) {
|
|
116
121
|
const client = useMemo(() => {
|
|
117
122
|
return new FoxPixelHttpClient(config);
|
|
118
123
|
}, [config.apiUrl, config.apiKey, config.tenantId]);
|
|
119
124
|
const value = useMemo(() => ({
|
|
120
125
|
client,
|
|
121
|
-
config
|
|
122
|
-
|
|
126
|
+
config,
|
|
127
|
+
queryClient: queryClient ?? null
|
|
128
|
+
}), [client, config, queryClient]);
|
|
123
129
|
return /* @__PURE__ */ jsx(FoxPixelContext.Provider, { value, children });
|
|
124
130
|
}
|
|
125
131
|
function useFoxPixelContext() {
|
|
@@ -346,11 +352,10 @@ function withAuth(Component, options = {}) {
|
|
|
346
352
|
}
|
|
347
353
|
|
|
348
354
|
// src/components/Editable.tsx
|
|
349
|
-
import { createElement, useCallback as useCallback3 } from "react";
|
|
355
|
+
import { createElement, useCallback as useCallback3, useState as useState7 } from "react";
|
|
350
356
|
|
|
351
357
|
// src/hooks/useEditMode.ts
|
|
352
358
|
import { useEffect as useEffect5, useState as useState5, useCallback as useCallback2 } from "react";
|
|
353
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
354
359
|
var SITE_CONTENT_QUERY_KEY = "siteContent";
|
|
355
360
|
function useEditMode() {
|
|
356
361
|
const [isEditMode, setIsEditMode] = useState5(false);
|
|
@@ -362,18 +367,29 @@ function useEditMode() {
|
|
|
362
367
|
return isEditMode;
|
|
363
368
|
}
|
|
364
369
|
function useEditModeMessaging() {
|
|
365
|
-
const
|
|
370
|
+
const ctx = useFoxPixelContext();
|
|
371
|
+
const queryClient = ctx?.queryClient ?? null;
|
|
366
372
|
const isEditMode = useEditMode();
|
|
367
373
|
useEffect5(() => {
|
|
368
374
|
if (!isEditMode || typeof window === "undefined") return;
|
|
369
375
|
window.parent.postMessage({ type: "FOXPIXEL_READY" }, "*");
|
|
370
376
|
const handleMessage = (event) => {
|
|
377
|
+
if (!queryClient) return;
|
|
371
378
|
const { type, payload } = event.data || {};
|
|
372
|
-
if (type
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
379
|
+
if (type !== "FOXPIXEL_CONTENT_UPDATED" || !payload?.contentKey) return;
|
|
380
|
+
const { contentKey, newValue } = payload;
|
|
381
|
+
if (typeof newValue === "string") {
|
|
382
|
+
queryClient.setQueryData(
|
|
383
|
+
[SITE_CONTENT_QUERY_KEY, contentKey],
|
|
384
|
+
(prev) => ({
|
|
385
|
+
value: newValue,
|
|
386
|
+
contentType: prev?.contentType ?? "TEXT"
|
|
387
|
+
})
|
|
388
|
+
);
|
|
376
389
|
}
|
|
390
|
+
queryClient.invalidateQueries({
|
|
391
|
+
queryKey: [SITE_CONTENT_QUERY_KEY, contentKey]
|
|
392
|
+
});
|
|
377
393
|
};
|
|
378
394
|
window.addEventListener("message", handleMessage);
|
|
379
395
|
return () => window.removeEventListener("message", handleMessage);
|
|
@@ -406,16 +422,40 @@ function useSendEditRequest() {
|
|
|
406
422
|
}
|
|
407
423
|
|
|
408
424
|
// src/hooks/useSiteContentQuery.ts
|
|
409
|
-
import {
|
|
425
|
+
import { useState as useState6, useEffect as useEffect6, useRef } from "react";
|
|
426
|
+
function getCached(queryClient, contentKey) {
|
|
427
|
+
const data = queryClient.getQueryData([
|
|
428
|
+
SITE_CONTENT_QUERY_KEY,
|
|
429
|
+
contentKey
|
|
430
|
+
]);
|
|
431
|
+
if (data == null) return void 0;
|
|
432
|
+
return { value: data.value ?? "", contentType: data.contentType ?? "TEXT" };
|
|
433
|
+
}
|
|
410
434
|
function useSiteContentQuery(contentKey, options) {
|
|
411
435
|
const { defaultValue } = options;
|
|
412
|
-
const { client } = useFoxPixelContext();
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
436
|
+
const { client, queryClient } = useFoxPixelContext();
|
|
437
|
+
const [state, setState] = useState6(() => {
|
|
438
|
+
if (queryClient) {
|
|
439
|
+
const cached = getCached(queryClient, contentKey);
|
|
440
|
+
if (cached) {
|
|
441
|
+
return { value: cached.value, isLoading: false, contentType: cached.contentType };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return { value: defaultValue, isLoading: true, contentType: "TEXT" };
|
|
445
|
+
});
|
|
446
|
+
const contentKeyRef = useRef(contentKey);
|
|
447
|
+
contentKeyRef.current = contentKey;
|
|
448
|
+
useEffect6(() => {
|
|
449
|
+
if (!queryClient) {
|
|
450
|
+
setState((s) => ({ ...s, value: defaultValue, isLoading: false }));
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const key = contentKeyRef.current;
|
|
454
|
+
const queryKey = [SITE_CONTENT_QUERY_KEY, key];
|
|
455
|
+
const queryFn = async () => {
|
|
416
456
|
try {
|
|
417
457
|
const content = await client.get(
|
|
418
|
-
`/api/site/content/${encodeURIComponent(
|
|
458
|
+
`/api/site/content/${encodeURIComponent(key)}`
|
|
419
459
|
);
|
|
420
460
|
if (!content) return null;
|
|
421
461
|
return {
|
|
@@ -423,23 +463,50 @@ function useSiteContentQuery(contentKey, options) {
|
|
|
423
463
|
contentType: content.contentType ?? "TEXT"
|
|
424
464
|
};
|
|
425
465
|
} catch (err) {
|
|
426
|
-
const status = err?.status;
|
|
466
|
+
const status = err?.response?.status;
|
|
427
467
|
if (status === 404) return null;
|
|
428
468
|
throw err;
|
|
429
469
|
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
470
|
+
};
|
|
471
|
+
let cancelled = false;
|
|
472
|
+
queryClient.fetchQuery({
|
|
473
|
+
queryKey,
|
|
474
|
+
queryFn,
|
|
475
|
+
staleTime: 1e3 * 60 * 5,
|
|
476
|
+
retry: 1
|
|
477
|
+
}).then((data) => {
|
|
478
|
+
if (cancelled) return;
|
|
479
|
+
setState({
|
|
480
|
+
value: data?.value ?? defaultValue,
|
|
481
|
+
isLoading: false,
|
|
482
|
+
contentType: data?.contentType ?? "TEXT"
|
|
483
|
+
});
|
|
484
|
+
}).catch(() => {
|
|
485
|
+
if (cancelled) return;
|
|
486
|
+
setState((s) => ({ ...s, value: defaultValue, isLoading: false }));
|
|
487
|
+
});
|
|
488
|
+
const unsub = queryClient.getQueryCache().subscribe((event) => {
|
|
489
|
+
if (event?.type === "updated" && event?.query?.queryKey[1] === key) {
|
|
490
|
+
const cached = getCached(queryClient, key);
|
|
491
|
+
if (cached && !cancelled) {
|
|
492
|
+
setState({
|
|
493
|
+
value: cached.value,
|
|
494
|
+
isLoading: false,
|
|
495
|
+
contentType: cached.contentType
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
return () => {
|
|
501
|
+
cancelled = true;
|
|
502
|
+
unsub();
|
|
503
|
+
};
|
|
504
|
+
}, [queryClient, contentKey, defaultValue, client]);
|
|
505
|
+
return state;
|
|
439
506
|
}
|
|
440
507
|
|
|
441
508
|
// src/utils/sanitize.ts
|
|
442
|
-
import
|
|
509
|
+
import sanitizeHtmlLib from "sanitize-html";
|
|
443
510
|
var DEFAULT_ALLOWED_TAGS = [
|
|
444
511
|
"p",
|
|
445
512
|
"br",
|
|
@@ -470,13 +537,16 @@ var DEFAULT_ALLOWED_TAGS = [
|
|
|
470
537
|
"th",
|
|
471
538
|
"td"
|
|
472
539
|
];
|
|
473
|
-
var DEFAULT_ALLOWED_ATTR =
|
|
540
|
+
var DEFAULT_ALLOWED_ATTR = {
|
|
541
|
+
a: ["href", "target", "rel", "title"],
|
|
542
|
+
img: ["src", "alt", "title", "width", "height"],
|
|
543
|
+
"*": ["class"]
|
|
544
|
+
};
|
|
474
545
|
function sanitizeHtml(html) {
|
|
475
546
|
if (typeof html !== "string") return "";
|
|
476
|
-
return
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
ADD_ATTR: ["target"]
|
|
547
|
+
return sanitizeHtmlLib(html, {
|
|
548
|
+
allowedTags: DEFAULT_ALLOWED_TAGS,
|
|
549
|
+
allowedAttributes: DEFAULT_ALLOWED_ATTR
|
|
480
550
|
});
|
|
481
551
|
}
|
|
482
552
|
|
|
@@ -486,7 +556,24 @@ function cn(...args) {
|
|
|
486
556
|
}
|
|
487
557
|
|
|
488
558
|
// src/components/Editable.tsx
|
|
489
|
-
import {
|
|
559
|
+
import { jsx as jsx6, jsxs } from "react/jsx-runtime";
|
|
560
|
+
var EDIT_MODE_TOOLTIP_STYLE = {
|
|
561
|
+
position: "absolute",
|
|
562
|
+
top: "-28px",
|
|
563
|
+
left: "50%",
|
|
564
|
+
transform: "translateX(-50%)",
|
|
565
|
+
fontSize: "10px",
|
|
566
|
+
fontFamily: "system-ui, sans-serif",
|
|
567
|
+
padding: "4px 8px",
|
|
568
|
+
backgroundColor: "rgb(37 99 235)",
|
|
569
|
+
color: "white",
|
|
570
|
+
borderRadius: "4px",
|
|
571
|
+
whiteSpace: "nowrap",
|
|
572
|
+
pointerEvents: "none",
|
|
573
|
+
zIndex: 100,
|
|
574
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.2)",
|
|
575
|
+
transition: "opacity 0.15s ease"
|
|
576
|
+
};
|
|
490
577
|
function Editable({
|
|
491
578
|
contentKey,
|
|
492
579
|
defaultValue,
|
|
@@ -494,6 +581,7 @@ function Editable({
|
|
|
494
581
|
multiline = false,
|
|
495
582
|
className
|
|
496
583
|
}) {
|
|
584
|
+
const [isHovered, setIsHovered] = useState7(false);
|
|
497
585
|
const isEditMode = useEditModeMessaging();
|
|
498
586
|
const sendEditRequest = useSendEditRequest();
|
|
499
587
|
const { value, isLoading, contentType } = useSiteContentQuery(contentKey, {
|
|
@@ -527,36 +615,59 @@ function Editable({
|
|
|
527
615
|
"aria-label": "Loading content..."
|
|
528
616
|
});
|
|
529
617
|
}
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
618
|
+
const editModeWrapperStyle = isEditMode ? {
|
|
619
|
+
position: "relative",
|
|
620
|
+
display: "inline",
|
|
621
|
+
cursor: "pointer",
|
|
622
|
+
borderRadius: "2px",
|
|
623
|
+
outline: isHovered ? "2px solid rgb(59 130 246)" : "none",
|
|
624
|
+
outlineOffset: "2px",
|
|
625
|
+
backgroundColor: isHovered ? "rgba(59 130 246 / 0.08)" : void 0
|
|
626
|
+
} : {};
|
|
627
|
+
const tooltipSpan = isEditMode ? /* @__PURE__ */ jsx6(
|
|
628
|
+
"span",
|
|
629
|
+
{
|
|
630
|
+
style: {
|
|
631
|
+
...EDIT_MODE_TOOLTIP_STYLE,
|
|
632
|
+
opacity: isHovered ? 1 : 0
|
|
633
|
+
},
|
|
634
|
+
"aria-hidden": true,
|
|
635
|
+
children: "Click to edit"
|
|
636
|
+
}
|
|
637
|
+
) : null;
|
|
638
|
+
const hoverHandlers = isEditMode ? {
|
|
639
|
+
onMouseEnter: () => setIsHovered(true),
|
|
640
|
+
onMouseLeave: () => setIsHovered(false)
|
|
641
|
+
} : {};
|
|
536
642
|
if (multiline && value.includes("\n")) {
|
|
537
643
|
const safeBr = sanitizeHtml(value.replace(/\n/g, "<br />"));
|
|
538
|
-
return createElement(
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
644
|
+
return createElement(
|
|
645
|
+
"span",
|
|
646
|
+
{ style: editModeWrapperStyle, ...hoverHandlers },
|
|
647
|
+
createElement(as, {
|
|
648
|
+
className,
|
|
649
|
+
"data-content-key": contentKey,
|
|
650
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
651
|
+
onClick: isEditMode ? handleClick : void 0,
|
|
652
|
+
dangerouslySetInnerHTML: { __html: safeBr }
|
|
653
|
+
}),
|
|
654
|
+
tooltipSpan
|
|
655
|
+
);
|
|
546
656
|
}
|
|
547
657
|
return createElement(
|
|
548
|
-
|
|
549
|
-
{
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
658
|
+
"span",
|
|
659
|
+
{ style: editModeWrapperStyle, ...hoverHandlers },
|
|
660
|
+
createElement(
|
|
661
|
+
as,
|
|
662
|
+
{
|
|
663
|
+
className,
|
|
664
|
+
"data-content-key": contentKey,
|
|
665
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
666
|
+
onClick: isEditMode ? handleClick : void 0
|
|
667
|
+
},
|
|
668
|
+
value
|
|
669
|
+
),
|
|
670
|
+
tooltipSpan
|
|
560
671
|
);
|
|
561
672
|
}
|
|
562
673
|
function EditableHTML({
|
|
@@ -565,6 +676,7 @@ function EditableHTML({
|
|
|
565
676
|
as = "div",
|
|
566
677
|
className
|
|
567
678
|
}) {
|
|
679
|
+
const [isHovered, setIsHovered] = useState7(false);
|
|
568
680
|
const isEditMode = useEditModeMessaging();
|
|
569
681
|
const sendEditRequest = useSendEditRequest();
|
|
570
682
|
const { value, isLoading } = useSiteContentQuery(contentKey, {
|
|
@@ -587,21 +699,39 @@ function EditableHTML({
|
|
|
587
699
|
"aria-busy": true
|
|
588
700
|
});
|
|
589
701
|
}
|
|
590
|
-
const
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
"
|
|
595
|
-
|
|
702
|
+
const wrapperStyle = isEditMode ? {
|
|
703
|
+
position: "relative",
|
|
704
|
+
cursor: "pointer",
|
|
705
|
+
borderRadius: "2px",
|
|
706
|
+
outline: isHovered ? "2px solid rgb(59 130 246)" : "none",
|
|
707
|
+
outlineOffset: "2px",
|
|
708
|
+
backgroundColor: isHovered ? "rgba(59 130 246 / 0.08)" : void 0
|
|
709
|
+
} : {};
|
|
596
710
|
const safeHtml = sanitizeHtml(value);
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
"
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
711
|
+
const hoverHandlers = isEditMode ? { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) } : {};
|
|
712
|
+
return createElement(
|
|
713
|
+
"div",
|
|
714
|
+
{ style: wrapperStyle, ...hoverHandlers },
|
|
715
|
+
createElement(as, {
|
|
716
|
+
className: cn("prose prose-slate dark:prose-invert", className),
|
|
717
|
+
"data-content-key": contentKey,
|
|
718
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
719
|
+
onClick: isEditMode ? handleClick : void 0,
|
|
720
|
+
dangerouslySetInnerHTML: { __html: safeHtml }
|
|
721
|
+
}),
|
|
722
|
+
isEditMode && /* @__PURE__ */ jsx6(
|
|
723
|
+
"span",
|
|
724
|
+
{
|
|
725
|
+
style: {
|
|
726
|
+
...EDIT_MODE_TOOLTIP_STYLE,
|
|
727
|
+
top: "-24px",
|
|
728
|
+
opacity: isHovered ? 1 : 0
|
|
729
|
+
},
|
|
730
|
+
"aria-hidden": true,
|
|
731
|
+
children: "Click to edit"
|
|
732
|
+
}
|
|
733
|
+
)
|
|
734
|
+
);
|
|
605
735
|
}
|
|
606
736
|
function EditableImage({
|
|
607
737
|
contentKey,
|
|
@@ -612,6 +742,7 @@ function EditableImage({
|
|
|
612
742
|
height,
|
|
613
743
|
priority = false
|
|
614
744
|
}) {
|
|
745
|
+
const [isHovered, setIsHovered] = useState7(false);
|
|
615
746
|
const isEditMode = useEditModeMessaging();
|
|
616
747
|
const sendEditRequest = useSendEditRequest();
|
|
617
748
|
const { value: src, isLoading } = useSiteContentQuery(contentKey, {
|
|
@@ -638,39 +769,55 @@ function EditableImage({
|
|
|
638
769
|
}
|
|
639
770
|
);
|
|
640
771
|
}
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
772
|
+
const wrapperStyle = isEditMode ? {
|
|
773
|
+
position: "relative",
|
|
774
|
+
display: "inline-block",
|
|
775
|
+
cursor: "pointer",
|
|
776
|
+
borderRadius: "2px",
|
|
777
|
+
outline: isHovered ? "2px solid rgb(59 130 246)" : "none",
|
|
778
|
+
outlineOffset: "2px"
|
|
779
|
+
} : {};
|
|
780
|
+
const hoverHandlers = isEditMode ? { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) } : {};
|
|
781
|
+
return /* @__PURE__ */ jsxs("div", { style: wrapperStyle, ...hoverHandlers, children: [
|
|
648
782
|
/* @__PURE__ */ jsx6(
|
|
649
783
|
"img",
|
|
650
784
|
{
|
|
651
785
|
src,
|
|
652
786
|
alt,
|
|
653
|
-
className
|
|
787
|
+
className,
|
|
788
|
+
style: isEditMode && isHovered ? { opacity: 0.95 } : void 0,
|
|
654
789
|
width,
|
|
655
790
|
height,
|
|
656
791
|
loading: priority ? "eager" : "lazy",
|
|
657
792
|
"data-content-key": contentKey,
|
|
658
793
|
"data-editable": isEditMode ? "true" : void 0,
|
|
659
|
-
onClick: isEditMode ? handleClick : void 0
|
|
660
|
-
title: isEditMode ? "Click to edit image" : void 0
|
|
794
|
+
onClick: isEditMode ? handleClick : void 0
|
|
661
795
|
}
|
|
662
796
|
),
|
|
663
|
-
isEditMode && /* @__PURE__ */ jsx6(
|
|
797
|
+
isEditMode && /* @__PURE__ */ jsx6(
|
|
798
|
+
"span",
|
|
799
|
+
{
|
|
800
|
+
style: {
|
|
801
|
+
...EDIT_MODE_TOOLTIP_STYLE,
|
|
802
|
+
top: "8px",
|
|
803
|
+
left: "8px",
|
|
804
|
+
transform: "none",
|
|
805
|
+
opacity: isHovered ? 1 : 0
|
|
806
|
+
},
|
|
807
|
+
"aria-hidden": true,
|
|
808
|
+
children: "Click to edit image"
|
|
809
|
+
}
|
|
810
|
+
)
|
|
664
811
|
] });
|
|
665
812
|
}
|
|
666
813
|
|
|
667
814
|
// src/hooks/useServices.ts
|
|
668
|
-
import { useState as
|
|
815
|
+
import { useState as useState8, useEffect as useEffect7 } from "react";
|
|
669
816
|
function useServices(options = {}) {
|
|
670
817
|
const { client } = useFoxPixelContext();
|
|
671
|
-
const [services, setServices] =
|
|
672
|
-
const [isLoading, setIsLoading] =
|
|
673
|
-
const [error, setError] =
|
|
818
|
+
const [services, setServices] = useState8(null);
|
|
819
|
+
const [isLoading, setIsLoading] = useState8(true);
|
|
820
|
+
const [error, setError] = useState8(null);
|
|
674
821
|
const fetchServices = async () => {
|
|
675
822
|
try {
|
|
676
823
|
setIsLoading(true);
|
|
@@ -688,7 +835,7 @@ function useServices(options = {}) {
|
|
|
688
835
|
setIsLoading(false);
|
|
689
836
|
}
|
|
690
837
|
};
|
|
691
|
-
|
|
838
|
+
useEffect7(() => {
|
|
692
839
|
fetchServices();
|
|
693
840
|
}, [options.category, options.active]);
|
|
694
841
|
return {
|
|
@@ -700,11 +847,11 @@ function useServices(options = {}) {
|
|
|
700
847
|
}
|
|
701
848
|
|
|
702
849
|
// src/hooks/useLeadCapture.ts
|
|
703
|
-
import { useState as
|
|
850
|
+
import { useState as useState9 } from "react";
|
|
704
851
|
function useLeadCapture() {
|
|
705
852
|
const { client } = useFoxPixelContext();
|
|
706
|
-
const [isLoading, setIsLoading] =
|
|
707
|
-
const [error, setError] =
|
|
853
|
+
const [isLoading, setIsLoading] = useState9(false);
|
|
854
|
+
const [error, setError] = useState9(null);
|
|
708
855
|
const captureLead = async (data) => {
|
|
709
856
|
try {
|
|
710
857
|
setIsLoading(true);
|
|
@@ -727,11 +874,11 @@ function useLeadCapture() {
|
|
|
727
874
|
}
|
|
728
875
|
|
|
729
876
|
// src/hooks/useContactCapture.ts
|
|
730
|
-
import { useState as
|
|
877
|
+
import { useState as useState10 } from "react";
|
|
731
878
|
function useContactCapture() {
|
|
732
879
|
const { client } = useFoxPixelContext();
|
|
733
|
-
const [isLoading, setIsLoading] =
|
|
734
|
-
const [error, setError] =
|
|
880
|
+
const [isLoading, setIsLoading] = useState10(false);
|
|
881
|
+
const [error, setError] = useState10(null);
|
|
735
882
|
const captureContact = async (data) => {
|
|
736
883
|
try {
|
|
737
884
|
setIsLoading(true);
|
|
@@ -754,14 +901,14 @@ function useContactCapture() {
|
|
|
754
901
|
}
|
|
755
902
|
|
|
756
903
|
// src/hooks/useSiteContent.ts
|
|
757
|
-
import { useState as
|
|
904
|
+
import { useState as useState11, useEffect as useEffect8, useCallback as useCallback4 } from "react";
|
|
758
905
|
function useSiteContent(contentKey, options = {}) {
|
|
759
906
|
const { defaultValue = "", fetchOnMount = true } = options;
|
|
760
907
|
const { client } = useFoxPixelContext();
|
|
761
908
|
const { user, hasPermission } = useAuth();
|
|
762
|
-
const [data, setData] =
|
|
763
|
-
const [isLoading, setIsLoading] =
|
|
764
|
-
const [error, setError] =
|
|
909
|
+
const [data, setData] = useState11(null);
|
|
910
|
+
const [isLoading, setIsLoading] = useState11(fetchOnMount);
|
|
911
|
+
const [error, setError] = useState11(null);
|
|
765
912
|
const canEdit = user !== null && hasPermission("site:content:update");
|
|
766
913
|
const fetchContent = useCallback4(async () => {
|
|
767
914
|
try {
|
|
@@ -794,7 +941,7 @@ function useSiteContent(contentKey, options = {}) {
|
|
|
794
941
|
throw err;
|
|
795
942
|
}
|
|
796
943
|
}, [client, contentKey]);
|
|
797
|
-
|
|
944
|
+
useEffect8(() => {
|
|
798
945
|
if (fetchOnMount) {
|
|
799
946
|
fetchContent();
|
|
800
947
|
}
|
|
@@ -813,9 +960,9 @@ function useSiteContent(contentKey, options = {}) {
|
|
|
813
960
|
function useSiteContents(contentKeys, options = {}) {
|
|
814
961
|
const { defaults = {} } = options;
|
|
815
962
|
const { client } = useFoxPixelContext();
|
|
816
|
-
const [data, setData] =
|
|
817
|
-
const [isLoading, setIsLoading] =
|
|
818
|
-
const [error, setError] =
|
|
963
|
+
const [data, setData] = useState11({});
|
|
964
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
965
|
+
const [error, setError] = useState11(null);
|
|
819
966
|
const fetchContents = useCallback4(async () => {
|
|
820
967
|
if (contentKeys.length === 0) {
|
|
821
968
|
setData({});
|
|
@@ -836,7 +983,7 @@ function useSiteContents(contentKeys, options = {}) {
|
|
|
836
983
|
setIsLoading(false);
|
|
837
984
|
}
|
|
838
985
|
}, [client, contentKeys.join(",")]);
|
|
839
|
-
|
|
986
|
+
useEffect8(() => {
|
|
840
987
|
fetchContents();
|
|
841
988
|
}, [fetchContents]);
|
|
842
989
|
const getValue = useCallback4((key, defaultValue) => {
|
|
@@ -856,9 +1003,9 @@ function useSiteContents(contentKeys, options = {}) {
|
|
|
856
1003
|
}
|
|
857
1004
|
function useSiteContentSection(section) {
|
|
858
1005
|
const { client } = useFoxPixelContext();
|
|
859
|
-
const [contents, setContents] =
|
|
860
|
-
const [isLoading, setIsLoading] =
|
|
861
|
-
const [error, setError] =
|
|
1006
|
+
const [contents, setContents] = useState11([]);
|
|
1007
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1008
|
+
const [error, setError] = useState11(null);
|
|
862
1009
|
const fetchContents = useCallback4(async () => {
|
|
863
1010
|
try {
|
|
864
1011
|
setIsLoading(true);
|
|
@@ -873,7 +1020,7 @@ function useSiteContentSection(section) {
|
|
|
873
1020
|
setIsLoading(false);
|
|
874
1021
|
}
|
|
875
1022
|
}, [client, section]);
|
|
876
|
-
|
|
1023
|
+
useEffect8(() => {
|
|
877
1024
|
fetchContents();
|
|
878
1025
|
}, [fetchContents]);
|
|
879
1026
|
return {
|
|
@@ -884,13 +1031,43 @@ function useSiteContentSection(section) {
|
|
|
884
1031
|
};
|
|
885
1032
|
}
|
|
886
1033
|
|
|
1034
|
+
// src/prefetchSiteContent.ts
|
|
1035
|
+
async function prefetchSiteContent(queryClient, options) {
|
|
1036
|
+
const { apiUrl, apiKey, tenantId, contentKeys } = options;
|
|
1037
|
+
const client = new FoxPixelHttpClient({ apiUrl, apiKey, tenantId });
|
|
1038
|
+
await Promise.all(
|
|
1039
|
+
contentKeys.map(async (contentKey) => {
|
|
1040
|
+
try {
|
|
1041
|
+
const content = await client.get(
|
|
1042
|
+
`/api/site/content/${encodeURIComponent(contentKey)}`
|
|
1043
|
+
);
|
|
1044
|
+
queryClient.setQueryData(
|
|
1045
|
+
[SITE_CONTENT_QUERY_KEY, contentKey],
|
|
1046
|
+
{
|
|
1047
|
+
value: content?.value ?? "",
|
|
1048
|
+
contentType: content?.contentType ?? "TEXT"
|
|
1049
|
+
}
|
|
1050
|
+
);
|
|
1051
|
+
} catch (err) {
|
|
1052
|
+
const status = err?.response?.status;
|
|
1053
|
+
if (status === 404) {
|
|
1054
|
+
queryClient.setQueryData([SITE_CONTENT_QUERY_KEY, contentKey], {
|
|
1055
|
+
value: "",
|
|
1056
|
+
contentType: "TEXT"
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
})
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
887
1064
|
// src/blog/hooks.ts
|
|
888
|
-
import { useState as
|
|
1065
|
+
import { useState as useState12, useEffect as useEffect9 } from "react";
|
|
889
1066
|
function useBlogPosts(options = {}) {
|
|
890
1067
|
const { client } = useFoxPixelContext();
|
|
891
|
-
const [data, setData] =
|
|
892
|
-
const [isLoading, setIsLoading] =
|
|
893
|
-
const [error, setError] =
|
|
1068
|
+
const [data, setData] = useState12(null);
|
|
1069
|
+
const [isLoading, setIsLoading] = useState12(true);
|
|
1070
|
+
const [error, setError] = useState12(null);
|
|
894
1071
|
const page = options.page ?? 0;
|
|
895
1072
|
const limit = options.limit ?? 10;
|
|
896
1073
|
const fetchPosts = async () => {
|
|
@@ -910,7 +1087,7 @@ function useBlogPosts(options = {}) {
|
|
|
910
1087
|
setIsLoading(false);
|
|
911
1088
|
}
|
|
912
1089
|
};
|
|
913
|
-
|
|
1090
|
+
useEffect9(() => {
|
|
914
1091
|
fetchPosts();
|
|
915
1092
|
}, [page, limit]);
|
|
916
1093
|
return {
|
|
@@ -922,9 +1099,9 @@ function useBlogPosts(options = {}) {
|
|
|
922
1099
|
}
|
|
923
1100
|
function useBlogPost(slug) {
|
|
924
1101
|
const { client } = useFoxPixelContext();
|
|
925
|
-
const [data, setData] =
|
|
926
|
-
const [isLoading, setIsLoading] =
|
|
927
|
-
const [error, setError] =
|
|
1102
|
+
const [data, setData] = useState12(null);
|
|
1103
|
+
const [isLoading, setIsLoading] = useState12(!!slug);
|
|
1104
|
+
const [error, setError] = useState12(null);
|
|
928
1105
|
const fetchPost = async () => {
|
|
929
1106
|
if (!slug) {
|
|
930
1107
|
setData(null);
|
|
@@ -943,7 +1120,7 @@ function useBlogPost(slug) {
|
|
|
943
1120
|
setIsLoading(false);
|
|
944
1121
|
}
|
|
945
1122
|
};
|
|
946
|
-
|
|
1123
|
+
useEffect9(() => {
|
|
947
1124
|
fetchPost();
|
|
948
1125
|
}, [slug]);
|
|
949
1126
|
return {
|
|
@@ -955,9 +1132,9 @@ function useBlogPost(slug) {
|
|
|
955
1132
|
}
|
|
956
1133
|
function useBlogCategories() {
|
|
957
1134
|
const { client } = useFoxPixelContext();
|
|
958
|
-
const [data, setData] =
|
|
959
|
-
const [isLoading, setIsLoading] =
|
|
960
|
-
const [error, setError] =
|
|
1135
|
+
const [data, setData] = useState12(null);
|
|
1136
|
+
const [isLoading, setIsLoading] = useState12(true);
|
|
1137
|
+
const [error, setError] = useState12(null);
|
|
961
1138
|
const fetchCategories = async () => {
|
|
962
1139
|
try {
|
|
963
1140
|
setIsLoading(true);
|
|
@@ -971,7 +1148,7 @@ function useBlogCategories() {
|
|
|
971
1148
|
setIsLoading(false);
|
|
972
1149
|
}
|
|
973
1150
|
};
|
|
974
|
-
|
|
1151
|
+
useEffect9(() => {
|
|
975
1152
|
fetchCategories();
|
|
976
1153
|
}, []);
|
|
977
1154
|
return {
|
|
@@ -983,9 +1160,9 @@ function useBlogCategories() {
|
|
|
983
1160
|
}
|
|
984
1161
|
function useBlogTags() {
|
|
985
1162
|
const { client } = useFoxPixelContext();
|
|
986
|
-
const [data, setData] =
|
|
987
|
-
const [isLoading, setIsLoading] =
|
|
988
|
-
const [error, setError] =
|
|
1163
|
+
const [data, setData] = useState12(null);
|
|
1164
|
+
const [isLoading, setIsLoading] = useState12(true);
|
|
1165
|
+
const [error, setError] = useState12(null);
|
|
989
1166
|
const fetchTags = async () => {
|
|
990
1167
|
try {
|
|
991
1168
|
setIsLoading(true);
|
|
@@ -999,7 +1176,7 @@ function useBlogTags() {
|
|
|
999
1176
|
setIsLoading(false);
|
|
1000
1177
|
}
|
|
1001
1178
|
};
|
|
1002
|
-
|
|
1179
|
+
useEffect9(() => {
|
|
1003
1180
|
fetchTags();
|
|
1004
1181
|
}, []);
|
|
1005
1182
|
return {
|
|
@@ -1011,9 +1188,9 @@ function useBlogTags() {
|
|
|
1011
1188
|
}
|
|
1012
1189
|
function useBlogComments(slug) {
|
|
1013
1190
|
const { client } = useFoxPixelContext();
|
|
1014
|
-
const [data, setData] =
|
|
1015
|
-
const [isLoading, setIsLoading] =
|
|
1016
|
-
const [error, setError] =
|
|
1191
|
+
const [data, setData] = useState12(null);
|
|
1192
|
+
const [isLoading, setIsLoading] = useState12(!!slug);
|
|
1193
|
+
const [error, setError] = useState12(null);
|
|
1017
1194
|
const fetchComments = async () => {
|
|
1018
1195
|
if (!slug) {
|
|
1019
1196
|
setData(null);
|
|
@@ -1034,7 +1211,7 @@ function useBlogComments(slug) {
|
|
|
1034
1211
|
setIsLoading(false);
|
|
1035
1212
|
}
|
|
1036
1213
|
};
|
|
1037
|
-
|
|
1214
|
+
useEffect9(() => {
|
|
1038
1215
|
fetchComments();
|
|
1039
1216
|
}, [slug]);
|
|
1040
1217
|
return {
|
|
@@ -1046,8 +1223,8 @@ function useBlogComments(slug) {
|
|
|
1046
1223
|
}
|
|
1047
1224
|
function useBlogCommentSubmit(slug) {
|
|
1048
1225
|
const { client } = useFoxPixelContext();
|
|
1049
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1050
|
-
const [error, setError] =
|
|
1226
|
+
const [isSubmitting, setIsSubmitting] = useState12(false);
|
|
1227
|
+
const [error, setError] = useState12(null);
|
|
1051
1228
|
const submit = async (payload) => {
|
|
1052
1229
|
if (!slug) return null;
|
|
1053
1230
|
try {
|
|
@@ -1075,9 +1252,9 @@ function useBlogCommentSubmit(slug) {
|
|
|
1075
1252
|
}
|
|
1076
1253
|
function useBlogFeaturedPosts(limit = 6) {
|
|
1077
1254
|
const { client } = useFoxPixelContext();
|
|
1078
|
-
const [data, setData] =
|
|
1079
|
-
const [isLoading, setIsLoading] =
|
|
1080
|
-
const [error, setError] =
|
|
1255
|
+
const [data, setData] = useState12(null);
|
|
1256
|
+
const [isLoading, setIsLoading] = useState12(true);
|
|
1257
|
+
const [error, setError] = useState12(null);
|
|
1081
1258
|
const fetchFeatured = async () => {
|
|
1082
1259
|
try {
|
|
1083
1260
|
setIsLoading(true);
|
|
@@ -1095,7 +1272,7 @@ function useBlogFeaturedPosts(limit = 6) {
|
|
|
1095
1272
|
setIsLoading(false);
|
|
1096
1273
|
}
|
|
1097
1274
|
};
|
|
1098
|
-
|
|
1275
|
+
useEffect9(() => {
|
|
1099
1276
|
fetchFeatured();
|
|
1100
1277
|
}, [limit]);
|
|
1101
1278
|
return {
|
|
@@ -1107,9 +1284,9 @@ function useBlogFeaturedPosts(limit = 6) {
|
|
|
1107
1284
|
}
|
|
1108
1285
|
function useNewsletterSubscribe() {
|
|
1109
1286
|
const { client } = useFoxPixelContext();
|
|
1110
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1111
|
-
const [error, setError] =
|
|
1112
|
-
const [success, setSuccess] =
|
|
1287
|
+
const [isSubmitting, setIsSubmitting] = useState12(false);
|
|
1288
|
+
const [error, setError] = useState12(null);
|
|
1289
|
+
const [success, setSuccess] = useState12(false);
|
|
1113
1290
|
const subscribe = async (payload) => {
|
|
1114
1291
|
try {
|
|
1115
1292
|
setIsSubmitting(true);
|
|
@@ -1142,9 +1319,9 @@ function useNewsletterSubscribe() {
|
|
|
1142
1319
|
}
|
|
1143
1320
|
function useNewsletterUnsubscribe() {
|
|
1144
1321
|
const { client } = useFoxPixelContext();
|
|
1145
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1146
|
-
const [error, setError] =
|
|
1147
|
-
const [success, setSuccess] =
|
|
1322
|
+
const [isSubmitting, setIsSubmitting] = useState12(false);
|
|
1323
|
+
const [error, setError] = useState12(null);
|
|
1324
|
+
const [success, setSuccess] = useState12(false);
|
|
1148
1325
|
const unsubscribe = async (email) => {
|
|
1149
1326
|
try {
|
|
1150
1327
|
setIsSubmitting(true);
|
|
@@ -1189,12 +1366,12 @@ function useNewsletterUnsubscribe() {
|
|
|
1189
1366
|
}
|
|
1190
1367
|
|
|
1191
1368
|
// src/blog/admin-hooks.ts
|
|
1192
|
-
import { useState as
|
|
1369
|
+
import { useState as useState13, useEffect as useEffect10, useCallback as useCallback5 } from "react";
|
|
1193
1370
|
function useAdminBlogPosts(options = {}) {
|
|
1194
1371
|
const { client } = useFoxPixelContext();
|
|
1195
|
-
const [data, setData] =
|
|
1196
|
-
const [isLoading, setIsLoading] =
|
|
1197
|
-
const [error, setError] =
|
|
1372
|
+
const [data, setData] = useState13(null);
|
|
1373
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1374
|
+
const [error, setError] = useState13(null);
|
|
1198
1375
|
const page = options.page ?? 0;
|
|
1199
1376
|
const size = options.size ?? 20;
|
|
1200
1377
|
const fetchPosts = useCallback5(async () => {
|
|
@@ -1212,16 +1389,16 @@ function useAdminBlogPosts(options = {}) {
|
|
|
1212
1389
|
setIsLoading(false);
|
|
1213
1390
|
}
|
|
1214
1391
|
}, [client, page, size]);
|
|
1215
|
-
|
|
1392
|
+
useEffect10(() => {
|
|
1216
1393
|
fetchPosts();
|
|
1217
1394
|
}, [fetchPosts]);
|
|
1218
1395
|
return { data, isLoading, error, refetch: fetchPosts };
|
|
1219
1396
|
}
|
|
1220
1397
|
function useAdminBlogPost(id) {
|
|
1221
1398
|
const { client } = useFoxPixelContext();
|
|
1222
|
-
const [data, setData] =
|
|
1223
|
-
const [isLoading, setIsLoading] =
|
|
1224
|
-
const [error, setError] =
|
|
1399
|
+
const [data, setData] = useState13(null);
|
|
1400
|
+
const [isLoading, setIsLoading] = useState13(!!id);
|
|
1401
|
+
const [error, setError] = useState13(null);
|
|
1225
1402
|
const fetchPost = useCallback5(async () => {
|
|
1226
1403
|
if (!id) {
|
|
1227
1404
|
setData(null);
|
|
@@ -1239,15 +1416,15 @@ function useAdminBlogPost(id) {
|
|
|
1239
1416
|
setIsLoading(false);
|
|
1240
1417
|
}
|
|
1241
1418
|
}, [client, id]);
|
|
1242
|
-
|
|
1419
|
+
useEffect10(() => {
|
|
1243
1420
|
fetchPost();
|
|
1244
1421
|
}, [fetchPost]);
|
|
1245
1422
|
return { data, isLoading, error, refetch: fetchPost };
|
|
1246
1423
|
}
|
|
1247
1424
|
function useAdminBlogPostMutations() {
|
|
1248
1425
|
const { client } = useFoxPixelContext();
|
|
1249
|
-
const [isLoading, setIsLoading] =
|
|
1250
|
-
const [error, setError] =
|
|
1426
|
+
const [isLoading, setIsLoading] = useState13(false);
|
|
1427
|
+
const [error, setError] = useState13(null);
|
|
1251
1428
|
const create = async (payload) => {
|
|
1252
1429
|
try {
|
|
1253
1430
|
setIsLoading(true);
|
|
@@ -1291,9 +1468,9 @@ function useAdminBlogPostMutations() {
|
|
|
1291
1468
|
}
|
|
1292
1469
|
function useAdminBlogCategories() {
|
|
1293
1470
|
const { client } = useFoxPixelContext();
|
|
1294
|
-
const [data, setData] =
|
|
1295
|
-
const [isLoading, setIsLoading] =
|
|
1296
|
-
const [error, setError] =
|
|
1471
|
+
const [data, setData] = useState13(null);
|
|
1472
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1473
|
+
const [error, setError] = useState13(null);
|
|
1297
1474
|
const fetchCategories = useCallback5(async () => {
|
|
1298
1475
|
try {
|
|
1299
1476
|
setIsLoading(true);
|
|
@@ -1306,7 +1483,7 @@ function useAdminBlogCategories() {
|
|
|
1306
1483
|
setIsLoading(false);
|
|
1307
1484
|
}
|
|
1308
1485
|
}, [client]);
|
|
1309
|
-
|
|
1486
|
+
useEffect10(() => {
|
|
1310
1487
|
fetchCategories();
|
|
1311
1488
|
}, [fetchCategories]);
|
|
1312
1489
|
const create = async (payload) => {
|
|
@@ -1343,9 +1520,9 @@ function useAdminBlogCategories() {
|
|
|
1343
1520
|
}
|
|
1344
1521
|
function useAdminBlogTags() {
|
|
1345
1522
|
const { client } = useFoxPixelContext();
|
|
1346
|
-
const [data, setData] =
|
|
1347
|
-
const [isLoading, setIsLoading] =
|
|
1348
|
-
const [error, setError] =
|
|
1523
|
+
const [data, setData] = useState13(null);
|
|
1524
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1525
|
+
const [error, setError] = useState13(null);
|
|
1349
1526
|
const fetchTags = useCallback5(async () => {
|
|
1350
1527
|
try {
|
|
1351
1528
|
setIsLoading(true);
|
|
@@ -1358,7 +1535,7 @@ function useAdminBlogTags() {
|
|
|
1358
1535
|
setIsLoading(false);
|
|
1359
1536
|
}
|
|
1360
1537
|
}, [client]);
|
|
1361
|
-
|
|
1538
|
+
useEffect10(() => {
|
|
1362
1539
|
fetchTags();
|
|
1363
1540
|
}, [fetchTags]);
|
|
1364
1541
|
const create = async (payload) => {
|
|
@@ -1395,9 +1572,9 @@ function useAdminBlogTags() {
|
|
|
1395
1572
|
}
|
|
1396
1573
|
function useAdminBlogComments(options = {}) {
|
|
1397
1574
|
const { client } = useFoxPixelContext();
|
|
1398
|
-
const [data, setData] =
|
|
1399
|
-
const [isLoading, setIsLoading] =
|
|
1400
|
-
const [error, setError] =
|
|
1575
|
+
const [data, setData] = useState13(null);
|
|
1576
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1577
|
+
const [error, setError] = useState13(null);
|
|
1401
1578
|
const { status, postId, page = 0, size = 20 } = options;
|
|
1402
1579
|
const fetchComments = useCallback5(async () => {
|
|
1403
1580
|
try {
|
|
@@ -1416,7 +1593,7 @@ function useAdminBlogComments(options = {}) {
|
|
|
1416
1593
|
setIsLoading(false);
|
|
1417
1594
|
}
|
|
1418
1595
|
}, [client, status, postId, page, size]);
|
|
1419
|
-
|
|
1596
|
+
useEffect10(() => {
|
|
1420
1597
|
fetchComments();
|
|
1421
1598
|
}, [fetchComments]);
|
|
1422
1599
|
const updateStatus = async (id, newStatus) => {
|
|
@@ -1443,9 +1620,9 @@ function useAdminBlogComments(options = {}) {
|
|
|
1443
1620
|
}
|
|
1444
1621
|
function useAdminNewsletterSubscribers(options = {}) {
|
|
1445
1622
|
const { client } = useFoxPixelContext();
|
|
1446
|
-
const [data, setData] =
|
|
1447
|
-
const [isLoading, setIsLoading] =
|
|
1448
|
-
const [error, setError] =
|
|
1623
|
+
const [data, setData] = useState13(null);
|
|
1624
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1625
|
+
const [error, setError] = useState13(null);
|
|
1449
1626
|
const { status, page = 0, size = 20 } = options;
|
|
1450
1627
|
const fetchSubscribers = useCallback5(async () => {
|
|
1451
1628
|
try {
|
|
@@ -1463,7 +1640,7 @@ function useAdminNewsletterSubscribers(options = {}) {
|
|
|
1463
1640
|
setIsLoading(false);
|
|
1464
1641
|
}
|
|
1465
1642
|
}, [client, status, page, size]);
|
|
1466
|
-
|
|
1643
|
+
useEffect10(() => {
|
|
1467
1644
|
fetchSubscribers();
|
|
1468
1645
|
}, [fetchSubscribers]);
|
|
1469
1646
|
const remove = async (id) => {
|
|
@@ -1480,9 +1657,9 @@ function useAdminNewsletterSubscribers(options = {}) {
|
|
|
1480
1657
|
}
|
|
1481
1658
|
function useAdminNewsletterStats() {
|
|
1482
1659
|
const { client } = useFoxPixelContext();
|
|
1483
|
-
const [data, setData] =
|
|
1484
|
-
const [isLoading, setIsLoading] =
|
|
1485
|
-
const [error, setError] =
|
|
1660
|
+
const [data, setData] = useState13(null);
|
|
1661
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1662
|
+
const [error, setError] = useState13(null);
|
|
1486
1663
|
const fetchStats = useCallback5(async () => {
|
|
1487
1664
|
try {
|
|
1488
1665
|
setIsLoading(true);
|
|
@@ -1495,16 +1672,16 @@ function useAdminNewsletterStats() {
|
|
|
1495
1672
|
setIsLoading(false);
|
|
1496
1673
|
}
|
|
1497
1674
|
}, [client]);
|
|
1498
|
-
|
|
1675
|
+
useEffect10(() => {
|
|
1499
1676
|
fetchStats();
|
|
1500
1677
|
}, [fetchStats]);
|
|
1501
1678
|
return { data, isLoading, error, refetch: fetchStats };
|
|
1502
1679
|
}
|
|
1503
1680
|
function useAdminBlogSettings() {
|
|
1504
1681
|
const { client } = useFoxPixelContext();
|
|
1505
|
-
const [data, setData] =
|
|
1506
|
-
const [isLoading, setIsLoading] =
|
|
1507
|
-
const [error, setError] =
|
|
1682
|
+
const [data, setData] = useState13(null);
|
|
1683
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1684
|
+
const [error, setError] = useState13(null);
|
|
1508
1685
|
const fetchSettings = useCallback5(async () => {
|
|
1509
1686
|
try {
|
|
1510
1687
|
setIsLoading(true);
|
|
@@ -1517,7 +1694,7 @@ function useAdminBlogSettings() {
|
|
|
1517
1694
|
setIsLoading(false);
|
|
1518
1695
|
}
|
|
1519
1696
|
}, [client]);
|
|
1520
|
-
|
|
1697
|
+
useEffect10(() => {
|
|
1521
1698
|
fetchSettings();
|
|
1522
1699
|
}, [fetchSettings]);
|
|
1523
1700
|
const update = async (settings) => {
|
|
@@ -1534,9 +1711,9 @@ function useAdminBlogSettings() {
|
|
|
1534
1711
|
}
|
|
1535
1712
|
function useAdminBlogAnalytics() {
|
|
1536
1713
|
const { client } = useFoxPixelContext();
|
|
1537
|
-
const [data, setData] =
|
|
1538
|
-
const [isLoading, setIsLoading] =
|
|
1539
|
-
const [error, setError] =
|
|
1714
|
+
const [data, setData] = useState13(null);
|
|
1715
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
1716
|
+
const [error, setError] = useState13(null);
|
|
1540
1717
|
const fetchAnalytics = useCallback5(async () => {
|
|
1541
1718
|
try {
|
|
1542
1719
|
setIsLoading(true);
|
|
@@ -1549,7 +1726,7 @@ function useAdminBlogAnalytics() {
|
|
|
1549
1726
|
setIsLoading(false);
|
|
1550
1727
|
}
|
|
1551
1728
|
}, [client]);
|
|
1552
|
-
|
|
1729
|
+
useEffect10(() => {
|
|
1553
1730
|
fetchAnalytics();
|
|
1554
1731
|
}, [fetchAnalytics]);
|
|
1555
1732
|
return { data, isLoading, error, refetch: fetchAnalytics };
|
|
@@ -1597,6 +1774,7 @@ export {
|
|
|
1597
1774
|
ProtectedRoute,
|
|
1598
1775
|
SITE_CONTENT_QUERY_KEY,
|
|
1599
1776
|
getBlogPostSchemaLd,
|
|
1777
|
+
prefetchSiteContent,
|
|
1600
1778
|
useAdminBlogAnalytics,
|
|
1601
1779
|
useAdminBlogCategories,
|
|
1602
1780
|
useAdminBlogComments,
|