@alphabite/medusa-reviews
Version:
Alphabite's Medusa Reviews Plugin
176 lines (175 loc) • 5.28 kB
JavaScript
"use strict";
const jsxRuntime = require("react/jsx-runtime");
const adminSdk = require("@medusajs/admin-sdk");
const icons = require("@medusajs/icons");
const ui = require("@medusajs/ui");
const reactQuery = require("@tanstack/react-query");
const react = require("react");
const Medusa = require("@medusajs/js-sdk");
const reactRouterDom = require("react-router-dom");
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
const sdk = new Medusa__default.default({
baseUrl: "http://localhost:9000",
debug: process.env.NODE_ENV === "development",
auth: {
type: "session"
}
});
const columnHelper = ui.createDataTableColumnHelper();
const columns = [
columnHelper.select(),
columnHelper.accessor("id", {
header: "ID"
}),
columnHelper.accessor("title", {
header: "Title"
}),
columnHelper.accessor("rating", {
header: "Rating"
}),
columnHelper.accessor("content", {
header: "Content"
}),
columnHelper.accessor("status", {
header: "Status",
cell: ({ row }) => {
const color = row.original.status === "approved" ? "green" : row.original.status === "rejected" ? "red" : "grey";
return /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color, children: row.original.status.charAt(0).toUpperCase() + row.original.status.slice(1) });
}
}),
columnHelper.accessor("product", {
header: "Product",
cell: ({ row }) => {
var _a;
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: `/products/${row.original.product_id}`, children: (_a = row.original.product) == null ? void 0 : _a.title });
}
})
];
const commandHelper = ui.createDataTableCommandHelper();
const useCommands = (refetch) => {
return [
commandHelper.command({
label: "Approve",
shortcut: "A",
action: async (selection) => {
const reviewsToApproveIds = Object.keys(selection);
sdk.client.fetch("/admin/reviews/status", {
method: "POST",
body: {
ids: reviewsToApproveIds,
status: "approved"
}
}).then(() => {
ui.toast.success("Reviews approved");
refetch();
}).catch(() => {
ui.toast.error("Failed to approve reviews");
});
}
}),
commandHelper.command({
label: "Reject",
shortcut: "R",
action: async (selection) => {
const reviewsToRejectIds = Object.keys(selection);
sdk.client.fetch("/admin/reviews/status", {
method: "POST",
body: {
ids: reviewsToRejectIds,
status: "rejected"
}
}).then(() => {
ui.toast.success("Reviews rejected");
refetch();
}).catch(() => {
ui.toast.error("Failed to reject reviews");
});
}
})
];
};
const limit = 15;
const ReviewsPage = () => {
const [rowSelection, setRowSelection] = react.useState(
{}
);
const [pagination, setPagination] = react.useState({
pageSize: limit,
pageIndex: 0
});
const offset = react.useMemo(() => {
return pagination.pageIndex * limit;
}, [pagination]);
const { data, isLoading, refetch } = reactQuery.useQuery({
queryKey: ["reviews", offset, limit],
queryFn: () => sdk.client.fetch("/admin/reviews", {
query: {
offset: pagination.pageIndex * pagination.pageSize,
limit: pagination.pageSize,
order: "-created_at"
}
})
});
const commands = useCommands(refetch);
const table = ui.useDataTable({
commands,
rowSelection: {
state: rowSelection,
onRowSelectionChange: setRowSelection
},
columns,
data: (data == null ? void 0 : data.reviews) || [],
rowCount: (data == null ? void 0 : data.count) || 0,
isLoading,
pagination: {
state: pagination,
onPaginationChange: setPagination
},
getRowId: (row) => row.id
});
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
/* @__PURE__ */ jsxRuntime.jsxs(ui.DataTable, { instance: table, children: [
/* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.CommandBar, { selectedLabel: (count) => `${count} selected` }),
/* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Toolbar, { className: "flex flex-col items-start justify-between gap-2 md:flex-row md:items-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Reviews" }) }),
/* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Table, {}),
/* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Pagination, {})
] }),
/* @__PURE__ */ jsxRuntime.jsx(ui.Toaster, {})
] });
};
const config = adminSdk.defineRouteConfig({
label: "Reviews",
icon: icons.ChatBubbleLeftRight
});
const widgetModule = { widgets: [] };
const routeModule = {
routes: [
{
Component: ReviewsPage,
path: "/reviews"
}
]
};
const menuItemModule = {
menuItems: [
{
label: config.label,
icon: config.icon,
path: "/reviews",
nested: void 0
}
]
};
const formModule = { customFields: {} };
const displayModule = {
displays: {}
};
const plugin = {
widgetModule,
routeModule,
menuItemModule,
formModule,
displayModule
};
module.exports = plugin;