@foxpixel/react 0.2.1 → 0.2.3
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 +30 -5
- package/dist/index.d.ts +30 -5
- package/dist/index.js +153 -83
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -107
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -124,7 +124,8 @@ function FoxPixelProvider({ children, config = {}, queryClient }) {
|
|
|
124
124
|
const value = useMemo(() => ({
|
|
125
125
|
client,
|
|
126
126
|
config,
|
|
127
|
-
queryClient: queryClient ?? null
|
|
127
|
+
queryClient: queryClient ?? null,
|
|
128
|
+
locale: config?.locale
|
|
128
129
|
}), [client, config, queryClient]);
|
|
129
130
|
return /* @__PURE__ */ jsx(FoxPixelContext.Provider, { value, children });
|
|
130
131
|
}
|
|
@@ -352,11 +353,33 @@ function withAuth(Component, options = {}) {
|
|
|
352
353
|
}
|
|
353
354
|
|
|
354
355
|
// src/components/Editable.tsx
|
|
355
|
-
import { createElement, useCallback as useCallback3, useState as useState7 } from "react";
|
|
356
|
+
import { createElement, useCallback as useCallback3, useState as useState7, useEffect as useEffect7 } from "react";
|
|
356
357
|
|
|
357
358
|
// src/hooks/useEditMode.ts
|
|
358
359
|
import { useEffect as useEffect5, useState as useState5, useCallback as useCallback2 } from "react";
|
|
359
360
|
var SITE_CONTENT_QUERY_KEY = "siteContent";
|
|
361
|
+
var contentKeysOnPage = /* @__PURE__ */ new Set();
|
|
362
|
+
var flushTimer = null;
|
|
363
|
+
function scheduleFlushContentKeys() {
|
|
364
|
+
if (flushTimer) return;
|
|
365
|
+
flushTimer = setTimeout(() => {
|
|
366
|
+
flushTimer = null;
|
|
367
|
+
if (typeof window !== "undefined" && window.parent !== window) {
|
|
368
|
+
window.parent.postMessage(
|
|
369
|
+
{ type: "FOXPIXEL_READY", payload: { contentKeys: Array.from(contentKeysOnPage) } },
|
|
370
|
+
"*"
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
}, 150);
|
|
374
|
+
}
|
|
375
|
+
function registerContentKey(key) {
|
|
376
|
+
contentKeysOnPage.add(key);
|
|
377
|
+
scheduleFlushContentKeys();
|
|
378
|
+
}
|
|
379
|
+
function unregisterContentKey(key) {
|
|
380
|
+
contentKeysOnPage.delete(key);
|
|
381
|
+
scheduleFlushContentKeys();
|
|
382
|
+
}
|
|
360
383
|
function useEditMode() {
|
|
361
384
|
const [isEditMode, setIsEditMode] = useState5(false);
|
|
362
385
|
useEffect5(() => {
|
|
@@ -377,19 +400,18 @@ function useEditModeMessaging() {
|
|
|
377
400
|
if (!queryClient) return;
|
|
378
401
|
const { type, payload } = event.data || {};
|
|
379
402
|
if (type !== "FOXPIXEL_CONTENT_UPDATED" || !payload?.contentKey) return;
|
|
380
|
-
const { contentKey, newValue } = payload;
|
|
403
|
+
const { contentKey, newValue, locale } = payload;
|
|
404
|
+
const cacheKey2 = locale != null && locale !== "" ? [SITE_CONTENT_QUERY_KEY, contentKey, locale] : [SITE_CONTENT_QUERY_KEY, contentKey];
|
|
381
405
|
if (typeof newValue === "string") {
|
|
382
406
|
queryClient.setQueryData(
|
|
383
|
-
|
|
407
|
+
cacheKey2,
|
|
384
408
|
(prev) => ({
|
|
385
409
|
value: newValue,
|
|
386
410
|
contentType: prev?.contentType ?? "TEXT"
|
|
387
411
|
})
|
|
388
412
|
);
|
|
389
413
|
}
|
|
390
|
-
queryClient.invalidateQueries({
|
|
391
|
-
queryKey: [SITE_CONTENT_QUERY_KEY, contentKey]
|
|
392
|
-
});
|
|
414
|
+
queryClient.invalidateQueries({ queryKey: cacheKey2 });
|
|
393
415
|
};
|
|
394
416
|
window.addEventListener("message", handleMessage);
|
|
395
417
|
return () => window.removeEventListener("message", handleMessage);
|
|
@@ -399,20 +421,19 @@ function useEditModeMessaging() {
|
|
|
399
421
|
function useSendEditRequest() {
|
|
400
422
|
const isEditMode = useEditMode();
|
|
401
423
|
return useCallback2(
|
|
402
|
-
(contentKey, currentValue, contentType = "text", section, description) => {
|
|
424
|
+
(contentKey, currentValue, contentType = "text", section, description, locale) => {
|
|
403
425
|
if (!isEditMode) return;
|
|
404
426
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
427
|
+
const payload = {
|
|
428
|
+
contentKey,
|
|
429
|
+
currentValue,
|
|
430
|
+
contentType,
|
|
431
|
+
section,
|
|
432
|
+
description
|
|
433
|
+
};
|
|
434
|
+
if (locale != null && locale !== "") payload.locale = locale;
|
|
405
435
|
window.parent.postMessage(
|
|
406
|
-
{
|
|
407
|
-
type: "FOXPIXEL_EDIT_CONTENT",
|
|
408
|
-
payload: {
|
|
409
|
-
contentKey,
|
|
410
|
-
currentValue,
|
|
411
|
-
contentType,
|
|
412
|
-
section,
|
|
413
|
-
description
|
|
414
|
-
}
|
|
415
|
-
},
|
|
436
|
+
{ type: "FOXPIXEL_EDIT_CONTENT", payload },
|
|
416
437
|
"*"
|
|
417
438
|
);
|
|
418
439
|
}
|
|
@@ -423,20 +444,23 @@ function useSendEditRequest() {
|
|
|
423
444
|
|
|
424
445
|
// src/hooks/useSiteContentQuery.ts
|
|
425
446
|
import { useState as useState6, useEffect as useEffect6, useRef } from "react";
|
|
426
|
-
function
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
447
|
+
function queryKey(contentKey, locale) {
|
|
448
|
+
return locale != null && locale !== "" ? [SITE_CONTENT_QUERY_KEY, contentKey, locale] : [SITE_CONTENT_QUERY_KEY, contentKey];
|
|
449
|
+
}
|
|
450
|
+
function getCached(queryClient, contentKey, locale) {
|
|
451
|
+
const data = queryClient.getQueryData(
|
|
452
|
+
queryKey(contentKey, locale)
|
|
453
|
+
);
|
|
431
454
|
if (data == null) return void 0;
|
|
432
455
|
return { value: data.value ?? "", contentType: data.contentType ?? "TEXT" };
|
|
433
456
|
}
|
|
434
457
|
function useSiteContentQuery(contentKey, options) {
|
|
435
|
-
const { defaultValue } = options;
|
|
458
|
+
const { defaultValue, locale } = options;
|
|
459
|
+
const loc = locale != null && locale !== "" ? locale : void 0;
|
|
436
460
|
const { client, queryClient } = useFoxPixelContext();
|
|
437
461
|
const [state, setState] = useState6(() => {
|
|
438
462
|
if (queryClient) {
|
|
439
|
-
const cached = getCached(queryClient, contentKey);
|
|
463
|
+
const cached = getCached(queryClient, contentKey, loc);
|
|
440
464
|
if (cached) {
|
|
441
465
|
return { value: cached.value, isLoading: false, contentType: cached.contentType };
|
|
442
466
|
}
|
|
@@ -445,18 +469,20 @@ function useSiteContentQuery(contentKey, options) {
|
|
|
445
469
|
});
|
|
446
470
|
const contentKeyRef = useRef(contentKey);
|
|
447
471
|
contentKeyRef.current = contentKey;
|
|
472
|
+
const localeRef = useRef(loc);
|
|
473
|
+
localeRef.current = loc;
|
|
448
474
|
useEffect6(() => {
|
|
449
475
|
if (!queryClient) {
|
|
450
476
|
setState((s) => ({ ...s, value: defaultValue, isLoading: false }));
|
|
451
477
|
return;
|
|
452
478
|
}
|
|
453
479
|
const key = contentKeyRef.current;
|
|
454
|
-
const
|
|
480
|
+
const locCurrent = localeRef.current;
|
|
481
|
+
const qKey = queryKey(key, locCurrent);
|
|
455
482
|
const queryFn = async () => {
|
|
456
483
|
try {
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
);
|
|
484
|
+
const url = `/api/site/content/${encodeURIComponent(key)}` + (locCurrent ? `?locale=${encodeURIComponent(locCurrent)}` : "");
|
|
485
|
+
const content = await client.get(url);
|
|
460
486
|
if (!content) return null;
|
|
461
487
|
return {
|
|
462
488
|
value: content.value ?? "",
|
|
@@ -470,7 +496,7 @@ function useSiteContentQuery(contentKey, options) {
|
|
|
470
496
|
};
|
|
471
497
|
let cancelled = false;
|
|
472
498
|
queryClient.fetchQuery({
|
|
473
|
-
queryKey,
|
|
499
|
+
queryKey: qKey,
|
|
474
500
|
queryFn,
|
|
475
501
|
staleTime: 1e3 * 60 * 5,
|
|
476
502
|
retry: 1
|
|
@@ -486,8 +512,11 @@ function useSiteContentQuery(contentKey, options) {
|
|
|
486
512
|
setState((s) => ({ ...s, value: defaultValue, isLoading: false }));
|
|
487
513
|
});
|
|
488
514
|
const unsub = queryClient.getQueryCache().subscribe((event) => {
|
|
489
|
-
|
|
490
|
-
|
|
515
|
+
const q = event?.query;
|
|
516
|
+
const keyMatch = q?.queryKey?.[1] === key;
|
|
517
|
+
const locMatch = (q?.queryKey?.[2] ?? void 0) === locCurrent;
|
|
518
|
+
if (event?.type === "updated" && q && keyMatch && locMatch) {
|
|
519
|
+
const cached = getCached(queryClient, key, locCurrent);
|
|
491
520
|
if (cached && !cancelled) {
|
|
492
521
|
setState({
|
|
493
522
|
value: cached.value,
|
|
@@ -501,7 +530,7 @@ function useSiteContentQuery(contentKey, options) {
|
|
|
501
530
|
cancelled = true;
|
|
502
531
|
unsub();
|
|
503
532
|
};
|
|
504
|
-
}, [queryClient, contentKey, defaultValue, client]);
|
|
533
|
+
}, [queryClient, contentKey, defaultValue, client, loc]);
|
|
505
534
|
return state;
|
|
506
535
|
}
|
|
507
536
|
|
|
@@ -579,15 +608,25 @@ function Editable({
|
|
|
579
608
|
defaultValue,
|
|
580
609
|
as = "span",
|
|
581
610
|
multiline = false,
|
|
582
|
-
className
|
|
611
|
+
className,
|
|
612
|
+
locale: localeProp
|
|
583
613
|
}) {
|
|
584
614
|
const [isHovered, setIsHovered] = useState7(false);
|
|
615
|
+
const { locale: contextLocale } = useFoxPixelContext();
|
|
616
|
+
const locale = localeProp ?? contextLocale;
|
|
585
617
|
const isEditMode = useEditModeMessaging();
|
|
586
618
|
const sendEditRequest = useSendEditRequest();
|
|
587
619
|
const { value, isLoading, contentType } = useSiteContentQuery(contentKey, {
|
|
588
|
-
defaultValue
|
|
620
|
+
defaultValue,
|
|
621
|
+
locale
|
|
589
622
|
});
|
|
590
623
|
const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
|
|
624
|
+
useEffect7(() => {
|
|
625
|
+
if (isEditMode) {
|
|
626
|
+
registerContentKey(contentKey);
|
|
627
|
+
return () => unregisterContentKey(contentKey);
|
|
628
|
+
}
|
|
629
|
+
}, [isEditMode, contentKey]);
|
|
591
630
|
const handleClick = useCallback3(
|
|
592
631
|
(e) => {
|
|
593
632
|
if (isEditMode) {
|
|
@@ -597,11 +636,13 @@ function Editable({
|
|
|
597
636
|
contentKey,
|
|
598
637
|
value,
|
|
599
638
|
contentType?.toLowerCase() || "text",
|
|
600
|
-
section
|
|
639
|
+
section,
|
|
640
|
+
void 0,
|
|
641
|
+
locale
|
|
601
642
|
);
|
|
602
643
|
}
|
|
603
644
|
},
|
|
604
|
-
[isEditMode, contentKey, value, contentType, section, sendEditRequest]
|
|
645
|
+
[isEditMode, contentKey, value, contentType, section, sendEditRequest, locale]
|
|
605
646
|
);
|
|
606
647
|
if (isLoading) {
|
|
607
648
|
return createElement(as, {
|
|
@@ -674,24 +715,34 @@ function EditableHTML({
|
|
|
674
715
|
contentKey,
|
|
675
716
|
defaultValue,
|
|
676
717
|
as = "div",
|
|
677
|
-
className
|
|
718
|
+
className,
|
|
719
|
+
locale: localeProp
|
|
678
720
|
}) {
|
|
679
721
|
const [isHovered, setIsHovered] = useState7(false);
|
|
722
|
+
const { locale: contextLocale } = useFoxPixelContext();
|
|
723
|
+
const locale = localeProp ?? contextLocale;
|
|
680
724
|
const isEditMode = useEditModeMessaging();
|
|
681
725
|
const sendEditRequest = useSendEditRequest();
|
|
682
726
|
const { value, isLoading } = useSiteContentQuery(contentKey, {
|
|
683
|
-
defaultValue
|
|
727
|
+
defaultValue,
|
|
728
|
+
locale
|
|
684
729
|
});
|
|
685
730
|
const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
|
|
731
|
+
useEffect7(() => {
|
|
732
|
+
if (isEditMode) {
|
|
733
|
+
registerContentKey(contentKey);
|
|
734
|
+
return () => unregisterContentKey(contentKey);
|
|
735
|
+
}
|
|
736
|
+
}, [isEditMode, contentKey]);
|
|
686
737
|
const handleClick = useCallback3(
|
|
687
738
|
(e) => {
|
|
688
739
|
if (isEditMode) {
|
|
689
740
|
e.preventDefault();
|
|
690
741
|
e.stopPropagation();
|
|
691
|
-
sendEditRequest(contentKey, value, "html", section);
|
|
742
|
+
sendEditRequest(contentKey, value, "html", section, void 0, locale);
|
|
692
743
|
}
|
|
693
744
|
},
|
|
694
|
-
[isEditMode, contentKey, value, section, sendEditRequest]
|
|
745
|
+
[isEditMode, contentKey, value, section, sendEditRequest, locale]
|
|
695
746
|
);
|
|
696
747
|
if (isLoading) {
|
|
697
748
|
return createElement(as, {
|
|
@@ -740,24 +791,34 @@ function EditableImage({
|
|
|
740
791
|
className,
|
|
741
792
|
width,
|
|
742
793
|
height,
|
|
743
|
-
priority = false
|
|
794
|
+
priority = false,
|
|
795
|
+
locale: localeProp
|
|
744
796
|
}) {
|
|
745
797
|
const [isHovered, setIsHovered] = useState7(false);
|
|
798
|
+
const { locale: contextLocale } = useFoxPixelContext();
|
|
799
|
+
const locale = localeProp ?? contextLocale;
|
|
746
800
|
const isEditMode = useEditModeMessaging();
|
|
747
801
|
const sendEditRequest = useSendEditRequest();
|
|
748
802
|
const { value: src, isLoading } = useSiteContentQuery(contentKey, {
|
|
749
|
-
defaultValue
|
|
803
|
+
defaultValue,
|
|
804
|
+
locale
|
|
750
805
|
});
|
|
751
806
|
const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
|
|
807
|
+
useEffect7(() => {
|
|
808
|
+
if (isEditMode) {
|
|
809
|
+
registerContentKey(contentKey);
|
|
810
|
+
return () => unregisterContentKey(contentKey);
|
|
811
|
+
}
|
|
812
|
+
}, [isEditMode, contentKey]);
|
|
752
813
|
const handleClick = useCallback3(
|
|
753
814
|
(e) => {
|
|
754
815
|
if (isEditMode) {
|
|
755
816
|
e.preventDefault();
|
|
756
817
|
e.stopPropagation();
|
|
757
|
-
sendEditRequest(contentKey, src, "image", section);
|
|
818
|
+
sendEditRequest(contentKey, src, "image", section, void 0, locale);
|
|
758
819
|
}
|
|
759
820
|
},
|
|
760
|
-
[isEditMode, contentKey, src, section, sendEditRequest]
|
|
821
|
+
[isEditMode, contentKey, src, section, sendEditRequest, locale]
|
|
761
822
|
);
|
|
762
823
|
if (isLoading) {
|
|
763
824
|
return /* @__PURE__ */ jsx6(
|
|
@@ -812,7 +873,7 @@ function EditableImage({
|
|
|
812
873
|
}
|
|
813
874
|
|
|
814
875
|
// src/hooks/useServices.ts
|
|
815
|
-
import { useState as useState8, useEffect as
|
|
876
|
+
import { useState as useState8, useEffect as useEffect8 } from "react";
|
|
816
877
|
function useServices(options = {}) {
|
|
817
878
|
const { client } = useFoxPixelContext();
|
|
818
879
|
const [services, setServices] = useState8(null);
|
|
@@ -835,7 +896,7 @@ function useServices(options = {}) {
|
|
|
835
896
|
setIsLoading(false);
|
|
836
897
|
}
|
|
837
898
|
};
|
|
838
|
-
|
|
899
|
+
useEffect8(() => {
|
|
839
900
|
fetchServices();
|
|
840
901
|
}, [options.category, options.active]);
|
|
841
902
|
return {
|
|
@@ -901,22 +962,22 @@ function useContactCapture() {
|
|
|
901
962
|
}
|
|
902
963
|
|
|
903
964
|
// src/hooks/useSiteContent.ts
|
|
904
|
-
import { useState as useState11, useEffect as
|
|
965
|
+
import { useState as useState11, useEffect as useEffect9, useCallback as useCallback4 } from "react";
|
|
905
966
|
function useSiteContent(contentKey, options = {}) {
|
|
906
|
-
const { defaultValue = "", fetchOnMount = true } = options;
|
|
967
|
+
const { defaultValue = "", fetchOnMount = true, locale } = options;
|
|
907
968
|
const { client } = useFoxPixelContext();
|
|
908
969
|
const { user, hasPermission } = useAuth();
|
|
909
970
|
const [data, setData] = useState11(null);
|
|
910
971
|
const [isLoading, setIsLoading] = useState11(fetchOnMount);
|
|
911
972
|
const [error, setError] = useState11(null);
|
|
912
973
|
const canEdit = user !== null && hasPermission("site:content:update");
|
|
974
|
+
const queryLocale = locale != null && locale !== "" ? locale : void 0;
|
|
913
975
|
const fetchContent = useCallback4(async () => {
|
|
914
976
|
try {
|
|
915
977
|
setIsLoading(true);
|
|
916
978
|
setError(null);
|
|
917
|
-
const
|
|
918
|
-
|
|
919
|
-
);
|
|
979
|
+
const url = `/api/site/content/${encodeURIComponent(contentKey)}` + (queryLocale ? `?locale=${encodeURIComponent(queryLocale)}` : "");
|
|
980
|
+
const content = await client.get(url);
|
|
920
981
|
setData(content);
|
|
921
982
|
} catch (err) {
|
|
922
983
|
if (err?.status === 404) {
|
|
@@ -927,21 +988,23 @@ function useSiteContent(contentKey, options = {}) {
|
|
|
927
988
|
} finally {
|
|
928
989
|
setIsLoading(false);
|
|
929
990
|
}
|
|
930
|
-
}, [client, contentKey]);
|
|
991
|
+
}, [client, contentKey, queryLocale]);
|
|
931
992
|
const updateContent = useCallback4(async (newValue) => {
|
|
932
993
|
try {
|
|
933
994
|
setError(null);
|
|
995
|
+
const body = { value: newValue };
|
|
996
|
+
if (queryLocale) body.locale = queryLocale;
|
|
934
997
|
const updated = await client.put(
|
|
935
998
|
`/api/site/content/${encodeURIComponent(contentKey)}`,
|
|
936
|
-
|
|
999
|
+
body
|
|
937
1000
|
);
|
|
938
1001
|
setData(updated);
|
|
939
1002
|
} catch (err) {
|
|
940
1003
|
setError(err);
|
|
941
1004
|
throw err;
|
|
942
1005
|
}
|
|
943
|
-
}, [client, contentKey]);
|
|
944
|
-
|
|
1006
|
+
}, [client, contentKey, queryLocale]);
|
|
1007
|
+
useEffect9(() => {
|
|
945
1008
|
if (fetchOnMount) {
|
|
946
1009
|
fetchContent();
|
|
947
1010
|
}
|
|
@@ -958,11 +1021,12 @@ function useSiteContent(contentKey, options = {}) {
|
|
|
958
1021
|
};
|
|
959
1022
|
}
|
|
960
1023
|
function useSiteContents(contentKeys, options = {}) {
|
|
961
|
-
const { defaults = {} } = options;
|
|
1024
|
+
const { defaults = {}, locale } = options;
|
|
962
1025
|
const { client } = useFoxPixelContext();
|
|
963
1026
|
const [data, setData] = useState11({});
|
|
964
1027
|
const [isLoading, setIsLoading] = useState11(true);
|
|
965
1028
|
const [error, setError] = useState11(null);
|
|
1029
|
+
const body = locale != null && locale !== "" ? { keys: contentKeys, locale } : contentKeys;
|
|
966
1030
|
const fetchContents = useCallback4(async () => {
|
|
967
1031
|
if (contentKeys.length === 0) {
|
|
968
1032
|
setData({});
|
|
@@ -974,7 +1038,7 @@ function useSiteContents(contentKeys, options = {}) {
|
|
|
974
1038
|
setError(null);
|
|
975
1039
|
const contents = await client.post(
|
|
976
1040
|
"/api/site/content/batch",
|
|
977
|
-
|
|
1041
|
+
body
|
|
978
1042
|
);
|
|
979
1043
|
setData(contents);
|
|
980
1044
|
} catch (err) {
|
|
@@ -982,8 +1046,8 @@ function useSiteContents(contentKeys, options = {}) {
|
|
|
982
1046
|
} finally {
|
|
983
1047
|
setIsLoading(false);
|
|
984
1048
|
}
|
|
985
|
-
}, [client, contentKeys.join(",")]);
|
|
986
|
-
|
|
1049
|
+
}, [client, contentKeys.join(","), locale]);
|
|
1050
|
+
useEffect9(() => {
|
|
987
1051
|
fetchContents();
|
|
988
1052
|
}, [fetchContents]);
|
|
989
1053
|
const getValue = useCallback4((key, defaultValue) => {
|
|
@@ -1001,26 +1065,26 @@ function useSiteContents(contentKeys, options = {}) {
|
|
|
1001
1065
|
refetch: fetchContents
|
|
1002
1066
|
};
|
|
1003
1067
|
}
|
|
1004
|
-
function useSiteContentSection(section) {
|
|
1068
|
+
function useSiteContentSection(section, options = {}) {
|
|
1069
|
+
const { locale } = options;
|
|
1005
1070
|
const { client } = useFoxPixelContext();
|
|
1006
1071
|
const [contents, setContents] = useState11([]);
|
|
1007
1072
|
const [isLoading, setIsLoading] = useState11(true);
|
|
1008
1073
|
const [error, setError] = useState11(null);
|
|
1074
|
+
const url = `/api/site/content/section/${encodeURIComponent(section)}` + (locale != null && locale !== "" ? `?locale=${encodeURIComponent(locale)}` : "");
|
|
1009
1075
|
const fetchContents = useCallback4(async () => {
|
|
1010
1076
|
try {
|
|
1011
1077
|
setIsLoading(true);
|
|
1012
1078
|
setError(null);
|
|
1013
|
-
const data = await client.get(
|
|
1014
|
-
`/api/site/content/section/${encodeURIComponent(section)}`
|
|
1015
|
-
);
|
|
1079
|
+
const data = await client.get(url);
|
|
1016
1080
|
setContents(data);
|
|
1017
1081
|
} catch (err) {
|
|
1018
1082
|
setError(err);
|
|
1019
1083
|
} finally {
|
|
1020
1084
|
setIsLoading(false);
|
|
1021
1085
|
}
|
|
1022
|
-
}, [client, section]);
|
|
1023
|
-
|
|
1086
|
+
}, [client, section, locale]);
|
|
1087
|
+
useEffect9(() => {
|
|
1024
1088
|
fetchContents();
|
|
1025
1089
|
}, [fetchContents]);
|
|
1026
1090
|
return {
|
|
@@ -1032,37 +1096,43 @@ function useSiteContentSection(section) {
|
|
|
1032
1096
|
}
|
|
1033
1097
|
|
|
1034
1098
|
// src/prefetchSiteContent.ts
|
|
1099
|
+
function cacheKey(contentKey, locale) {
|
|
1100
|
+
return locale != null && locale !== "" ? [SITE_CONTENT_QUERY_KEY, contentKey, locale] : [SITE_CONTENT_QUERY_KEY, contentKey];
|
|
1101
|
+
}
|
|
1035
1102
|
async function prefetchSiteContent(queryClient, options) {
|
|
1036
|
-
const { apiUrl, apiKey, tenantId, contentKeys } = options;
|
|
1103
|
+
const { apiUrl, apiKey, tenantId, contentKeys, locale } = options;
|
|
1037
1104
|
const client = new FoxPixelHttpClient({ apiUrl, apiKey, tenantId });
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
)
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1105
|
+
const locales = locale == null ? [void 0] : Array.isArray(locale) ? locale : [locale];
|
|
1106
|
+
const tasks = [];
|
|
1107
|
+
for (const contentKey of contentKeys) {
|
|
1108
|
+
for (const loc of locales) {
|
|
1109
|
+
tasks.push(
|
|
1110
|
+
(async () => {
|
|
1111
|
+
try {
|
|
1112
|
+
const url = `/api/site/content/${encodeURIComponent(contentKey)}` + (loc != null && loc !== "" ? `?locale=${encodeURIComponent(loc)}` : "");
|
|
1113
|
+
const content = await client.get(url);
|
|
1114
|
+
queryClient.setQueryData(cacheKey(contentKey, loc), {
|
|
1115
|
+
value: content?.value ?? "",
|
|
1116
|
+
contentType: content?.contentType ?? "TEXT"
|
|
1117
|
+
});
|
|
1118
|
+
} catch (err) {
|
|
1119
|
+
const status = err?.response?.status;
|
|
1120
|
+
if (status === 404) {
|
|
1121
|
+
queryClient.setQueryData(cacheKey(contentKey, loc), {
|
|
1122
|
+
value: "",
|
|
1123
|
+
contentType: "TEXT"
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1049
1126
|
}
|
|
1050
|
-
)
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
value: "",
|
|
1056
|
-
contentType: "TEXT"
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
})
|
|
1061
|
-
);
|
|
1127
|
+
})()
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
await Promise.all(tasks);
|
|
1062
1132
|
}
|
|
1063
1133
|
|
|
1064
1134
|
// src/blog/hooks.ts
|
|
1065
|
-
import { useState as useState12, useEffect as
|
|
1135
|
+
import { useState as useState12, useEffect as useEffect10 } from "react";
|
|
1066
1136
|
function useBlogPosts(options = {}) {
|
|
1067
1137
|
const { client } = useFoxPixelContext();
|
|
1068
1138
|
const [data, setData] = useState12(null);
|
|
@@ -1087,7 +1157,7 @@ function useBlogPosts(options = {}) {
|
|
|
1087
1157
|
setIsLoading(false);
|
|
1088
1158
|
}
|
|
1089
1159
|
};
|
|
1090
|
-
|
|
1160
|
+
useEffect10(() => {
|
|
1091
1161
|
fetchPosts();
|
|
1092
1162
|
}, [page, limit]);
|
|
1093
1163
|
return {
|
|
@@ -1120,7 +1190,7 @@ function useBlogPost(slug) {
|
|
|
1120
1190
|
setIsLoading(false);
|
|
1121
1191
|
}
|
|
1122
1192
|
};
|
|
1123
|
-
|
|
1193
|
+
useEffect10(() => {
|
|
1124
1194
|
fetchPost();
|
|
1125
1195
|
}, [slug]);
|
|
1126
1196
|
return {
|
|
@@ -1148,7 +1218,7 @@ function useBlogCategories() {
|
|
|
1148
1218
|
setIsLoading(false);
|
|
1149
1219
|
}
|
|
1150
1220
|
};
|
|
1151
|
-
|
|
1221
|
+
useEffect10(() => {
|
|
1152
1222
|
fetchCategories();
|
|
1153
1223
|
}, []);
|
|
1154
1224
|
return {
|
|
@@ -1176,7 +1246,7 @@ function useBlogTags() {
|
|
|
1176
1246
|
setIsLoading(false);
|
|
1177
1247
|
}
|
|
1178
1248
|
};
|
|
1179
|
-
|
|
1249
|
+
useEffect10(() => {
|
|
1180
1250
|
fetchTags();
|
|
1181
1251
|
}, []);
|
|
1182
1252
|
return {
|
|
@@ -1211,7 +1281,7 @@ function useBlogComments(slug) {
|
|
|
1211
1281
|
setIsLoading(false);
|
|
1212
1282
|
}
|
|
1213
1283
|
};
|
|
1214
|
-
|
|
1284
|
+
useEffect10(() => {
|
|
1215
1285
|
fetchComments();
|
|
1216
1286
|
}, [slug]);
|
|
1217
1287
|
return {
|
|
@@ -1272,7 +1342,7 @@ function useBlogFeaturedPosts(limit = 6) {
|
|
|
1272
1342
|
setIsLoading(false);
|
|
1273
1343
|
}
|
|
1274
1344
|
};
|
|
1275
|
-
|
|
1345
|
+
useEffect10(() => {
|
|
1276
1346
|
fetchFeatured();
|
|
1277
1347
|
}, [limit]);
|
|
1278
1348
|
return {
|
|
@@ -1366,7 +1436,7 @@ function useNewsletterUnsubscribe() {
|
|
|
1366
1436
|
}
|
|
1367
1437
|
|
|
1368
1438
|
// src/blog/admin-hooks.ts
|
|
1369
|
-
import { useState as useState13, useEffect as
|
|
1439
|
+
import { useState as useState13, useEffect as useEffect11, useCallback as useCallback5 } from "react";
|
|
1370
1440
|
function useAdminBlogPosts(options = {}) {
|
|
1371
1441
|
const { client } = useFoxPixelContext();
|
|
1372
1442
|
const [data, setData] = useState13(null);
|
|
@@ -1389,7 +1459,7 @@ function useAdminBlogPosts(options = {}) {
|
|
|
1389
1459
|
setIsLoading(false);
|
|
1390
1460
|
}
|
|
1391
1461
|
}, [client, page, size]);
|
|
1392
|
-
|
|
1462
|
+
useEffect11(() => {
|
|
1393
1463
|
fetchPosts();
|
|
1394
1464
|
}, [fetchPosts]);
|
|
1395
1465
|
return { data, isLoading, error, refetch: fetchPosts };
|
|
@@ -1416,7 +1486,7 @@ function useAdminBlogPost(id) {
|
|
|
1416
1486
|
setIsLoading(false);
|
|
1417
1487
|
}
|
|
1418
1488
|
}, [client, id]);
|
|
1419
|
-
|
|
1489
|
+
useEffect11(() => {
|
|
1420
1490
|
fetchPost();
|
|
1421
1491
|
}, [fetchPost]);
|
|
1422
1492
|
return { data, isLoading, error, refetch: fetchPost };
|
|
@@ -1483,7 +1553,7 @@ function useAdminBlogCategories() {
|
|
|
1483
1553
|
setIsLoading(false);
|
|
1484
1554
|
}
|
|
1485
1555
|
}, [client]);
|
|
1486
|
-
|
|
1556
|
+
useEffect11(() => {
|
|
1487
1557
|
fetchCategories();
|
|
1488
1558
|
}, [fetchCategories]);
|
|
1489
1559
|
const create = async (payload) => {
|
|
@@ -1535,7 +1605,7 @@ function useAdminBlogTags() {
|
|
|
1535
1605
|
setIsLoading(false);
|
|
1536
1606
|
}
|
|
1537
1607
|
}, [client]);
|
|
1538
|
-
|
|
1608
|
+
useEffect11(() => {
|
|
1539
1609
|
fetchTags();
|
|
1540
1610
|
}, [fetchTags]);
|
|
1541
1611
|
const create = async (payload) => {
|
|
@@ -1593,7 +1663,7 @@ function useAdminBlogComments(options = {}) {
|
|
|
1593
1663
|
setIsLoading(false);
|
|
1594
1664
|
}
|
|
1595
1665
|
}, [client, status, postId, page, size]);
|
|
1596
|
-
|
|
1666
|
+
useEffect11(() => {
|
|
1597
1667
|
fetchComments();
|
|
1598
1668
|
}, [fetchComments]);
|
|
1599
1669
|
const updateStatus = async (id, newStatus) => {
|
|
@@ -1640,7 +1710,7 @@ function useAdminNewsletterSubscribers(options = {}) {
|
|
|
1640
1710
|
setIsLoading(false);
|
|
1641
1711
|
}
|
|
1642
1712
|
}, [client, status, page, size]);
|
|
1643
|
-
|
|
1713
|
+
useEffect11(() => {
|
|
1644
1714
|
fetchSubscribers();
|
|
1645
1715
|
}, [fetchSubscribers]);
|
|
1646
1716
|
const remove = async (id) => {
|
|
@@ -1672,7 +1742,7 @@ function useAdminNewsletterStats() {
|
|
|
1672
1742
|
setIsLoading(false);
|
|
1673
1743
|
}
|
|
1674
1744
|
}, [client]);
|
|
1675
|
-
|
|
1745
|
+
useEffect11(() => {
|
|
1676
1746
|
fetchStats();
|
|
1677
1747
|
}, [fetchStats]);
|
|
1678
1748
|
return { data, isLoading, error, refetch: fetchStats };
|
|
@@ -1694,7 +1764,7 @@ function useAdminBlogSettings() {
|
|
|
1694
1764
|
setIsLoading(false);
|
|
1695
1765
|
}
|
|
1696
1766
|
}, [client]);
|
|
1697
|
-
|
|
1767
|
+
useEffect11(() => {
|
|
1698
1768
|
fetchSettings();
|
|
1699
1769
|
}, [fetchSettings]);
|
|
1700
1770
|
const update = async (settings) => {
|
|
@@ -1726,7 +1796,7 @@ function useAdminBlogAnalytics() {
|
|
|
1726
1796
|
setIsLoading(false);
|
|
1727
1797
|
}
|
|
1728
1798
|
}, [client]);
|
|
1729
|
-
|
|
1799
|
+
useEffect11(() => {
|
|
1730
1800
|
fetchAnalytics();
|
|
1731
1801
|
}, [fetchAnalytics]);
|
|
1732
1802
|
return { data, isLoading, error, refetch: fetchAnalytics };
|