@jytextiles/medusa-plugin-faire-store-sync 0.2.11 → 0.2.13

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.
@@ -619,213 +619,6 @@ const config = adminSdk.defineRouteConfig({
619
619
  const handle$3 = {
620
620
  breadcrumb: () => "Faire Sync"
621
621
  };
622
- const STATUS_KEY = ["faire", "status"];
623
- const TAXONOMY_KEY = ["faire", "taxonomy"];
624
- const PARENT$1 = "/settings/faire";
625
- const NONE = "__none__";
626
- const cleanSettings = (form) => {
627
- const out = { ...form };
628
- for (const key of [
629
- "default_brand_id",
630
- "default_category"
631
- ]) {
632
- if (!out[key] || out[key] === NONE) out[key] = null;
633
- }
634
- if (out.default_wholesale_markup_percent === "" || out.default_wholesale_markup_percent === NONE) {
635
- out.default_wholesale_markup_percent = null;
636
- }
637
- if (out.default_lead_time_days === "" || out.default_lead_time_days === NONE) {
638
- out.default_lead_time_days = null;
639
- }
640
- return out;
641
- };
642
- const FaireSyncSettingsDrawer = () => {
643
- const navigate = reactRouterDom.useNavigate();
644
- const queryClient = reactQuery.useQueryClient();
645
- const [open, setOpen] = react.useState(true);
646
- const [form, setForm] = react.useState({});
647
- const close = () => {
648
- setOpen(false);
649
- navigate(PARENT$1);
650
- };
651
- const statusQuery = reactQuery.useQuery({
652
- queryKey: STATUS_KEY,
653
- queryFn: () => faireApi.status()
654
- });
655
- const status = statusQuery.data;
656
- const connected = !!(status == null ? void 0 : status.connected);
657
- const taxonomyQuery = reactQuery.useQuery({
658
- queryKey: TAXONOMY_KEY,
659
- queryFn: async () => (await faireApi.taxonomy().catch(() => ({ taxonomy: [] }))).taxonomy || []
660
- });
661
- const taxonomy = taxonomyQuery.data ?? [];
662
- react.useEffect(() => {
663
- if (status == null ? void 0 : status.settings) setForm(status.settings);
664
- }, [status == null ? void 0 : status.settings]);
665
- const saveMutation = reactQuery.useMutation({
666
- mutationFn: (payload) => faireApi.saveSettings(payload),
667
- onSuccess: () => {
668
- queryClient.invalidateQueries({ queryKey: STATUS_KEY });
669
- ui.toast.success("Sync settings saved");
670
- close();
671
- },
672
- onError: (err) => ui.toast.error("Failed to save settings", { description: err.message })
673
- });
674
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer, { open, onOpenChange: (o) => o ? setOpen(true) : close(), children: [
675
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
676
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Header, { children: [
677
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: "Sync settings" }),
678
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { children: "Publish readiness and the defaults applied to every product pushed to Faire." })
679
- ] }),
680
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { className: "flex flex-col gap-6 overflow-y-auto", children: statusQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-10 w-full" }, i)) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
681
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
682
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
683
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Publish readiness" }),
684
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", size: "small", children: "Faire needs a brand and a wholesale-pricing strategy to publish products. Missing fields sync products as drafts." })
685
- ] }),
686
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
687
- /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.connected, label: "Faire connected" }),
688
- /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.brand, label: "Brand configured" }),
689
- /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.wholesale_pricing, label: "Wholesale pricing" }),
690
- /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.taxonomy, label: "Default category" })
691
- ] })
692
- ] }),
693
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
694
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
695
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Sync defaults" }),
696
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", size: "small", children: "Applied to every product unless overridden in product metadata." })
697
- ] }),
698
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
699
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Brand ID", children: /* @__PURE__ */ jsxRuntime.jsx(
700
- ui.Input,
701
- {
702
- value: String(form.default_brand_id ?? ""),
703
- onChange: (e) => setForm({ ...form, default_brand_id: e.target.value || null }),
704
- disabled: !connected,
705
- placeholder: "b_..."
706
- }
707
- ) }),
708
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Wholesale markup % (off retail)", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Wholesale price = retail × (100 − markup%) / 100. E.g. 50 → half of retail.", children: /* @__PURE__ */ jsxRuntime.jsx(
709
- ui.Input,
710
- {
711
- type: "number",
712
- value: String(form.default_wholesale_markup_percent ?? ""),
713
- onChange: (e) => setForm({
714
- ...form,
715
- default_wholesale_markup_percent: e.target.value ? Number(e.target.value) : null
716
- }),
717
- disabled: !connected,
718
- placeholder: "e.g. 50"
719
- }
720
- ) }) }),
721
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Default min order quantity", children: /* @__PURE__ */ jsxRuntime.jsx(
722
- ui.Input,
723
- {
724
- type: "number",
725
- value: String(form.default_min_order_quantity ?? 1),
726
- onChange: (e) => setForm({
727
- ...form,
728
- default_min_order_quantity: e.target.value ? Number(e.target.value) : 1
729
- }),
730
- disabled: !connected
731
- }
732
- ) }),
733
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Default lead time (days)", children: /* @__PURE__ */ jsxRuntime.jsx(
734
- ui.Input,
735
- {
736
- type: "number",
737
- value: String(form.default_lead_time_days ?? ""),
738
- onChange: (e) => setForm({
739
- ...form,
740
- default_lead_time_days: e.target.value ? Number(e.target.value) : null
741
- }),
742
- disabled: !connected,
743
- placeholder: "e.g. 14"
744
- }
745
- ) }),
746
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Fallback category (taxonomy)", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Faire requires a category per product. Resolution order: product metadata → the product's Type (matched by name) → this fallback. Set the product Type or pick a category on the product page for accuracy.", children: /* @__PURE__ */ jsxRuntime.jsx(
747
- SelectField,
748
- {
749
- value: String(form.default_category ?? ""),
750
- onValueChange: (v) => setForm({ ...form, default_category: v || null }),
751
- disabled: !connected,
752
- options: taxonomy.map((t) => ({ value: t.id, label: t.name }))
753
- }
754
- ) }) }),
755
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Follow product status", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "If on, published Medusa products are published on Faire; draft products sync as drafts.", children: /* @__PURE__ */ jsxRuntime.jsx(
756
- ui.Switch,
757
- {
758
- checked: form.follow_product_status !== false,
759
- onCheckedChange: (v) => setForm({ ...form, follow_product_status: v })
760
- }
761
- ) }) }),
762
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Auto publish", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Publish products to Faire automatically on sync (otherwise create as draft).", children: /* @__PURE__ */ jsxRuntime.jsx(
763
- ui.Switch,
764
- {
765
- checked: !!form.auto_publish,
766
- onCheckedChange: (v) => setForm({ ...form, auto_publish: v })
767
- }
768
- ) }) })
769
- ] })
770
- ] })
771
- ] }) }),
772
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Footer, { children: [
773
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: close, children: "Cancel" }),
774
- /* @__PURE__ */ jsxRuntime.jsx(
775
- ui.Button,
776
- {
777
- onClick: () => saveMutation.mutate(cleanSettings(form)),
778
- isLoading: saveMutation.isPending,
779
- disabled: !connected,
780
- children: "Save settings"
781
- }
782
- )
783
- ] })
784
- ] }),
785
- /* @__PURE__ */ jsxRuntime.jsx(ui.Toaster, {})
786
- ] });
787
- };
788
- const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
789
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: label }),
790
- children
791
- ] });
792
- const SelectField = ({
793
- value,
794
- onValueChange,
795
- options,
796
- disabled
797
- }) => /* @__PURE__ */ jsxRuntime.jsxs(
798
- ui.Select,
799
- {
800
- value: value ? value : NONE,
801
- onValueChange: (v) => onValueChange(v === NONE ? "" : v),
802
- disabled,
803
- size: "small",
804
- children: [
805
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Not set" }) }),
806
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
807
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: NONE, children: "Not set" }),
808
- options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: o.value, children: o.label }, o.value))
809
- ] })
810
- ]
811
- }
812
- );
813
- const ChecklistItem = ({ ok, label }) => /* @__PURE__ */ jsxRuntime.jsxs(
814
- "div",
815
- {
816
- className: ui.clx(
817
- "flex items-center gap-2 rounded-lg border px-3 py-2",
818
- ok ? "border-ui-tag-green-border bg-ui-tag-green-bg" : "border-ui-tag-red-border bg-ui-tag-red-bg"
819
- ),
820
- children: [
821
- /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: ok ? "green" : "red", children: ok ? "Ready" : "Missing" }),
822
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: label })
823
- ]
824
- }
825
- );
826
- const handle$2 = {
827
- breadcrumb: () => "Sync settings"
828
- };
829
622
  const Root = ({ prev = "..", children }) => {
830
623
  const navigate = reactRouterDom.useNavigate();
831
624
  const [open, setOpen] = react.useState(false);
@@ -1135,9 +928,216 @@ const FaireBulkPage = () => {
1135
928
  /* @__PURE__ */ jsxRuntime.jsx(ui.Toaster, {})
1136
929
  ] });
