@zaamx/netme-pos 0.0.11 → 0.0.12

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.
@@ -1,10 +1,11 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { defineRouteConfig } from "@medusajs/admin-sdk";
3
- import { EllipsisHorizontal, PencilSquare, Trash, Users, CurrencyDollar } from "@medusajs/icons";
4
- import { toast, Drawer, Label, Input, Text, Button, Prompt, DropdownMenu, IconButton, FocusModal, createDataTableColumnHelper, useDataTable, DataTable, Container, Heading, Select, Badge } from "@medusajs/ui";
5
- import { useState, useMemo, useEffect } from "react";
3
+ import { EllipsisHorizontal, PencilSquare, ShieldCheck, Trash, Users, CurrencyDollar, XMark, ChevronUpDown, ArrowUturnLeft, Spinner, ArrowLeft, Buildings, ChannelsSolid, Tag } from "@medusajs/icons";
4
+ import { toast, Drawer, Label, Input, Text, Button, Prompt, DropdownMenu, IconButton, FocusModal, createDataTableColumnHelper, useDataTable, DataTable, Container, Heading, Select, Badge, Popover, clx, Checkbox, Switch } from "@medusajs/ui";
5
+ import { useState, useMemo, useEffect, useRef } from "react";
6
6
  import { useQueryClient, useMutation, useQuery } from "@tanstack/react-query";
7
7
  import Medusa from "@medusajs/js-sdk";
8
+ import { useNavigate, Link, useParams } from "react-router-dom";
8
9
  const sdk = new Medusa({
9
10
  // @ts-ignore
10
11
  baseUrl: "/",
@@ -163,6 +164,7 @@ const DeleteOperatorModal = ({
163
164
  const OperatorActions = ({ operator }) => {
164
165
  const [editOpen, setEditOpen] = useState(false);
165
166
  const [deleteOpen, setDeleteOpen] = useState(false);
167
+ const navigate = useNavigate();
166
168
  return /* @__PURE__ */ jsxs(Fragment, { children: [
167
169
  /* @__PURE__ */ jsxs(DropdownMenu, { children: [
168
170
  /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { size: "small", variant: "transparent", children: /* @__PURE__ */ jsx(EllipsisHorizontal, {}) }) }),
@@ -171,6 +173,17 @@ const OperatorActions = ({ operator }) => {
171
173
  /* @__PURE__ */ jsx(PencilSquare, { className: "text-ui-fg-subtle" }),
172
174
  "Edit"
173
175
  ] }),
176
+ /* @__PURE__ */ jsxs(
177
+ DropdownMenu.Item,
178
+ {
179
+ onClick: () => navigate(`/pos-permissions/${operator.id}`),
180
+ className: "gap-x-2",
181
+ children: [
182
+ /* @__PURE__ */ jsx(ShieldCheck, { className: "text-ui-fg-subtle" }),
183
+ "Permisos POS"
184
+ ]
185
+ }
186
+ ),
174
187
  /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
175
188
  /* @__PURE__ */ jsxs(DropdownMenu.Item, { onClick: () => setDeleteOpen(true), className: "gap-x-2", children: [
176
189
  /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
@@ -308,24 +321,24 @@ const CreateOperatorModal = () => {
308
321
  ] }) }) })
309
322
  ] });
310
323
  };
