@zaamx/netme-pos 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/.medusa/server/src/admin/index.js +428 -0
  2. package/.medusa/server/src/admin/index.mjs +427 -0
  3. package/.medusa/server/src/api/admin/netme-pos/payment-collections/[id]/mark-as-paid/route.js +20 -0
  4. package/.medusa/server/src/api/admin/netme-pos/payment-collections/[id]/payment-sessions/route.js +21 -0
  5. package/.medusa/server/src/api/admin/operators/[id]/route.js +69 -0
  6. package/.medusa/server/src/api/admin/operators/route.js +48 -0
  7. package/.medusa/server/src/api/admin/orders/[id]/cancel-no-refound/route.js +22 -0
  8. package/.medusa/server/src/api/admin/orders/search-by-display-id/route.js +25 -0
  9. package/.medusa/server/src/api/admin/pays/[payment_id]/options/[id]/route.js +35 -0
  10. package/.medusa/server/src/api/admin/pays/[payment_id]/options/route.js +46 -0
  11. package/.medusa/server/src/api/admin/plugin/route.js +7 -0
  12. package/.medusa/server/src/api/lib/connection-pool.js +47 -0
  13. package/.medusa/server/src/api/lib/customer-types.js +24 -0
  14. package/.medusa/server/src/api/lib/sdk.js +112 -0
  15. package/.medusa/server/src/api/lib/utils/password.js +27 -0
  16. package/.medusa/server/src/api/store/custom-shipping-methods/route.js +30 -0
  17. package/.medusa/server/src/api/store/plugin/route.js +7 -0
  18. package/.medusa/server/src/links/posoption-payment.js +16 -0
  19. package/.medusa/server/src/modules/payment-options/index.js +13 -0
  20. package/.medusa/server/src/modules/payment-options/migrations/Migration20250407125141.js +15 -0
  21. package/.medusa/server/src/modules/payment-options/models/payment-option.js +38 -0
  22. package/.medusa/server/src/modules/payment-options/service.js +14 -0
  23. package/.medusa/server/src/workflows/admin-create-operator/index.js +29 -0
  24. package/.medusa/server/src/workflows/admin-create-operator/steps/create-identity.js +27 -0
  25. package/.medusa/server/src/workflows/admin-create-operator/steps/create-operator-user.js +24 -0
  26. package/.medusa/server/src/workflows/authorize-payment-collection/index.js +42 -0
  27. package/.medusa/server/src/workflows/cancel-order-no-refund.js +104 -0
  28. package/.medusa/server/src/workflows/delete-operator.js +41 -0
  29. package/README.md +64 -0
  30. package/package.json +76 -0
