@lodashventure/medusa-review 1.4.18 → 1.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +207 -4
- package/.medusa/server/src/admin/index.mjs +210 -7
- package/.medusa/server/src/api/admin/reviews/route.js +6 -1
- package/.medusa/server/src/api/admin/reviews/status/route.js +5 -5
- package/.medusa/server/src/api/store/reviews/route.js +9 -9
- package/.medusa/server/src/utils/z.js +13 -0
- package/.medusa/server/src/workflows/review/getReviewsWorkflow.js +48 -4
- package/package.json +1 -1
|
@@ -1,18 +1,216 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const react = require("react");
|
|
3
4
|
const adminSdk = require("@medusajs/admin-sdk");
|
|
4
|
-
const icons = require("@medusajs/icons");
|
|
5
5
|
const ui = require("@medusajs/ui");
|
|
6
|
+
const icons = require("@medusajs/icons");
|
|
6
7
|
const axios = require("axios");
|
|
7
|
-
const Mentions = require("rc-mentions");
|
|
8
|
-
const react = require("react");
|
|
9
8
|
const reactRouterDom = require("react-router-dom");
|
|
9
|
+
const Mentions = require("rc-mentions");
|
|
10
10
|
const Medusa = require("@medusajs/js-sdk");
|
|
11
11
|
require("@medusajs/admin-shared");
|
|
12
12
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
13
13
|
const axios__default = /* @__PURE__ */ _interopDefault(axios);
|
|
14
14
|
const Mentions__default = /* @__PURE__ */ _interopDefault(Mentions);
|
|
15
15
|
const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
|
|
16
|
+
const ProductReviewWidget = ({ data }) => {
|
|
17
|
+
const [reviews, setReviews] = react.useState([]);
|
|
18
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
19
|
+
const [error, setError] = react.useState(null);
|
|
20
|
+
const [stats, setStats] = react.useState({
|
|
21
|
+
total: 0,
|
|
22
|
+
average: 0,
|
|
23
|
+
pending: 0,
|
|
24
|
+
approved: 0,
|
|
25
|
+
rejected: 0
|
|
26
|
+
});
|
|
27
|
+
const fetchReviews = async () => {
|
|
28
|
+
setIsLoading(true);
|
|
29
|
+
setError(null);
|
|
30
|
+
try {
|
|
31
|
+
const { data: response } = await axios__default.default.get(
|
|
32
|
+
`/admin/reviews`,
|
|
33
|
+
{
|
|
34
|
+
params: {
|
|
35
|
+
product_id: data.id,
|
|
36
|
+
limit: 5,
|
|
37
|
+
offset: 0,
|
|
38
|
+
order: "-created_at",
|
|
39
|
+
fields: "id,title,content,rating,status,created_at,first_name,last_name,is_admin"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
setReviews(response.reviews);
|
|
44
|
+
const total = response.count || response.reviews.length;
|
|
45
|
+
const average = response.reviews.length > 0 ? response.reviews.reduce((sum, r) => sum + r.rating, 0) / response.reviews.length : 0;
|
|
46
|
+
const pending = response.reviews.filter(
|
|
47
|
+
(r) => r.status === "pending"
|
|
48
|
+
).length;
|
|
49
|
+
const approved = response.reviews.filter(
|
|
50
|
+
(r) => r.status === "approved"
|
|
51
|
+
).length;
|
|
52
|
+
const rejected = response.reviews.filter(
|
|
53
|
+
(r) => r.status === "rejected"
|
|
54
|
+
).length;
|
|
55
|
+
setStats({ total, average, pending, approved, rejected });
|
|
56
|
+
} catch (err) {
|
|
57
|
+
setError(
|
|
58
|
+
err instanceof Error ? err.message : "Failed to fetch reviews"
|
|
59
|
+
);
|
|
60
|
+
} finally {
|
|
61
|
+
setIsLoading(false);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
react.useEffect(() => {
|
|
65
|
+
fetchReviews();
|
|
66
|
+
}, [data.id]);
|
|
67
|
+
const handleStatusChange = async (reviewId, status) => {
|
|
68
|
+
try {
|
|
69
|
+
await axios__default.default.post("/admin/reviews/status", {
|
|
70
|
+
ids: [reviewId],
|
|
71
|
+
status
|
|
72
|
+
});
|
|
73
|
+
ui.toast.success(`Review ${status}`, {
|
|
74
|
+
description: `The review has been ${status} successfully`
|
|
75
|
+
});
|
|
76
|
+
fetchReviews();
|
|
77
|
+
} catch (err) {
|
|
78
|
+
ui.toast.error("Failed to update review", {
|
|
79
|
+
description: err instanceof Error ? err.message : "An error occurred"
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const getStatusColor = (status) => {
|
|
84
|
+
switch (status) {
|
|
85
|
+
case "approved":
|
|
86
|
+
return "green";
|
|
87
|
+
case "rejected":
|
|
88
|
+
return "red";
|
|
89
|
+
case "pending":
|
|
90
|
+
return "orange";
|
|
91
|
+
default:
|
|
92
|
+
return "grey";
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const renderStars = (rating) => {
|
|
96
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
97
|
+
"span",
|
|
98
|
+
{
|
|
99
|
+
className: `text-lg ${star <= rating ? "text-yellow-500" : "text-gray-300"}`,
|
|
100
|
+
children: "★"
|
|
101
|
+
},
|
|
102
|
+
star
|
|
103
|
+
)) });
|
|
104
|
+
};
|
|
105
|
+
if (error) {
|
|
106
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "error", children: error }) });
|
|
107
|
+
}
|
|
108
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "divide-y px-0 pb-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-6 space-y-6", children: [
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 md:flex-row md:items-center md:justify-between", children: [
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChatBubbleLeftRight, { className: "h-6 w-6 text-ui-fg-subtle" }),
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Product Reviews" }),
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-subtle", children: "Customer reviews and ratings for this product" })
|
|
115
|
+
] })
|
|
116
|
+
] }),
|
|
117
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
118
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { color: "blue", size: "small", children: [
|
|
119
|
+
stats.total,
|
|
120
|
+
" Total"
|
|
121
|
+
] }),
|
|
122
|
+
stats.pending > 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { color: "orange", size: "small", children: [
|
|
123
|
+
stats.pending,
|
|
124
|
+
" Pending"
|
|
125
|
+
] })
|
|
126
|
+
] })
|
|
127
|
+
] }),
|
|
128
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border bg-ui-bg-base p-6 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-muted", children: "Loading reviews..." }) }) : reviews.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed bg-ui-bg-subtle p-6 text-center", children: [
|
|
129
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChatBubbleLeftRight, { className: "h-8 w-8 mx-auto mb-2 text-ui-fg-muted" }),
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-muted", children: "No reviews yet for this product" }),
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-subtle", children: "Reviews will appear here once customers submit them" })
|
|
132
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
133
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border bg-ui-bg-base p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
135
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-subtle mb-1", children: "Average Rating" }),
|
|
136
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
137
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl font-bold", children: stats.average.toFixed(1) }),
|
|
138
|
+
renderStars(Math.round(stats.average))
|
|
139
|
+
] })
|
|
140
|
+
] }),
|
|
141
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
142
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-subtle mb-1", children: "Status Breakdown" }),
|
|
143
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 justify-end", children: [
|
|
144
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { color: "green", size: "small", children: [
|
|
145
|
+
stats.approved,
|
|
146
|
+
" Approved"
|
|
147
|
+
] }),
|
|
148
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { color: "red", size: "small", children: [
|
|
149
|
+
stats.rejected,
|
|
150
|
+
" Rejected"
|
|
151
|
+
] })
|
|
152
|
+
] })
|
|
153
|
+
] })
|
|
154
|
+
] }) }),
|
|
155
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
156
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
157
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-base", children: "Recent Reviews" }),
|
|
158
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: "/reviews", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", children: [
|
|
159
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "mr-1 h-4 w-4" }),
|
|
160
|
+
"View All"
|
|
161
|
+
] }) })
|
|
162
|
+
] }),
|
|
163
|
+
reviews.map((review) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
164
|
+
"div",
|
|
165
|
+
{
|
|
166
|
+
className: "rounded-lg border bg-ui-bg-subtle p-4 space-y-3",
|
|
167
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
170
|
+
renderStars(review.rating),
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: getStatusColor(review.status), children: review.status.charAt(0).toUpperCase() + review.status.slice(1) })
|
|
172
|
+
] }),
|
|
173
|
+
review.title && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium mb-1", children: review.title }),
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-ui-fg-subtle line-clamp-2", children: review.content }),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-muted", children: review.is_admin ? "Admin" : review.first_name ? `${review.first_name} ${review.last_name || ""}` : "Anonymous" }),
|
|
177
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "•" }),
|
|
178
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-muted", children: new Date(review.created_at).toLocaleDateString() })
|
|
179
|
+
] })
|
|
180
|
+
] }),
|
|
181
|
+
review.status === "pending" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1 ml-4", children: [
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
183
|
+
ui.Button,
|
|
184
|
+
{
|
|
185
|
+
variant: "secondary",
|
|
186
|
+
size: "small",
|
|
187
|
+
onClick: () => handleStatusChange(review.id, "approved"),
|
|
188
|
+
title: "Approve review",
|
|
189
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircleSolid, { className: "h-4 w-4 text-green-600" })
|
|
190
|
+
}
|
|
191
|
+
),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
193
|
+
ui.Button,
|
|
194
|
+
{
|
|
195
|
+
variant: "secondary",
|
|
196
|
+
size: "small",
|
|
197
|
+
onClick: () => handleStatusChange(review.id, "rejected"),
|
|
198
|
+
title: "Reject review",
|
|
199
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(icons.XCircleSolid, { className: "h-4 w-4 text-red-600" })
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
] })
|
|
203
|
+
] })
|
|
204
|
+
},
|
|
205
|
+
review.id
|
|
206
|
+
))
|
|
207
|
+
] })
|
|
208
|
+
] })
|
|
209
|
+
] }) });
|
|
210
|
+
};
|
|
211
|
+
adminSdk.defineWidgetConfig({
|
|
212
|
+
zone: "product.details.after"
|
|
213
|
+
});
|
|
16
214
|
const statusColor = (status) => status === "approved" ? "green" : status === "rejected" ? "red" : "grey";
|
|
17
215
|
const mimeTypes = ["image", "video"];
|
|
18
216
|
const MediaViewer = ({ media, className }) => {
|
|
@@ -459,7 +657,12 @@ const config = adminSdk.defineRouteConfig({
|
|
|
459
657
|
label: "Reviews",
|
|
460
658
|
icon: icons.ChatBubbleLeftRight
|
|
461
659
|
});
|
|
462
|
-
const widgetModule = { widgets: [
|
|
660
|
+
const widgetModule = { widgets: [
|
|
661
|
+
{
|
|
662
|
+
Component: ProductReviewWidget,
|
|
663
|
+
zone: ["product.details.after"]
|
|
664
|
+
}
|
|
665
|
+
] };
|
|
463
666
|
const routeModule = {
|
|
464
667
|
routes: [
|
|
465
668
|
{
|
|
@@ -1,13 +1,211 @@
|
|
|
1
|
-
import { jsx,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useMemo } from "react";
|
|
3
|
+
import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
|
|
4
|
+
import { Container, Alert, Heading, Text, Badge, Button, StatusBadge, toast, FocusModal, clx, ProgressAccordion, createDataTableColumnHelper, DataTable, Toaster, createDataTableCommandHelper, useDataTable, Drawer } from "@medusajs/ui";
|
|
5
|
+
import { ChatBubbleLeftRight, ArrowUpRightOnBox, CheckCircleSolid, XCircleSolid } from "@medusajs/icons";
|
|
5
6
|
import axios from "axios";
|
|
6
|
-
import Mentions from "rc-mentions";
|
|
7
|
-
import { useState, useMemo, useEffect } from "react";
|
|
8
7
|
import { Link } from "react-router-dom";
|
|
8
|
+
import Mentions from "rc-mentions";
|
|
9
9
|
import Medusa from "@medusajs/js-sdk";
|
|
10
10
|
import "@medusajs/admin-shared";
|
|
11
|
+
const ProductReviewWidget = ({ data }) => {
|
|
12
|
+
const [reviews, setReviews] = useState([]);
|
|
13
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
14
|
+
const [error, setError] = useState(null);
|
|
15
|
+
const [stats, setStats] = useState({
|
|
16
|
+
total: 0,
|
|
17
|
+
average: 0,
|
|
18
|
+
pending: 0,
|
|
19
|
+
approved: 0,
|
|
20
|
+
rejected: 0
|
|
21
|
+
});
|
|
22
|
+
const fetchReviews = async () => {
|
|
23
|
+
setIsLoading(true);
|
|
24
|
+
setError(null);
|
|
25
|
+
try {
|
|
26
|
+
const { data: response } = await axios.get(
|
|
27
|
+
`/admin/reviews`,
|
|
28
|
+
{
|
|
29
|
+
params: {
|
|
30
|
+
product_id: data.id,
|
|
31
|
+
limit: 5,
|
|
32
|
+
offset: 0,
|
|
33
|
+
order: "-created_at",
|
|
34
|
+
fields: "id,title,content,rating,status,created_at,first_name,last_name,is_admin"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
setReviews(response.reviews);
|
|
39
|
+
const total = response.count || response.reviews.length;
|
|
40
|
+
const average = response.reviews.length > 0 ? response.reviews.reduce((sum, r) => sum + r.rating, 0) / response.reviews.length : 0;
|
|
41
|
+
const pending = response.reviews.filter(
|
|
42
|
+
(r) => r.status === "pending"
|
|
43
|
+
).length;
|
|
44
|
+
const approved = response.reviews.filter(
|
|
45
|
+
(r) => r.status === "approved"
|
|
46
|
+
).length;
|
|
47
|
+
const rejected = response.reviews.filter(
|
|
48
|
+
(r) => r.status === "rejected"
|
|
49
|
+
).length;
|
|
50
|
+
setStats({ total, average, pending, approved, rejected });
|
|
51
|
+
} catch (err) {
|
|
52
|
+
setError(
|
|
53
|
+
err instanceof Error ? err.message : "Failed to fetch reviews"
|
|
54
|
+
);
|
|
55
|
+
} finally {
|
|
56
|
+
setIsLoading(false);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
fetchReviews();
|
|
61
|
+
}, [data.id]);
|
|
62
|
+
const handleStatusChange = async (reviewId, status) => {
|
|
63
|
+
try {
|
|
64
|
+
await axios.post("/admin/reviews/status", {
|
|
65
|
+
ids: [reviewId],
|
|
66
|
+
status
|
|
67
|
+
});
|
|
68
|
+
toast.success(`Review ${status}`, {
|
|
69
|
+
description: `The review has been ${status} successfully`
|
|
70
|
+
});
|
|
71
|
+
fetchReviews();
|
|
72
|
+
} catch (err) {
|
|
73
|
+
toast.error("Failed to update review", {
|
|
74
|
+
description: err instanceof Error ? err.message : "An error occurred"
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const getStatusColor = (status) => {
|
|
79
|
+
switch (status) {
|
|
80
|
+
case "approved":
|
|
81
|
+
return "green";
|
|
82
|
+
case "rejected":
|
|
83
|
+
return "red";
|
|
84
|
+
case "pending":
|
|
85
|
+
return "orange";
|
|
86
|
+
default:
|
|
87
|
+
return "grey";
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const renderStars = (rating) => {
|
|
91
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
|
|
92
|
+
"span",
|
|
93
|
+
{
|
|
94
|
+
className: `text-lg ${star <= rating ? "text-yellow-500" : "text-gray-300"}`,
|
|
95
|
+
children: "★"
|
|
96
|
+
},
|
|
97
|
+
star
|
|
98
|
+
)) });
|
|
99
|
+
};
|
|
100
|
+
if (error) {
|
|
101
|
+
return /* @__PURE__ */ jsx(Container, { className: "p-6", children: /* @__PURE__ */ jsx(Alert, { variant: "error", children: error }) });
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ jsx(Container, { className: "divide-y px-0 pb-0", children: /* @__PURE__ */ jsxs("div", { className: "px-6 py-6 space-y-6", children: [
|
|
104
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 md:flex-row md:items-center md:justify-between", children: [
|
|
105
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
106
|
+
/* @__PURE__ */ jsx(ChatBubbleLeftRight, { className: "h-6 w-6 text-ui-fg-subtle" }),
|
|
107
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
108
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "Product Reviews" }),
|
|
109
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-ui-fg-subtle", children: "Customer reviews and ratings for this product" })
|
|
110
|
+
] })
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
113
|
+
/* @__PURE__ */ jsxs(Badge, { color: "blue", size: "small", children: [
|
|
114
|
+
stats.total,
|
|
115
|
+
" Total"
|
|
116
|
+
] }),
|
|
117
|
+
stats.pending > 0 && /* @__PURE__ */ jsxs(Badge, { color: "orange", size: "small", children: [
|
|
118
|
+
stats.pending,
|
|
119
|
+
" Pending"
|
|
120
|
+
] })
|
|
121
|
+
] })
|
|
122
|
+
] }),
|
|
123
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-ui-bg-base p-6 text-center", children: /* @__PURE__ */ jsx(Text, { className: "text-sm text-ui-fg-muted", children: "Loading reviews..." }) }) : reviews.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed bg-ui-bg-subtle p-6 text-center", children: [
|
|
124
|
+
/* @__PURE__ */ jsx(ChatBubbleLeftRight, { className: "h-8 w-8 mx-auto mb-2 text-ui-fg-muted" }),
|
|
125
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-ui-fg-muted", children: "No reviews yet for this product" }),
|
|
126
|
+
/* @__PURE__ */ jsx(Text, { className: "text-xs text-ui-fg-subtle", children: "Reviews will appear here once customers submit them" })
|
|
127
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
128
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-ui-bg-base p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
129
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
130
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-ui-fg-subtle mb-1", children: "Average Rating" }),
|
|
131
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
132
|
+
/* @__PURE__ */ jsx("span", { className: "text-2xl font-bold", children: stats.average.toFixed(1) }),
|
|
133
|
+
renderStars(Math.round(stats.average))
|
|
134
|
+
] })
|
|
135
|
+
] }),
|
|
136
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
137
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-ui-fg-subtle mb-1", children: "Status Breakdown" }),
|
|
138
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2 justify-end", children: [
|
|
139
|
+
/* @__PURE__ */ jsxs(Badge, { color: "green", size: "small", children: [
|
|
140
|
+
stats.approved,
|
|
141
|
+
" Approved"
|
|
142
|
+
] }),
|
|
143
|
+
/* @__PURE__ */ jsxs(Badge, { color: "red", size: "small", children: [
|
|
144
|
+
stats.rejected,
|
|
145
|
+
" Rejected"
|
|
146
|
+
] })
|
|
147
|
+
] })
|
|
148
|
+
] })
|
|
149
|
+
] }) }),
|
|
150
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
151
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
152
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-base", children: "Recent Reviews" }),
|
|
153
|
+
/* @__PURE__ */ jsx(Link, { to: "/reviews", children: /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "small", children: [
|
|
154
|
+
/* @__PURE__ */ jsx(ArrowUpRightOnBox, { className: "mr-1 h-4 w-4" }),
|
|
155
|
+
"View All"
|
|
156
|
+
] }) })
|
|
157
|
+
] }),
|
|
158
|
+
reviews.map((review) => /* @__PURE__ */ jsx(
|
|
159
|
+
"div",
|
|
160
|
+
{
|
|
161
|
+
className: "rounded-lg border bg-ui-bg-subtle p-4 space-y-3",
|
|
162
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
|
|
163
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
164
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
165
|
+
renderStars(review.rating),
|
|
166
|
+
/* @__PURE__ */ jsx(StatusBadge, { color: getStatusColor(review.status), children: review.status.charAt(0).toUpperCase() + review.status.slice(1) })
|
|
167
|
+
] }),
|
|
168
|
+
review.title && /* @__PURE__ */ jsx(Text, { className: "font-medium mb-1", children: review.title }),
|
|
169
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-ui-fg-subtle line-clamp-2", children: review.content }),
|
|
170
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
171
|
+
/* @__PURE__ */ jsx(Text, { className: "text-xs text-ui-fg-muted", children: review.is_admin ? "Admin" : review.first_name ? `${review.first_name} ${review.last_name || ""}` : "Anonymous" }),
|
|
172
|
+
/* @__PURE__ */ jsx("span", { className: "text-ui-fg-muted", children: "•" }),
|
|
173
|
+
/* @__PURE__ */ jsx(Text, { className: "text-xs text-ui-fg-muted", children: new Date(review.created_at).toLocaleDateString() })
|
|
174
|
+
] })
|
|
175
|
+
] }),
|
|
176
|
+
review.status === "pending" && /* @__PURE__ */ jsxs("div", { className: "flex gap-1 ml-4", children: [
|
|
177
|
+
/* @__PURE__ */ jsx(
|
|
178
|
+
Button,
|
|
179
|
+
{
|
|
180
|
+
variant: "secondary",
|
|
181
|
+
size: "small",
|
|
182
|
+
onClick: () => handleStatusChange(review.id, "approved"),
|
|
183
|
+
title: "Approve review",
|
|
184
|
+
children: /* @__PURE__ */ jsx(CheckCircleSolid, { className: "h-4 w-4 text-green-600" })
|
|
185
|
+
}
|
|
186
|
+
),
|
|
187
|
+
/* @__PURE__ */ jsx(
|
|
188
|
+
Button,
|
|
189
|
+
{
|
|
190
|
+
variant: "secondary",
|
|
191
|
+
size: "small",
|
|
192
|
+
onClick: () => handleStatusChange(review.id, "rejected"),
|
|
193
|
+
title: "Reject review",
|
|
194
|
+
children: /* @__PURE__ */ jsx(XCircleSolid, { className: "h-4 w-4 text-red-600" })
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
] })
|
|
198
|
+
] })
|
|
199
|
+
},
|
|
200
|
+
review.id
|
|
201
|
+
))
|
|
202
|
+
] })
|
|
203
|
+
] })
|
|
204
|
+
] }) });
|
|
205
|
+
};
|
|
206
|
+
defineWidgetConfig({
|
|
207
|
+
zone: "product.details.after"
|
|
208
|
+
});
|
|
11
209
|
const statusColor = (status) => status === "approved" ? "green" : status === "rejected" ? "red" : "grey";
|
|
12
210
|
const mimeTypes = ["image", "video"];
|
|
13
211
|
const MediaViewer = ({ media, className }) => {
|
|
@@ -454,7 +652,12 @@ const config = defineRouteConfig({
|
|
|
454
652
|
label: "Reviews",
|
|
455
653
|
icon: ChatBubbleLeftRight
|
|
456
654
|
});
|
|
457
|
-
const widgetModule = { widgets: [
|
|
655
|
+
const widgetModule = { widgets: [
|
|
656
|
+
{
|
|
657
|
+
Component: ProductReviewWidget,
|
|
658
|
+
zone: ["product.details.after"]
|
|
659
|
+
}
|
|
660
|
+
] };
|
|
458
661
|
const routeModule = {
|
|
459
662
|
routes: [
|
|
460
663
|
{
|
|
@@ -4,11 +4,16 @@ exports.POST = exports.GET = void 0;
|
|
|
4
4
|
const getReviewsWorkflow_1 = require("../../../workflows/review/getReviewsWorkflow");
|
|
5
5
|
const createReviewWorkflow_1 = require("../../../workflows/review/createReviewWorkflow");
|
|
6
6
|
const GET = async (req, res) => {
|
|
7
|
+
// Extract filters from query parameters
|
|
8
|
+
const validatedQuery = (req.validatedQuery ?? {});
|
|
9
|
+
const { product_id, status } = validatedQuery;
|
|
7
10
|
const { result } = await (0, getReviewsWorkflow_1.getReviewsWorkflow)().run({
|
|
8
11
|
input: {
|
|
9
12
|
queryConfig: req.queryConfig,
|
|
10
13
|
filters: {
|
|
11
14
|
parent: null,
|
|
15
|
+
...(product_id && { product_id }),
|
|
16
|
+
...(status && { status }),
|
|
12
17
|
},
|
|
13
18
|
},
|
|
14
19
|
});
|
|
@@ -32,4 +37,4 @@ const POST = async (req, res) => {
|
|
|
32
37
|
res.json(result);
|
|
33
38
|
};
|
|
34
39
|
exports.POST = POST;
|
|
35
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Jldmlld3Mvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBS0EscUZBR3NEO0FBQ3RELHlGQUFzRjtBQUcvRSxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQ3RCLEdBQTRDLEVBQzVDLEdBQW1CLEVBQ25CLEVBQUU7SUFDRix3Q0FBd0M7SUFDeEMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxHQUFHLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBb0IsQ0FBQztJQUNyRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLGNBRzlCLENBQUM7SUFFRixNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFBLHVDQUFrQixHQUFFLENBQUMsR0FBRyxDQUFDO1FBQ2hELEtBQUssRUFBRTtZQUNMLFdBQVcsRUFBRSxHQUFHLENBQUMsV0FBVztZQUM1QixPQUFPLEVBQUU7Z0JBQ1AsTUFBTSxFQUFFLElBQUk7Z0JBQ1osR0FBRyxDQUFDLFVBQVUsSUFBSSxFQUFFLFVBQVUsRUFBRSxDQUFDO2dCQUNqQyxHQUFHLENBQUMsTUFBTSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7YUFDMUI7U0FDRjtLQUNGLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbkIsQ0FBQyxDQUFDO0FBdkJXLFFBQUEsR0FBRyxPQXVCZDtBQUVLLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFDdkIsR0FBbUQsRUFDbkQsR0FBbUIsRUFDbkIsRUFBRTtJQUNGOzs7T0FHRztJQUNILE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxZQUFZLEVBQUUsVUFBVSxLQUFLLE1BQU0sQ0FBQztJQUV4RCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFBLDJDQUFvQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDM0QsS0FBSyxFQUFFO1lBQ0wsR0FBRyxHQUFHLENBQUMsYUFBYTtZQUNwQixRQUFRLEVBQUUsT0FBTztZQUNqQixNQUFNLEVBQUUsVUFBVTtZQUNsQixNQUFNLEVBQUUsRUFBRTtTQUNYO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNuQixDQUFDLENBQUM7QUFwQlcsUUFBQSxJQUFJLFFBb0JmIn0=
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PostAdminUpdateReviewsStatusSchema = void 0;
|
|
4
4
|
exports.POST = POST;
|
|
5
|
-
const
|
|
5
|
+
const z_1 = require("../../../../utils/z");
|
|
6
6
|
const updateReviewWorkflow_1 = require("../../../../workflows/review/updateReviewWorkflow");
|
|
7
|
-
exports.PostAdminUpdateReviewsStatusSchema =
|
|
8
|
-
ids:
|
|
9
|
-
status:
|
|
7
|
+
exports.PostAdminUpdateReviewsStatusSchema = z_1.z.object({
|
|
8
|
+
ids: z_1.z.array(z_1.z.string()),
|
|
9
|
+
status: z_1.z.enum(["pending", "approved", "rejected"]),
|
|
10
10
|
});
|
|
11
11
|
async function POST(req, res) {
|
|
12
12
|
const { ids, status } = req.validatedBody;
|
|
@@ -18,4 +18,4 @@ async function POST(req, res) {
|
|
|
18
18
|
});
|
|
19
19
|
res.json(result);
|
|
20
20
|
}
|
|
21
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Jldmlld3Mvc3RhdHVzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVVBLG9CQWNDO0FBdEJELDJDQUF3QztBQUN4Qyw0RkFBeUY7QUFFNUUsUUFBQSxrQ0FBa0MsR0FBRyxLQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3pELEdBQUcsRUFBRSxLQUFDLENBQUMsS0FBSyxDQUFDLEtBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN4QixNQUFNLEVBQUUsS0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7Q0FDcEQsQ0FBQyxDQUFDO0FBRUksS0FBSyxVQUFVLElBQUksQ0FDeEIsR0FBd0UsRUFDeEUsR0FBbUI7SUFFbkIsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFDO0lBRTFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLElBQUEsMkNBQW9CLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUMzRCxLQUFLLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN0QixFQUFFO1lBQ0YsTUFBTTtTQUNQLENBQUMsQ0FBQztLQUNKLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbkIsQ0FBQyJ9
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.POST = exports.PostStoreReviewSchema = void 0;
|
|
4
|
-
const
|
|
4
|
+
const z_1 = require("../../../utils/z");
|
|
5
5
|
const createReviewWorkflow_1 = require("../../../workflows/review/createReviewWorkflow");
|
|
6
6
|
const core_flows_1 = require("@medusajs/medusa/core-flows");
|
|
7
|
-
exports.PostStoreReviewSchema =
|
|
8
|
-
parent_id:
|
|
9
|
-
title:
|
|
10
|
-
content:
|
|
11
|
-
rating:
|
|
7
|
+
exports.PostStoreReviewSchema = z_1.z.object({
|
|
8
|
+
parent_id: z_1.z.string().optional(),
|
|
9
|
+
title: z_1.z.string().optional(),
|
|
10
|
+
content: z_1.z.string(),
|
|
11
|
+
rating: z_1.z.preprocess((val) => {
|
|
12
12
|
if (val && typeof val === "string") {
|
|
13
13
|
return parseInt(val);
|
|
14
14
|
}
|
|
15
15
|
return val;
|
|
16
|
-
},
|
|
17
|
-
product_id:
|
|
16
|
+
}, z_1.z.number().min(1).max(5).optional()),
|
|
17
|
+
product_id: z_1.z.string(),
|
|
18
18
|
});
|
|
19
19
|
const POST = async (req, res) => {
|
|
20
20
|
const input = req.body;
|
|
@@ -54,4 +54,4 @@ const POST = async (req, res) => {
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
exports.POST = POST;
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3Jldmlld3Mvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBTUEsd0NBQXFDO0FBQ3JDLHlGQUFzRjtBQUV0Riw0REFHcUM7QUFFeEIsUUFBQSxxQkFBcUIsR0FBRyxLQUFDLENBQUMsTUFBTSxDQUFDO0lBQzVDLFNBQVMsRUFBRSxLQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ2hDLEtBQUssRUFBRSxLQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQzVCLE9BQU8sRUFBRSxLQUFDLENBQUMsTUFBTSxFQUFFO0lBQ25CLE1BQU0sRUFBRSxLQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDM0IsSUFBSSxHQUFHLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDbkMsT0FBTyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQyxFQUFFLEtBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3ZDLFVBQVUsRUFBRSxLQUFDLENBQUMsTUFBTSxFQUFFO0NBQ3ZCLENBQUMsQ0FBQztBQVFJLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFDdkIsR0FBa0IsRUFDbEIsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7SUFDdkIsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQztJQUU3QixNQUFNLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxHQUFHLE1BQU0sSUFBQSxnQ0FBbUIsRUFBQyxHQUFHLENBQUMsS0FBWSxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ2hGLEtBQUssRUFBRTtZQUNMLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUM3QixRQUFRLEVBQUUsQ0FBQyxDQUFDLFlBQVk7Z0JBQ3hCLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUTtnQkFDcEIsT0FBTyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztnQkFDcEMsTUFBTSxFQUFFLFFBQVE7YUFDakIsQ0FBQyxDQUFDLElBQUksRUFBRTtTQUNWO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakQsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFO1FBQ2YsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHO1FBQ2pCLFFBQVEsRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsSUFBSSxFQUFFO0tBQ2hELENBQUMsQ0FBQyxDQUFDO0lBRUosSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLElBQUEsMkNBQW9CLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUNuRSxLQUFLLEVBQUU7Z0JBQ0wsR0FBRyxLQUFLO2dCQUNSLFdBQVcsRUFBRSxHQUFHLENBQUMsWUFBWSxFQUFFLFFBQVE7Z0JBQ3ZDLE1BQU07YUFDUDtTQUNGLENBQUMsQ0FBQztRQUVILEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFBLGdDQUFtQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7WUFDakMsS0FBSyxFQUFFO2dCQUNMLEdBQUcsRUFBRSxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2FBQzFDO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBMUNXLFFBQUEsSUFBSSxRQTBDZiJ9
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.z = void 0;
|
|
4
|
+
const module_1 = require("module");
|
|
5
|
+
/**
|
|
6
|
+
* Ensure we always use the same Zod version that Medusa ships with (v3).
|
|
7
|
+
* Resolving Zod through the framework's require avoids mixing major versions.
|
|
8
|
+
*/
|
|
9
|
+
const frameworkRequire = (0, module_1.createRequire)(require.resolve("@medusajs/framework"));
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const { z } = frameworkRequire("zod");
|
|
12
|
+
exports.z = z;
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiei5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy91dGlscy96LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUF1QztBQUd2Qzs7O0dBR0c7QUFDSCxNQUFNLGdCQUFnQixHQUFHLElBQUEsc0JBQWEsRUFBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztBQUUvRSw4REFBOEQ7QUFDOUQsTUFBTSxFQUFFLENBQUMsRUFBRSxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBZSxDQUFDO0FBRTNDLGNBQUMifQ==
|
|
@@ -4,9 +4,53 @@ exports.getReviewsWorkflow = exports.GetReviewsSchema = void 0;
|
|
|
4
4
|
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
5
5
|
const framework_1 = require("@medusajs/framework");
|
|
6
6
|
const workflows_sdk_2 = require("@medusajs/framework/workflows-sdk");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const z_1 = require("../../utils/z");
|
|
8
|
+
const numberParam = (schema) => z_1.z.preprocess((val) => {
|
|
9
|
+
if (val === undefined || val === null || val === "") {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
if (typeof val === "string") {
|
|
13
|
+
const parsed = Number(val);
|
|
14
|
+
return Number.isNaN(parsed) ? undefined : parsed;
|
|
15
|
+
}
|
|
16
|
+
return val;
|
|
17
|
+
}, schema.optional());
|
|
18
|
+
const booleanParam = () => z_1.z.preprocess((val) => {
|
|
19
|
+
if (val === undefined || val === null || val === "") {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (typeof val === "string") {
|
|
23
|
+
if (val.toLowerCase() === "true") {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (val.toLowerCase() === "false") {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return val;
|
|
31
|
+
}, z_1.z.boolean().optional());
|
|
32
|
+
exports.GetReviewsSchema = z_1.z.object({
|
|
33
|
+
limit: numberParam(z_1.z.number().int().positive()),
|
|
34
|
+
offset: numberParam(z_1.z.number().int().min(0)),
|
|
35
|
+
order: z_1.z.string().optional(),
|
|
36
|
+
fields: z_1.z.string().optional(),
|
|
37
|
+
with_deleted: booleanParam(),
|
|
38
|
+
product_id: z_1.z.string().optional(),
|
|
39
|
+
status: z_1.z.enum(["pending", "approved", "rejected"]).optional(),
|
|
40
|
+
parent: z_1.z
|
|
41
|
+
.preprocess((val) => {
|
|
42
|
+
if (val === undefined) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
if (val === null) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (typeof val === "string") {
|
|
49
|
+
return val.toLowerCase() === "null" ? null : val;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}, z_1.z.union([z_1.z.string(), z_1.z.null()]).optional())
|
|
53
|
+
.optional(),
|
|
10
54
|
});
|
|
11
55
|
const getReviewsStep = (0, workflows_sdk_2.createStep)("get-reviews-step", async (input) => {
|
|
12
56
|
const query = framework_1.container.resolve("query");
|
|
@@ -44,4 +88,4 @@ exports.getReviewsWorkflow = (0, workflows_sdk_1.createWorkflow)("get-reviews",
|
|
|
44
88
|
const reviews = getReviewsStep(input);
|
|
45
89
|
return new workflows_sdk_1.WorkflowResponse(reviews);
|
|
46
90
|
});
|
|
47
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0UmV2aWV3c1dvcmtmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9yZXZpZXcvZ2V0UmV2aWV3c1dvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFFQUcyQztBQUUzQyxtREFBK0Q7QUFDL0QscUVBQTZFO0FBRTdFLHFDQUFrQztBQUVsQyxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQXFCLEVBQUUsRUFBRSxDQUM1QyxLQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7SUFDbkIsSUFBSSxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ3BELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzVCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMzQixPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ25ELENBQUM7SUFFRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUV4QixNQUFNLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FDeEIsS0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO0lBQ25CLElBQUksR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNwRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM1QixJQUFJLEdBQUcsQ0FBQyxX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
|