1137
930
  };
1138
- const handle$1 = {
931
+ const handle$2 = {
1139
932
  breadcrumb: () => "Bulk sync"
1140
933
  };
934
+ const STATUS_KEY = ["faire", "status"];
935
+ const TAXONOMY_KEY = ["faire", "taxonomy"];
936
+ const PARENT$1 = "/settings/faire";
937
+ const NONE = "__none__";
938
+ const cleanSettings = (form) => {
939
+ const out = { ...form };
940
+ for (const key of [
941
+ "default_brand_id",
942
+ "default_category"
943
+ ]) {
944
+ if (!out[key] || out[key] === NONE) out[key] = null;
945
+ }
946
+ if (out.default_wholesale_markup_percent === "" || out.default_wholesale_markup_percent === NONE) {
947
+ out.default_wholesale_markup_percent = null;
948
+ }
949
+ if (out.default_lead_time_days === "" || out.default_lead_time_days === NONE) {
950
+ out.default_lead_time_days = null;
951
+ }
952
+ return out;
953
+ };
954
+ const FaireSyncSettingsDrawer = () => {
955
+ const navigate = reactRouterDom.useNavigate();
956
+ const queryClient = reactQuery.useQueryClient();
957
+ const [open, setOpen] = react.useState(true);
958
+ const [form, setForm] = react.useState({});
959
+ const close = () => {
960
+ setOpen(false);
961
+ navigate(PARENT$1);
962
+ };
963
+ const statusQuery = reactQuery.useQuery({
964
+ queryKey: STATUS_KEY,
965
+ queryFn: () => faireApi.status()
966
+ });
967
+ const status = statusQuery.data;
968
+ const connected = !!(status == null ? void 0 : status.connected);
969
+ const taxonomyQuery = reactQuery.useQuery({
970
+ queryKey: TAXONOMY_KEY,
971
+ queryFn: async () => (await faireApi.taxonomy().catch(() => ({ taxonomy: [] }))).taxonomy || []
972
+ });
973
+ const taxonomy = taxonomyQuery.data ?? [];
974
+ react.useEffect(() => {
975
+ if (status == null ? void 0 : status.settings) setForm(status.settings);
976
+ }, [status == null ? void 0 : status.settings]);
977
+ const saveMutation = reactQuery.useMutation({
978
+ mutationFn: (payload) => faireApi.saveSettings(payload),
979
+ onSuccess: () => {
980
+ queryClient.invalidateQueries({ queryKey: STATUS_KEY });
981
+ ui.toast.success("Sync settings saved");
982
+ close();
983
+ },
984
+ onError: (err) => ui.toast.error("Failed to save settings", { description: err.message })
985
+ });
986
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer, { open, onOpenChange: (o) => o ? setOpen(true) : close(), children: [
987
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
988
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Header, { children: [
989
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: "Sync settings" }),
990
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { children: "Publish readiness and the defaults applied to every product pushed to Faire." })
991
+ ] }),
992
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { className: "flex flex-col gap-6 overflow-y-auto", children: statusQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-10 w-full" }, i)) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
993
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
994
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
995
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Publish readiness" }),
996
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", size: "small", children: "Faire needs a brand and a wholesale-pricing strategy to publish products. Missing fields sync products as drafts." })
997
+ ] }),
998
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
999
+ /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.connected, label: "Faire connected" }),
1000
+ /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.brand, label: "Brand configured" }),
1001
+ /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.wholesale_pricing, label: "Wholesale pricing" }),
1002
+ /* @__PURE__ */ jsxRuntime.jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.taxonomy, label: "Default category" })
1003
+ ] })
1004
+ ] }),
1005
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
1006
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
1007
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Sync defaults" }),
1008
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", size: "small", children: "Applied to every product unless overridden in product metadata." })
1009
+ ] }),
1010
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
1011
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Brand ID", children: /* @__PURE__ */ jsxRuntime.jsx(
1012
+ ui.Input,
1013
+ {
1014
+ value: String(form.default_brand_id ?? ""),
1015
+ onChange: (e) => setForm({ ...form, default_brand_id: e.target.value || null }),
1016
+ disabled: !connected,
1017
+ placeholder: "b_..."
1018
+ }
1019
+ ) }),
1020
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Wholesale markup % (off retail)", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Wholesale price = retail × (100 − markup%) / 100. E.g. 50 → half of retail.", children: /* @__PURE__ */ jsxRuntime.jsx(
1021
+ ui.Input,
1022
+ {
1023
+ type: "number",
1024
+ value: String(form.default_wholesale_markup_percent ?? ""),
1025
+ onChange: (e) => setForm({
1026
+ ...form,
1027
+ default_wholesale_markup_percent: e.target.value ? Number(e.target.value) : null
1028
+ }),
1029
+ disabled: !connected,
1030
+ placeholder: "e.g. 50"
1031
+ }
1032
+ ) }) }),
1033
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Default min order quantity", children: /* @__PURE__ */ jsxRuntime.jsx(
1034
+ ui.Input,
1035
+ {
1036
+ type: "number",
1037
+ value: String(form.default_min_order_quantity ?? 1),
1038
+ onChange: (e) => setForm({
1039
+ ...form,
1040
+ default_min_order_quantity: e.target.value ? Number(e.target.value) : 1
1041
+ }),
1042
+ disabled: !connected
1043
+ }
1044
+ ) }),
1045
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Default lead time (days)", children: /* @__PURE__ */ jsxRuntime.jsx(
1046
+ ui.Input,
1047
+ {
1048
+ type: "number",
1049
+ value: String(form.default_lead_time_days ?? ""),
1050
+ onChange: (e) => setForm({
1051
+ ...form,
1052
+ default_lead_time_days: e.target.value ? Number(e.target.value) : null
1053
+ }),
1054
+ disabled: !connected,
1055
+ placeholder: "e.g. 14"
1056
+ }
1057
+ ) }),
1058
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Fallback category (taxonomy)", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Faire requires a category per product. Resolution order: product metadata → the product's Type (matched by name) → this fallback. Set the product Type or pick a category on the product page for accuracy.", children: /* @__PURE__ */ jsxRuntime.jsx(
1059
+ SelectField,
1060
+ {
1061
+ value: String(form.default_category ?? ""),
1062
+ onValueChange: (v) => setForm({ ...form, default_category: v || null }),
1063
+ disabled: !connected,
1064
+ options: taxonomy.map((t) => ({ value: t.id, label: t.name }))
1065
+ }
1066
+ ) }) }),
1067
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Follow product status", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "If on, published Medusa products are published on Faire; draft products sync as drafts.", children: /* @__PURE__ */ jsxRuntime.jsx(
1068
+ ui.Switch,
1069
+ {
1070
+ checked: form.follow_product_status !== false,
1071
+ onCheckedChange: (v) => setForm({ ...form, follow_product_status: v })
1072
+ }
1073
+ ) }) }),
1074
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Auto publish", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Publish products to Faire automatically on sync (otherwise create as draft).", children: /* @__PURE__ */ jsxRuntime.jsx(
1075
+ ui.Switch,
1076
+ {
1077
+ checked: !!form.auto_publish,
1078
+ onCheckedChange: (v) => setForm({ ...form, auto_publish: v })
1079
+ }
1080
+ ) }) })
1081
+ ] })
1082
+ ] })
1083
+ ] }) }),
1084
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Footer, { children: [
1085
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: close, children: "Cancel" }),
1086
+ /* @__PURE__ */ jsxRuntime.jsx(
1087
+ ui.Button,
1088
+ {
1089
+ onClick: () => saveMutation.mutate(cleanSettings(form)),
1090
+ isLoading: saveMutation.isPending,
1091
+ disabled: !connected,
1092
+ children: "Save settings"
1093
+ }
1094
+ )
1095
+ ] })
1096
+ ] }),
1097
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Toaster, {})
1098
+ ] });
1099
+ };
1100
+ const Field = ({ label, children }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
1101
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: label }),
1102
+ children
1103
+ ] });
1104
+ const SelectField = ({
1105
+ value,
1106
+ onValueChange,
1107
+ options,
1108
+ disabled
1109
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(
1110
+ ui.Select,
1111
+ {
1112
+ value: value ? value : NONE,
1113
+ onValueChange: (v) => onValueChange(v === NONE ? "" : v),
1114
+ disabled,
1115
+ size: "small",
1116
+ children: [
1117
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Not set" }) }),
1118
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
1119
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: NONE, children: "Not set" }),
1120
+ options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: o.value, children: o.label }, o.value))
1121
+ ] })
1122
+ ]
1123
+ }
1124
+ );
1125
+ const ChecklistItem = ({ ok, label }) => /* @__PURE__ */ jsxRuntime.jsxs(
1126
+ "div",
1127
+ {
1128
+ className: ui.clx(
1129
+ "flex items-center gap-2 rounded-lg border px-3 py-2",
1130
+ ok ? "border-ui-tag-green-border bg-ui-tag-green-bg" : "border-ui-tag-red-border bg-ui-tag-red-bg"
1131
+ ),
1132
+ children: [
1133
+ /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: ok ? "green" : "red", children: ok ? "Ready" : "Missing" }),
1134
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: label })
1135
+ ]
1136
+ }
1137
+ );
1138
+ const handle$1 = {
1139
+ breadcrumb: () => "Sync settings"
1140
+ };
1141
1141
  const PARENT = "/settings/faire";
