@foxpixel/react 0.1.1 → 0.2.0
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 +285 -2
- package/dist/index.d.ts +285 -2
- package/dist/index.js +584 -93
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +573 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -3
package/dist/index.mjs
CHANGED
|
@@ -238,7 +238,8 @@ function AuthProvider({
|
|
|
238
238
|
logout,
|
|
239
239
|
register,
|
|
240
240
|
updateProfile,
|
|
241
|
-
refetch: fetchCurrentUser
|
|
241
|
+
refetch: fetchCurrentUser,
|
|
242
|
+
hasPermission: (permission) => user !== null && permission === "site:content:update"
|
|
242
243
|
};
|
|
243
244
|
return /* @__PURE__ */ jsx2(AuthContext.Provider, { value, children });
|
|
244
245
|
}
|
|
@@ -344,13 +345,332 @@ function withAuth(Component, options = {}) {
|
|
|
344
345
|
};
|
|
345
346
|
}
|
|
346
347
|
|
|
348
|
+
// src/components/Editable.tsx
|
|
349
|
+
import { createElement, useCallback as useCallback3 } from "react";
|
|
350
|
+
|
|
351
|
+
// src/hooks/useEditMode.ts
|
|
352
|
+
import { useEffect as useEffect5, useState as useState5, useCallback as useCallback2 } from "react";
|
|
353
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
354
|
+
var SITE_CONTENT_QUERY_KEY = "siteContent";
|
|
355
|
+
function useEditMode() {
|
|
356
|
+
const [isEditMode, setIsEditMode] = useState5(false);
|
|
357
|
+
useEffect5(() => {
|
|
358
|
+
if (typeof window === "undefined") return;
|
|
359
|
+
const params = new URLSearchParams(window.location.search);
|
|
360
|
+
setIsEditMode(params.get("edit-mode") === "true");
|
|
361
|
+
}, []);
|
|
362
|
+
return isEditMode;
|
|
363
|
+
}
|
|
364
|
+
function useEditModeMessaging() {
|
|
365
|
+
const queryClient = useQueryClient();
|
|
366
|
+
const isEditMode = useEditMode();
|
|
367
|
+
useEffect5(() => {
|
|
368
|
+
if (!isEditMode || typeof window === "undefined") return;
|
|
369
|
+
window.parent.postMessage({ type: "FOXPIXEL_READY" }, "*");
|
|
370
|
+
const handleMessage = (event) => {
|
|
371
|
+
const { type, payload } = event.data || {};
|
|
372
|
+
if (type === "FOXPIXEL_CONTENT_UPDATED" && payload?.contentKey) {
|
|
373
|
+
queryClient.invalidateQueries({
|
|
374
|
+
queryKey: [SITE_CONTENT_QUERY_KEY, payload.contentKey]
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
window.addEventListener("message", handleMessage);
|
|
379
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
380
|
+
}, [isEditMode, queryClient]);
|
|
381
|
+
return isEditMode;
|
|
382
|
+
}
|
|
383
|
+
function useSendEditRequest() {
|
|
384
|
+
const isEditMode = useEditMode();
|
|
385
|
+
return useCallback2(
|
|
386
|
+
(contentKey, currentValue, contentType = "text", section, description) => {
|
|
387
|
+
if (!isEditMode) return;
|
|
388
|
+
if (typeof window !== "undefined" && window.parent !== window) {
|
|
389
|
+
window.parent.postMessage(
|
|
390
|
+
{
|
|
391
|
+
type: "FOXPIXEL_EDIT_CONTENT",
|
|
392
|
+
payload: {
|
|
393
|
+
contentKey,
|
|
394
|
+
currentValue,
|
|
395
|
+
contentType,
|
|
396
|
+
section,
|
|
397
|
+
description
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
"*"
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
[isEditMode]
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/hooks/useSiteContentQuery.ts
|
|
409
|
+
import { useQuery } from "@tanstack/react-query";
|
|
410
|
+
function useSiteContentQuery(contentKey, options) {
|
|
411
|
+
const { defaultValue } = options;
|
|
412
|
+
const { client } = useFoxPixelContext();
|
|
413
|
+
const { data, isLoading } = useQuery({
|
|
414
|
+
queryKey: [SITE_CONTENT_QUERY_KEY, contentKey],
|
|
415
|
+
queryFn: async () => {
|
|
416
|
+
try {
|
|
417
|
+
const content = await client.get(
|
|
418
|
+
`/api/site/content/${encodeURIComponent(contentKey)}`
|
|
419
|
+
);
|
|
420
|
+
if (!content) return null;
|
|
421
|
+
return {
|
|
422
|
+
value: content.value ?? "",
|
|
423
|
+
contentType: content.contentType ?? "TEXT"
|
|
424
|
+
};
|
|
425
|
+
} catch (err) {
|
|
426
|
+
const status = err?.status;
|
|
427
|
+
if (status === 404) return null;
|
|
428
|
+
throw err;
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
staleTime: 1e3 * 60 * 5,
|
|
432
|
+
retry: 1
|
|
433
|
+
});
|
|
434
|
+
return {
|
|
435
|
+
value: data?.value ?? defaultValue,
|
|
436
|
+
isLoading,
|
|
437
|
+
contentType: data?.contentType ?? "TEXT"
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// src/utils/sanitize.ts
|
|
442
|
+
import DOMPurify from "isomorphic-dompurify";
|
|
443
|
+
var DEFAULT_ALLOWED_TAGS = [
|
|
444
|
+
"p",
|
|
445
|
+
"br",
|
|
446
|
+
"strong",
|
|
447
|
+
"em",
|
|
448
|
+
"u",
|
|
449
|
+
"s",
|
|
450
|
+
"a",
|
|
451
|
+
"ul",
|
|
452
|
+
"ol",
|
|
453
|
+
"li",
|
|
454
|
+
"h1",
|
|
455
|
+
"h2",
|
|
456
|
+
"h3",
|
|
457
|
+
"h4",
|
|
458
|
+
"h5",
|
|
459
|
+
"h6",
|
|
460
|
+
"blockquote",
|
|
461
|
+
"code",
|
|
462
|
+
"pre",
|
|
463
|
+
"span",
|
|
464
|
+
"div",
|
|
465
|
+
"img",
|
|
466
|
+
"table",
|
|
467
|
+
"thead",
|
|
468
|
+
"tbody",
|
|
469
|
+
"tr",
|
|
470
|
+
"th",
|
|
471
|
+
"td"
|
|
472
|
+
];
|
|
473
|
+
var DEFAULT_ALLOWED_ATTR = ["href", "target", "rel", "src", "alt", "title", "class"];
|
|
474
|
+
function sanitizeHtml(html) {
|
|
475
|
+
if (typeof html !== "string") return "";
|
|
476
|
+
return DOMPurify.sanitize(html, {
|
|
477
|
+
ALLOWED_TAGS: DEFAULT_ALLOWED_TAGS,
|
|
478
|
+
ALLOWED_ATTR: DEFAULT_ALLOWED_ATTR,
|
|
479
|
+
ADD_ATTR: ["target"]
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/utils/cn.ts
|
|
484
|
+
function cn(...args) {
|
|
485
|
+
return args.filter(Boolean).join(" ");
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// src/components/Editable.tsx
|
|
489
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs } from "react/jsx-runtime";
|
|
490
|
+
function Editable({
|
|
491
|
+
contentKey,
|
|
492
|
+
defaultValue,
|
|
493
|
+
as = "span",
|
|
494
|
+
multiline = false,
|
|
495
|
+
className
|
|
496
|
+
}) {
|
|
497
|
+
const isEditMode = useEditModeMessaging();
|
|
498
|
+
const sendEditRequest = useSendEditRequest();
|
|
499
|
+
const { value, isLoading, contentType } = useSiteContentQuery(contentKey, {
|
|
500
|
+
defaultValue
|
|
501
|
+
});
|
|
502
|
+
const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
|
|
503
|
+
const handleClick = useCallback3(
|
|
504
|
+
(e) => {
|
|
505
|
+
if (isEditMode) {
|
|
506
|
+
e.preventDefault();
|
|
507
|
+
e.stopPropagation();
|
|
508
|
+
sendEditRequest(
|
|
509
|
+
contentKey,
|
|
510
|
+
value,
|
|
511
|
+
contentType?.toLowerCase() || "text",
|
|
512
|
+
section
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
[isEditMode, contentKey, value, contentType, section, sendEditRequest]
|
|
517
|
+
);
|
|
518
|
+
if (isLoading) {
|
|
519
|
+
return createElement(as, {
|
|
520
|
+
className: cn(
|
|
521
|
+
"animate-pulse bg-muted rounded",
|
|
522
|
+
multiline ? "h-20" : "h-6",
|
|
523
|
+
"inline-block min-w-[100px]",
|
|
524
|
+
className
|
|
525
|
+
),
|
|
526
|
+
"aria-busy": true,
|
|
527
|
+
"aria-label": "Loading content..."
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
const editModeStyles = isEditMode ? cn(
|
|
531
|
+
"cursor-pointer transition-all duration-200",
|
|
532
|
+
"hover:ring-2 hover:ring-blue-500 hover:ring-offset-2",
|
|
533
|
+
"hover:bg-blue-50/50 dark:hover:bg-blue-950/30",
|
|
534
|
+
"relative group"
|
|
535
|
+
) : "";
|
|
536
|
+
if (multiline && value.includes("\n")) {
|
|
537
|
+
const safeBr = sanitizeHtml(value.replace(/\n/g, "<br />"));
|
|
538
|
+
return createElement(as, {
|
|
539
|
+
className: cn(className, editModeStyles),
|
|
540
|
+
"data-content-key": contentKey,
|
|
541
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
542
|
+
onClick: isEditMode ? handleClick : void 0,
|
|
543
|
+
dangerouslySetInnerHTML: { __html: safeBr },
|
|
544
|
+
title: isEditMode ? "Click to edit" : void 0
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
return createElement(
|
|
548
|
+
as,
|
|
549
|
+
{
|
|
550
|
+
className: cn(className, editModeStyles),
|
|
551
|
+
"data-content-key": contentKey,
|
|
552
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
553
|
+
onClick: isEditMode ? handleClick : void 0,
|
|
554
|
+
title: isEditMode ? "Click to edit" : void 0
|
|
555
|
+
},
|
|
556
|
+
/* @__PURE__ */ jsxs(Fragment3, { children: [
|
|
557
|
+
value,
|
|
558
|
+
isEditMode && /* @__PURE__ */ jsx6("span", { className: "absolute -top-6 left-1/2 -translate-x-1/2 px-2 py-0.5 bg-blue-600 text-white text-[10px] rounded opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-50", children: "Click to edit" })
|
|
559
|
+
] })
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
function EditableHTML({
|
|
563
|
+
contentKey,
|
|
564
|
+
defaultValue,
|
|
565
|
+
as = "div",
|
|
566
|
+
className
|
|
567
|
+
}) {
|
|
568
|
+
const isEditMode = useEditModeMessaging();
|
|
569
|
+
const sendEditRequest = useSendEditRequest();
|
|
570
|
+
const { value, isLoading } = useSiteContentQuery(contentKey, {
|
|
571
|
+
defaultValue
|
|
572
|
+
});
|
|
573
|
+
const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
|
|
574
|
+
const handleClick = useCallback3(
|
|
575
|
+
(e) => {
|
|
576
|
+
if (isEditMode) {
|
|
577
|
+
e.preventDefault();
|
|
578
|
+
e.stopPropagation();
|
|
579
|
+
sendEditRequest(contentKey, value, "html", section);
|
|
580
|
+
}
|
|
581
|
+
},
|
|
582
|
+
[isEditMode, contentKey, value, section, sendEditRequest]
|
|
583
|
+
);
|
|
584
|
+
if (isLoading) {
|
|
585
|
+
return createElement(as, {
|
|
586
|
+
className: cn("animate-pulse bg-muted rounded h-32", className),
|
|
587
|
+
"aria-busy": true
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
const editModeStyles = isEditMode ? cn(
|
|
591
|
+
"cursor-pointer transition-all duration-200",
|
|
592
|
+
"hover:ring-2 hover:ring-blue-500 hover:ring-offset-2",
|
|
593
|
+
"hover:bg-blue-50/50 dark:hover:bg-blue-950/30",
|
|
594
|
+
"relative group"
|
|
595
|
+
) : "";
|
|
596
|
+
const safeHtml = sanitizeHtml(value);
|
|
597
|
+
return createElement(as, {
|
|
598
|
+
className: cn("prose prose-slate dark:prose-invert", className, editModeStyles),
|
|
599
|
+
"data-content-key": contentKey,
|
|
600
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
601
|
+
onClick: isEditMode ? handleClick : void 0,
|
|
602
|
+
title: isEditMode ? "Click to edit" : void 0,
|
|
603
|
+
dangerouslySetInnerHTML: { __html: safeHtml }
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
function EditableImage({
|
|
607
|
+
contentKey,
|
|
608
|
+
defaultValue,
|
|
609
|
+
alt,
|
|
610
|
+
className,
|
|
611
|
+
width,
|
|
612
|
+
height,
|
|
613
|
+
priority = false
|
|
614
|
+
}) {
|
|
615
|
+
const isEditMode = useEditModeMessaging();
|
|
616
|
+
const sendEditRequest = useSendEditRequest();
|
|
617
|
+
const { value: src, isLoading } = useSiteContentQuery(contentKey, {
|
|
618
|
+
defaultValue
|
|
619
|
+
});
|
|
620
|
+
const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
|
|
621
|
+
const handleClick = useCallback3(
|
|
622
|
+
(e) => {
|
|
623
|
+
if (isEditMode) {
|
|
624
|
+
e.preventDefault();
|
|
625
|
+
e.stopPropagation();
|
|
626
|
+
sendEditRequest(contentKey, src, "image", section);
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
[isEditMode, contentKey, src, section, sendEditRequest]
|
|
630
|
+
);
|
|
631
|
+
if (isLoading) {
|
|
632
|
+
return /* @__PURE__ */ jsx6(
|
|
633
|
+
"div",
|
|
634
|
+
{
|
|
635
|
+
className: cn("animate-pulse bg-muted rounded", className),
|
|
636
|
+
style: { width, height },
|
|
637
|
+
"aria-busy": "true"
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
const editModeStyles = isEditMode ? cn(
|
|
642
|
+
"cursor-pointer transition-all duration-200",
|
|
643
|
+
"hover:ring-2 hover:ring-blue-500 hover:ring-offset-2",
|
|
644
|
+
"hover:opacity-90",
|
|
645
|
+
"relative group"
|
|
646
|
+
) : "";
|
|
647
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", isEditMode && "group"), children: [
|
|
648
|
+
/* @__PURE__ */ jsx6(
|
|
649
|
+
"img",
|
|
650
|
+
{
|
|
651
|
+
src,
|
|
652
|
+
alt,
|
|
653
|
+
className: cn(className, editModeStyles),
|
|
654
|
+
width,
|
|
655
|
+
height,
|
|
656
|
+
loading: priority ? "eager" : "lazy",
|
|
657
|
+
"data-content-key": contentKey,
|
|
658
|
+
"data-editable": isEditMode ? "true" : void 0,
|
|
659
|
+
onClick: isEditMode ? handleClick : void 0,
|
|
660
|
+
title: isEditMode ? "Click to edit image" : void 0
|
|
661
|
+
}
|
|
662
|
+
),
|
|
663
|
+
isEditMode && /* @__PURE__ */ jsx6("span", { className: "absolute top-2 left-2 px-2 py-0.5 bg-blue-600 text-white text-[10px] rounded opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none", children: "Click to edit image" })
|
|
664
|
+
] });
|
|
665
|
+
}
|
|
666
|
+
|
|
347
667
|
// src/hooks/useServices.ts
|
|
348
|
-
import { useState as
|
|
668
|
+
import { useState as useState6, useEffect as useEffect6 } from "react";
|
|
349
669
|
function useServices(options = {}) {
|
|
350
670
|
const { client } = useFoxPixelContext();
|
|
351
|
-
const [services, setServices] =
|
|
352
|
-
const [isLoading, setIsLoading] =
|
|
353
|
-
const [error, setError] =
|
|
671
|
+
const [services, setServices] = useState6(null);
|
|
672
|
+
const [isLoading, setIsLoading] = useState6(true);
|
|
673
|
+
const [error, setError] = useState6(null);
|
|
354
674
|
const fetchServices = async () => {
|
|
355
675
|
try {
|
|
356
676
|
setIsLoading(true);
|
|
@@ -368,7 +688,7 @@ function useServices(options = {}) {
|
|
|
368
688
|
setIsLoading(false);
|
|
369
689
|
}
|
|
370
690
|
};
|
|
371
|
-
|
|
691
|
+
useEffect6(() => {
|
|
372
692
|
fetchServices();
|
|
373
693
|
}, [options.category, options.active]);
|
|
374
694
|
return {
|
|
@@ -380,11 +700,11 @@ function useServices(options = {}) {
|
|
|
380
700
|
}
|
|
381
701
|
|
|
382
702
|
// src/hooks/useLeadCapture.ts
|
|
383
|
-
import { useState as
|
|
703
|
+
import { useState as useState7 } from "react";
|
|
384
704
|
function useLeadCapture() {
|
|
385
705
|
const { client } = useFoxPixelContext();
|
|
386
|
-
const [isLoading, setIsLoading] =
|
|
387
|
-
const [error, setError] =
|
|
706
|
+
const [isLoading, setIsLoading] = useState7(false);
|
|
707
|
+
const [error, setError] = useState7(null);
|
|
388
708
|
const captureLead = async (data) => {
|
|
389
709
|
try {
|
|
390
710
|
setIsLoading(true);
|
|
@@ -407,11 +727,11 @@ function useLeadCapture() {
|
|
|
407
727
|
}
|
|
408
728
|
|
|
409
729
|
// src/hooks/useContactCapture.ts
|
|
410
|
-
import { useState as
|
|
730
|
+
import { useState as useState8 } from "react";
|
|
411
731
|
function useContactCapture() {
|
|
412
732
|
const { client } = useFoxPixelContext();
|
|
413
|
-
const [isLoading, setIsLoading] =
|
|
414
|
-
const [error, setError] =
|
|
733
|
+
const [isLoading, setIsLoading] = useState8(false);
|
|
734
|
+
const [error, setError] = useState8(null);
|
|
415
735
|
const captureContact = async (data) => {
|
|
416
736
|
try {
|
|
417
737
|
setIsLoading(true);
|
|
@@ -433,13 +753,144 @@ function useContactCapture() {
|
|
|
433
753
|
};
|
|
434
754
|
}
|
|
435
755
|
|
|
756
|
+
// src/hooks/useSiteContent.ts
|
|
757
|
+
import { useState as useState9, useEffect as useEffect7, useCallback as useCallback4 } from "react";
|
|
758
|
+
function useSiteContent(contentKey, options = {}) {
|
|
759
|
+
const { defaultValue = "", fetchOnMount = true } = options;
|
|
760
|
+
const { client } = useFoxPixelContext();
|
|
761
|
+
const { user, hasPermission } = useAuth();
|
|
762
|
+
const [data, setData] = useState9(null);
|
|
763
|
+
const [isLoading, setIsLoading] = useState9(fetchOnMount);
|
|
764
|
+
const [error, setError] = useState9(null);
|
|
765
|
+
const canEdit = user !== null && hasPermission("site:content:update");
|
|
766
|
+
const fetchContent = useCallback4(async () => {
|
|
767
|
+
try {
|
|
768
|
+
setIsLoading(true);
|
|
769
|
+
setError(null);
|
|
770
|
+
const content = await client.get(
|
|
771
|
+
`/api/site/content/${encodeURIComponent(contentKey)}`
|
|
772
|
+
);
|
|
773
|
+
setData(content);
|
|
774
|
+
} catch (err) {
|
|
775
|
+
if (err?.status === 404) {
|
|
776
|
+
setData(null);
|
|
777
|
+
} else {
|
|
778
|
+
setError(err);
|
|
779
|
+
}
|
|
780
|
+
} finally {
|
|
781
|
+
setIsLoading(false);
|
|
782
|
+
}
|
|
783
|
+
}, [client, contentKey]);
|
|
784
|
+
const updateContent = useCallback4(async (newValue) => {
|
|
785
|
+
try {
|
|
786
|
+
setError(null);
|
|
787
|
+
const updated = await client.put(
|
|
788
|
+
`/api/site/content/${encodeURIComponent(contentKey)}`,
|
|
789
|
+
{ value: newValue }
|
|
790
|
+
);
|
|
791
|
+
setData(updated);
|
|
792
|
+
} catch (err) {
|
|
793
|
+
setError(err);
|
|
794
|
+
throw err;
|
|
795
|
+
}
|
|
796
|
+
}, [client, contentKey]);
|
|
797
|
+
useEffect7(() => {
|
|
798
|
+
if (fetchOnMount) {
|
|
799
|
+
fetchContent();
|
|
800
|
+
}
|
|
801
|
+
}, [contentKey, fetchOnMount]);
|
|
802
|
+
const value = data?.value ?? defaultValue;
|
|
803
|
+
return {
|
|
804
|
+
data,
|
|
805
|
+
value,
|
|
806
|
+
isLoading,
|
|
807
|
+
error,
|
|
808
|
+
canEdit,
|
|
809
|
+
update: updateContent,
|
|
810
|
+
refetch: fetchContent
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function useSiteContents(contentKeys, options = {}) {
|
|
814
|
+
const { defaults = {} } = options;
|
|
815
|
+
const { client } = useFoxPixelContext();
|
|
816
|
+
const [data, setData] = useState9({});
|
|
817
|
+
const [isLoading, setIsLoading] = useState9(true);
|
|
818
|
+
const [error, setError] = useState9(null);
|
|
819
|
+
const fetchContents = useCallback4(async () => {
|
|
820
|
+
if (contentKeys.length === 0) {
|
|
821
|
+
setData({});
|
|
822
|
+
setIsLoading(false);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
setIsLoading(true);
|
|
827
|
+
setError(null);
|
|
828
|
+
const contents = await client.post(
|
|
829
|
+
"/api/site/content/batch",
|
|
830
|
+
contentKeys
|
|
831
|
+
);
|
|
832
|
+
setData(contents);
|
|
833
|
+
} catch (err) {
|
|
834
|
+
setError(err);
|
|
835
|
+
} finally {
|
|
836
|
+
setIsLoading(false);
|
|
837
|
+
}
|
|
838
|
+
}, [client, contentKeys.join(",")]);
|
|
839
|
+
useEffect7(() => {
|
|
840
|
+
fetchContents();
|
|
841
|
+
}, [fetchContents]);
|
|
842
|
+
const getValue = useCallback4((key, defaultValue) => {
|
|
843
|
+
const content = data[key];
|
|
844
|
+
if (content?.value) {
|
|
845
|
+
return content.value;
|
|
846
|
+
}
|
|
847
|
+
return defaultValue ?? defaults[key] ?? "";
|
|
848
|
+
}, [data, defaults]);
|
|
849
|
+
return {
|
|
850
|
+
data,
|
|
851
|
+
getValue,
|
|
852
|
+
isLoading,
|
|
853
|
+
error,
|
|
854
|
+
refetch: fetchContents
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
function useSiteContentSection(section) {
|
|
858
|
+
const { client } = useFoxPixelContext();
|
|
859
|
+
const [contents, setContents] = useState9([]);
|
|
860
|
+
const [isLoading, setIsLoading] = useState9(true);
|
|
861
|
+
const [error, setError] = useState9(null);
|
|
862
|
+
const fetchContents = useCallback4(async () => {
|
|
863
|
+
try {
|
|
864
|
+
setIsLoading(true);
|
|
865
|
+
setError(null);
|
|
866
|
+
const data = await client.get(
|
|
867
|
+
`/api/site/content/section/${encodeURIComponent(section)}`
|
|
868
|
+
);
|
|
869
|
+
setContents(data);
|
|
870
|
+
} catch (err) {
|
|
871
|
+
setError(err);
|
|
872
|
+
} finally {
|
|
873
|
+
setIsLoading(false);
|
|
874
|
+
}
|
|
875
|
+
}, [client, section]);
|
|
876
|
+
useEffect7(() => {
|
|
877
|
+
fetchContents();
|
|
878
|
+
}, [fetchContents]);
|
|
879
|
+
return {
|
|
880
|
+
contents,
|
|
881
|
+
isLoading,
|
|
882
|
+
error,
|
|
883
|
+
refetch: fetchContents
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
|
|
436
887
|
// src/blog/hooks.ts
|
|
437
|
-
import { useState as
|
|
888
|
+
import { useState as useState10, useEffect as useEffect8 } from "react";
|
|
438
889
|
function useBlogPosts(options = {}) {
|
|
439
890
|
const { client } = useFoxPixelContext();
|
|
440
|
-
const [data, setData] =
|
|
441
|
-
const [isLoading, setIsLoading] =
|
|
442
|
-
const [error, setError] =
|
|
891
|
+
const [data, setData] = useState10(null);
|
|
892
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
893
|
+
const [error, setError] = useState10(null);
|
|
443
894
|
const page = options.page ?? 0;
|
|
444
895
|
const limit = options.limit ?? 10;
|
|
445
896
|
const fetchPosts = async () => {
|
|
@@ -459,7 +910,7 @@ function useBlogPosts(options = {}) {
|
|
|
459
910
|
setIsLoading(false);
|
|
460
911
|
}
|
|
461
912
|
};
|
|
462
|
-
|
|
913
|
+
useEffect8(() => {
|
|
463
914
|
fetchPosts();
|
|
464
915
|
}, [page, limit]);
|
|
465
916
|
return {
|
|
@@ -471,9 +922,9 @@ function useBlogPosts(options = {}) {
|
|
|
471
922
|
}
|
|
472
923
|
function useBlogPost(slug) {
|
|
473
924
|
const { client } = useFoxPixelContext();
|
|
474
|
-
const [data, setData] =
|
|
475
|
-
const [isLoading, setIsLoading] =
|
|
476
|
-
const [error, setError] =
|
|
925
|
+
const [data, setData] = useState10(null);
|
|
926
|
+
const [isLoading, setIsLoading] = useState10(!!slug);
|
|
927
|
+
const [error, setError] = useState10(null);
|
|
477
928
|
const fetchPost = async () => {
|
|
478
929
|
if (!slug) {
|
|
479
930
|
setData(null);
|
|
@@ -492,7 +943,7 @@ function useBlogPost(slug) {
|
|
|
492
943
|
setIsLoading(false);
|
|
493
944
|
}
|
|
494
945
|
};
|
|
495
|
-
|
|
946
|
+
useEffect8(() => {
|
|
496
947
|
fetchPost();
|
|
497
948
|
}, [slug]);
|
|
498
949
|
return {
|
|
@@ -504,9 +955,9 @@ function useBlogPost(slug) {
|
|
|
504
955
|
}
|
|
505
956
|
function useBlogCategories() {
|
|
506
957
|
const { client } = useFoxPixelContext();
|
|
507
|
-
const [data, setData] =
|
|
508
|
-
const [isLoading, setIsLoading] =
|
|
509
|
-
const [error, setError] =
|
|
958
|
+
const [data, setData] = useState10(null);
|
|
959
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
960
|
+
const [error, setError] = useState10(null);
|
|
510
961
|
const fetchCategories = async () => {
|
|
511
962
|
try {
|
|
512
963
|
setIsLoading(true);
|
|
@@ -520,7 +971,7 @@ function useBlogCategories() {
|
|
|
520
971
|
setIsLoading(false);
|
|
521
972
|
}
|
|
522
973
|
};
|
|
523
|
-
|
|
974
|
+
useEffect8(() => {
|
|
524
975
|
fetchCategories();
|
|
525
976
|
}, []);
|
|
526
977
|
return {
|
|
@@ -532,9 +983,9 @@ function useBlogCategories() {
|
|
|
532
983
|
}
|
|
533
984
|
function useBlogTags() {
|
|
534
985
|
const { client } = useFoxPixelContext();
|
|
535
|
-
const [data, setData] =
|
|
536
|
-
const [isLoading, setIsLoading] =
|
|
537
|
-
const [error, setError] =
|
|
986
|
+
const [data, setData] = useState10(null);
|
|
987
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
988
|
+
const [error, setError] = useState10(null);
|
|
538
989
|
const fetchTags = async () => {
|
|
539
990
|
try {
|
|
540
991
|
setIsLoading(true);
|
|
@@ -548,7 +999,7 @@ function useBlogTags() {
|
|
|
548
999
|
setIsLoading(false);
|
|
549
1000
|
}
|
|
550
1001
|
};
|
|
551
|
-
|
|
1002
|
+
useEffect8(() => {
|
|
552
1003
|
fetchTags();
|
|
553
1004
|
}, []);
|
|
554
1005
|
return {
|
|
@@ -560,9 +1011,9 @@ function useBlogTags() {
|
|
|
560
1011
|
}
|
|
561
1012
|
function useBlogComments(slug) {
|
|
562
1013
|
const { client } = useFoxPixelContext();
|
|
563
|
-
const [data, setData] =
|
|
564
|
-
const [isLoading, setIsLoading] =
|
|
565
|
-
const [error, setError] =
|
|
1014
|
+
const [data, setData] = useState10(null);
|
|
1015
|
+
const [isLoading, setIsLoading] = useState10(!!slug);
|
|
1016
|
+
const [error, setError] = useState10(null);
|
|
566
1017
|
const fetchComments = async () => {
|
|
567
1018
|
if (!slug) {
|
|
568
1019
|
setData(null);
|
|
@@ -583,7 +1034,7 @@ function useBlogComments(slug) {
|
|
|
583
1034
|
setIsLoading(false);
|
|
584
1035
|
}
|
|
585
1036
|
};
|
|
586
|
-
|
|
1037
|
+
useEffect8(() => {
|
|
587
1038
|
fetchComments();
|
|
588
1039
|
}, [slug]);
|
|
589
1040
|
return {
|
|
@@ -595,8 +1046,8 @@ function useBlogComments(slug) {
|
|
|
595
1046
|
}
|
|
596
1047
|
function useBlogCommentSubmit(slug) {
|
|
597
1048
|
const { client } = useFoxPixelContext();
|
|
598
|
-
const [isSubmitting, setIsSubmitting] =
|
|
599
|
-
const [error, setError] =
|
|
1049
|
+
const [isSubmitting, setIsSubmitting] = useState10(false);
|
|
1050
|
+
const [error, setError] = useState10(null);
|
|
600
1051
|
const submit = async (payload) => {
|
|
601
1052
|
if (!slug) return null;
|
|
602
1053
|
try {
|
|
@@ -624,9 +1075,9 @@ function useBlogCommentSubmit(slug) {
|
|
|
624
1075
|
}
|
|
625
1076
|
function useBlogFeaturedPosts(limit = 6) {
|
|
626
1077
|
const { client } = useFoxPixelContext();
|
|
627
|
-
const [data, setData] =
|
|
628
|
-
const [isLoading, setIsLoading] =
|
|
629
|
-
const [error, setError] =
|
|
1078
|
+
const [data, setData] = useState10(null);
|
|
1079
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
1080
|
+
const [error, setError] = useState10(null);
|
|
630
1081
|
const fetchFeatured = async () => {
|
|
631
1082
|
try {
|
|
632
1083
|
setIsLoading(true);
|
|
@@ -644,7 +1095,7 @@ function useBlogFeaturedPosts(limit = 6) {
|
|
|
644
1095
|
setIsLoading(false);
|
|
645
1096
|
}
|
|
646
1097
|
};
|
|
647
|
-
|
|
1098
|
+
useEffect8(() => {
|
|
648
1099
|
fetchFeatured();
|
|
649
1100
|
}, [limit]);
|
|
650
1101
|
return {
|
|
@@ -656,9 +1107,9 @@ function useBlogFeaturedPosts(limit = 6) {
|
|
|
656
1107
|
}
|
|
657
1108
|
function useNewsletterSubscribe() {
|
|
658
1109
|
const { client } = useFoxPixelContext();
|
|
659
|
-
const [isSubmitting, setIsSubmitting] =
|
|
660
|
-
const [error, setError] =
|
|
661
|
-
const [success, setSuccess] =
|
|
1110
|
+
const [isSubmitting, setIsSubmitting] = useState10(false);
|
|
1111
|
+
const [error, setError] = useState10(null);
|
|
1112
|
+
const [success, setSuccess] = useState10(false);
|
|
662
1113
|
const subscribe = async (payload) => {
|
|
663
1114
|
try {
|
|
664
1115
|
setIsSubmitting(true);
|
|
@@ -691,9 +1142,9 @@ function useNewsletterSubscribe() {
|
|
|
691
1142
|
}
|
|
692
1143
|
function useNewsletterUnsubscribe() {
|
|
693
1144
|
const { client } = useFoxPixelContext();
|
|
694
|
-
const [isSubmitting, setIsSubmitting] =
|
|
695
|
-
const [error, setError] =
|
|
696
|
-
const [success, setSuccess] =
|
|
1145
|
+
const [isSubmitting, setIsSubmitting] = useState10(false);
|
|
1146
|
+
const [error, setError] = useState10(null);
|
|
1147
|
+
const [success, setSuccess] = useState10(false);
|
|
697
1148
|
const unsubscribe = async (email) => {
|
|
698
1149
|
try {
|
|
699
1150
|
setIsSubmitting(true);
|
|
@@ -711,8 +1162,26 @@ function useNewsletterUnsubscribe() {
|
|
|
711
1162
|
setIsSubmitting(false);
|
|
712
1163
|
}
|
|
713
1164
|
};
|
|
1165
|
+
const unsubscribeByToken = async (token) => {
|
|
1166
|
+
try {
|
|
1167
|
+
setIsSubmitting(true);
|
|
1168
|
+
setError(null);
|
|
1169
|
+
setSuccess(false);
|
|
1170
|
+
await client.get("/api/v1/blog/newsletter/unsubscribe", {
|
|
1171
|
+
params: { token }
|
|
1172
|
+
});
|
|
1173
|
+
setSuccess(true);
|
|
1174
|
+
return true;
|
|
1175
|
+
} catch (err) {
|
|
1176
|
+
setError(err);
|
|
1177
|
+
return false;
|
|
1178
|
+
} finally {
|
|
1179
|
+
setIsSubmitting(false);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
714
1182
|
return {
|
|
715
1183
|
unsubscribe,
|
|
1184
|
+
unsubscribeByToken,
|
|
716
1185
|
isSubmitting,
|
|
717
1186
|
error,
|
|
718
1187
|
success
|
|
@@ -720,15 +1189,15 @@ function useNewsletterUnsubscribe() {
|
|
|
720
1189
|
}
|
|
721
1190
|
|
|
722
1191
|
// src/blog/admin-hooks.ts
|
|
723
|
-
import { useState as
|
|
1192
|
+
import { useState as useState11, useEffect as useEffect9, useCallback as useCallback5 } from "react";
|
|
724
1193
|
function useAdminBlogPosts(options = {}) {
|
|
725
1194
|
const { client } = useFoxPixelContext();
|
|
726
|
-
const [data, setData] =
|
|
727
|
-
const [isLoading, setIsLoading] =
|
|
728
|
-
const [error, setError] =
|
|
1195
|
+
const [data, setData] = useState11(null);
|
|
1196
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1197
|
+
const [error, setError] = useState11(null);
|
|
729
1198
|
const page = options.page ?? 0;
|
|
730
1199
|
const size = options.size ?? 20;
|
|
731
|
-
const fetchPosts =
|
|
1200
|
+
const fetchPosts = useCallback5(async () => {
|
|
732
1201
|
try {
|
|
733
1202
|
setIsLoading(true);
|
|
734
1203
|
setError(null);
|
|
@@ -743,17 +1212,17 @@ function useAdminBlogPosts(options = {}) {
|
|
|
743
1212
|
setIsLoading(false);
|
|
744
1213
|
}
|
|
745
1214
|
}, [client, page, size]);
|
|
746
|
-
|
|
1215
|
+
useEffect9(() => {
|
|
747
1216
|
fetchPosts();
|
|
748
1217
|
}, [fetchPosts]);
|
|
749
1218
|
return { data, isLoading, error, refetch: fetchPosts };
|
|
750
1219
|
}
|
|
751
1220
|
function useAdminBlogPost(id) {
|
|
752
1221
|
const { client } = useFoxPixelContext();
|
|
753
|
-
const [data, setData] =
|
|
754
|
-
const [isLoading, setIsLoading] =
|
|
755
|
-
const [error, setError] =
|
|
756
|
-
const fetchPost =
|
|
1222
|
+
const [data, setData] = useState11(null);
|
|
1223
|
+
const [isLoading, setIsLoading] = useState11(!!id);
|
|
1224
|
+
const [error, setError] = useState11(null);
|
|
1225
|
+
const fetchPost = useCallback5(async () => {
|
|
757
1226
|
if (!id) {
|
|
758
1227
|
setData(null);
|
|
759
1228
|
setIsLoading(false);
|
|
@@ -770,15 +1239,15 @@ function useAdminBlogPost(id) {
|
|
|
770
1239
|
setIsLoading(false);
|
|
771
1240
|
}
|
|
772
1241
|
}, [client, id]);
|
|
773
|
-
|
|
1242
|
+
useEffect9(() => {
|
|
774
1243
|
fetchPost();
|
|
775
1244
|
}, [fetchPost]);
|
|
776
1245
|
return { data, isLoading, error, refetch: fetchPost };
|
|
777
1246
|
}
|
|
778
1247
|
function useAdminBlogPostMutations() {
|
|
779
1248
|
const { client } = useFoxPixelContext();
|
|
780
|
-
const [isLoading, setIsLoading] =
|
|
781
|
-
const [error, setError] =
|
|
1249
|
+
const [isLoading, setIsLoading] = useState11(false);
|
|
1250
|
+
const [error, setError] = useState11(null);
|
|
782
1251
|
const create = async (payload) => {
|
|
783
1252
|
try {
|
|
784
1253
|
setIsLoading(true);
|
|
@@ -822,10 +1291,10 @@ function useAdminBlogPostMutations() {
|
|
|
822
1291
|
}
|
|
823
1292
|
function useAdminBlogCategories() {
|
|
824
1293
|
const { client } = useFoxPixelContext();
|
|
825
|
-
const [data, setData] =
|
|
826
|
-
const [isLoading, setIsLoading] =
|
|
827
|
-
const [error, setError] =
|
|
828
|
-
const fetchCategories =
|
|
1294
|
+
const [data, setData] = useState11(null);
|
|
1295
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1296
|
+
const [error, setError] = useState11(null);
|
|
1297
|
+
const fetchCategories = useCallback5(async () => {
|
|
829
1298
|
try {
|
|
830
1299
|
setIsLoading(true);
|
|
831
1300
|
setError(null);
|
|
@@ -837,7 +1306,7 @@ function useAdminBlogCategories() {
|
|
|
837
1306
|
setIsLoading(false);
|
|
838
1307
|
}
|
|
839
1308
|
}, [client]);
|
|
840
|
-
|
|
1309
|
+
useEffect9(() => {
|
|
841
1310
|
fetchCategories();
|
|
842
1311
|
}, [fetchCategories]);
|
|
843
1312
|
const create = async (payload) => {
|
|
@@ -874,10 +1343,10 @@ function useAdminBlogCategories() {
|
|
|
874
1343
|
}
|
|
875
1344
|
function useAdminBlogTags() {
|
|
876
1345
|
const { client } = useFoxPixelContext();
|
|
877
|
-
const [data, setData] =
|
|
878
|
-
const [isLoading, setIsLoading] =
|
|
879
|
-
const [error, setError] =
|
|
880
|
-
const fetchTags =
|
|
1346
|
+
const [data, setData] = useState11(null);
|
|
1347
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1348
|
+
const [error, setError] = useState11(null);
|
|
1349
|
+
const fetchTags = useCallback5(async () => {
|
|
881
1350
|
try {
|
|
882
1351
|
setIsLoading(true);
|
|
883
1352
|
setError(null);
|
|
@@ -889,7 +1358,7 @@ function useAdminBlogTags() {
|
|
|
889
1358
|
setIsLoading(false);
|
|
890
1359
|
}
|
|
891
1360
|
}, [client]);
|
|
892
|
-
|
|
1361
|
+
useEffect9(() => {
|
|
893
1362
|
fetchTags();
|
|
894
1363
|
}, [fetchTags]);
|
|
895
1364
|
const create = async (payload) => {
|
|
@@ -926,11 +1395,11 @@ function useAdminBlogTags() {
|
|
|
926
1395
|
}
|
|
927
1396
|
function useAdminBlogComments(options = {}) {
|
|
928
1397
|
const { client } = useFoxPixelContext();
|
|
929
|
-
const [data, setData] =
|
|
930
|
-
const [isLoading, setIsLoading] =
|
|
931
|
-
const [error, setError] =
|
|
1398
|
+
const [data, setData] = useState11(null);
|
|
1399
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1400
|
+
const [error, setError] = useState11(null);
|
|
932
1401
|
const { status, postId, page = 0, size = 20 } = options;
|
|
933
|
-
const fetchComments =
|
|
1402
|
+
const fetchComments = useCallback5(async () => {
|
|
934
1403
|
try {
|
|
935
1404
|
setIsLoading(true);
|
|
936
1405
|
setError(null);
|
|
@@ -947,7 +1416,7 @@ function useAdminBlogComments(options = {}) {
|
|
|
947
1416
|
setIsLoading(false);
|
|
948
1417
|
}
|
|
949
1418
|
}, [client, status, postId, page, size]);
|
|
950
|
-
|
|
1419
|
+
useEffect9(() => {
|
|
951
1420
|
fetchComments();
|
|
952
1421
|
}, [fetchComments]);
|
|
953
1422
|
const updateStatus = async (id, newStatus) => {
|
|
@@ -974,11 +1443,11 @@ function useAdminBlogComments(options = {}) {
|
|
|
974
1443
|
}
|
|
975
1444
|
function useAdminNewsletterSubscribers(options = {}) {
|
|
976
1445
|
const { client } = useFoxPixelContext();
|
|
977
|
-
const [data, setData] =
|
|
978
|
-
const [isLoading, setIsLoading] =
|
|
979
|
-
const [error, setError] =
|
|
1446
|
+
const [data, setData] = useState11(null);
|
|
1447
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1448
|
+
const [error, setError] = useState11(null);
|
|
980
1449
|
const { status, page = 0, size = 20 } = options;
|
|
981
|
-
const fetchSubscribers =
|
|
1450
|
+
const fetchSubscribers = useCallback5(async () => {
|
|
982
1451
|
try {
|
|
983
1452
|
setIsLoading(true);
|
|
984
1453
|
setError(null);
|
|
@@ -994,7 +1463,7 @@ function useAdminNewsletterSubscribers(options = {}) {
|
|
|
994
1463
|
setIsLoading(false);
|
|
995
1464
|
}
|
|
996
1465
|
}, [client, status, page, size]);
|
|
997
|
-
|
|
1466
|
+
useEffect9(() => {
|
|
998
1467
|
fetchSubscribers();
|
|
999
1468
|
}, [fetchSubscribers]);
|
|
1000
1469
|
const remove = async (id) => {
|
|
@@ -1011,10 +1480,10 @@ function useAdminNewsletterSubscribers(options = {}) {
|
|
|
1011
1480
|
}
|
|
1012
1481
|
function useAdminNewsletterStats() {
|
|
1013
1482
|
const { client } = useFoxPixelContext();
|
|
1014
|
-
const [data, setData] =
|
|
1015
|
-
const [isLoading, setIsLoading] =
|
|
1016
|
-
const [error, setError] =
|
|
1017
|
-
const fetchStats =
|
|
1483
|
+
const [data, setData] = useState11(null);
|
|
1484
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1485
|
+
const [error, setError] = useState11(null);
|
|
1486
|
+
const fetchStats = useCallback5(async () => {
|
|
1018
1487
|
try {
|
|
1019
1488
|
setIsLoading(true);
|
|
1020
1489
|
setError(null);
|
|
@@ -1026,17 +1495,17 @@ function useAdminNewsletterStats() {
|
|
|
1026
1495
|
setIsLoading(false);
|
|
1027
1496
|
}
|
|
1028
1497
|
}, [client]);
|
|
1029
|
-
|
|
1498
|
+
useEffect9(() => {
|
|
1030
1499
|
fetchStats();
|
|
1031
1500
|
}, [fetchStats]);
|
|
1032
1501
|
return { data, isLoading, error, refetch: fetchStats };
|
|
1033
1502
|
}
|
|
1034
1503
|
function useAdminBlogSettings() {
|
|
1035
1504
|
const { client } = useFoxPixelContext();
|
|
1036
|
-
const [data, setData] =
|
|
1037
|
-
const [isLoading, setIsLoading] =
|
|
1038
|
-
const [error, setError] =
|
|
1039
|
-
const fetchSettings =
|
|
1505
|
+
const [data, setData] = useState11(null);
|
|
1506
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1507
|
+
const [error, setError] = useState11(null);
|
|
1508
|
+
const fetchSettings = useCallback5(async () => {
|
|
1040
1509
|
try {
|
|
1041
1510
|
setIsLoading(true);
|
|
1042
1511
|
setError(null);
|
|
@@ -1048,7 +1517,7 @@ function useAdminBlogSettings() {
|
|
|
1048
1517
|
setIsLoading(false);
|
|
1049
1518
|
}
|
|
1050
1519
|
}, [client]);
|
|
1051
|
-
|
|
1520
|
+
useEffect9(() => {
|
|
1052
1521
|
fetchSettings();
|
|
1053
1522
|
}, [fetchSettings]);
|
|
1054
1523
|
const update = async (settings) => {
|
|
@@ -1065,10 +1534,10 @@ function useAdminBlogSettings() {
|
|
|
1065
1534
|
}
|
|
1066
1535
|
function useAdminBlogAnalytics() {
|
|
1067
1536
|
const { client } = useFoxPixelContext();
|
|
1068
|
-
const [data, setData] =
|
|
1069
|
-
const [isLoading, setIsLoading] =
|
|
1070
|
-
const [error, setError] =
|
|
1071
|
-
const fetchAnalytics =
|
|
1537
|
+
const [data, setData] = useState11(null);
|
|
1538
|
+
const [isLoading, setIsLoading] = useState11(true);
|
|
1539
|
+
const [error, setError] = useState11(null);
|
|
1540
|
+
const fetchAnalytics = useCallback5(async () => {
|
|
1072
1541
|
try {
|
|
1073
1542
|
setIsLoading(true);
|
|
1074
1543
|
setError(null);
|
|
@@ -1080,7 +1549,7 @@ function useAdminBlogAnalytics() {
|
|
|
1080
1549
|
setIsLoading(false);
|
|
1081
1550
|
}
|
|
1082
1551
|
}, [client]);
|
|
1083
|
-
|
|
1552
|
+
useEffect9(() => {
|
|
1084
1553
|
fetchAnalytics();
|
|
1085
1554
|
}, [fetchAnalytics]);
|
|
1086
1555
|
return { data, isLoading, error, refetch: fetchAnalytics };
|
|
@@ -1119,10 +1588,14 @@ function getBlogPostSchemaLd(post, options) {
|
|
|
1119
1588
|
}
|
|
1120
1589
|
export {
|
|
1121
1590
|
AuthProvider,
|
|
1591
|
+
Editable,
|
|
1592
|
+
EditableHTML,
|
|
1593
|
+
EditableImage,
|
|
1122
1594
|
FoxPixelHttpClient,
|
|
1123
1595
|
FoxPixelProvider,
|
|
1124
1596
|
GuestOnlyRoute,
|
|
1125
1597
|
ProtectedRoute,
|
|
1598
|
+
SITE_CONTENT_QUERY_KEY,
|
|
1126
1599
|
getBlogPostSchemaLd,
|
|
1127
1600
|
useAdminBlogAnalytics,
|
|
1128
1601
|
useAdminBlogCategories,
|
|
@@ -1143,11 +1616,18 @@ export {
|
|
|
1143
1616
|
useBlogPosts,
|
|
1144
1617
|
useBlogTags,
|
|
1145
1618
|
useContactCapture,
|
|
1619
|
+
useEditMode,
|
|
1620
|
+
useEditModeMessaging,
|
|
1146
1621
|
useFoxPixelContext,
|
|
1147
1622
|
useLeadCapture,
|
|
1148
1623
|
useNewsletterSubscribe,
|
|
1149
1624
|
useNewsletterUnsubscribe,
|
|
1625
|
+
useSendEditRequest,
|
|
1150
1626
|
useServices,
|
|
1627
|
+
useSiteContent,
|
|
1628
|
+
useSiteContentQuery,
|
|
1629
|
+
useSiteContentSection,
|
|
1630
|
+
useSiteContents,
|
|
1151
1631
|
withAuth
|
|
1152
1632
|
};
|
|
1153
1633
|
//# sourceMappingURL=index.mjs.map
|