@jytextiles/medusa-plugin-faire-store-sync 0.2.5 → 0.2.7
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/.medusa/server/src/__tests__/faire-client.spec.js +124 -7
- package/.medusa/server/src/__tests__/ingest-faire-order-support.spec.js +61 -1
- package/.medusa/server/src/admin/index.js +167 -137
- package/.medusa/server/src/admin/index.mjs +168 -138
- package/.medusa/server/src/api/admin/faire/status/route.js +4 -2
- package/.medusa/server/src/api/admin/faire/taxonomy/route.js +12 -0
- package/.medusa/server/src/lib/faire-client.js +120 -18
- package/.medusa/server/src/lib/types.js +6 -2
- package/.medusa/server/src/modules/faire-sync/service.js +18 -3
- package/.medusa/server/src/workflows/ingest-faire-order-support.js +81 -28
- package/.medusa/server/src/workflows/sync-product-to-faire.js +108 -37
- package/package.json +1 -1
- package/src/__tests__/faire-client.spec.ts +135 -6
- package/src/__tests__/ingest-faire-order-support.spec.ts +63 -0
- package/src/admin/lib/api.ts +4 -0
- package/src/admin/routes/settings/faire/[id]/page.tsx +56 -61
- package/src/admin/routes/settings/faire/settings/page.tsx +62 -13
- package/src/api/admin/faire/status/route.ts +3 -1
- package/src/api/admin/faire/taxonomy/route.ts +10 -0
- package/src/lib/faire-client.ts +139 -16
- package/src/lib/types.ts +57 -18
- package/src/modules/faire-sync/service.ts +23 -2
- package/src/workflows/ingest-faire-order-support.ts +96 -29
- package/src/workflows/sync-product-to-faire.ts +146 -42
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
|
|
3
|
-
import { Container, Heading, Text, StatusBadge, Alert, Tooltip, Button, createDataTableColumnHelper, toast, createDataTableFilterHelper, useDataTable, Skeleton, DropdownMenu, DataTable, Drawer, Label, Input, Toaster,
|
|
3
|
+
import { Container, Heading, Text, StatusBadge, Alert, Tooltip, Button, createDataTableColumnHelper, toast, createDataTableFilterHelper, useDataTable, Skeleton, DropdownMenu, DataTable, Drawer, Label, Input, Toaster, FocusModal, Badge, IconButton, Switch, clx, Select } from "@medusajs/ui";
|
|
4
4
|
import { useQueryClient, useQuery, useMutation, keepPreviousData } from "@tanstack/react-query";
|
|
5
5
|
import Medusa from "@medusajs/js-sdk";
|
|
6
6
|
import { BuildingStorefront, ChevronDownMini, EllipsisHorizontal, ArrowPath, ArrowUpRightOnBox } from "@medusajs/icons";
|
|
@@ -60,6 +60,9 @@ const faireApi = {
|
|
|
60
60
|
getSync: (id) => sdk.client.fetch(`/admin/faire/syncs/${id}`),
|
|
61
61
|
retrySync: (id) => sdk.client.fetch(`/admin/faire/syncs/${id}`, { method: "POST" }),
|
|
62
62
|
brand: () => sdk.client.fetch("/admin/faire/brand"),
|
|
63
|
+
taxonomy: () => sdk.client.fetch(
|
|
64
|
+
"/admin/faire/taxonomy"
|
|
65
|
+
),
|
|
63
66
|
products: (opts = {}) => {
|
|
64
67
|
const query = {};
|
|
65
68
|
if (opts.limit !== void 0) query.limit = String(opts.limit);
|
|
@@ -478,124 +481,6 @@ const config = defineRouteConfig({
|
|
|
478
481
|
const handle$3 = {
|
|
479
482
|
breadcrumb: () => "Faire Sync"
|
|
480
483
|
};
|
|
481
|
-
const STATUS_COLORS = {
|
|
482
|
-
success: "green",
|
|
483
|
-
failed: "red",
|
|
484
|
-
draft: "orange",
|
|
485
|
-
pending: "grey",
|
|
486
|
-
syncing: "grey"
|
|
487
|
-
};
|
|
488
|
-
const FaireSyncDetailPage = () => {
|
|
489
|
-
const { id } = useParams();
|
|
490
|
-
const navigate = useNavigate();
|
|
491
|
-
const [record, setRecord] = useState(null);
|
|
492
|
-
const [loading, setLoading] = useState(true);
|
|
493
|
-
const [retrying, setRetrying] = useState(false);
|
|
494
|
-
const [error, setError] = useState(null);
|
|
495
|
-
useEffect(() => {
|
|
496
|
-
if (!id) return;
|
|
497
|
-
setLoading(true);
|
|
498
|
-
faireApi.getSync(id).then((res) => {
|
|
499
|
-
setRecord(res.sync || res);
|
|
500
|
-
}).catch((err) => setError(err.message || "Failed to load sync record")).finally(() => setLoading(false));
|
|
501
|
-
}, [id]);
|
|
502
|
-
const handleRetry = async () => {
|
|
503
|
-
if (!record) return;
|
|
504
|
-
setRetrying(true);
|
|
505
|
-
setError(null);
|
|
506
|
-
try {
|
|
507
|
-
await faireApi.retrySync(record.id);
|
|
508
|
-
const updated = await faireApi.getSync(record.id).catch(() => null);
|
|
509
|
-
if (updated) setRecord(updated.sync || updated);
|
|
510
|
-
} catch (err) {
|
|
511
|
-
setError(err.message || "Retry failed");
|
|
512
|
-
} finally {
|
|
513
|
-
setRetrying(false);
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
if (loading) {
|
|
517
|
-
return /* @__PURE__ */ jsx(Container, { className: "p-6", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }) });
|
|
518
|
-
}
|
|
519
|
-
if (!record) {
|
|
520
|
-
return /* @__PURE__ */ jsxs(Container, { className: "p-6 flex flex-col gap-4", children: [
|
|
521
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Sync record not found" }),
|
|
522
|
-
/* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: () => navigate("/settings/faire"), children: "Back to Faire settings" })
|
|
523
|
-
] });
|
|
524
|
-
}
|
|
525
|
-
const warnings = record.error_message ? record.error_message.split(" | ") : [];
|
|
526
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
527
|
-
error && /* @__PURE__ */ jsx(Container, { className: "p-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-tag-red-text", children: error }) }),
|
|
528
|
-
/* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
529
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
|
|
530
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
531
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Sync record" }),
|
|
532
|
-
/* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle font-mono text-xs", children: record.id })
|
|
533
|
-
] }),
|
|
534
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
535
|
-
/* @__PURE__ */ jsx(StatusBadge, { color: STATUS_COLORS[record.status] || "grey", children: record.status }),
|
|
536
|
-
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
537
|
-
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { size: "small", variant: "transparent", disabled: retrying, children: /* @__PURE__ */ jsx(EllipsisHorizontal, {}) }) }),
|
|
538
|
-
/* @__PURE__ */ jsxs(DropdownMenu.Content, { align: "end", children: [
|
|
539
|
-
/* @__PURE__ */ jsxs(
|
|
540
|
-
DropdownMenu.Item,
|
|
541
|
-
{
|
|
542
|
-
className: "gap-x-2",
|
|
543
|
-
onClick: handleRetry,
|
|
544
|
-
disabled: retrying,
|
|
545
|
-
children: [
|
|
546
|
-
/* @__PURE__ */ jsx(ArrowPath, { className: "text-ui-fg-subtle" }),
|
|
547
|
-
retrying ? "Re-syncing…" : "Re-sync product"
|
|
548
|
-
]
|
|
549
|
-
}
|
|
550
|
-
),
|
|
551
|
-
record.product_url && /* @__PURE__ */ jsxs(
|
|
552
|
-
DropdownMenu.Item,
|
|
553
|
-
{
|
|
554
|
-
className: "gap-x-2",
|
|
555
|
-
onClick: () => window.open(record.product_url, "_blank"),
|
|
556
|
-
children: [
|
|
557
|
-
/* @__PURE__ */ jsx(ArrowUpRightOnBox, { className: "text-ui-fg-subtle" }),
|
|
558
|
-
"Open on Faire"
|
|
559
|
-
]
|
|
560
|
-
}
|
|
561
|
-
)
|
|
562
|
-
] })
|
|
563
|
-
] })
|
|
564
|
-
] })
|
|
565
|
-
] }),
|
|
566
|
-
/* @__PURE__ */ jsxs("div", { className: "px-6 py-4 grid grid-cols-2 gap-4", children: [
|
|
567
|
-
/* @__PURE__ */ jsx(Detail, { label: "Product", value: record.product_id, mono: true }),
|
|
568
|
-
/* @__PURE__ */ jsx(Detail, { label: "Action", value: record.action }),
|
|
569
|
-
/* @__PURE__ */ jsx(Detail, { label: "Faire product token", value: record.product_token || "—", mono: true }),
|
|
570
|
-
/* @__PURE__ */ jsx(Detail, { label: "State", value: record.product_state || "—" }),
|
|
571
|
-
/* @__PURE__ */ jsx(Detail, { label: "Published", value: record.published ? "Yes" : "No" }),
|
|
572
|
-
/* @__PURE__ */ jsx(
|
|
573
|
-
Detail,
|
|
574
|
-
{
|
|
575
|
-
label: "Synced at",
|
|
576
|
-
value: record.synced_at ? new Date(record.synced_at).toLocaleString() : "—"
|
|
577
|
-
}
|
|
578
|
-
)
|
|
579
|
-
] })
|
|
580
|
-
] }),
|
|
581
|
-
warnings.length > 0 && /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
582
|
-
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Issues" }) }),
|
|
583
|
-
/* @__PURE__ */ jsx("div", { className: "px-6 py-4 flex flex-col gap-2", children: warnings.map((w, i) => /* @__PURE__ */ jsx(Text, { className: "text-ui-tag-red-text text-sm", children: w }, i)) })
|
|
584
|
-
] }),
|
|
585
|
-
/* @__PURE__ */ jsx(Toaster, {})
|
|
586
|
-
] });
|
|
587
|
-
};
|
|
588
|
-
const Detail = ({
|
|
589
|
-
label,
|
|
590
|
-
value,
|
|
591
|
-
mono
|
|
592
|
-
}) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
593
|
-
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
594
|
-
/* @__PURE__ */ jsx(Text, { className: mono ? "font-mono text-xs" : "", children: value })
|
|
595
|
-
] });
|
|
596
|
-
const handle$2 = {
|
|
597
|
-
breadcrumb: () => "Sync record"
|
|
598
|
-
};
|
|
599
484
|
const Root = ({ prev = "..", children }) => {
|
|
600
485
|
const navigate = useNavigate();
|
|
601
486
|
const [open, setOpen] = useState(false);
|
|
@@ -892,10 +777,124 @@ const FaireBulkPage = () => {
|
|
|
892
777
|
/* @__PURE__ */ jsx(Toaster, {})
|
|
893
778
|
] });
|
|
894
779
|
};
|
|
895
|
-
const handle$
|
|
780
|
+
const handle$2 = {
|
|
896
781
|
breadcrumb: () => "Bulk sync"
|
|
897
782
|
};
|
|
783
|
+
const PARENT$1 = "/settings/faire";
|
|
784
|
+
const STATUS_COLORS = {
|
|
785
|
+
success: "green",
|
|
786
|
+
failed: "red",
|
|
787
|
+
draft: "orange",
|
|
788
|
+
pending: "grey",
|
|
789
|
+
syncing: "grey"
|
|
790
|
+
};
|
|
791
|
+
const FaireSyncDetailPage = () => {
|
|
792
|
+
const { id } = useParams();
|
|
793
|
+
const navigate = useNavigate();
|
|
794
|
+
const [record, setRecord] = useState(null);
|
|
795
|
+
const [loading, setLoading] = useState(true);
|
|
796
|
+
const [retrying, setRetrying] = useState(false);
|
|
797
|
+
const [error, setError] = useState(null);
|
|
798
|
+
useEffect(() => {
|
|
799
|
+
if (!id) return;
|
|
800
|
+
setLoading(true);
|
|
801
|
+
faireApi.getSync(id).then((res) => {
|
|
802
|
+
setRecord(res.sync || res);
|
|
803
|
+
}).catch((err) => setError(err.message || "Failed to load sync record")).finally(() => setLoading(false));
|
|
804
|
+
}, [id]);
|
|
805
|
+
const handleRetry = async () => {
|
|
806
|
+
if (!record) return;
|
|
807
|
+
setRetrying(true);
|
|
808
|
+
setError(null);
|
|
809
|
+
try {
|
|
810
|
+
await faireApi.retrySync(record.id);
|
|
811
|
+
const updated = await faireApi.getSync(record.id).catch(() => null);
|
|
812
|
+
if (updated) setRecord(updated.sync || updated);
|
|
813
|
+
} catch (err) {
|
|
814
|
+
setError(err.message || "Retry failed");
|
|
815
|
+
} finally {
|
|
816
|
+
setRetrying(false);
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
const warnings = (record == null ? void 0 : record.error_message) ? record.error_message.split(" | ") : [];
|
|
820
|
+
return /* @__PURE__ */ jsxs(RouteFocusModal, { prev: PARENT$1, children: [
|
|
821
|
+
/* @__PURE__ */ jsxs(RouteFocusModal.Header, { children: [
|
|
822
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
823
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Sync record" }),
|
|
824
|
+
record && /* @__PURE__ */ jsx(StatusBadge, { color: STATUS_COLORS[record.status] || "grey", children: record.status })
|
|
825
|
+
] }),
|
|
826
|
+
record && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
827
|
+
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { size: "small", variant: "transparent", disabled: retrying, children: /* @__PURE__ */ jsx(EllipsisHorizontal, {}) }) }),
|
|
828
|
+
/* @__PURE__ */ jsxs(DropdownMenu.Content, { align: "end", children: [
|
|
829
|
+
/* @__PURE__ */ jsxs(
|
|
830
|
+
DropdownMenu.Item,
|
|
831
|
+
{
|
|
832
|
+
className: "gap-x-2",
|
|
833
|
+
onClick: handleRetry,
|
|
834
|
+
disabled: retrying,
|
|
835
|
+
children: [
|
|
836
|
+
/* @__PURE__ */ jsx(ArrowPath, { className: "text-ui-fg-subtle" }),
|
|
837
|
+
retrying ? "Re-syncing…" : "Re-sync product"
|
|
838
|
+
]
|
|
839
|
+
}
|
|
840
|
+
),
|
|
841
|
+
record.product_url && /* @__PURE__ */ jsxs(
|
|
842
|
+
DropdownMenu.Item,
|
|
843
|
+
{
|
|
844
|
+
className: "gap-x-2",
|
|
845
|
+
onClick: () => window.open(record.product_url, "_blank"),
|
|
846
|
+
children: [
|
|
847
|
+
/* @__PURE__ */ jsx(ArrowUpRightOnBox, { className: "text-ui-fg-subtle" }),
|
|
848
|
+
"Open on Faire"
|
|
849
|
+
]
|
|
850
|
+
}
|
|
851
|
+
)
|
|
852
|
+
] })
|
|
853
|
+
] }) })
|
|
854
|
+
] }),
|
|
855
|
+
/* @__PURE__ */ jsxs(RouteFocusModal.Body, { className: "flex flex-col gap-4 overflow-y-auto p-6", children: [
|
|
856
|
+
error && /* @__PURE__ */ jsx(Text, { className: "text-ui-tag-red-text", children: error }),
|
|
857
|
+
loading ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" }, i)) }) : !record ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-4", children: [
|
|
858
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "Sync record not found" }),
|
|
859
|
+
/* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: () => navigate(PARENT$1), children: "Back to Faire settings" })
|
|
860
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
861
|
+
/* @__PURE__ */ jsxs("div", { className: "border-ui-border-base grid grid-cols-2 gap-4 rounded-lg border p-4", children: [
|
|
862
|
+
/* @__PURE__ */ jsx(Detail, { label: "Record id", value: record.id, mono: true }),
|
|
863
|
+
/* @__PURE__ */ jsx(Detail, { label: "Product", value: record.product_id, mono: true }),
|
|
864
|
+
/* @__PURE__ */ jsx(Detail, { label: "Action", value: record.action }),
|
|
865
|
+
/* @__PURE__ */ jsx(Detail, { label: "Faire product token", value: record.product_token || "—", mono: true }),
|
|
866
|
+
/* @__PURE__ */ jsx(Detail, { label: "State", value: record.product_state || "—" }),
|
|
867
|
+
/* @__PURE__ */ jsx(Detail, { label: "Published", value: record.published ? "Yes" : "No" }),
|
|
868
|
+
/* @__PURE__ */ jsx(
|
|
869
|
+
Detail,
|
|
870
|
+
{
|
|
871
|
+
label: "Synced at",
|
|
872
|
+
value: record.synced_at ? new Date(record.synced_at).toLocaleString() : "—"
|
|
873
|
+
}
|
|
874
|
+
)
|
|
875
|
+
] }),
|
|
876
|
+
warnings.length > 0 && /* @__PURE__ */ jsxs("div", { className: "border-ui-border-base flex flex-col gap-2 rounded-lg border p-4", children: [
|
|
877
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "Issues" }),
|
|
878
|
+
warnings.map((w, i) => /* @__PURE__ */ jsx(Text, { className: "text-ui-tag-red-text text-sm", children: w }, i))
|
|
879
|
+
] })
|
|
880
|
+
] })
|
|
881
|
+
] }),
|
|
882
|
+
/* @__PURE__ */ jsx(Toaster, {})
|
|
883
|
+
] });
|
|
884
|
+
};
|
|
885
|
+
const Detail = ({
|
|
886
|
+
label,
|
|
887
|
+
value,
|
|
888
|
+
mono
|
|
889
|
+
}) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
890
|
+
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
891
|
+
/* @__PURE__ */ jsx(Text, { className: mono ? "font-mono text-xs" : "", children: value })
|
|
892
|
+
] });
|
|
893
|
+
const handle$1 = {
|
|
894
|
+
breadcrumb: () => "Sync record"
|
|
895
|
+
};
|
|
898
896
|
const STATUS_KEY = ["faire", "status"];
|
|
897
|
+
const TAXONOMY_KEY = ["faire", "taxonomy"];
|
|
899
898
|
const PARENT = "/settings/faire";
|
|
900
899
|
const NONE = "__none__";
|
|
901
900
|
const cleanSettings = (form) => {
|
|
@@ -930,6 +929,11 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
930
929
|
});
|
|
931
930
|
const status = statusQuery.data;
|
|
932
931
|
const connected = !!(status == null ? void 0 : status.connected);
|
|
932
|
+
const taxonomyQuery = useQuery({
|
|
933
|
+
queryKey: TAXONOMY_KEY,
|
|
934
|
+
queryFn: async () => (await faireApi.taxonomy().catch(() => ({ taxonomy: [] }))).taxonomy || []
|
|
935
|
+
});
|
|
936
|
+
const taxonomy = taxonomyQuery.data ?? [];
|
|
933
937
|
useEffect(() => {
|
|
934
938
|
if (status == null ? void 0 : status.settings) setForm(status.settings);
|
|
935
939
|
}, [status == null ? void 0 : status.settings]);
|
|
@@ -958,7 +962,8 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
958
962
|
/* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.connected, label: "Faire connected" }),
|
|
959
963
|
/* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.brand, label: "Brand configured" }),
|
|
960
964
|
/* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.wholesale_pricing, label: "Wholesale pricing" }),
|
|
961
|
-
/* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.shipping_policy, label: "Shipping policy" })
|
|
965
|
+
/* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.shipping_policy, label: "Shipping policy" }),
|
|
966
|
+
/* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.taxonomy, label: "Default category" })
|
|
962
967
|
] })
|
|
963
968
|
] }),
|
|
964
969
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
@@ -968,9 +973,8 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
968
973
|
] }),
|
|
969
974
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
|
|
970
975
|
/* @__PURE__ */ jsx(Field, { label: "Brand ID", children: /* @__PURE__ */ jsx(
|
|
971
|
-
|
|
976
|
+
Input,
|
|
972
977
|
{
|
|
973
|
-
className: "border-ui-border-base rounded-lg border px-3 py-2 text-sm",
|
|
974
978
|
value: String(form.default_brand_id ?? ""),
|
|
975
979
|
onChange: (e) => setForm({ ...form, default_brand_id: e.target.value || null }),
|
|
976
980
|
disabled: !connected,
|
|
@@ -978,10 +982,9 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
978
982
|
}
|
|
979
983
|
) }),
|
|
980
984
|
/* @__PURE__ */ jsx(Field, { label: "Wholesale markup % (off retail)", children: /* @__PURE__ */ jsx(Tooltip, { content: "Wholesale price = retail × (100 − markup%) / 100. E.g. 50 → half of retail.", children: /* @__PURE__ */ jsx(
|
|
981
|
-
|
|
985
|
+
Input,
|
|
982
986
|
{
|
|
983
987
|
type: "number",
|
|
984
|
-
className: "border-ui-border-base rounded-lg border px-3 py-2 text-sm",
|
|
985
988
|
value: String(form.default_wholesale_markup_percent ?? ""),
|
|
986
989
|
onChange: (e) => setForm({
|
|
987
990
|
...form,
|
|
@@ -992,10 +995,9 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
992
995
|
}
|
|
993
996
|
) }) }),
|
|
994
997
|
/* @__PURE__ */ jsx(Field, { label: "Default min order quantity", children: /* @__PURE__ */ jsx(
|
|
995
|
-
|
|
998
|
+
Input,
|
|
996
999
|
{
|
|
997
1000
|
type: "number",
|
|
998
|
-
className: "border-ui-border-base rounded-lg border px-3 py-2 text-sm",
|
|
999
1001
|
value: String(form.default_min_order_quantity ?? 1),
|
|
1000
1002
|
onChange: (e) => setForm({
|
|
1001
1003
|
...form,
|
|
@@ -1005,10 +1007,9 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
1005
1007
|
}
|
|
1006
1008
|
) }),
|
|
1007
1009
|
/* @__PURE__ */ jsx(Field, { label: "Default lead time (days)", children: /* @__PURE__ */ jsx(
|
|
1008
|
-
|
|
1010
|
+
Input,
|
|
1009
1011
|
{
|
|
1010
1012
|
type: "number",
|
|
1011
|
-
className: "border-ui-border-base rounded-lg border px-3 py-2 text-sm",
|
|
1012
1013
|
value: String(form.default_lead_time_days ?? ""),
|
|
1013
1014
|
onChange: (e) => setForm({
|
|
1014
1015
|
...form,
|
|
@@ -1018,14 +1019,22 @@ const FaireSyncSettingsDrawer = () => {
|
|
|
1018
1019
|
placeholder: "e.g. 14"
|
|
1019
1020
|
}
|
|
1020
1021
|
) }),
|
|
1021
|
-
/* @__PURE__ */ jsx(Field, { label: "Default category", children: /* @__PURE__ */ jsx(
|
|
1022
|
-
|
|
1022
|
+
/* @__PURE__ */ jsx(Field, { label: "Default category (taxonomy)", children: /* @__PURE__ */ jsx(
|
|
1023
|
+
SelectField,
|
|
1023
1024
|
{
|
|
1024
|
-
className: "border-ui-border-base rounded-lg border px-3 py-2 text-sm",
|
|
1025
1025
|
value: String(form.default_category ?? ""),
|
|
1026
|
-
|
|
1026
|
+
onValueChange: (v) => setForm({ ...form, default_category: v || null }),
|
|
1027
1027
|
disabled: !connected,
|
|
1028
|
-
|
|
1028
|
+
options: taxonomy.map((t) => ({ value: t.id, label: t.name }))
|
|
1029
|
+
}
|
|
1030
|
+
) }),
|
|
1031
|
+
/* @__PURE__ */ jsx(Field, { label: "Shipping policy ID", children: /* @__PURE__ */ jsx(
|
|
1032
|
+
Input,
|
|
1033
|
+
{
|
|
1034
|
+
value: String(form.default_shipping_policy_id ?? ""),
|
|
1035
|
+
onChange: (e) => setForm({ ...form, default_shipping_policy_id: e.target.value || null }),
|
|
1036
|
+
disabled: !connected,
|
|
1037
|
+
placeholder: "sp_..."
|
|
1029
1038
|
}
|
|
1030
1039
|
) }),
|
|
1031
1040
|
/* @__PURE__ */ jsx(Field, { label: "Follow product status", children: /* @__PURE__ */ jsx(Tooltip, { content: "If on, published Medusa products are published on Faire; draft products sync as drafts.", children: /* @__PURE__ */ jsx(
|
|
@@ -1065,6 +1074,27 @@ const Field = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className:
|
|
|
1065
1074
|
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
1066
1075
|
children
|
|
1067
1076
|
] });
|
|
1077
|
+
const SelectField = ({
|
|
1078
|
+
value,
|
|
1079
|
+
onValueChange,
|
|
1080
|
+
options,
|
|
1081
|
+
disabled
|
|
1082
|
+
}) => /* @__PURE__ */ jsxs(
|
|
1083
|
+
Select,
|
|
1084
|
+
{
|
|
1085
|
+
value: value ? value : NONE,
|
|
1086
|
+
onValueChange: (v) => onValueChange(v === NONE ? "" : v),
|
|
1087
|
+
disabled,
|
|
1088
|
+
size: "small",
|
|
1089
|
+
children: [
|
|
1090
|
+
/* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Not set" }) }),
|
|
1091
|
+
/* @__PURE__ */ jsxs(Select.Content, { children: [
|
|
1092
|
+
/* @__PURE__ */ jsx(Select.Item, { value: NONE, children: "Not set" }),
|
|
1093
|
+
options.map((o) => /* @__PURE__ */ jsx(Select.Item, { value: o.value, children: o.label }, o.value))
|
|
1094
|
+
] })
|
|
1095
|
+
]
|
|
1096
|
+
}
|
|
1097
|
+
);
|
|
1068
1098
|
const ChecklistItem = ({ ok, label }) => /* @__PURE__ */ jsxs(
|
|
1069
1099
|
"div",
|
|
1070
1100
|
{
|
|
@@ -1162,13 +1192,13 @@ const routeModule = {
|
|
|
1162
1192
|
handle: handle$3
|
|
1163
1193
|
},
|
|
1164
1194
|
{
|
|
1165
|
-
Component:
|
|
1166
|
-
path: "/settings/faire
|
|
1195
|
+
Component: FaireBulkPage,
|
|
1196
|
+
path: "/settings/faire/bulk",
|
|
1167
1197
|
handle: handle$2
|
|
1168
1198
|
},
|
|
1169
1199
|
{
|
|
1170
|
-
Component:
|
|
1171
|
-
path: "/settings/faire
|
|
1200
|
+
Component: FaireSyncDetailPage,
|
|
1201
|
+
path: "/settings/faire/:id",
|
|
1172
1202
|
handle: handle$1
|
|
1173
1203
|
},
|
|
1174
1204
|
{
|
|
@@ -12,6 +12,7 @@ const GET = async (req, res) => {
|
|
|
12
12
|
const hasMarkup = settings.default_wholesale_markup_percent != null &&
|
|
13
13
|
settings.default_wholesale_markup_percent > 0;
|
|
14
14
|
const hasShipping = !!settings.default_shipping_policy_id;
|
|
15
|
+
const hasTaxonomy = !!settings.default_category;
|
|
15
16
|
res.json({
|
|
16
17
|
connected,
|
|
17
18
|
account: account
|
|
@@ -38,9 +39,10 @@ const GET = async (req, res) => {
|
|
|
38
39
|
brand: hasBrand,
|
|
39
40
|
wholesale_pricing: hasMarkup,
|
|
40
41
|
shipping_policy: hasShipping,
|
|
41
|
-
|
|
42
|
+
taxonomy: hasTaxonomy,
|
|
43
|
+
ready_to_publish: connected && hasBrand && hasTaxonomy,
|
|
42
44
|
},
|
|
43
45
|
});
|
|
44
46
|
};
|
|
45
47
|
exports.GET = GET;
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ZhaXJlL3N0YXR1cy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSwrREFBa0U7QUFHbEUsb0VBQW9FO0FBQzdELE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLE9BQU8sR0FBcUIsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsOEJBQWlCLENBQUMsQ0FBQTtJQUN0RSxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO0lBQ2hELE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBRTVDLE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQTtJQUNoRCxNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFBO0lBQzVDLE1BQU0sU0FBUyxHQUNiLFFBQVEsQ0FBQyxnQ0FBZ0MsSUFBSSxJQUFJO1FBQ2pELFFBQVEsQ0FBQyxnQ0FBZ0MsR0FBRyxDQUFDLENBQUE7SUFDL0MsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQywwQkFBMEIsQ0FBQTtJQUN6RCxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFBO0lBRS9DLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDUCxTQUFTO1FBQ1QsT0FBTyxFQUFFLE9BQU87WUFDZCxDQUFDLENBQUM7Z0JBQ0UsRUFBRSxFQUFFLE9BQU8sQ0FBQyxFQUFFO2dCQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtnQkFDMUIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVO2dCQUM5QixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7Z0JBQzFCLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0I7YUFDM0M7WUFDSCxDQUFDLENBQUMsSUFBSTtRQUNSLFFBQVEsRUFBRTtZQUNSLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxnQkFBZ0I7WUFDM0MsZ0NBQWdDLEVBQUUsUUFBUSxDQUFDLGdDQUFnQztZQUMzRSwwQkFBMEIsRUFBRSxRQUFRLENBQUMsMEJBQTBCO1lBQy9ELHNCQUFzQixFQUFFLFFBQVEsQ0FBQyxzQkFBc0I7WUFDdkQsMEJBQTBCLEVBQUUsUUFBUSxDQUFDLDBCQUEwQjtZQUMvRCxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsZ0JBQWdCO1lBQzNDLFlBQVksRUFBRSxRQUFRLENBQUMsWUFBWTtZQUNuQyxxQkFBcUIsRUFBRSxRQUFRLENBQUMscUJBQXFCO1NBQ3REO1FBQ0QsU0FBUyxFQUFFO1lBQ1QsU0FBUztZQUNULEtBQUssRUFBRSxRQUFRO1lBQ2YsaUJBQWlCLEVBQUUsU0FBUztZQUM1QixlQUFlLEVBQUUsV0FBVztZQUM1QixRQUFRLEVBQUUsV0FBVztZQUNyQixnQkFBZ0IsRUFBRSxTQUFTLElBQUksUUFBUSxJQUFJLFdBQVc7U0FDdkQ7S0FDRixDQUFDLENBQUE7QUFDSixDQUFDLENBQUE7QUEzQ1ksUUFBQSxHQUFHLE9BMkNmIn0=
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const faire_sync_1 = require("../../../../modules/faire-sync");
|
|
5
|
+
// GET /admin/faire/taxonomy — taxonomy types from Faire's /products/types
|
|
6
|
+
const GET = async (req, res) => {
|
|
7
|
+
const service = req.scope.resolve(faire_sync_1.FAIRE_SYNC_MODULE);
|
|
8
|
+
const types = await service.getTaxonomyTypes();
|
|
9
|
+
res.json({ taxonomy: types });
|
|
10
|
+
};
|
|
11
|
+
exports.GET = GET;
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ZhaXJlL3RheG9ub215L3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLCtEQUFrRTtBQUdsRSwwRUFBMEU7QUFDbkUsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sT0FBTyxHQUFxQixHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBQyxDQUFBO0lBQ3RFLE1BQU0sS0FBSyxHQUFHLE1BQU0sT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUE7SUFDOUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO0FBQy9CLENBQUMsQ0FBQTtBQUpZLFFBQUEsR0FBRyxPQUlmIn0=
|