1142
1142
  const STATUS_COLORS = {
1143
1143
  success: "green",
@@ -1332,13 +1332,13 @@ const routeModule = {
1332
1332
  handle: handle$3,
1333
1333
  children: [
1334
1334
  {
1335
- Component: FaireSyncSettingsDrawer,
1336
- path: "/settings/faire/settings",
1335
+ Component: FaireBulkPage,
1336
+ path: "/settings/faire/bulk",
1337
1337
  handle: handle$2
1338
1338
  },
1339
1339
  {
1340
- Component: FaireBulkPage,
1341
- path: "/settings/faire/bulk",
1340
+ Component: FaireSyncSettingsDrawer,
1341
+ path: "/settings/faire/settings",
1342
1342
  handle: handle$1
1343
1343
  }
1344
1344
  ]
@@ -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 { toast, Container, Heading, Text, StatusBadge, Alert, Badge, Button, Tooltip, Drawer, Input, clx, createDataTableColumnHelper, createDataTableFilterHelper, useDataTable, Skeleton, DropdownMenu, DataTable, Label, Toaster, Switch, Select, FocusModal, IconButton } from "@medusajs/ui";
3
+ import { toast, Container, Heading, Text, StatusBadge, Alert, Badge, Button, Tooltip, Drawer, Input, clx, createDataTableColumnHelper, createDataTableFilterHelper, useDataTable, Skeleton, DropdownMenu, DataTable, Label, Toaster, FocusModal, Switch, Select, IconButton } from "@medusajs/ui";
4
4
  import { useQueryClient, useQuery, useMutation, keepPreviousData } from "@tanstack/react-query";
5
5
  import { useState, useEffect, useMemo } from "react";
6
6
  import Medusa from "@medusajs/js-sdk";
@@ -616,213 +616,6 @@ const config = defineRouteConfig({
616
616
  const handle$3 = {
617
617
  breadcrumb: () => "Faire Sync"
618
618
  };
619
- const STATUS_KEY = ["faire", "status"];
620
- const TAXONOMY_KEY = ["faire", "taxonomy"];
621
- const PARENT$1 = "/settings/faire";
622
- const NONE = "__none__";
623
- const cleanSettings = (form) => {
624
- const out = { ...form };
625
- for (const key of [
626
- "default_brand_id",
627
- "default_category"
628
- ]) {
629
- if (!out[key] || out[key] === NONE) out[key] = null;
630
- }
631
- if (out.default_wholesale_markup_percent === "" || out.default_wholesale_markup_percent === NONE) {
632
- out.default_wholesale_markup_percent = null;
633
- }
634
- if (out.default_lead_time_days === "" || out.default_lead_time_days === NONE) {
635
- out.default_lead_time_days = null;
636
- }
637
- return out;
638
- };
639
- const FaireSyncSettingsDrawer = () => {
640
- const navigate = useNavigate();
641
- const queryClient = useQueryClient();
642
- const [open, setOpen] = useState(true);
643
- const [form, setForm] = useState({});
644
- const close = () => {
645
- setOpen(false);
646
- navigate(PARENT$1);
647
- };
648
- const statusQuery = useQuery({
649
- queryKey: STATUS_KEY,
650
- queryFn: () => faireApi.status()
651
- });
652
- const status = statusQuery.data;
653
- const connected = !!(status == null ? void 0 : status.connected);
654
- const taxonomyQuery = useQuery({
655
- queryKey: TAXONOMY_KEY,
656
- queryFn: async () => (await faireApi.taxonomy().catch(() => ({ taxonomy: [] }))).taxonomy || []
657
- });
658
- const taxonomy = taxonomyQuery.data ?? [];
659
- useEffect(() => {
660
- if (status == null ? void 0 : status.settings) setForm(status.settings);
661
- }, [status == null ? void 0 : status.settings]);
662
- const saveMutation = useMutation({
663
- mutationFn: (payload) => faireApi.saveSettings(payload),
664
- onSuccess: () => {
665
- queryClient.invalidateQueries({ queryKey: STATUS_KEY });
666
- toast.success("Sync settings saved");
667
- close();
668
- },
669
- onError: (err) => toast.error("Failed to save settings", { description: err.message })
670
- });
671
- return /* @__PURE__ */ jsxs(Drawer, { open, onOpenChange: (o) => o ? setOpen(true) : close(), children: [
672
- /* @__PURE__ */ jsxs(Drawer.Content, { children: [
673
- /* @__PURE__ */ jsxs(Drawer.Header, { children: [
674
- /* @__PURE__ */ jsx(Drawer.Title, { children: "Sync settings" }),
675
- /* @__PURE__ */ jsx(Drawer.Description, { children: "Publish readiness and the defaults applied to every product pushed to Faire." })
676
- ] }),
677
- /* @__PURE__ */ jsx(Drawer.Body, { className: "flex flex-col gap-6 overflow-y-auto", children: statusQuery.isLoading ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" }, i)) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
678
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
679
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
680
- /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Publish readiness" }),
681
- /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", size: "small", children: "Faire needs a brand and a wholesale-pricing strategy to publish products. Missing fields sync products as drafts." })
682
- ] }),
683
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
684
- /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.connected, label: "Faire connected" }),
685
- /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.brand, label: "Brand configured" }),
686
- /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.wholesale_pricing, label: "Wholesale pricing" }),
687
- /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.taxonomy, label: "Default category" })
688
- ] })
689
- ] }),
690
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
691
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
692
- /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Sync defaults" }),
693
- /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", size: "small", children: "Applied to every product unless overridden in product metadata." })
694
- ] }),
695
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
696
- /* @__PURE__ */ jsx(Field, { label: "Brand ID", children: /* @__PURE__ */ jsx(
697
- Input,
698
- {
699
- value: String(form.default_brand_id ?? ""),
700
- onChange: (e) => setForm({ ...form, default_brand_id: e.target.value || null }),
701
- disabled: !connected,
702
- placeholder: "b_..."
703
- }
704
- ) }),
705
- /* @__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(
706
- Input,
707
- {
708
- type: "number",
709
- value: String(form.default_wholesale_markup_percent ?? ""),
710
- onChange: (e) => setForm({
711
- ...form,
712
- default_wholesale_markup_percent: e.target.value ? Number(e.target.value) : null
713
- }),
714
- disabled: !connected,
715
- placeholder: "e.g. 50"
716
- }
717
- ) }) }),
718
- /* @__PURE__ */ jsx(Field, { label: "Default min order quantity", children: /* @__PURE__ */ jsx(
719
- Input,
720
- {
721
- type: "number",
722
- value: String(form.default_min_order_quantity ?? 1),
723
- onChange: (e) => setForm({
724
- ...form,
725
- default_min_order_quantity: e.target.value ? Number(e.target.value) : 1
726
- }),
727
- disabled: !connected
728
- }
729
- ) }),
730
- /* @__PURE__ */ jsx(Field, { label: "Default lead time (days)", children: /* @__PURE__ */ jsx(
731
- Input,
732
- {
733
- type: "number",
734
- value: String(form.default_lead_time_days ?? ""),
735
- onChange: (e) => setForm({
736
- ...form,
737
- default_lead_time_days: e.target.value ? Number(e.target.value) : null
738
- }),
739
- disabled: !connected,
740
- placeholder: "e.g. 14"
741
- }
742
- ) }),
743
- /* @__PURE__ */ jsx(Field, { label: "Fallback category (taxonomy)", children: /* @__PURE__ */ jsx(Tooltip, { content: "Faire requires a category per product. Resolution order: product metadata → the product's Type (matched by name) → this fallback. Set the product Type or pick a category on the product page for accuracy.", children: /* @__PURE__ */ jsx(
744
- SelectField,
745
- {
746
- value: String(form.default_category ?? ""),
747
- onValueChange: (v) => setForm({ ...form, default_category: v || null }),
748
- disabled: !connected,
749
- options: taxonomy.map((t) => ({ value: t.id, label: t.name }))
750
- }
751
- ) }) }),
752
- /* @__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(
753
- Switch,
754
- {
755
- checked: form.follow_product_status !== false,
756
- onCheckedChange: (v) => setForm({ ...form, follow_product_status: v })
757
- }
758
- ) }) }),
759
- /* @__PURE__ */ jsx(Field, { label: "Auto publish", children: /* @__PURE__ */ jsx(Tooltip, { content: "Publish products to Faire automatically on sync (otherwise create as draft).", children: /* @__PURE__ */ jsx(
760
- Switch,
761
- {
762
- checked: !!form.auto_publish,
763
- onCheckedChange: (v) => setForm({ ...form, auto_publish: v })
764
- }
765
- ) }) })
766
- ] })
767
- ] })
768
- ] }) }),
769
- /* @__PURE__ */ jsxs(Drawer.Footer, { children: [
770
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: close, children: "Cancel" }),
771
- /* @__PURE__ */ jsx(
772
- Button,
773
- {
774
- onClick: () => saveMutation.mutate(cleanSettings(form)),
775
- isLoading: saveMutation.isPending,
776
- disabled: !connected,
777
- children: "Save settings"
778
- }
779
- )
780
- ] })
781
- ] }),
782
- /* @__PURE__ */ jsx(Toaster, {})
783
- ] });
784
- };
785
- const Field = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
786
- /* @__PURE__ */ jsx(Label, { children: label }),
787
- children
788
- ] });
789
- const SelectField = ({
790
- value,
791
- onValueChange,
792
- options,
793
- disabled
794
- }) => /* @__PURE__ */ jsxs(
795
- Select,
796
- {
797
- value: value ? value : NONE,
798
- onValueChange: (v) => onValueChange(v === NONE ? "" : v),
799
- disabled,
800
- size: "small",
801
- children: [
802
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Not set" }) }),
803
- /* @__PURE__ */ jsxs(Select.Content, { children: [
804
- /* @__PURE__ */ jsx(Select.Item, { value: NONE, children: "Not set" }),
805
- options.map((o) => /* @__PURE__ */ jsx(Select.Item, { value: o.value, children: o.label }, o.value))
806
- ] })
807
- ]
808
- }
809
- );
810
- const ChecklistItem = ({ ok, label }) => /* @__PURE__ */ jsxs(
811
- "div",
812
- {
813
- className: clx(
814
- "flex items-center gap-2 rounded-lg border px-3 py-2",
815
- ok ? "border-ui-tag-green-border bg-ui-tag-green-bg" : "border-ui-tag-red-border bg-ui-tag-red-bg"
816
- ),
817
- children: [
818
- /* @__PURE__ */ jsx(StatusBadge, { color: ok ? "green" : "red", children: ok ? "Ready" : "Missing" }),
819
- /* @__PURE__ */ jsx(Text, { children: label })
820
- ]
821
- }
822
- );
823
- const handle$2 = {
824
- breadcrumb: () => "Sync settings"
825
- };
826
619
  const Root = ({ prev = "..", children }) => {
827
620
  const navigate = useNavigate();
828
621
  const [open, setOpen] = useState(false);
@@ -1132,9 +925,216 @@ const FaireBulkPage = () => {
1132
925
  /* @__PURE__ */ jsx(Toaster, {})
1133
926
  ] });