311
- const columnHelper$1 = createDataTableColumnHelper();
312
- const useColumns$1 = () => {
324
+ const columnHelper$2 = createDataTableColumnHelper();
325
+ const useColumns$2 = () => {
313
326
  return useMemo(
314
327
  () => [
315
- columnHelper$1.accessor("first_name", {
328
+ columnHelper$2.accessor("first_name", {
316
329
  header: "First Name"
317
330
  }),
318
- columnHelper$1.accessor("last_name", {
331
+ columnHelper$2.accessor("last_name", {
319
332
  header: "Last Name"
320
333
  }),
321
- columnHelper$1.accessor("email", {
334
+ columnHelper$2.accessor("email", {
322
335
  header: "Email"
323
336
  }),
324
- columnHelper$1.accessor("created_at", {
337
+ columnHelper$2.accessor("created_at", {
325
338
  header: "Date Added",
326
339
  cell: ({ getValue }) => new Date(getValue()).toLocaleDateString()
327
340
  }),
328
- columnHelper$1.display({
341
+ columnHelper$2.display({
329
342
  id: "actions",
330
343
  cell: ({ row }) => /* @__PURE__ */ jsx(OperatorActions, { operator: row.original })
331
344
  })
@@ -352,7 +365,7 @@ const OperatorTable = () => {
352
365
  queryKey: ["operators", limit, offset, searchValue],
353
366
  placeholderData: (previousData) => previousData
354
367
  });
355
- const columns = useColumns$1();
368
+ const columns = useColumns$2();
356
369
  const table = useDataTable({
357
370
  data: (data == null ? void 0 : data.operators) || [],
358
371
  columns,
@@ -383,7 +396,7 @@ const OperatorsPage = () => {
383
396
  /* @__PURE__ */ jsx(OperatorTable, {})
384
397
  ] });
385
398
  };
386
- const config$1 = defineRouteConfig({
399
+ const config$2 = defineRouteConfig({
387
400
  label: "Operators",
388
401
  icon: Users
389
402
  });
@@ -719,7 +732,7 @@ const PaymentOptionActions = ({
719
732
  )
720
733
  ] });
721
734
  };
722
- const columnHelper = createDataTableColumnHelper();
735
+ const columnHelper$1 = createDataTableColumnHelper();
723
736
  const formatAmount = (value) => {
724
737
  const n = Number(value ?? 0);
725
738
  return n.toLocaleString("es-MX", {
@@ -750,10 +763,10 @@ const statusColor = (status) => {
750
763
  return "grey";
751
764
  }
752
765
  };
753
- const useColumns = () => {
766
+ const useColumns$1 = () => {
754
767
  return useMemo(
755
768
  () => [
756
- columnHelper.accessor("order_display_id", {
769
+ columnHelper$1.accessor("order_display_id", {
757
770
  header: "Orden",
758
771
  cell: ({ row }) => {
759
772
  const displayId = row.original.order_display_id;
@@ -778,19 +791,19 @@ const useColumns = () => {
778
791
  );
779
792
  }
780
793
  }),
781
- columnHelper.accessor("reference_code", {
794
+ columnHelper$1.accessor("reference_code", {
782
795
  header: "Folio / Referencia",
783
796
  cell: ({ getValue }) => getValue() || "—"
784
797
  }),
785
- columnHelper.accessor("payment_method", {
798
+ columnHelper$1.accessor("payment_method", {
786
799
  header: "Método",
787
800
  cell: ({ getValue }) => getValue() || "—"
788
801
  }),
789
- columnHelper.accessor("amount", {
802
+ columnHelper$1.accessor("amount", {
790
803
  header: "Monto",
791
804
  cell: ({ getValue }) => formatAmount(getValue())
792
805
  }),
793
- columnHelper.accessor("status", {
806
+ columnHelper$1.accessor("status", {
794
807
  header: "Estatus",
795
808
  cell: ({ getValue }) => {
796
809
  const status = getValue();
@@ -800,15 +813,15 @@ const useColumns = () => {
800
813
  return /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: statusColor(status), children: status });
801
814
  }
802
815
  }),
803
- columnHelper.accessor("concept", {
816
+ columnHelper$1.accessor("concept", {
804
817
  header: "Concepto",
805
818
  cell: ({ getValue }) => getValue() || "—"
806
819
  }),
807
- columnHelper.accessor("created_at", {
820
+ columnHelper$1.accessor("created_at", {
808
821
  header: "Fecha",
809
822
  cell: ({ getValue }) => new Date(getValue()).toLocaleString()
810
823
  }),
811
- columnHelper.display({
824
+ columnHelper$1.display({
812
825
  id: "actions",
813
826
  cell: ({ row }) => /* @__PURE__ */ jsx(PaymentOptionActions, { paymentOption: row.original })
814
827
  })
@@ -835,7 +848,7 @@ const PaymentOptionTable = () => {
835
848
  queryKey: ["payment-options", limit, offset, searchValue],
836
849
  placeholderData: (previousData) => previousData
837
850
  });
838
- const columns = useColumns();
851
+ const columns = useColumns$1();
839
852
  const table = useDataTable({
840
853
  data: (data == null ? void 0 : data.payment_options) || [],
841
854
  columns,
@@ -872,10 +885,811 @@ const PaymentOptionsPage = () => {
872
885
  /* @__PURE__ */ jsx(PaymentOptionTable, {})
873
886
  ] });
874
887
  };
875
- const config = defineRouteConfig({
888
+ const config$1 = defineRouteConfig({
876
889
  label: "Notas de pago",
877
890
  icon: CurrencyDollar
878
891
  });
892
+ const POS_ROLES = [
893
+ { value: "cashier", label: "Cajero" },
894
+ { value: "supervisor", label: "Supervisor" },
895
+ { value: "manager", label: "Gerente" }
896
+ ];
897
+ const CAPABILITY_GROUPS = [
898
+ {
899
+ title: "Venta / carrito",
900
+ items: [
901
+ { key: "cancel_sale", label: "Cancelar venta", description: "Botón que borra el draft" },
902
+ { key: "pause_sale", label: "Pausar venta", description: "Guardar para después" },
903
+ { key: "remove_item", label: "Eliminar ítems del carrito" },
904
+ { key: "edit_quantity", label: "Cambiar cantidades" },
905
+ { key: "apply_promotion", label: "Aplicar / quitar cupón" },
906
+ { key: "apply_manual_discount", label: "Descuento manual (override de precio)", description: "Acción sensible" }
907
+ ]
908
+ },
909
+ {
910
+ title: "Configuración de la sesión",
911
+ items: [
912
+ { key: "change_region", label: "Cambiar región" },
913
+ { key: "change_sales_channel", label: "Cambiar canal de venta" },
914
+ { key: "change_location", label: "Cambiar ubicación de surtido" }
915
+ ]
916
+ },
917
+ {
918
+ title: "Pago",
919
+ items: [
920
+ { key: "pay_cash", label: "Cobrar en caja (efectivo)" },
921
+ { key: "pay_card", label: "Cobrar con tarjeta (Stripe)" },
922
+ { key: "use_store_credit", label: "Pagar con Monedero (store credit)" },
923
+ { key: "capture_payment", label: "Capturar pago" },
924
+ { key: "capture_without_docs", label: "Capturar sin documentación", description: "Acción sensible" }
925
+ ]
926
+ },
927
+ {
928
+ title: "Envío / dirección",
929
+ items: [
930
+ { key: "edit_shipping", label: "Elegir / cambiar método de envío" },
931
+ { key: "edit_customer_address", label: "Editar dirección de envío del cliente" }
932
+ ]
933
+ },
934
+ {
935
+ title: "Ventas pendientes",
936
+ items: [
937
+ { key: "view_pending_drafts", label: "Ver ventas pendientes (/pos-drafts)" },
938
+ { key: "recover_draft", label: "Recuperar / cargar un draft" }
939
+ ]
940
+ }
941
+ ];
942
+ const CAPABILITY_KEYS = CAPABILITY_GROUPS.flatMap(
943
+ (g) => g.items.map((i) => i.key)
944
+ );
945
+ const allTrue = () => CAPABILITY_KEYS.reduce(
946
+ (acc, key) => ({ ...acc, [key]: true }),
947
+ {}
948
+ );
949
+ const ROLE_PRESETS = {
950
+ cashier: {
951
+ ...allTrue(),
952
+ cancel_sale: false,
953
+ apply_manual_discount: false,
954
+ change_region: false,
955
+ change_sales_channel: false,
956
+ capture_payment: false,
957
+ capture_without_docs: false,
958
+ view_pending_drafts: false,
959
+ recover_draft: false
960
+ },
961
+ supervisor: {
962
+ ...allTrue(),
963
+ capture_without_docs: false
964
+ },
965
+ manager: {
966
+ ...allTrue()
967
+ }
968
+ };
969
+ const presetForRole = (role) => {
970
+ if (role && ROLE_PRESETS[role]) {
971
+ return ROLE_PRESETS[role];
972
+ }
973
+ return allTrue();
974
+ };
975
+ const resolveCapabilities = (role, stored) => {
976
+ const preset = presetForRole(role);
977
+ return CAPABILITY_KEYS.reduce((acc, key) => {
978
+ const storedValue = stored && typeof stored[key] === "boolean" ? stored[key] : void 0;
979
+ acc[key] = storedValue ?? preset[key] ?? true;
980
+ return acc;
981
+ }, {});
982
+ };
983
+ const columnHelper = createDataTableColumnHelper();
984
+ const roleLabel = (role) => {
985
+ var _a;
986
+ return ((_a = POS_ROLES.find((r) => r.value === role)) == null ? void 0 : _a.label) || null;
987
+ };
988
+ const scopeSummary = (ids) => Array.isArray(ids) ? `${ids.length} seleccionada${ids.length === 1 ? "" : "s"}` : "Todas";
989
+ const useColumns = () => useMemo(
990
+ () => [
991
+ columnHelper.accessor("first_name", {
992
+ header: "Nombre",
993
+ cell: ({ row }) => `${row.original.first_name ?? ""} ${row.original.last_name ?? ""}`.trim() || "—"
994
+ }),
995
+ columnHelper.accessor("email", {
996
+ header: "Email"
997
+ }),
998
+ columnHelper.display({
999
+ id: "role",
1000
+ header: "Rol POS",
1001
+ cell: ({ row }) => {
1002
+ var _a;
1003
+ const label = roleLabel((_a = row.original.metadata) == null ? void 0 : _a.pos_role);
1004
+ return label ? /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "blue", children: label }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: "Sin rol" });
1005
+ }
1006
+ }),
1007
+ columnHelper.display({
1008
+ id: "locations",
1009
+ header: "Ubicaciones",
1010
+ cell: ({ row }) => {
1011
+ var _a;
1012
+ return /* @__PURE__ */ jsx(Text, { size: "small", children: scopeSummary((_a = row.original.metadata) == null ? void 0 : _a.pos_stock_location_ids) });
1013
+ }
1014
+ }),
1015
+ columnHelper.display({
1016
+ id: "actions",
1017
+ cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { asChild: true, size: "small", variant: "secondary", children: /* @__PURE__ */ jsx(Link, { to: `/pos-permissions/${row.original.id}`, children: "Editar permisos" }) }) })
1018
+ })
1019
+ ],
1020
+ []
1021
+ );
1022
+ const PosPermissionsPage = () => {
1023
+ const [searchValue, setSearchValue] = useState("");
1024
+ const [pagination, setPagination] = useState({
1025
+ pageIndex: 0,
1026
+ pageSize: 15
1027
+ });
1028
+ const limit = pagination.pageSize;
1029
+ const offset = pagination.pageIndex * limit;
1030
+ const { data, isLoading } = useQuery({
1031
+ queryFn: () => sdk.client.fetch("/admin/operators", {
1032
+ query: {
1033
+ limit,
1034
+ offset,
1035
+ q: searchValue || void 0
1036
+ }
1037
+ }),
1038
+ queryKey: ["operators", "pos-permissions", limit, offset, searchValue],
1039
+ placeholderData: (previousData) => previousData
1040
+ });
1041
+ const columns = useColumns();
1042
+ const table = useDataTable({
1043
+ data: (data == null ? void 0 : data.operators) || [],
1044
+ columns,
1045
+ getRowId: (row) => row.id,
1046
+ rowCount: (data == null ? void 0 : data.count) || 0,
1047
+ isLoading,
1048
+ search: {
1049
+ state: searchValue,
1050
+ onSearchChange: setSearchValue
1051
+ },
1052
+ pagination: {
1053
+ state: pagination,
1054
+ onPaginationChange: setPagination
1055
+ }
1056
+ });
1057
+ return /* @__PURE__ */ jsxs(Container, { className: "flex flex-col items-stretch overflow-hidden p-0", children: [
1058
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between border-b border-ui-border-base px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
1059
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Permisos POS" }),
1060
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Define el alcance (ubicaciones, canales, regiones) y las capacidades de cada operador del Punto de Venta." })
1061
+ ] }) }),
1062
+ /* @__PURE__ */ jsxs(DataTable, { instance: table, children: [
1063
+ /* @__PURE__ */ jsx(DataTable.Toolbar, { children: /* @__PURE__ */ jsx("div", { className: "flex w-full items-center justify-end", children: /* @__PURE__ */ jsx(DataTable.Search, { placeholder: "Buscar operador..." }) }) }),
1064
+ /* @__PURE__ */ jsx(DataTable.Table, {}),
1065
+ /* @__PURE__ */ jsx(DataTable.Pagination, {})
1066
+ ] })
1067
+ ] });
1068
+ };
1069
+ const config = defineRouteConfig({
1070
+ label: "Permisos POS",
1071
+ icon: ShieldCheck
1072
+ });
1073
+ const MultiSelect = ({
1074
+ options,
1075
+ value,
1076
+ onChange,
1077
+ placeholder = "Seleccionar...",
1078
+ searchPlaceholder = "Buscar...",
1079
+ disabled = false
1080
+ }) => {
1081
+ const [open, setOpen] = useState(false);
1082
+ const [search, setSearch] = useState("");
1083
+ const filtered = useMemo(() => {
1084
+ const q = search.trim().toLowerCase();
1085
+ if (!q) {
1086
+ return options;
1087
+ }
1088
+ return options.filter(
1089
+ (o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q)
1090
+ );
1091
+ }, [options, search]);
1092
+ const selectedOptions = useMemo(
1093
+ () => value.map(
1094
+ (v) => options.find((o) => o.value === v) || { value: v, label: v }
1095
+ ),
1096
+ [value, options]
1097
+ );
1098
+ const toggle = (val) => {
1099
+ if (value.includes(val)) {
1100
+ onChange(value.filter((v) => v !== val));
1101
+ } else {
1102
+ onChange([...value, val]);
1103
+ }
1104
+ };
1105
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
1106
+ /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1107
+ "button",
1108
+ {
1109
+ type: "button",
1110
+ disabled,
1111
+ className: clx(
1112
+ "flex min-h-8 w-full items-center justify-between gap-2 rounded-md border bg-ui-bg-field px-3 py-1.5 text-left shadow-borders-base transition-colors",
1113
+ "hover:bg-ui-bg-field-hover focus:outline-none focus:shadow-borders-interactive-with-active",
1114
+ disabled && "cursor-not-allowed opacity-60"
1115
+ ),
1116
+ children: [
1117
+ selectedOptions.length === 0 ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: placeholder }) : /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: selectedOptions.map((o) => /* @__PURE__ */ jsxs(Badge, { size: "2xsmall", className: "gap-x-1", children: [
1118
+ o.label,
1119
+ /* @__PURE__ */ jsx(
1120
+ "span",
1121
+ {
1122
+ role: "button",
1123
+ tabIndex: -1,
1124
+ onClick: (e) => {
1125
+ e.stopPropagation();
1126
+ toggle(o.value);
1127
+ },
1128
+ className: "hover:text-ui-fg-base",
1129
+ children: /* @__PURE__ */ jsx(XMark, { className: "h-3 w-3" })
1130
+ }
1131
+ )
1132
+ ] }, o.value)) }),
1133
+ /* @__PURE__ */ jsx(ChevronUpDown, { className: "shrink-0 text-ui-fg-muted" })
1134
+ ]
1135
+ }
1136
+ ) }),
1137
+ /* @__PURE__ */ jsxs(
1138
+ Popover.Content,
1139
+ {
1140
+ align: "start",
1141
+ sideOffset: 4,
1142
+ className: "z-50 w-[var(--radix-popover-trigger-width)] min-w-[280px] p-0",
1143
+ children: [
1144
+ /* @__PURE__ */ jsx("div", { className: "border-b border-ui-border-base p-2", children: /* @__PURE__ */ jsx(
1145
+ Input,
1146
+ {
1147
+ autoFocus: true,
1148
+ placeholder: searchPlaceholder,
1149
+ value: search,
1150
+ onChange: (e) => setSearch(e.target.value)
1151
+ }
1152
+ ) }),
1153
+ /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-auto p-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx(
1154
+ Text,
1155
+ {
1156
+ size: "small",
1157
+ className: "px-2 py-3 text-center text-ui-fg-muted",
1158
+ children: "Sin resultados"
1159
+ }
1160
+ ) : filtered.map((o) => {
1161
+ const checked = value.includes(o.value);
1162
+ return /* @__PURE__ */ jsxs(
1163
+ "button",
1164
+ {
1165
+ type: "button",
1166
+ onClick: () => toggle(o.value),
1167
+ className: "flex w-full items-center gap-x-2 rounded-md px-2 py-1.5 text-left hover:bg-ui-bg-base-hover",
1168
+ children: [
1169
+ /* @__PURE__ */ jsx(
1170
+ Checkbox,
1171
+ {
1172
+ checked,
1173
+ className: "pointer-events-none"
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ jsx(Text, { size: "small", children: o.label })
1177
+ ]
1178
+ },
1179
+ o.value
1180
+ );
1181
+ }) }),
1182
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-ui-border-base px-2 py-1.5", children: [
1183
+ /* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [
1184
+ value.length,
1185
+ " seleccionado",
1186
+ value.length === 1 ? "" : "s"
1187
+ ] }),
1188
+ value.length > 0 && /* @__PURE__ */ jsx(
1189
+ Button,
1190
+ {
1191
+ size: "small",
1192
+ variant: "transparent",
1193
+ onClick: () => onChange([]),
1194
+ children: "Limpiar"
1195
+ }
1196
+ )
1197
+ ] })
1198
+ ]
1199
+ }
1200
+ )
1201
+ ] });
1202
+ };
1203
+ const AllowListField = ({
1204
+ label,
1205
+ description,
1206
+ icon,
1207
+ options,
1208
+ restricted,
1209
+ onRestrictedChange,
1210
+ selected,
1211
+ onSelectedChange,
1212
+ error,
1213
+ searchPlaceholder
1214
+ }) => {
1215
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-3 rounded-lg border border-ui-border-base p-4", children: [
1216
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
1217
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-x-2", children: [
1218
+ icon ? /* @__PURE__ */ jsx("span", { className: "mt-0.5 text-ui-fg-subtle", children: icon }) : null,
1219
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
1220
+ /* @__PURE__ */ jsx(Label, { weight: "plus", children: label }),
1221
+ description ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: description }) : null
1222
+ ] })
1223
+ ] }),
1224
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-x-2", children: [
1225
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: restricted ? "Restringido" : "Todas" }),
1226
+ /* @__PURE__ */ jsx(
1227
+ Switch,
1228
+ {
1229
+ checked: restricted,
1230
+ onCheckedChange: onRestrictedChange
1231
+ }
1232
+ )
1233
+ ] })
1234
+ ] }),
1235
+ restricted ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
1236
+ /* @__PURE__ */ jsx(
1237
+ MultiSelect,
1238
+ {
1239
+ options,
1240
+ value: selected,
1241
+ onChange: onSelectedChange,
1242
+ searchPlaceholder
1243
+ }
1244
+ ),
1245
+ error ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-error", children: error }) : null
1246
+ ] }) : null
1247
+ ] });
1248
+ };
1249
+ const NONE$1 = "__none__";
1250
+ const CapabilitiesSection = ({
1251
+ role,
1252
+ onRoleChange,
1253
+ capabilities,
1254
+ onCapabilitiesChange
1255
+ }) => {
1256
+ const preset = presetForRole(role);
1257
+ const setCapability = (key, nextValue) => {
1258
+ onCapabilitiesChange({ ...capabilities, [key]: nextValue });
1259
+ };
1260
+ const diffCount = Object.keys(preset).filter(
1261
+ (k) => capabilities[k] !== preset[k]
1262
+ ).length;
1263
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
1264
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
1265
+ /* @__PURE__ */ jsx(Label, { weight: "plus", children: "Rol POS" }),
1266
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "El rol aplica un preset de capacidades. Puedes ajustar capacidades puntuales abajo; se guarda el mapa completo resuelto." }),
1267
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
1268
+ /* @__PURE__ */ jsx("div", { className: "max-w-xs flex-1", children: /* @__PURE__ */ jsxs(
1269
+ Select,
1270
+ {
1271
+ value: role || NONE$1,
1272
+ onValueChange: (v) => onRoleChange(v === NONE$1 ? "" : v),
1273
+ children: [
1274
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Sin rol" }) }),
1275
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
1276
+ /* @__PURE__ */ jsx(Select.Item, { value: NONE$1, children: "Sin rol (todo permitido)" }),
1277
+ POS_ROLES.map((r) => /* @__PURE__ */ jsx(Select.Item, { value: r.value, children: r.label }, r.value))
1278
+ ] })
1279
+ ]
1280
+ }
1281
+ ) }),
1282
+ diffCount > 0 ? /* @__PURE__ */ jsxs(
1283
+ Button,
1284
+ {
1285
+ size: "small",
1286
+ variant: "secondary",
1287
+ onClick: () => onCapabilitiesChange({ ...preset }),
1288
+ children: [
1289
+ /* @__PURE__ */ jsx(ArrowUturnLeft, {}),
1290
+ "Restablecer al preset"
1291
+ ]
1292
+ }
1293
+ ) : null
1294
+ ] })
1295
+ ] }),
1296
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
1297
+ /* @__PURE__ */ jsx(Label, { weight: "plus", children: "Capacidades" }),
1298
+ diffCount > 0 ? /* @__PURE__ */ jsxs(Badge, { size: "2xsmall", color: "orange", children: [
1299
+ diffCount,
1300
+ " distinta",
1301
+ diffCount === 1 ? "" : "s",
1302
+ " del preset"
1303
+ ] }) : null
1304
+ ] }),
1305
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-5", children: CAPABILITY_GROUPS.map((group) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
1306
+ /* @__PURE__ */ jsx(
1307
+ Text,
1308
+ {
1309
+ size: "small",
1310
+ weight: "plus",
1311
+ className: "text-ui-fg-subtle",
1312
+ children: group.title
1313
+ }
1314
+ ),
1315
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col divide-y divide-ui-border-base rounded-lg border border-ui-border-base", children: group.items.map((item) => {
1316
+ const value = capabilities[item.key] ?? true;
1317
+ const differs = value !== (preset[item.key] ?? true);
1318
+ return /* @__PURE__ */ jsxs(
1319
+ "div",
1320
+ {
1321
+ className: "flex items-center justify-between gap-x-4 px-4 py-3",
1322
+ children: [
1323
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
1324
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
1325
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.label }),
1326
+ differs ? /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "orange", children: "≠ preset" }) : null
1327
+ ] }),
1328
+ item.description ? /* @__PURE__ */ jsx(
1329
+ Text,
1330
+ {
1331
+ size: "small",
1332
+ className: "text-ui-fg-subtle",
1333
+ children: item.description
1334
+ }
1335
+ ) : null
1336
+ ] }),
1337
+ /* @__PURE__ */ jsx(
1338
+ Switch,
1339
+ {
1340
+ checked: value,
1341
+ onCheckedChange: (checked) => setCapability(item.key, checked)
1342
+ }
1343
+ )
1344
+ ]
1345
+ },
1346
+ item.key
1347
+ );
1348
+ }) })
1349
+ ] }, group.title)) })
1350
+ ] });
1351
+ };
1352
+ const NONE = "__none__";
1353
+ const buildInitialState = (metadata) => {
1354
+ const role = metadata.pos_role ?? "";
1355
+ return {
1356
+ stockRestricted: Array.isArray(metadata.pos_stock_location_ids),
1357
+ stockIds: metadata.pos_stock_location_ids ?? [],
1358
+ channelRestricted: Array.isArray(metadata.pos_sales_channel_ids),
1359
+ channelIds: metadata.pos_sales_channel_ids ?? [],
1360
+ regionRestricted: Array.isArray(metadata.pos_region_ids),
1361
+ regionIds: metadata.pos_region_ids ?? [],
1362
+ shippingRestricted: Array.isArray(metadata.pos_shipping_option_ids),
1363
+ shippingIds: metadata.pos_shipping_option_ids ?? [],
1364
+ defaultRegionId: metadata.pos_default_region_id ?? "",
1365
+ defaultChannelId: metadata.pos_default_sales_channel_id ?? "",
1366
+ defaultStockId: metadata.pos_default_stock_location_id ?? "",
1367
+ role,
1368
+ // Full resolved map (folds any stored partial caps onto the role preset).
1369
+ capabilities: resolveCapabilities(role, metadata.pos_capabilities)
1370
+ };
1371
+ };
1372
+ const toOptions = (items, decorate) => (items ?? []).map((i) => ({
1373
+ value: i.id,
1374
+ label: decorate ? decorate(i) : i.name || i.id
1375
+ }));
1376
+ const DefaultSelect = ({
1377
+ label,
1378
+ value,
1379
+ onChange,
1380
+ options: opts,
1381
+ disabledHint
1382
+ }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
1383
+ /* @__PURE__ */ jsx(Label, { weight: "plus", children: label }),
1384
+ /* @__PURE__ */ jsxs(
1385
+ Select,
1386
+ {
1387
+ value: value || NONE,
1388
+ onValueChange: (v) => onChange(v === NONE ? "" : v),
1389
+ children: [
1390
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Sin valor por defecto" }) }),
1391
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
1392
+ /* @__PURE__ */ jsx(Select.Item, { value: NONE, children: "Sin valor por defecto" }),
1393
+ opts.map((o) => /* @__PURE__ */ jsx(Select.Item, { value: o.value, children: o.label }, o.value))
1394
+ ] })
1395
+ ]
1396
+ }
1397
+ ),
1398
+ opts.length === 0 && disabledHint ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: disabledHint }) : null
1399
+ ] });
1400
+ const PosPermissionEditorPage = () => {
1401
+ const { id } = useParams();
1402
+ const navigate = useNavigate();
1403
+ const queryClient = useQueryClient();
1404
+ const { data: operatorData, isLoading: operatorLoading } = useQuery({
1405
+ queryFn: () => sdk.client.fetch(`/admin/pos-permissions/${id}`),
1406
+ queryKey: ["pos-permissions-operator", id],
1407
+ enabled: !!id
1408
+ });
1409
+ const { data: options, isLoading: optionsLoading } = useQuery({
1410
+ queryFn: () => sdk.client.fetch(`/admin/pos-permissions/options`),
1411
+ queryKey: ["pos-permissions-options"]
1412
+ });
1413
+ const [form, setForm] = useState(null);
1414
+ const initializedFor = useRef(null);
1415
+ useEffect(() => {
1416
+ const operator2 = operatorData == null ? void 0 : operatorData.operator;
1417
+ if (operator2 && initializedFor.current !== operator2.id) {
1418
+ initializedFor.current = operator2.id;
1419
+ setForm(buildInitialState(operator2.metadata ?? {}));
1420
+ }
1421
+ }, [operatorData]);
1422
+ const stockOptions = useMemo(
1423
+ () => toOptions(options == null ? void 0 : options.stock_locations),
1424
+ [options]
1425
+ );
1426
+ const channelOptions = useMemo(
1427
+ () => toOptions(options == null ? void 0 : options.sales_channels),
1428
+ [options]
1429
+ );
1430
+ const regionOptions = useMemo(
1431
+ () => toOptions(
1432
+ options == null ? void 0 : options.regions,
1433
+ (r) => r.currency_code ? `${r.name} (${String(r.currency_code).toUpperCase()})` : r.name
1434
+ ),
1435
+ [options]
1436
+ );
1437
+ const shippingOptions = useMemo(
1438
+ () => toOptions(options == null ? void 0 : options.shipping_options),
1439
+ [options]
1440
+ );
1441
+ const saveMutation = useMutation({
1442
+ mutationFn: (payload) => sdk.client.fetch(`/admin/pos-permissions/${id}`, {
1443
+ method: "POST",
1444
+ body: payload
1445
+ }),
1446
+ onSuccess: () => {
1447
+ queryClient.invalidateQueries({ queryKey: ["operators"] });
1448
+ queryClient.invalidateQueries({
1449
+ queryKey: ["pos-permissions-operator", id]
1450
+ });
1451
+ toast.success("Permisos del operador actualizados");
1452
+ },
1453
+ onError: (error) => {
1454
+ toast.error(error.message || "No se pudieron guardar los permisos");
1455
+ }
1456
+ });
1457
+ if (operatorLoading || optionsLoading || !form) {
1458
+ return /* @__PURE__ */ jsx(Container, { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx(Spinner, { className: "animate-spin text-ui-fg-subtle" }) });
1459
+ }
1460
+ const operator = operatorData == null ? void 0 : operatorData.operator;
1461
+ const operatorName = `${(operator == null ? void 0 : operator.first_name) ?? ""} ${(operator == null ? void 0 : operator.last_name) ?? ""}`.trim() || (operator == null ? void 0 : operator.email) || id;
1462
+ const patch = (changes) => setForm((prev) => prev ? { ...prev, ...changes } : prev);
1463
+ const setStockIds = (ids) => setForm((prev) => {
1464
+ if (!prev) return prev;
1465
+ const next = { ...prev, stockIds: ids };
1466
+ if (prev.defaultStockId && !ids.includes(prev.defaultStockId)) {
1467
+ next.defaultStockId = "";
1468
+ }
1469
+ return next;
1470
+ });
1471
+ const setStockRestricted = (restricted) => setForm((prev) => {
1472
+ if (!prev) return prev;
1473
+ const next = { ...prev, stockRestricted: restricted };
1474
+ if (restricted && prev.defaultStockId && !prev.stockIds.includes(prev.defaultStockId)) {
1475
+ next.defaultStockId = "";
1476
+ }
1477
+ return next;
1478
+ });
1479
+ const setChannelIds = (ids) => setForm((prev) => {
1480
+ if (!prev) return prev;
1481
+ const next = { ...prev, channelIds: ids };
1482
+ if (prev.defaultChannelId && !ids.includes(prev.defaultChannelId)) {
1483
+ next.defaultChannelId = "";
1484
+ }
1485
+ return next;
1486
+ });
1487
+ const setChannelRestricted = (restricted) => setForm((prev) => {
1488
+ if (!prev) return prev;
1489
+ const next = { ...prev, channelRestricted: restricted };
1490
+ if (restricted && prev.defaultChannelId && !prev.channelIds.includes(prev.defaultChannelId)) {
1491
+ next.defaultChannelId = "";
1492
+ }
1493
+ return next;
1494
+ });
1495
+ const setRegionIds = (ids) => setForm((prev) => {
1496
+ if (!prev) return prev;
1497
+ const next = { ...prev, regionIds: ids };
1498
+ if (prev.defaultRegionId && !ids.includes(prev.defaultRegionId)) {
1499
+ next.defaultRegionId = "";
1500
+ }
1501
+ return next;
1502
+ });
1503
+ const setRegionRestricted = (restricted) => setForm((prev) => {
1504
+ if (!prev) return prev;
1505
+ const next = { ...prev, regionRestricted: restricted };
1506
+ if (restricted && prev.defaultRegionId && !prev.regionIds.includes(prev.defaultRegionId)) {
1507
+ next.defaultRegionId = "";
1508
+ }
1509
+ return next;
1510
+ });
1511
+ const regionDefaultOptions = form.regionRestricted ? regionOptions.filter((o) => form.regionIds.includes(o.value)) : regionOptions;
1512
+ const channelDefaultOptions = form.channelRestricted ? channelOptions.filter((o) => form.channelIds.includes(o.value)) : channelOptions;
1513
+ const stockDefaultOptions = form.stockRestricted ? stockOptions.filter((o) => form.stockIds.includes(o.value)) : stockOptions;
1514
+ const handleSave = () => {
1515
+ if (form.stockRestricted && form.stockIds.length === 0) {
1516
+ toast.error(
1517
+ "Selecciona al menos una ubicación o desactiva la restricción de ubicaciones."
1518
+ );
1519
+ return;
1520
+ }
1521
+ const payload = {
1522
+ pos_stock_location_ids: form.stockRestricted ? form.stockIds : null,
1523
+ pos_sales_channel_ids: form.channelRestricted ? form.channelIds : null,
1524
+ pos_region_ids: form.regionRestricted ? form.regionIds : null,
1525
+ pos_shipping_option_ids: form.shippingRestricted ? form.shippingIds : null,
1526
+ pos_default_region_id: form.defaultRegionId || null,
1527
+ pos_default_sales_channel_id: form.defaultChannelId || null,
1528
+ pos_default_stock_location_id: form.defaultStockId || null,
1529
+ pos_role: form.role || null,
1530
+ // Store the full resolved capability map so the frontend reads each
1531
+ // flag directly (cap ausente ⇒ permitido) without a preset table.
1532
+ pos_capabilities: form.capabilities
1533
+ };
1534
+ saveMutation.mutate(payload);
1535
+ };
1536
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-3", children: [
1537
+ /* @__PURE__ */ jsxs(Container, { className: "flex items-center justify-between p-4", children: [
1538
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
1539
+ /* @__PURE__ */ jsx(
1540
+ IconButton,
1541
+ {
1542
+ size: "small",
1543
+ variant: "transparent",
1544
+ onClick: () => navigate("/pos-permissions"),
1545
+ children: /* @__PURE__ */ jsx(ArrowLeft, {})
1546
+ }
1547
+ ),
1548
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
1549
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: operatorName }),
1550
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
1551
+ operator == null ? void 0 : operator.email,
1552
+ " · Permisos del Punto de Venta"
1553
+ ] })
1554
+ ] })
1555
+ ] }),
1556
+ /* @__PURE__ */ jsx(
1557
+ Button,
1558
+ {
1559
+ size: "small",
1560
+ onClick: handleSave,
1561
+ isLoading: saveMutation.isPending,
1562
+ children: "Guardar cambios"
1563
+ }
1564
+ )
1565
+ ] }),
1566
+ /* @__PURE__ */ jsxs(Container, { className: "flex flex-col gap-y-4 p-6", children: [
1567
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
1568
+ /* @__PURE__ */ jsx(Heading, { level: "h3", children: "Alcance de catálogo" }),
1569
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: 'Restringe a qué ubicaciones, canales, regiones y envíos puede acceder. "Todas" significa sin restricción.' })
1570
+ ] }),
1571
+ /* @__PURE__ */ jsx(
1572
+ AllowListField,
1573
+ {
1574
+ label: "Ubicaciones (sucursales pickup)",
1575
+ description: "Ubicaciones de surtido/recolección que puede usar.",
1576
+ icon: /* @__PURE__ */ jsx(Buildings, {}),
1577
+ options: stockOptions,
1578
+ restricted: form.stockRestricted,
1579
+ onRestrictedChange: setStockRestricted,
1580
+ selected: form.stockIds,
1581
+ onSelectedChange: setStockIds,
1582
+ searchPlaceholder: "Buscar ubicación...",
1583
+ error: form.stockRestricted && form.stockIds.length === 0 ? "Selecciona al menos una ubicación." : void 0
1584
+ }
1585
+ ),
1586
+ /* @__PURE__ */ jsx(
1587
+ AllowListField,
1588
+ {
1589
+ label: "Canales de venta",
1590
+ icon: /* @__PURE__ */ jsx(ChannelsSolid, {}),
1591
+ options: channelOptions,
1592
+ restricted: form.channelRestricted,
1593
+ onRestrictedChange: setChannelRestricted,
1594
+ selected: form.channelIds,
1595
+ onSelectedChange: setChannelIds,
1596
+ searchPlaceholder: "Buscar canal..."
1597
+ }
1598
+ ),
1599
+ /* @__PURE__ */ jsx(
1600
+ AllowListField,
1601
+ {
1602
+ label: "Regiones",
1603
+ icon: /* @__PURE__ */ jsx(CurrencyDollar, {}),
1604
+ options: regionOptions,
1605
+ restricted: form.regionRestricted,
1606
+ onRestrictedChange: setRegionRestricted,
1607
+ selected: form.regionIds,
1608
+ onSelectedChange: setRegionIds,
1609
+ searchPlaceholder: "Buscar región..."
1610
+ }
1611
+ ),
1612
+ /* @__PURE__ */ jsx(
1613
+ AllowListField,
1614
+ {
1615
+ label: "Opciones de envío",
1616
+ icon: /* @__PURE__ */ jsx(Tag, {}),
1617
+ options: shippingOptions,
1618
+ restricted: form.shippingRestricted,
1619
+ onRestrictedChange: (r) => patch({ shippingRestricted: r }),
1620
+ selected: form.shippingIds,
1621
+ onSelectedChange: (ids) => patch({ shippingIds: ids }),
1622
+ searchPlaceholder: "Buscar opción de envío..."
1623
+ }
1624
+ )
1625
+ ] }),
1626
+ /* @__PURE__ */ jsxs(Container, { className: "flex flex-col gap-y-4 p-6", children: [
1627
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
1628
+ /* @__PURE__ */ jsx(Heading, { level: "h3", children: "Valores por defecto" }),
1629
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Pre-selección al abrir la sesión. Deben pertenecer a su allow-list cuando esté restringida." })
1630
+ ] }),
1631
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-3", children: [
1632
+ /* @__PURE__ */ jsx(
1633
+ DefaultSelect,
1634
+ {
1635
+ label: "Región por defecto",
1636
+ value: form.defaultRegionId,
1637
+ onChange: (v) => patch({ defaultRegionId: v }),
1638
+ options: regionDefaultOptions,
1639
+ disabledHint: "Restringe regiones y selecciona alguna para elegir un default."
1640
+ }
1641
+ ),
1642
+ /* @__PURE__ */ jsx(
1643
+ DefaultSelect,
1644
+ {
1645
+ label: "Canal por defecto",
1646
+ value: form.defaultChannelId,
1647
+ onChange: (v) => patch({ defaultChannelId: v }),
1648
+ options: channelDefaultOptions,
1649
+ disabledHint: "Restringe canales y selecciona alguno para elegir un default."
1650
+ }
1651
+ ),
1652
+ /* @__PURE__ */ jsx(
1653
+ DefaultSelect,
1654
+ {
1655
+ label: "Ubicación por defecto",
1656
+ value: form.defaultStockId,
1657
+ onChange: (v) => patch({ defaultStockId: v }),
1658
+ options: stockDefaultOptions,
1659
+ disabledHint: "Restringe ubicaciones y selecciona alguna para elegir un default."
1660
+ }
1661
+ )
1662
+ ] })
1663
+ ] }),
1664
+ /* @__PURE__ */ jsxs(Container, { className: "flex flex-col gap-y-4 p-6", children: [
1665
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
1666
+ /* @__PURE__ */ jsx(Heading, { level: "h3", children: "Rol y capacidades" }),
1667
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "El rol define un preset; las capacidades permiten ajustes puntuales. El backend debe re-validar las acciones sensibles." })
1668
+ ] }),
1669
+ /* @__PURE__ */ jsx(
1670
+ CapabilitiesSection,
1671
+ {
1672
+ role: form.role,
1673
+ onRoleChange: (role) => patch({ role, capabilities: presetForRole(role) }),
1674
+ capabilities: form.capabilities,
1675
+ onCapabilitiesChange: (capabilities) => patch({ capabilities })
1676
+ }
1677
+ )
1678
+ ] }),
1679
+ /* @__PURE__ */ jsxs(Container, { className: "flex items-center justify-end gap-x-2 p-4", children: [
1680
+ /* @__PURE__ */ jsx(Button, { asChild: true, size: "small", variant: "secondary", children: /* @__PURE__ */ jsx(Link, { to: "/pos-permissions", children: "Volver" }) }),
1681
+ /* @__PURE__ */ jsx(
1682
+ Button,
1683
+ {
1684
+ size: "small",
1685
+ onClick: handleSave,
1686
+ isLoading: saveMutation.isPending,
1687
+ children: "Guardar cambios"
1688
+ }
1689
+ )
1690
+ ] })
1691
+ ] });
1692
+ };
879
1693
  const i18nTranslations0 = {};