@@ -0,0 +1,428 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const adminSdk = require("@medusajs/admin-sdk");
4
+ const icons = require("@medusajs/icons");
5
+ const ui = require("@medusajs/ui");
6
+ const react = require("react");
7
+ const reactQuery = require("@tanstack/react-query");
8
+ const Medusa = require("@medusajs/js-sdk");
9
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
10
+ const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
11
+ const sdk = new Medusa__default.default({
12
+ // @ts-ignore
13
+ baseUrl: "http://localhost:9000",
14
+ // @ts-ignore
15
+ debug: false,
16
+ auth: {
17
+ type: "session"
18
+ }
19
+ });
20
+ const EditOperatorDrawer = ({
21
+ operator,
22
+ open,
23
+ setOpen
24
+ }) => {
25
+ const [formData, setFormData] = react.useState({
26
+ first_name: operator.first_name,
27
+ last_name: operator.last_name,
28
+ email: operator.email
29
+ });
30
+ const [errors, setErrors] = react.useState({});
31
+ const queryClient = reactQuery.useQueryClient();
32
+ const updateOperator = reactQuery.useMutation({
33
+ mutationFn: (data) => sdk.client.fetch(`/admin/operators/${operator.id}`, {
34
+ method: "POST",
35
+ body: data
36
+ }),
37
+ onSuccess: () => {
38
+ queryClient.invalidateQueries({ queryKey: ["operators"] });
39
+ ui.toast.success("Operator updated successfully");
40
+ setOpen(false);
41
+ },
42
+ onError: (error) => {
43
+ ui.toast.error(error.message || "Failed to update operator");
44
+ }
45
+ });
46
+ const handleSubmit = () => {
47
+ const newErrors = {};
48
+ if (!formData.first_name) newErrors.first_name = "First name is required";
49
+ if (!formData.last_name) newErrors.last_name = "Last name is required";
50
+ if (!formData.email) newErrors.email = "Email is required";
51
+ else if (!formData.email.includes("@")) newErrors.email = "Valid email is required";
52
+ if (Object.keys(newErrors).length > 0) {
53
+ setErrors(newErrors);
54
+ return;
55
+ }
56
+ updateOperator.mutate(formData);
57
+ };
58
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
59
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: "Edit Operator" }) }),
60
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { className: "flex-1 overflow-auto p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
61
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
62
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "First Name" }),
63
+ /* @__PURE__ */ jsxRuntime.jsx(
64
+ ui.Input,
65
+ {
66
+ value: formData.first_name,
67
+ onChange: (e) => {
68
+ setFormData({ ...formData, first_name: e.target.value });
69
+ setErrors({ ...errors, first_name: "" });
70
+ }
71
+ }
72
+ ),
73
+ errors.first_name && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.first_name })
74
+ ] }),
75
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
76
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Last Name" }),
77
+ /* @__PURE__ */ jsxRuntime.jsx(
78
+ ui.Input,
79
+ {
80
+ value: formData.last_name,
81
+ onChange: (e) => {
82
+ setFormData({ ...formData, last_name: e.target.value });
83
+ setErrors({ ...errors, last_name: "" });
84
+ }
85
+ }
86
+ ),
87
+ errors.last_name && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.last_name })
88
+ ] }),
89
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
90
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Email" }),
91
+ /* @__PURE__ */ jsxRuntime.jsx(
92
+ ui.Input,
93
+ {
94
+ type: "email",
95
+ value: formData.email,
96
+ onChange: (e) => {
97
+ setFormData({ ...formData, email: e.target.value });
98
+ setErrors({ ...errors, email: "" });
99
+ }
100
+ }
101
+ ),
102
+ errors.email && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.email })
103
+ ] })
104
+ ] }) }),
105
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
106
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
107
+ ui.Button,
108
+ {
109
+ size: "small",
110
+ variant: "secondary",
111
+ disabled: updateOperator.isPending,
112
+ children: "Cancel"
113
+ }
114
+ ) }),
115
+ /* @__PURE__ */ jsxRuntime.jsx(
116
+ ui.Button,
117
+ {
118
+ size: "small",
119
+ onClick: handleSubmit,
120
+ isLoading: updateOperator.isPending,
121
+ children: "Save"
122
+ }
123
+ )
124
+ ] }) })
125
+ ] }) });
126
+ };
127
+ const DeleteOperatorModal = ({
128
+ operator,
129
+ open,
130
+ setOpen
131
+ }) => {
132
+ const queryClient = reactQuery.useQueryClient();
133
+ const deleteMutation = reactQuery.useMutation({
134
+ mutationFn: () => sdk.client.fetch(`/admin/operators/${operator.id}`, { method: "DELETE" }),
135
+ onSuccess: () => {
136
+ queryClient.invalidateQueries({ queryKey: ["operators"] });
137
+ ui.toast.success("Operator deleted successfully");
138
+ setOpen(false);
139
+ },
140
+ onError: (error) => {
141
+ ui.toast.error(error.message || "Failed to delete operator");
142
+ }
143
+ });
144
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Prompt, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Content, { children: [
145
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Header, { children: [
146
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "Delete Operator" }),
147
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Description, { children: [
148
+ "Are you sure you want to delete ",
149
+ operator.first_name,
150
+ "? This action cannot be undone."
151
+ ] })
152
+ ] }),
153
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Footer, { children: [
154
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Cancel, { children: "Cancel" }),
155
+ /* @__PURE__ */ jsxRuntime.jsx(
156
+ ui.Prompt.Action,
157
+ {
158
+ onClick: () => deleteMutation.mutate(),
159
+ disabled: deleteMutation.isPending,
160
+ children: "Delete"
161
+ }
162
+ )
163
+ ] })
164
+ ] }) });
165
+ };
166
+ const OperatorActions = ({ operator }) => {
167
+ const [editOpen, setEditOpen] = react.useState(false);
168
+ const [deleteOpen, setDeleteOpen] = react.useState(false);
169
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
170
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
171
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "small", variant: "transparent", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisHorizontal, {}) }) }),
172
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
173
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Item, { onClick: () => setEditOpen(true), className: "gap-x-2", children: [
174
+ /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, { className: "text-ui-fg-subtle" }),
175
+ "Edit"
176
+ ] }),
177
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
178
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Item, { onClick: () => setDeleteOpen(true), className: "gap-x-2", children: [
179
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
180
+ "Delete"
181
+ ] })
182
+ ] })
183
+ ] }),
184
+ /* @__PURE__ */ jsxRuntime.jsx(EditOperatorDrawer, { operator, open: editOpen, setOpen: setEditOpen }),
185
+ /* @__PURE__ */ jsxRuntime.jsx(DeleteOperatorModal, { operator, open: deleteOpen, setOpen: setDeleteOpen })
186
+ ] });
187
+ };
188
+ const CreateOperatorModal = () => {
189
+ const [open, setOpen] = react.useState(false);
190
+ const [formData, setFormData] = react.useState({
191
+ first_name: "",
192
+ last_name: "",
193
+ email: "",
194
+ password: ""
195
+ });
196
+ const [errors, setErrors] = react.useState({});
197
+ const queryClient = reactQuery.useQueryClient();
198
+ const createOperator = reactQuery.useMutation({
199
+ mutationFn: (data) => sdk.client.fetch("/admin/operators", {
200
+ method: "POST",
201
+ body: data
202
+ }),
203
+ onSuccess: () => {
204
+ queryClient.invalidateQueries({ queryKey: ["operators"] });
205
+ ui.toast.success("Operator created successfully");
206
+ setOpen(false);
207
+ setFormData({ first_name: "", last_name: "", email: "", password: "" });
208
+ setErrors({});
209
+ },
210
+ onError: (error) => {
211
+ ui.toast.error(error.message || "Failed to create operator");
212
+ }
213
+ });
214
+ const handleSubmit = () => {
215
+ const newErrors = {};
216
+ if (!formData.first_name) newErrors.first_name = "First name is required";
217
+ if (!formData.last_name) newErrors.last_name = "Last name is required";
218
+ if (!formData.email) newErrors.email = "Email is required";
219
+ else if (!formData.email.includes("@")) newErrors.email = "Valid email is required";
220
+ if (!formData.password) newErrors.password = "Password is required";
221
+ if (Object.keys(newErrors).length > 0) {
222
+ setErrors(newErrors);
223
+ return;
224
+ }
225
+ createOperator.mutate(formData);
226
+ };
227
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
228
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => setOpen(true), children: "Create Operator" }),
229
+ /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col overflow-hidden h-full", children: [
230
+ /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
231
+ /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
232
+ ui.Button,
233
+ {
234
+ size: "small",
235
+ variant: "secondary",
236
+ disabled: createOperator.isPending,
237
+ children: "Cancel"
238
+ }
239
+ ) }),
240
+ /* @__PURE__ */ jsxRuntime.jsx(
241
+ ui.Button,
242
+ {
243
+ size: "small",
244
+ onClick: handleSubmit,
245
+ isLoading: createOperator.isPending,
246
+ children: "Save"
247
+ }
248
+ )
249
+ ] }) }),
250
+ /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Body, { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4 max-w-[600px] mx-auto mt-8", children: [
251
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
252
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "First Name *" }),
253
+ /* @__PURE__ */ jsxRuntime.jsx(
254
+ ui.Input,
255
+ {
256
+ value: formData.first_name,
257
+ onChange: (e) => {
258
+ setFormData({ ...formData, first_name: e.target.value });
259
+ setErrors({ ...errors, first_name: "" });
260
+ }
261
+ }
262
+ ),
263
+ errors.first_name && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.first_name })
264
+ ] }),
265
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
266
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Last Name *" }),
267
+ /* @__PURE__ */ jsxRuntime.jsx(
268
+ ui.Input,
269
+ {
270
+ value: formData.last_name,
271
+ onChange: (e) => {
272
+ setFormData({ ...formData, last_name: e.target.value });
273
+ setErrors({ ...errors, last_name: "" });
274
+ }
275
+ }
276
+ ),
277
+ errors.last_name && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.last_name })
278
+ ] }),
279
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
280
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Email *" }),
281
+ /* @__PURE__ */ jsxRuntime.jsx(
282
+ ui.Input,
283
+ {
284
+ type: "email",
285
+ value: formData.email,
286
+ onChange: (e) => {
287
+ setFormData({ ...formData, email: e.target.value });
288
+ setErrors({ ...errors, email: "" });
289
+ }
290
+ }
291
+ ),
292
+ errors.email && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.email })
293
+ ] }),
294
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
295
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Password *" }),
296
+ /* @__PURE__ */ jsxRuntime.jsx(
297
+ ui.Input,
298
+ {
299
+ type: "password",
300
+ value: formData.password,
301
+ onChange: (e) => {
302
+ setFormData({ ...formData, password: e.target.value });
303
+ setErrors({ ...errors, password: "" });
304
+ }
305
+ }
306
+ ),
307
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This password will be used by the operator to log into their portal." }),
308
+ errors.password && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-error", children: errors.password })
309
+ ] })
310
+ ] }) })
311
+ ] }) }) })
312
+ ] });
313
+ };
314
+ const columnHelper = ui.createDataTableColumnHelper();
315
+ const useColumns = () => {
316
+ return react.useMemo(
317
+ () => [
318
+ columnHelper.accessor("first_name", {
319
+ header: "First Name"
320
+ }),
321
+ columnHelper.accessor("last_name", {
322
+ header: "Last Name"
323
+ }),
324
+ columnHelper.accessor("email", {
325
+ header: "Email"
326
+ }),
327
+ columnHelper.accessor("created_at", {
328
+ header: "Date Added",
329
+ cell: ({ getValue }) => new Date(getValue()).toLocaleDateString()
330
+ }),
331
+ columnHelper.display({
332
+ id: "actions",
333
+ cell: ({ row }) => /* @__PURE__ */ jsxRuntime.jsx(OperatorActions, { operator: row.original })
334
+ })
335
+ ],
336
+ []
337
+ );
338
+ };
339
+ const OperatorTable = () => {
340
+ const [searchValue, setSearchValue] = react.useState("");
341
+ const [pagination, setPagination] = react.useState({
342
+ pageIndex: 0,
343
+ pageSize: 15
344
+ });
345
+ const limit = pagination.pageSize;
346
+ const offset = pagination.pageIndex * limit;
347
+ const { data, isLoading } = reactQuery.useQuery({
348
+ queryFn: () => sdk.client.fetch("/admin/operators", {
349
+ query: {
350
+ limit,
351
+ offset,
352
+ q: searchValue || void 0
353
+ }
354
+ }),
355
+ queryKey: ["operators", limit, offset, searchValue],
356
+ placeholderData: (previousData) => previousData
357
+ });
358
+ const columns = useColumns();
359
+ const table = ui.useDataTable({
360
+ data: (data == null ? void 0 : data.operators) || [],
361
+ columns,
362
+ getRowId: (row) => row.id,
363
+ rowCount: (data == null ? void 0 : data.count) || 0,
364
+ isLoading,
365
+ search: {
366
+ state: searchValue,
367
+ onSearchChange: setSearchValue
368
+ },
369
+ pagination: {
370
+ state: pagination,
371
+ onPaginationChange: setPagination
372
+ }
373
+ });
374
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.DataTable, { instance: table, children: [
375
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Toolbar, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
376
+ /* @__PURE__ */ jsxRuntime.jsx(CreateOperatorModal, {}),
377
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Search, { placeholder: "Search operators..." })
378
+ ] }) }),
379
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Table, {}),
380
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Pagination, {})
381
+ ] });
382
+ };
383
+ const OperatorsPage = () => {
384
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex flex-col items-stretch overflow-hidden p-0", children: [
385
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between border-b border-ui-border-base px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Operators" }) }),
386
+ /* @__PURE__ */ jsxRuntime.jsx(OperatorTable, {})
387
+ ] });
388
+ };
389
+ const config = adminSdk.defineRouteConfig({
390
+ label: "Operators",
391
+ icon: icons.Users
392
+ });
393
+ const i18nTranslations0 = {};
394
+ const widgetModule = { widgets: [] };
395
+ const routeModule = {
396
+ routes: [
397
+ {
398
+ Component: OperatorsPage,
399
+ path: "/operators"
400
+ }
401
+ ]
402
+ };
403
+ const menuItemModule = {
404
+ menuItems: [
405
+ {
406
+ label: config.label,
407
+ icon: config.icon,
408
+ path: "/operators",
409
+ nested: void 0,
410
+ rank: void 0,
411
+ translationNs: void 0
412
+ }
413
+ ]
414
+ };
415
+ const formModule = { customFields: {} };
416
+ const displayModule = {
417
+ displays: {}
418
+ };
419
+ const i18nModule = { resources: i18nTranslations0 };
420
+ const plugin = {
421
+ widgetModule,
422
+ routeModule,
423
+ menuItemModule,
424
+ formModule,
425
+ displayModule,
426
+ i18nModule
427
+ };
428
+ module.exports = plugin;