1134
927
  };
1135
- const handle$1 = {
928
+ const handle$2 = {
1136
929
  breadcrumb: () => "Bulk sync"
1137
930
  };
931
+ const STATUS_KEY = ["faire", "status"];
932
+ const TAXONOMY_KEY = ["faire", "taxonomy"];
933
+ const PARENT$1 = "/settings/faire";
934
+ const NONE = "__none__";
935
+ const cleanSettings = (form) => {
936
+ const out = { ...form };
937
+ for (const key of [
938
+ "default_brand_id",
939
+ "default_category"
940
+ ]) {
941
+ if (!out[key] || out[key] === NONE) out[key] = null;
942
+ }
943
+ if (out.default_wholesale_markup_percent === "" || out.default_wholesale_markup_percent === NONE) {
944
+ out.default_wholesale_markup_percent = null;
945
+ }
946
+ if (out.default_lead_time_days === "" || out.default_lead_time_days === NONE) {
947
+ out.default_lead_time_days = null;
948
+ }
949
+ return out;
950
+ };
951
+ const FaireSyncSettingsDrawer = () => {
952
+ const navigate = useNavigate();
953
+ const queryClient = useQueryClient();
954
+ const [open, setOpen] = useState(true);
955
+ const [form, setForm] = useState({});
956
+ const close = () => {
957
+ setOpen(false);
958
+ navigate(PARENT$1);
959
+ };
960
+ const statusQuery = useQuery({
961
+ queryKey: STATUS_KEY,
962
+ queryFn: () => faireApi.status()
963
+ });
964
+ const status = statusQuery.data;
965
+ const connected = !!(status == null ? void 0 : status.connected);
966
+ const taxonomyQuery = useQuery({
967
+ queryKey: TAXONOMY_KEY,
968
+ queryFn: async () => (await faireApi.taxonomy().catch(() => ({ taxonomy: [] }))).taxonomy || []
969
+ });
970
+ const taxonomy = taxonomyQuery.data ?? [];
971
+ useEffect(() => {
972
+ if (status == null ? void 0 : status.settings) setForm(status.settings);
973
+ }, [status == null ? void 0 : status.settings]);
974
+ const saveMutation = useMutation({
975
+ mutationFn: (payload) => faireApi.saveSettings(payload),
976
+ onSuccess: () => {
977
+ queryClient.invalidateQueries({ queryKey: STATUS_KEY });
978
+ toast.success("Sync settings saved");
979
+ close();
980
+ },
981
+ onError: (err) => toast.error("Failed to save settings", { description: err.message })
982
+ });
983
+ return /* @__PURE__ */ jsxs(Drawer, { open, onOpenChange: (o) => o ? setOpen(true) : close(), children: [
984
+ /* @__PURE__ */ jsxs(Drawer.Content, { children: [
985
+ /* @__PURE__ */ jsxs(Drawer.Header, { children: [
986
+ /* @__PURE__ */ jsx(Drawer.Title, { children: "Sync settings" }),
987
+ /* @__PURE__ */ jsx(Drawer.Description, { children: "Publish readiness and the defaults applied to every product pushed to Faire." })
988
+ ] }),
989
+ /* @__PURE__ */ jsx(Drawer.Body, { className: "flex flex-col gap-6 overflow-y-auto", children: statusQuery.isLoading ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" }, i)) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
990
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
991
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
992
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Publish readiness" }),
993
+ /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", size: "small", children: "Faire needs a brand and a wholesale-pricing strategy to publish products. Missing fields sync products as drafts." })
994
+ ] }),
995
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
996
+ /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.connected, label: "Faire connected" }),
997
+ /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.brand, label: "Brand configured" }),
998
+ /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.wholesale_pricing, label: "Wholesale pricing" }),
999
+ /* @__PURE__ */ jsx(ChecklistItem, { ok: status == null ? void 0 : status.readiness.taxonomy, label: "Default category" })
1000
+ ] })
1001
+ ] }),
1002
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
1003
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
1004
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Sync defaults" }),
1005
+ /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", size: "small", children: "Applied to every product unless overridden in product metadata." })
1006
+ ] }),
1007
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
1008
+ /* @__PURE__ */ jsx(Field, { label: "Brand ID", children: /* @__PURE__ */ jsx(
1009
+ Input,
1010
+ {
1011
+ value: String(form.default_brand_id ?? ""),
1012
+ onChange: (e) => setForm({ ...form, default_brand_id: e.target.value || null }),
1013
+ disabled: !connected,
1014
+ placeholder: "b_..."
1015
+ }
1016
+ ) }),
1017
+ /* @__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(
1018
+ Input,
1019
+ {
1020
+ type: "number",
1021
+ value: String(form.default_wholesale_markup_percent ?? ""),
1022
+ onChange: (e) => setForm({
1023
+ ...form,
1024
+ default_wholesale_markup_percent: e.target.value ? Number(e.target.value) : null
1025
+ }),
1026
+ disabled: !connected,
1027
+ placeholder: "e.g. 50"
1028
+ }
1029
+ ) }) }),
1030
+ /* @__PURE__ */ jsx(Field, { label: "Default min order quantity", children: /* @__PURE__ */ jsx(
1031
+ Input,
1032
+ {
1033
+ type: "number",
1034
+ value: String(form.default_min_order_quantity ?? 1),
1035
+ onChange: (e) => setForm({
1036
+ ...form,
1037
+ default_min_order_quantity: e.target.value ? Number(e.target.value) : 1
1038
+ }),
1039
+ disabled: !connected
1040
+ }
1041
+ ) }),
1042
+ /* @__PURE__ */ jsx(Field, { label: "Default lead time (days)", children: /* @__PURE__ */ jsx(
1043
+ Input,
1044
+ {
1045
+ type: "number",
1046
+ value: String(form.default_lead_time_days ?? ""),
1047
+ onChange: (e) => setForm({
1048
+ ...form,
1049
+ default_lead_time_days: e.target.value ? Number(e.target.value) : null
1050
+ }),
1051
+ disabled: !connected,
1052
+ placeholder: "e.g. 14"
1053
+ }
1054
+ ) }),
1055
+ /* @__PURE__ */ jsx(Field, { label: "Fallback category (taxonomy)", children: /* @__PURE__ */ jsx(Tooltip, { content: "Faire requires a category per product. Resolution order: product metadata → the product's Type (matched by name) → this fallback. Set the product Type or pick a category on the product page for accuracy.", children: /* @__PURE__ */ jsx(
1056
+ SelectField,
1057
+ {
1058
+ value: String(form.default_category ?? ""),
1059
+ onValueChange: (v) => setForm({ ...form, default_category: v || null }),
1060
+ disabled: !connected,
1061
+ options: taxonomy.map((t) => ({ value: t.id, label: t.name }))
1062
+ }
1063
+ ) }) }),
1064
+ /* @__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
+ Switch,
1066
+ {
1067
+ checked: form.follow_product_status !== false,
1068
+ onCheckedChange: (v) => setForm({ ...form, follow_product_status: v })
1069
+ }
1070
+ ) }) }),
1071
+ /* @__PURE__ */ jsx(Field, { label: "Auto publish", children: /* @__PURE__ */ jsx(Tooltip, { content: "Publish products to Faire automatically on sync (otherwise create as draft).", children: /* @__PURE__ */ jsx(
1072
+ Switch,
1073
+ {
1074
+ checked: !!form.auto_publish,
1075
+ onCheckedChange: (v) => setForm({ ...form, auto_publish: v })
1076
+ }
1077
+ ) }) })
1078
+ ] })
1079
+ ] })
1080
+ ] }) }),
1081
+ /* @__PURE__ */ jsxs(Drawer.Footer, { children: [
1082
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: close, children: "Cancel" }),
1083
+ /* @__PURE__ */ jsx(
1084
+ Button,
1085
+ {
1086
+ onClick: () => saveMutation.mutate(cleanSettings(form)),
1087
+ isLoading: saveMutation.isPending,
1088
+ disabled: !connected,
1089
+ children: "Save settings"
1090
+ }
1091
+ )
1092
+ ] })
1093
+ ] }),
1094
+ /* @__PURE__ */ jsx(Toaster, {})
1095
+ ] });
1096
+ };
1097
+ const Field = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
1098
+ /* @__PURE__ */ jsx(Label, { children: label }),
1099
+ children
1100
+ ] });
1101
+ const SelectField = ({
1102
+ value,
1103
+ onValueChange,
1104
+ options,
1105
+ disabled
1106
+ }) => /* @__PURE__ */ jsxs(
1107
+ Select,
1108
+ {
1109
+ value: value ? value : NONE,
1110
+ onValueChange: (v) => onValueChange(v === NONE ? "" : v),
1111
+ disabled,
1112
+ size: "small",
1113
+ children: [
1114
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Not set" }) }),
1115
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
1116
+ /* @__PURE__ */ jsx(Select.Item, { value: NONE, children: "Not set" }),
1117
+ options.map((o) => /* @__PURE__ */ jsx(Select.Item, { value: o.value, children: o.label }, o.value))
1118
+ ] })
1119
+ ]
1120
+ }
1121
+ );
1122
+ const ChecklistItem = ({ ok, label }) => /* @__PURE__ */ jsxs(
1123
+ "div",
1124
+ {
1125
+ className: clx(
1126
+ "flex items-center gap-2 rounded-lg border px-3 py-2",
1127
+ ok ? "border-ui-tag-green-border bg-ui-tag-green-bg" : "border-ui-tag-red-border bg-ui-tag-red-bg"
1128
+ ),
1129
+ children: [
1130
+ /* @__PURE__ */ jsx(StatusBadge, { color: ok ? "green" : "red", children: ok ? "Ready" : "Missing" }),
1131
+ /* @__PURE__ */ jsx(Text, { children: label })
1132
+ ]
1133
+ }
1134
+ );
1135
+ const handle$1 = {
1136
+ breadcrumb: () => "Sync settings"
1137
+ };
1138
1138
  const PARENT = "/settings/faire";