880
1694
  const widgetModule = { widgets: [] };
881
1695
  const routeModule = {
@@ -887,6 +1701,14 @@ const routeModule = {
887
1701
  {
888
1702
  Component: PaymentOptionsPage,
889
1703
  path: "/payment-options"
1704
+ },
1705
+ {
1706
+ Component: PosPermissionsPage,
1707
+ path: "/pos-permissions"
1708
+ },
1709
+ {
1710
+ Component: PosPermissionEditorPage,
1711
+ path: "/pos-permissions/:id"
890
1712
  }
891
1713
  ]
892
1714
  };
@@ -895,6 +1717,14 @@ const menuItemModule = {
895
1717
  {
896
1718
  label: config$1.label,
897
1719
  icon: config$1.icon,
1720
+ path: "/payment-options",
1721
+ nested: void 0,
1722
+ rank: void 0,
1723
+ translationNs: void 0
1724
+ },
1725
+ {
1726
+ label: config$2.label,
1727
+ icon: config$2.icon,
898
1728
  path: "/operators",
899
1729
  nested: void 0,
900
1730
  rank: void 0,
@@ -903,7 +1733,7 @@ const menuItemModule = {
903
1733
  {
904
1734
  label: config.label,
905
1735
  icon: config.icon,
906
- path: "/payment-options",
1736
+ path: "/pos-permissions",
907
1737
  nested: void 0,
908
1738
  rank: void 0,
909
1739
  translationNs: void 0