1139
1139
  const STATUS_COLORS = {
1140
1140
  success: "green",
@@ -1329,13 +1329,13 @@ const routeModule = {
1329
1329
  handle: handle$3,
1330
1330
  children: [
1331
1331
  {
1332
- Component: FaireSyncSettingsDrawer,
1333
- path: "/settings/faire/settings",
1332
+ Component: FaireBulkPage,
1333
+ path: "/settings/faire/bulk",
1334
1334
  handle: handle$2
1335
1335
  },
1336
1336
  {
1337
- Component: FaireBulkPage,
1338
- path: "/settings/faire/bulk",
1337
+ Component: FaireSyncSettingsDrawer,
1338
+ path: "/settings/faire/settings",
1339
1339
  handle: handle$1
1340
1340
  }
1341
1341
  ]
@@ -29,6 +29,8 @@ const geoForCurrency = (currency, country) => {
29
29
  return { country: "GB" };
30
30
  case "USD":
31
31
  return { country: "US" };
32
+ case "INR":
33
+ return { country: "IN" };
32
34
  case "CAD":
33
35
  return { country: "CA" };
34
36
  case "AUD":
@@ -153,12 +155,54 @@ const prepareProductStep = (0, workflows_sdk_1.createStep)("faire-prepare-produc
153
155
  }
154
156
  return Number.isFinite(available) ? Math.max(0, available) : 0;
155
157
  };
158
+ const wholesaleFrom = (retailMinor) => markupPercent > 0
159
+ ? Math.round((retailMinor * (100 - markupPercent)) / 100)
160
+ : retailMinor;
161
+ // Faire prices are geo-scoped and a variant may carry several — one per
162
+ // currency the product is priced in. Emit a price for EVERY currency present
163
+ // (INR → India, USD → US, EUR → the EU group, etc.) so buyers in each region
164
+ // see their own currency, and fall back to the chosen/default currency +
165
+ // geo (EUR by default) when the product has no multi-currency prices.
166
+ const buildPrices = (variantPrices) => {
167
+ const byCurrency = new Map();
168
+ for (const p of variantPrices || []) {
169
+ const c = String(p.currency_code || "").toUpperCase();
170
+ if (!c)
171
+ continue;
172
+ // First price row per currency wins (Medusa may hold several tiers).
173
+ if (!byCurrency.has(c))
174
+ byCurrency.set(c, p);
175
+ }
176
+ const rows = [];
177
+ for (const [c, p] of byCurrency) {
178
+ const retailMinor = toMinor(p.amount);
179
+ if (retailMinor <= 0)
180
+ continue;
181
+ // The explicit metadata override only applies to the brand's primary
182
+ // currency; every other currency is scoped by its natural geo.
183
+ const geo = c === currency ? geoConstraint : geoForCurrency(c, input.country);
184
+ rows.push({
185
+ geo_constraint: geo,
186
+ wholesale_price: { amount_minor: wholesaleFrom(retailMinor), currency: c },
187
+ retail_price: { amount_minor: retailMinor, currency: c },
188
+ });
189
+ }
190
+ // Guarantee at least the chosen-currency price so a create never ships a
191
+ // variant with no price at all.
192
+ if (!rows.length) {
193
+ const retail = pickPrice(variantPrices || []);
194
+ const retailMinor = retail ? toMinor(retail.amount) : 0;
195
+ if (retailMinor > 0) {
196
+ rows.push({
197
+ geo_constraint: geoConstraint,
198
+ wholesale_price: { amount_minor: wholesaleFrom(retailMinor), currency },
199
+ retail_price: { amount_minor: retailMinor, currency },
200
+ });
201
+ }
202
+ }
203
+ return rows.length ? rows : undefined;
204
+ };
156
205
  const buildVariant = (v, idx) => {
157
- const retail = pickPrice(v.prices || []);
158
- const retailMinor = retail ? toMinor(retail.amount) : 0;
159
- const wholesaleMinor = markupPercent > 0
160
- ? Math.round((retailMinor * (100 - markupPercent)) / 100)
161
- : retailMinor;
162
206
  const sku = v.sku || v.id;
163
207
  const options = (v.options || [])
164
208
  .map((o) => ({
@@ -172,15 +216,7 @@ const prepareProductStep = (0, workflows_sdk_1.createStep)("faire-prepare-produc
172
216
  idempotence_token: `${product.id}:${v.id || sku}`,
173
217
  options: options.length ? options : undefined,
174
218
  available_quantity: variantQuantity(v),
175
- prices: retailMinor > 0
176
- ? [
177
- {
178
- geo_constraint: geoConstraint,
179
- wholesale_price: { amount_minor: wholesaleMinor, currency },
180
- retail_price: { amount_minor: retailMinor, currency },
181
- },
182
- ]
183
- : undefined,
219
+ prices: buildPrices(v.prices || []),
184
220
  };
185
221
  };
186
222
  const images = (product.images || [])
@@ -280,17 +316,26 @@ const syncProductStep = (0, workflows_sdk_1.createStep)("faire-sync-product-step
280
316
  warnings.push(`Product create/update failed: ${err?.message || err}`);
281
317
  throw err;
282
318
  }
283
- // Push inventory levels for each variant.
319
+ // Push inventory levels — but ONLY for variants with a real SKU. When a
320
+ // Medusa variant has no SKU we fall back to its id for the create payload
321
+ // (Faire needs *something*), but that synthetic id (`variant_…` / `prod_…`)
322
+ // is NOT a Faire SKU, so `PATCH product-inventory/by-skus` 404s on it. Those
323
+ // variants are already stocked via the create payload's `available_quantity`,
324
+ // so skip them here rather than push an id Faire will reject.
284
325
  if (product_input.variants?.length) {
285
- try {
286
- const levels = product_input.variants.map((v) => ({
287
- sku: v.sku,
288
- on_hand_quantity: v.available_quantity ?? 0,
289
- }));
290
- await client.updateInventory(access_token, levels);
291
- }
292
- catch (err) {
293
- warnings.push(`Inventory push failed: ${err?.message || err}`);
326
+ const levels = product_input.variants
327
+ .filter((v) => v.sku && !/^(prod|variant)_/.test(v.sku))
328
+ .map((v) => ({
329
+ sku: v.sku,
330
+ on_hand_quantity: v.available_quantity ?? 0,
331
+ }));
332
+ if (levels.length) {
333
+ try {
334
+ await client.updateInventory(access_token, levels);
335
+ }
336
+ catch (err) {
337
+ warnings.push(`Inventory push failed: ${err?.message || err}`);
338
+ }
294
339
  }
295
340
  }
296
341
  // Publish decision: follow product status.
@@ -386,4 +431,4 @@ exports.syncProductToFaireWorkflow = (0, workflows_sdk_1.createWorkflow)(exports
386
431
  warnings: result.warnings,
387
432
  });
388
433
  });
389
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wcm9kdWN0LXRvLWZhaXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zeW5jLXByb2R1Y3QtdG8tZmFpcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBTzBDO0FBQzFDLHFEQUEyRjtBQUczRixzREFBeUQ7QUFPNUMsUUFBQSxxQkFBcUIsR0FBRyxvQkFBb0IsQ0FBQTtBQThCekQ7OztHQUdHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE9BQXdCLEVBQWlCLEVBQUU7SUFDcEUsSUFBSSxPQUFPLENBQUMsR0FBRztRQUFFLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQTtJQUNuQyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWE7UUFBRSxPQUFPLElBQUksQ0FBQTtJQUN2QyxPQUFPLHdDQUF3QyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUE7QUFDeEUsQ0FBQyxDQUFBO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sY0FBYyxHQUFHLENBQ3JCLFFBQWdCLEVBQ2hCLE9BQXNCLEVBQ3dCLEVBQUU7SUFDaEQsUUFBUSxRQUFRLEVBQUUsQ0FBQztRQUNqQixLQUFLLEtBQUs7WUFDUixPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLENBQUE7UUFDNUMsS0FBSyxLQUFLO1lBQ1IsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQTtRQUMxQixLQUFLLEtBQUs7WUFDUixPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFBO1FBQzFCLEtBQUssS0FBSztZQUNSLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUE7UUFDMUIsS0FBSyxLQUFLO1lBQ1IsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQTtRQUMxQjtZQUNFLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLGFB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
434
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wcm9kdWN0LXRvLWZhaXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9zeW5jLXByb2R1Y3QtdG8tZmFpcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscUVBTzBDO0FBQzFDLHFEQUEyRjtBQUczRixzREFBeUQ7QUFPNUMsUUFBQSxxQkFBcUIsR0FBRyxvQkFBb0IsQ0FBQTtBQThCekQ7OztHQUdHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE9BQXdCLEVBQWlCLEVBQUU7SUFDcEUsSUFBSSxPQUFPLENBQUMsR0FBRztRQUFFLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQTtJQUNuQyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWE7UUFBRSxPQUFPLElBQUksQ0FBQTtJQUN2QyxPQUFPLHdDQUF3QyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUE7QUFDeEUsQ0FBQyxDQUFBO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sY0FBYyxHQUFHLENBQ3JCLFFBQWdCLEVBQ2hCLE9BQXNCLEVBQ3dCLEVBQUU7SUFDaEQsUUFBUSxRQUFRLEVBQUUsQ0FBQztRQUNqQixLQUFLLEtBQUs7WUFDUixPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLENBQUE7UUFDNUMsS0FBSyxLQUFLO1lBQ1IsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQTtRQUMxQixLQUFLLEtBQUs7WUFDUixPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFBO1FBQzFCLEtBQUssS0FBSztZQUNSLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUE7UUFDMUIsS0FBSyxLQUFLO1lBQ1IsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQTtRQUMxQixLQUFLLEtBQUs7WUFDUixPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFBO1FBQzFCO1lBQ0UsT0FBTyxP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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jytextiles/medusa-plugin-faire-store-sync",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
@@ -72,6 +72,8 @@ const geoForCurrency = (
72
72
  return { country: "GB" }
73
73
  case "USD":
74
74
  return { country: "US" }
75
+ case "INR":
76
+ return { country: "IN" }
75
77
  case "CAD":
76
78
  return { country: "CA" }
77
79
  case "AUD":
@@ -234,13 +236,61 @@ const prepareProductStep = createStep(
234
236
  return Number.isFinite(available) ? Math.max(0, available) : 0
235
237
  }
236
238
 
239
+ const wholesaleFrom = (retailMinor: number): number =>
240
+ markupPercent > 0
241
+ ? Math.round((retailMinor * (100 - markupPercent)) / 100)
242
+ : retailMinor
243
+
244
+ // Faire prices are geo-scoped and a variant may carry several — one per
245
+ // currency the product is priced in. Emit a price for EVERY currency present
246
+ // (INR → India, USD → US, EUR → the EU group, etc.) so buyers in each region
247
+ // see their own currency, and fall back to the chosen/default currency +
248
+ // geo (EUR by default) when the product has no multi-currency prices.
249
+ const buildPrices = (variantPrices: any[]) => {
250
+ const byCurrency = new Map<string, any>()
251
+ for (const p of variantPrices || []) {
252
+ const c = String(p.currency_code || "").toUpperCase()
253
+ if (!c) continue
254
+ // First price row per currency wins (Medusa may hold several tiers).
255
+ if (!byCurrency.has(c)) byCurrency.set(c, p)
256
+ }
257
+
258
+ const rows: {
259
+ geo_constraint: { country?: string; country_group?: string }
260
+ wholesale_price: { amount_minor: number; currency: string }
261
+ retail_price: { amount_minor: number; currency: string }
262
+ }[] = []
263
+ for (const [c, p] of byCurrency) {
264
+ const retailMinor = toMinor(p.amount)
265
+ if (retailMinor <= 0) continue
266
+ // The explicit metadata override only applies to the brand's primary
267
+ // currency; every other currency is scoped by its natural geo.
268
+ const geo =
269
+ c === currency ? geoConstraint : geoForCurrency(c, input.country)
270
+ rows.push({
271
+ geo_constraint: geo,
272
+ wholesale_price: { amount_minor: wholesaleFrom(retailMinor), currency: c },
273
+ retail_price: { amount_minor: retailMinor, currency: c },
274
+ })
275
+ }
276
+
277
+ // Guarantee at least the chosen-currency price so a create never ships a
278
+ // variant with no price at all.
279
+ if (!rows.length) {
280
+ const retail = pickPrice(variantPrices || [])
281
+ const retailMinor = retail ? toMinor(retail.amount) : 0
282
+ if (retailMinor > 0) {
283
+ rows.push({
284
+ geo_constraint: geoConstraint,
285
+ wholesale_price: { amount_minor: wholesaleFrom(retailMinor), currency },
286
+ retail_price: { amount_minor: retailMinor, currency },
287
+ })
288
+ }
289
+ }
290
+ return rows.length ? rows : undefined
291
+ }
292
+
237
293
  const buildVariant = (v: any, idx: number) => {
238
- const retail = pickPrice(v.prices || [])
239
- const retailMinor = retail ? toMinor(retail.amount) : 0
240
- const wholesaleMinor =
241
- markupPercent > 0
242
- ? Math.round((retailMinor * (100 - markupPercent)) / 100)
243
- : retailMinor
244
294
  const sku = v.sku || v.id
245
295
  const options =
246
296
  (v.options || [])
@@ -255,16 +305,7 @@ const prepareProductStep = createStep(
255
305
  idempotence_token: `${product.id}:${v.id || sku}`,
256
306
  options: options.length ? options : undefined,
257
307
  available_quantity: variantQuantity(v),
258
- prices:
259
- retailMinor > 0
260
- ? [
261
- {
262
- geo_constraint: geoConstraint,
263
- wholesale_price: { amount_minor: wholesaleMinor, currency },
264
- retail_price: { amount_minor: retailMinor, currency },
265
- },
266
- ]
267
- : undefined,
308
+ prices: buildPrices(v.prices || []),
268
309
  }
269
310
  }
270
311
 
@@ -396,16 +437,25 @@ const syncProductStep = createStep(
396
437
  throw err
397
438
  }
398
439
 
399
- // Push inventory levels for each variant.
440
+ // Push inventory levels — but ONLY for variants with a real SKU. When a
441
+ // Medusa variant has no SKU we fall back to its id for the create payload
442
+ // (Faire needs *something*), but that synthetic id (`variant_…` / `prod_…`)
443
+ // is NOT a Faire SKU, so `PATCH product-inventory/by-skus` 404s on it. Those
444
+ // variants are already stocked via the create payload's `available_quantity`,
445
+ // so skip them here rather than push an id Faire will reject.
400
446
  if (product_input.variants?.length) {
401
- try {
402
- const levels = product_input.variants.map((v) => ({
447
+ const levels = product_input.variants
448
+ .filter((v) => v.sku && !/^(prod|variant)_/.test(v.sku))
449
+ .map((v) => ({
403
450
  sku: v.sku,
404
451
  on_hand_quantity: v.available_quantity ?? 0,
405
452
  }))
406
- await client.updateInventory(access_token, levels)
407
- } catch (err: any) {
408
- warnings.push(`Inventory push failed: ${err?.message || err}`)
453
+ if (levels.length) {
454
+ try {
455
+ await client.updateInventory(access_token, levels)
456
+ } catch (err: any) {
457
+ warnings.push(`Inventory push failed: ${err?.message || err}`)
458
+ }
409
459
  }
410
460
  }
411
461