order-management 0.0.72 → 0.0.74
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 +487 -487
- package/.medusa/server/src/admin/index.mjs +488 -488
- package/.medusa/server/src/api/store/guest-orders/[id]/returns/route.js +11 -7
- package/.medusa/server/src/api/store/returns/[id]/route.js +13 -4
- package/.medusa/server/src/api/store/returns/route.js +14 -6
- package/.medusa/server/src/api/store/returns/validators.js +6 -4
- package/.medusa/server/src/helpers/returns.js +52 -5
- package/package.json +1 -1
|
@@ -1066,6 +1066,238 @@ const useDebounce$2 = (value, delay) => {
|
|
|
1066
1066
|
return debouncedValue;
|
|
1067
1067
|
};
|
|
1068
1068
|
const getStatusBadgeClass$6 = (status) => {
|
|
1069
|
+
const statusLower = status.toLowerCase();
|
|
1070
|
+
if (statusLower === "requested") {
|
|
1071
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1072
|
+
}
|
|
1073
|
+
if (statusLower === "received") {
|
|
1074
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1075
|
+
}
|
|
1076
|
+
if (statusLower === "requires_action") {
|
|
1077
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1078
|
+
}
|
|
1079
|
+
if (statusLower === "completed") {
|
|
1080
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1081
|
+
}
|
|
1082
|
+
if (statusLower === "canceled") {
|
|
1083
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1084
|
+
}
|
|
1085
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1086
|
+
};
|
|
1087
|
+
const ReturnsPage = () => {
|
|
1088
|
+
const navigate = reactRouterDom.useNavigate();
|
|
1089
|
+
const [items, setItems] = react.useState([]);
|
|
1090
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
1091
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
1092
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
1093
|
+
const debouncedSearchQuery = useDebounce$2(searchQuery, 300);
|
|
1094
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
1095
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1096
|
+
const [error, setError] = react.useState(null);
|
|
1097
|
+
const [offset, setOffset] = react.useState(0);
|
|
1098
|
+
const [count, setCount] = react.useState(0);
|
|
1099
|
+
const limit = 50;
|
|
1100
|
+
const loadReturns = react.useCallback(
|
|
1101
|
+
async (nextOffset, replace = false) => {
|
|
1102
|
+
var _a;
|
|
1103
|
+
try {
|
|
1104
|
+
if (replace) {
|
|
1105
|
+
setIsLoading(true);
|
|
1106
|
+
} else {
|
|
1107
|
+
setIsFetchingMore(true);
|
|
1108
|
+
}
|
|
1109
|
+
setError(null);
|
|
1110
|
+
const params = new URLSearchParams();
|
|
1111
|
+
params.set("limit", String(limit));
|
|
1112
|
+
params.set("offset", String(nextOffset));
|
|
1113
|
+
if (statusFilter !== "all") {
|
|
1114
|
+
params.set("status", statusFilter);
|
|
1115
|
+
}
|
|
1116
|
+
if (debouncedSearchQuery.trim()) {
|
|
1117
|
+
params.set("q", debouncedSearchQuery.trim());
|
|
1118
|
+
}
|
|
1119
|
+
if (createdByFilter !== "all") {
|
|
1120
|
+
params.set("created_by", createdByFilter);
|
|
1121
|
+
}
|
|
1122
|
+
params.set("order", "created_at");
|
|
1123
|
+
const response = await fetch(
|
|
1124
|
+
`/admin/return?${params.toString()}`,
|
|
1125
|
+
{ credentials: "include" }
|
|
1126
|
+
);
|
|
1127
|
+
if (!response.ok) {
|
|
1128
|
+
const message = await response.text();
|
|
1129
|
+
throw new Error(message || "Unable to load return orders");
|
|
1130
|
+
}
|
|
1131
|
+
const payload = await response.json();
|
|
1132
|
+
setCount(payload.count ?? 0);
|
|
1133
|
+
setOffset(nextOffset + (((_a = payload.returns) == null ? void 0 : _a.length) ?? 0));
|
|
1134
|
+
setItems(
|
|
1135
|
+
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
1136
|
+
);
|
|
1137
|
+
} catch (loadError) {
|
|
1138
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
1139
|
+
setError(message);
|
|
1140
|
+
} finally {
|
|
1141
|
+
setIsLoading(false);
|
|
1142
|
+
setIsFetchingMore(false);
|
|
1143
|
+
}
|
|
1144
|
+
},
|
|
1145
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
1146
|
+
);
|
|
1147
|
+
react.useEffect(() => {
|
|
1148
|
+
void loadReturns(0, true);
|
|
1149
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
1150
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
1151
|
+
const availableStatuses = react.useMemo(() => {
|
|
1152
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
1153
|
+
items.forEach((item) => statuses.add(item.status));
|
|
1154
|
+
return Array.from(statuses).sort();
|
|
1155
|
+
}, [items]);
|
|
1156
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1157
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1158
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1159
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Orders" }),
|
|
1160
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
1161
|
+
] }),
|
|
1162
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
1163
|
+
] }),
|
|
1164
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1166
|
+
ui.Input,
|
|
1167
|
+
{
|
|
1168
|
+
placeholder: "Search by return ID, order ID, or customer email",
|
|
1169
|
+
value: searchQuery,
|
|
1170
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
1171
|
+
className: "md:max-w-sm"
|
|
1172
|
+
}
|
|
1173
|
+
),
|
|
1174
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
1175
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1176
|
+
"select",
|
|
1177
|
+
{
|
|
1178
|
+
value: createdByFilter,
|
|
1179
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
1180
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1181
|
+
children: [
|
|
1182
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
1183
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
1184
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
1185
|
+
]
|
|
1186
|
+
}
|
|
1187
|
+
),
|
|
1188
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1189
|
+
"select",
|
|
1190
|
+
{
|
|
1191
|
+
value: statusFilter,
|
|
1192
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
1193
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1194
|
+
children: [
|
|
1195
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
1196
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
1197
|
+
]
|
|
1198
|
+
}
|
|
1199
|
+
)
|
|
1200
|
+
] })
|
|
1201
|
+
] }),
|
|
1202
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1203
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1205
|
+
ui.Button,
|
|
1206
|
+
{
|
|
1207
|
+
variant: "secondary",
|
|
1208
|
+
onClick: () => loadReturns(0, true),
|
|
1209
|
+
children: "Try again"
|
|
1210
|
+
}
|
|
1211
|
+
) })
|
|
1212
|
+
] }) : null,
|
|
1213
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1214
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
1215
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
1216
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1217
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1218
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
1219
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1220
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
1221
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1222
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
1223
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1224
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1225
|
+
] }) }),
|
|
1226
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1227
|
+
"tr",
|
|
1228
|
+
{
|
|
1229
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1230
|
+
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
1231
|
+
children: [
|
|
1232
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: returnOrder.id }) }) }),
|
|
1233
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
1234
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
1235
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1236
|
+
ui.Badge,
|
|
1237
|
+
{
|
|
1238
|
+
size: "2xsmall",
|
|
1239
|
+
className: `uppercase ${getStatusBadgeClass$6(returnOrder.status)}`,
|
|
1240
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
1241
|
+
}
|
|
1242
|
+
) }),
|
|
1243
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
1244
|
+
const amount = returnOrder.refund_amount;
|
|
1245
|
+
if (amount == null || amount === void 0) {
|
|
1246
|
+
return "—";
|
|
1247
|
+
}
|
|
1248
|
+
const displayAmount = Number(amount) / 100;
|
|
1249
|
+
const currency = returnOrder.currency_code || "$";
|
|
1250
|
+
return `${currency}${displayAmount.toFixed(2)}`;
|
|
1251
|
+
})() }),
|
|
1252
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
1253
|
+
year: "numeric",
|
|
1254
|
+
month: "short",
|
|
1255
|
+
day: "numeric",
|
|
1256
|
+
hour: "numeric",
|
|
1257
|
+
minute: "2-digit",
|
|
1258
|
+
hour12: true
|
|
1259
|
+
}) }),
|
|
1260
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1261
|
+
ui.Button,
|
|
1262
|
+
{
|
|
1263
|
+
variant: "transparent",
|
|
1264
|
+
size: "small",
|
|
1265
|
+
onClick: (e) => {
|
|
1266
|
+
e.stopPropagation();
|
|
1267
|
+
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
1268
|
+
},
|
|
1269
|
+
children: "Go to order"
|
|
1270
|
+
}
|
|
1271
|
+
) })
|
|
1272
|
+
]
|
|
1273
|
+
},
|
|
1274
|
+
returnOrder.id
|
|
1275
|
+
)) })
|
|
1276
|
+
] }) }),
|
|
1277
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1278
|
+
ui.Button,
|
|
1279
|
+
{
|
|
1280
|
+
variant: "secondary",
|
|
1281
|
+
isLoading: isFetchingMore,
|
|
1282
|
+
onClick: () => loadReturns(offset, false),
|
|
1283
|
+
children: "Load more"
|
|
1284
|
+
}
|
|
1285
|
+
) }) : null
|
|
1286
|
+
] }) });
|
|
1287
|
+
};
|
|
1288
|
+
const config$6 = adminSdk.defineRouteConfig({
|
|
1289
|
+
label: "Return Orders",
|
|
1290
|
+
icon: icons.ArrowPath
|
|
1291
|
+
});
|
|
1292
|
+
const useDebounce$1 = (value, delay) => {
|
|
1293
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1294
|
+
react.useEffect(() => {
|
|
1295
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1296
|
+
return () => clearTimeout(handler);
|
|
1297
|
+
}, [value, delay]);
|
|
1298
|
+
return debouncedValue;
|
|
1299
|
+
};
|
|
1300
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
1069
1301
|
const s2 = status.toLowerCase();
|
|
1070
1302
|
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1071
1303
|
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
@@ -1077,12 +1309,12 @@ const RefundsPage = () => {
|
|
|
1077
1309
|
const navigate = reactRouterDom.useNavigate();
|
|
1078
1310
|
const [items, setItems] = react.useState([]);
|
|
1079
1311
|
const [orderIdSearch, setOrderIdSearch] = react.useState("");
|
|
1080
|
-
const debouncedOrderId = useDebounce$
|
|
1312
|
+
const debouncedOrderId = useDebounce$1(orderIdSearch, 300);
|
|
1081
1313
|
const [paymentStatusFilter, setPaymentStatusFilter] = react.useState("all");
|
|
1082
1314
|
const [providerSearch, setProviderSearch] = react.useState("");
|
|
1083
|
-
const debouncedProvider = useDebounce$
|
|
1315
|
+
const debouncedProvider = useDebounce$1(providerSearch, 300);
|
|
1084
1316
|
const [currencySearch, setCurrencySearch] = react.useState("");
|
|
1085
|
-
const debouncedCurrency = useDebounce$
|
|
1317
|
+
const debouncedCurrency = useDebounce$1(currencySearch, 300);
|
|
1086
1318
|
const [dateFrom, setDateFrom] = react.useState("");
|
|
1087
1319
|
const [dateTo, setDateTo] = react.useState("");
|
|
1088
1320
|
const [amountMin, setAmountMin] = react.useState("");
|
|
@@ -1294,7 +1526,7 @@ const RefundsPage = () => {
|
|
|
1294
1526
|
ui.Badge,
|
|
1295
1527
|
{
|
|
1296
1528
|
size: "2xsmall",
|
|
1297
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
1529
|
+
className: `uppercase ${getStatusBadgeClass$5(displayStatus(r))}`,
|
|
1298
1530
|
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
1299
1531
|
}
|
|
1300
1532
|
) }),
|
|
@@ -1348,11 +1580,11 @@ const RefundsPage = () => {
|
|
|
1348
1580
|
) }) : null
|
|
1349
1581
|
] }) });
|
|
1350
1582
|
};
|
|
1351
|
-
const config$
|
|
1583
|
+
const config$5 = adminSdk.defineRouteConfig({
|
|
1352
1584
|
label: "Refunds",
|
|
1353
1585
|
icon: icons.Receipt
|
|
1354
1586
|
});
|
|
1355
|
-
const useDebounce
|
|
1587
|
+
const useDebounce = (value, delay) => {
|
|
1356
1588
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1357
1589
|
react.useEffect(() => {
|
|
1358
1590
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -1360,39 +1592,39 @@ const useDebounce$1 = (value, delay) => {
|
|
|
1360
1592
|
}, [value, delay]);
|
|
1361
1593
|
return debouncedValue;
|
|
1362
1594
|
};
|
|
1363
|
-
const getStatusBadgeClass$
|
|
1595
|
+
const getStatusBadgeClass$4 = (status) => {
|
|
1364
1596
|
const statusLower = status.toLowerCase();
|
|
1365
1597
|
if (statusLower === "requested") {
|
|
1366
1598
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1367
1599
|
}
|
|
1368
|
-
if (statusLower === "
|
|
1600
|
+
if (statusLower === "approved") {
|
|
1369
1601
|
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1370
1602
|
}
|
|
1371
|
-
if (statusLower === "
|
|
1603
|
+
if (statusLower === "rejected") {
|
|
1372
1604
|
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1373
1605
|
}
|
|
1374
1606
|
if (statusLower === "completed") {
|
|
1375
1607
|
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1376
1608
|
}
|
|
1377
|
-
if (statusLower === "
|
|
1609
|
+
if (statusLower === "cancelled") {
|
|
1378
1610
|
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1379
1611
|
}
|
|
1380
1612
|
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1381
1613
|
};
|
|
1382
|
-
const
|
|
1614
|
+
const SwapsPage = () => {
|
|
1383
1615
|
const navigate = reactRouterDom.useNavigate();
|
|
1384
1616
|
const [items, setItems] = react.useState([]);
|
|
1385
1617
|
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
1386
1618
|
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
1387
1619
|
const [searchQuery, setSearchQuery] = react.useState("");
|
|
1388
|
-
const debouncedSearchQuery = useDebounce
|
|
1620
|
+
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
1389
1621
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
1390
1622
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1391
1623
|
const [error, setError] = react.useState(null);
|
|
1392
1624
|
const [offset, setOffset] = react.useState(0);
|
|
1393
1625
|
const [count, setCount] = react.useState(0);
|
|
1394
1626
|
const limit = 50;
|
|
1395
|
-
const
|
|
1627
|
+
const loadSwaps = react.useCallback(
|
|
1396
1628
|
async (nextOffset, replace = false) => {
|
|
1397
1629
|
var _a;
|
|
1398
1630
|
try {
|
|
@@ -1409,254 +1641,22 @@ const ReturnsPage = () => {
|
|
|
1409
1641
|
params.set("status", statusFilter);
|
|
1410
1642
|
}
|
|
1411
1643
|
if (debouncedSearchQuery.trim()) {
|
|
1412
|
-
params.set("
|
|
1644
|
+
params.set("order_id", debouncedSearchQuery.trim());
|
|
1413
1645
|
}
|
|
1414
1646
|
if (createdByFilter !== "all") {
|
|
1415
1647
|
params.set("created_by", createdByFilter);
|
|
1416
1648
|
}
|
|
1417
|
-
params.set("order", "created_at");
|
|
1418
1649
|
const response = await fetch(
|
|
1419
|
-
`/admin/
|
|
1650
|
+
`/admin/swaps?${params.toString()}`,
|
|
1420
1651
|
{ credentials: "include" }
|
|
1421
1652
|
);
|
|
1422
1653
|
if (!response.ok) {
|
|
1423
1654
|
const message = await response.text();
|
|
1424
|
-
throw new Error(message || "Unable to load
|
|
1655
|
+
throw new Error(message || "Unable to load swaps");
|
|
1425
1656
|
}
|
|
1426
1657
|
const payload = await response.json();
|
|
1427
1658
|
setCount(payload.count ?? 0);
|
|
1428
|
-
setOffset(nextOffset + (((_a = payload.
|
|
1429
|
-
setItems(
|
|
1430
|
-
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
1431
|
-
);
|
|
1432
|
-
} catch (loadError) {
|
|
1433
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
1434
|
-
setError(message);
|
|
1435
|
-
} finally {
|
|
1436
|
-
setIsLoading(false);
|
|
1437
|
-
setIsFetchingMore(false);
|
|
1438
|
-
}
|
|
1439
|
-
},
|
|
1440
|
-
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
1441
|
-
);
|
|
1442
|
-
react.useEffect(() => {
|
|
1443
|
-
void loadReturns(0, true);
|
|
1444
|
-
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
1445
|
-
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
1446
|
-
const availableStatuses = react.useMemo(() => {
|
|
1447
|
-
const statuses = /* @__PURE__ */ new Set();
|
|
1448
|
-
items.forEach((item) => statuses.add(item.status));
|
|
1449
|
-
return Array.from(statuses).sort();
|
|
1450
|
-
}, [items]);
|
|
1451
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1452
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1453
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1454
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Orders" }),
|
|
1455
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
1456
|
-
] }),
|
|
1457
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
1458
|
-
] }),
|
|
1459
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1460
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1461
|
-
ui.Input,
|
|
1462
|
-
{
|
|
1463
|
-
placeholder: "Search by return ID, order ID, or customer email",
|
|
1464
|
-
value: searchQuery,
|
|
1465
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
1466
|
-
className: "md:max-w-sm"
|
|
1467
|
-
}
|
|
1468
|
-
),
|
|
1469
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
1470
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1471
|
-
"select",
|
|
1472
|
-
{
|
|
1473
|
-
value: createdByFilter,
|
|
1474
|
-
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
1475
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1476
|
-
children: [
|
|
1477
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
1478
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
1479
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
1480
|
-
]
|
|
1481
|
-
}
|
|
1482
|
-
),
|
|
1483
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1484
|
-
"select",
|
|
1485
|
-
{
|
|
1486
|
-
value: statusFilter,
|
|
1487
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
1488
|
-
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1489
|
-
children: [
|
|
1490
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
1491
|
-
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
1492
|
-
]
|
|
1493
|
-
}
|
|
1494
|
-
)
|
|
1495
|
-
] })
|
|
1496
|
-
] }),
|
|
1497
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1498
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1499
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1500
|
-
ui.Button,
|
|
1501
|
-
{
|
|
1502
|
-
variant: "secondary",
|
|
1503
|
-
onClick: () => loadReturns(0, true),
|
|
1504
|
-
children: "Try again"
|
|
1505
|
-
}
|
|
1506
|
-
) })
|
|
1507
|
-
] }) : null,
|
|
1508
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1509
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
1510
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
1511
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1512
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1513
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
1514
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1515
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
1516
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1517
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
1518
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1519
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1520
|
-
] }) }),
|
|
1521
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1522
|
-
"tr",
|
|
1523
|
-
{
|
|
1524
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1525
|
-
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
1526
|
-
children: [
|
|
1527
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: returnOrder.id }) }) }),
|
|
1528
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
1529
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
1530
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1531
|
-
ui.Badge,
|
|
1532
|
-
{
|
|
1533
|
-
size: "2xsmall",
|
|
1534
|
-
className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
|
|
1535
|
-
children: returnOrder.status.replace(/_/g, " ")
|
|
1536
|
-
}
|
|
1537
|
-
) }),
|
|
1538
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
1539
|
-
const amount = returnOrder.refund_amount;
|
|
1540
|
-
if (amount == null || amount === void 0) {
|
|
1541
|
-
return "—";
|
|
1542
|
-
}
|
|
1543
|
-
const displayAmount = Number(amount) / 100;
|
|
1544
|
-
const currency = returnOrder.currency_code || "$";
|
|
1545
|
-
return `${currency}${displayAmount.toFixed(2)}`;
|
|
1546
|
-
})() }),
|
|
1547
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
1548
|
-
year: "numeric",
|
|
1549
|
-
month: "short",
|
|
1550
|
-
day: "numeric",
|
|
1551
|
-
hour: "numeric",
|
|
1552
|
-
minute: "2-digit",
|
|
1553
|
-
hour12: true
|
|
1554
|
-
}) }),
|
|
1555
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1556
|
-
ui.Button,
|
|
1557
|
-
{
|
|
1558
|
-
variant: "transparent",
|
|
1559
|
-
size: "small",
|
|
1560
|
-
onClick: (e) => {
|
|
1561
|
-
e.stopPropagation();
|
|
1562
|
-
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
1563
|
-
},
|
|
1564
|
-
children: "Go to order"
|
|
1565
|
-
}
|
|
1566
|
-
) })
|
|
1567
|
-
]
|
|
1568
|
-
},
|
|
1569
|
-
returnOrder.id
|
|
1570
|
-
)) })
|
|
1571
|
-
] }) }),
|
|
1572
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1573
|
-
ui.Button,
|
|
1574
|
-
{
|
|
1575
|
-
variant: "secondary",
|
|
1576
|
-
isLoading: isFetchingMore,
|
|
1577
|
-
onClick: () => loadReturns(offset, false),
|
|
1578
|
-
children: "Load more"
|
|
1579
|
-
}
|
|
1580
|
-
) }) : null
|
|
1581
|
-
] }) });
|
|
1582
|
-
};
|
|
1583
|
-
const config$5 = adminSdk.defineRouteConfig({
|
|
1584
|
-
label: "Return Orders",
|
|
1585
|
-
icon: icons.ArrowPath
|
|
1586
|
-
});
|
|
1587
|
-
const useDebounce = (value, delay) => {
|
|
1588
|
-
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1589
|
-
react.useEffect(() => {
|
|
1590
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1591
|
-
return () => clearTimeout(handler);
|
|
1592
|
-
}, [value, delay]);
|
|
1593
|
-
return debouncedValue;
|
|
1594
|
-
};
|
|
1595
|
-
const getStatusBadgeClass$4 = (status) => {
|
|
1596
|
-
const statusLower = status.toLowerCase();
|
|
1597
|
-
if (statusLower === "requested") {
|
|
1598
|
-
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1599
|
-
}
|
|
1600
|
-
if (statusLower === "approved") {
|
|
1601
|
-
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1602
|
-
}
|
|
1603
|
-
if (statusLower === "rejected") {
|
|
1604
|
-
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1605
|
-
}
|
|
1606
|
-
if (statusLower === "completed") {
|
|
1607
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1608
|
-
}
|
|
1609
|
-
if (statusLower === "cancelled") {
|
|
1610
|
-
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1611
|
-
}
|
|
1612
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1613
|
-
};
|
|
1614
|
-
const SwapsPage = () => {
|
|
1615
|
-
const navigate = reactRouterDom.useNavigate();
|
|
1616
|
-
const [items, setItems] = react.useState([]);
|
|
1617
|
-
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
1618
|
-
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
1619
|
-
const [searchQuery, setSearchQuery] = react.useState("");
|
|
1620
|
-
const debouncedSearchQuery = useDebounce(searchQuery, 300);
|
|
1621
|
-
const [isLoading, setIsLoading] = react.useState(true);
|
|
1622
|
-
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1623
|
-
const [error, setError] = react.useState(null);
|
|
1624
|
-
const [offset, setOffset] = react.useState(0);
|
|
1625
|
-
const [count, setCount] = react.useState(0);
|
|
1626
|
-
const limit = 50;
|
|
1627
|
-
const loadSwaps = react.useCallback(
|
|
1628
|
-
async (nextOffset, replace = false) => {
|
|
1629
|
-
var _a;
|
|
1630
|
-
try {
|
|
1631
|
-
if (replace) {
|
|
1632
|
-
setIsLoading(true);
|
|
1633
|
-
} else {
|
|
1634
|
-
setIsFetchingMore(true);
|
|
1635
|
-
}
|
|
1636
|
-
setError(null);
|
|
1637
|
-
const params = new URLSearchParams();
|
|
1638
|
-
params.set("limit", String(limit));
|
|
1639
|
-
params.set("offset", String(nextOffset));
|
|
1640
|
-
if (statusFilter !== "all") {
|
|
1641
|
-
params.set("status", statusFilter);
|
|
1642
|
-
}
|
|
1643
|
-
if (debouncedSearchQuery.trim()) {
|
|
1644
|
-
params.set("order_id", debouncedSearchQuery.trim());
|
|
1645
|
-
}
|
|
1646
|
-
if (createdByFilter !== "all") {
|
|
1647
|
-
params.set("created_by", createdByFilter);
|
|
1648
|
-
}
|
|
1649
|
-
const response = await fetch(
|
|
1650
|
-
`/admin/swaps?${params.toString()}`,
|
|
1651
|
-
{ credentials: "include" }
|
|
1652
|
-
);
|
|
1653
|
-
if (!response.ok) {
|
|
1654
|
-
const message = await response.text();
|
|
1655
|
-
throw new Error(message || "Unable to load swaps");
|
|
1656
|
-
}
|
|
1657
|
-
const payload = await response.json();
|
|
1658
|
-
setCount(payload.count ?? 0);
|
|
1659
|
-
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
1659
|
+
setOffset(nextOffset + (((_a = payload.swaps) == null ? void 0 : _a.length) ?? 0));
|
|
1660
1660
|
setItems(
|
|
1661
1661
|
(prev) => replace ? payload.swaps ?? [] : [...prev, ...payload.swaps ?? []]
|
|
1662
1662
|
);
|
|
@@ -1903,229 +1903,37 @@ const PaymentDetailPage = () => {
|
|
|
1903
1903
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
1904
1904
|
] }),
|
|
1905
1905
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1906
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
1907
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
1908
|
-
] }),
|
|
1909
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1910
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
1911
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
1912
|
-
] }),
|
|
1913
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1914
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
1915
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
1916
|
-
year: "numeric",
|
|
1917
|
-
month: "short",
|
|
1918
|
-
day: "numeric",
|
|
1919
|
-
hour: "numeric",
|
|
1920
|
-
minute: "2-digit",
|
|
1921
|
-
hour12: true
|
|
1922
|
-
}) })
|
|
1923
|
-
] })
|
|
1924
|
-
] }) }),
|
|
1925
|
-
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
1926
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
1927
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
|
|
1928
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
|
|
1929
|
-
] }) : null
|
|
1930
|
-
] }) });
|
|
1931
|
-
};
|
|
1932
|
-
const config$3 = adminSdk.defineRouteConfig({
|
|
1933
|
-
label: "Payment details",
|
|
1934
|
-
icon: icons.CreditCard
|
|
1935
|
-
});
|
|
1936
|
-
const getStatusBadgeClass$2 = (status) => {
|
|
1937
|
-
const s2 = status.toLowerCase();
|
|
1938
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1939
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1940
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1941
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1942
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1943
|
-
};
|
|
1944
|
-
const formatAmount = (value) => {
|
|
1945
|
-
return String(value);
|
|
1946
|
-
};
|
|
1947
|
-
const RefundDetailPage = () => {
|
|
1948
|
-
var _a, _b, _c;
|
|
1949
|
-
const navigate = reactRouterDom.useNavigate();
|
|
1950
|
-
const params = reactRouterDom.useParams();
|
|
1951
|
-
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
1952
|
-
const [detail, setDetail] = react.useState(null);
|
|
1953
|
-
const [loading, setLoading] = react.useState(!!id);
|
|
1954
|
-
const [error, setError] = react.useState(null);
|
|
1955
|
-
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
1956
|
-
react.useEffect(() => {
|
|
1957
|
-
if (!id) {
|
|
1958
|
-
setLoading(false);
|
|
1959
|
-
return;
|
|
1960
|
-
}
|
|
1961
|
-
let cancelled = false;
|
|
1962
|
-
setLoading(true);
|
|
1963
|
-
setError(null);
|
|
1964
|
-
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
1965
|
-
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
1966
|
-
return res.json();
|
|
1967
|
-
}).then((data) => {
|
|
1968
|
-
if (!cancelled) setDetail(data);
|
|
1969
|
-
}).catch((e) => {
|
|
1970
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
1971
|
-
}).finally(() => {
|
|
1972
|
-
if (!cancelled) setLoading(false);
|
|
1973
|
-
});
|
|
1974
|
-
return () => {
|
|
1975
|
-
cancelled = true;
|
|
1976
|
-
};
|
|
1977
|
-
}, [id]);
|
|
1978
|
-
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
1979
|
-
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
1980
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
1981
|
-
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1982
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
1983
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
1984
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
1985
|
-
] }) }),
|
|
1986
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1987
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1988
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
1989
|
-
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
1990
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
1991
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
1992
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
1993
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1994
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
1995
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
1996
|
-
] }),
|
|
1997
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1998
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
1999
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
2000
|
-
] }),
|
|
2001
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2002
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
2003
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
2004
|
-
] }),
|
|
2005
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2006
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
2007
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
2008
|
-
year: "numeric",
|
|
2009
|
-
month: "short",
|
|
2010
|
-
day: "numeric",
|
|
2011
|
-
hour: "numeric",
|
|
2012
|
-
minute: "2-digit",
|
|
2013
|
-
hour12: true
|
|
2014
|
-
}) })
|
|
2015
|
-
] }),
|
|
2016
|
-
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2017
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
2018
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
2019
|
-
] }) : null
|
|
2020
|
-
] })
|
|
2021
|
-
] }),
|
|
2022
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2023
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
2024
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2025
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2026
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
2027
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
2028
|
-
] }),
|
|
2029
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2030
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
2031
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
2032
|
-
] }),
|
|
2033
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2034
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
2035
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
2036
|
-
] }),
|
|
2037
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2038
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
2039
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
2040
|
-
] }),
|
|
2041
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2042
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
2043
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2044
|
-
ui.Badge,
|
|
2045
|
-
{
|
|
2046
|
-
size: "2xsmall",
|
|
2047
|
-
className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
|
|
2048
|
-
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
2049
|
-
}
|
|
2050
|
-
) })
|
|
2051
|
-
] }),
|
|
2052
|
-
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2053
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2054
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
2055
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
2056
|
-
] }),
|
|
2057
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2058
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
2059
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
2060
|
-
] }),
|
|
2061
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2062
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
2063
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
2064
|
-
detail.computed.refund_percentage.toFixed(1),
|
|
2065
|
-
"%"
|
|
2066
|
-
] })
|
|
2067
|
-
] })
|
|
2068
|
-
] }) : null
|
|
2069
|
-
] })
|
|
2070
|
-
] }),
|
|
2071
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2072
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
2073
|
-
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2074
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2075
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
2076
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2077
|
-
ui.Button,
|
|
2078
|
-
{
|
|
2079
|
-
variant: "transparent",
|
|
2080
|
-
size: "small",
|
|
2081
|
-
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
2082
|
-
children: detail.order.order_number ?? detail.order.order_id
|
|
2083
|
-
}
|
|
2084
|
-
) })
|
|
2085
|
-
] }),
|
|
2086
|
-
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2087
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
2088
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
2089
|
-
] }) : null,
|
|
2090
|
-
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2091
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
2092
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
2093
|
-
] }) : null,
|
|
2094
|
-
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2095
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
2096
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
2097
|
-
] }) : null,
|
|
2098
|
-
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2099
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
2100
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
2101
|
-
] }) : null
|
|
2102
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
2103
|
-
] }),
|
|
2104
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2105
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2106
|
-
"button",
|
|
2107
|
-
{
|
|
2108
|
-
type: "button",
|
|
2109
|
-
className: "flex w-full items-center justify-between text-left",
|
|
2110
|
-
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
2111
|
-
"aria-expanded": gatewayExpanded,
|
|
2112
|
-
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
2113
|
-
children: [
|
|
2114
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
2115
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
2116
|
-
]
|
|
2117
|
-
}
|
|
2118
|
-
),
|
|
2119
|
-
gatewayExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
|
|
2120
|
-
] })
|
|
1906
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
1907
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
1908
|
+
] }),
|
|
1909
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1910
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
1911
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
1912
|
+
] }),
|
|
1913
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1914
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
1915
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
1916
|
+
year: "numeric",
|
|
1917
|
+
month: "short",
|
|
1918
|
+
day: "numeric",
|
|
1919
|
+
hour: "numeric",
|
|
1920
|
+
minute: "2-digit",
|
|
1921
|
+
hour12: true
|
|
1922
|
+
}) })
|
|
1923
|
+
] })
|
|
1924
|
+
] }) }),
|
|
1925
|
+
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
1926
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
1927
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
|
|
1928
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
|
|
2121
1929
|
] }) : null
|
|
2122
1930
|
] }) });
|
|
2123
1931
|
};
|
|
2124
|
-
const config$
|
|
2125
|
-
label: "
|
|
2126
|
-
icon: icons.
|
|
1932
|
+
const config$3 = adminSdk.defineRouteConfig({
|
|
1933
|
+
label: "Payment details",
|
|
1934
|
+
icon: icons.CreditCard
|
|
2127
1935
|
});
|
|
2128
|
-
const getStatusBadgeClass$
|
|
1936
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
2129
1937
|
const statusLower = status.toLowerCase();
|
|
2130
1938
|
if (statusLower === "requested") {
|
|
2131
1939
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -2259,7 +2067,7 @@ const ReturnDetailPage = () => {
|
|
|
2259
2067
|
ui.Badge,
|
|
2260
2068
|
{
|
|
2261
2069
|
size: "small",
|
|
2262
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2070
|
+
className: `uppercase ${getStatusBadgeClass$2(returnOrder.status)}`,
|
|
2263
2071
|
children: returnOrder.status.replace(/_/g, " ")
|
|
2264
2072
|
}
|
|
2265
2073
|
)
|
|
@@ -2341,7 +2149,7 @@ const ReturnDetailPage = () => {
|
|
|
2341
2149
|
ui.Badge,
|
|
2342
2150
|
{
|
|
2343
2151
|
size: "2xsmall",
|
|
2344
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2152
|
+
className: `uppercase ${getStatusBadgeClass$2(entry.status)}`,
|
|
2345
2153
|
children: entry.status.replace(/_/g, " ")
|
|
2346
2154
|
}
|
|
2347
2155
|
) }),
|
|
@@ -2399,10 +2207,202 @@ const ReturnDetailPage = () => {
|
|
|
2399
2207
|
updateSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
|
|
2400
2208
|
] }) });
|
|
2401
2209
|
};
|
|
2402
|
-
const config$
|
|
2210
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
2403
2211
|
label: "Return Order Details",
|
|
2404
2212
|
icon: icons.CheckCircle
|
|
2405
2213
|
});
|
|
2214
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
2215
|
+
const s2 = status.toLowerCase();
|
|
2216
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
2217
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
2218
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
2219
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
2220
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
2221
|
+
};
|
|
2222
|
+
const formatAmount = (value) => {
|
|
2223
|
+
return String(value);
|
|
2224
|
+
};
|
|
2225
|
+
const RefundDetailPage = () => {
|
|
2226
|
+
var _a, _b, _c;
|
|
2227
|
+
const navigate = reactRouterDom.useNavigate();
|
|
2228
|
+
const params = reactRouterDom.useParams();
|
|
2229
|
+
const id = (_a = params == null ? void 0 : params.id) == null ? void 0 : _a.trim();
|
|
2230
|
+
const [detail, setDetail] = react.useState(null);
|
|
2231
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
2232
|
+
const [error, setError] = react.useState(null);
|
|
2233
|
+
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
2234
|
+
react.useEffect(() => {
|
|
2235
|
+
if (!id) {
|
|
2236
|
+
setLoading(false);
|
|
2237
|
+
return;
|
|
2238
|
+
}
|
|
2239
|
+
let cancelled = false;
|
|
2240
|
+
setLoading(true);
|
|
2241
|
+
setError(null);
|
|
2242
|
+
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
2243
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
2244
|
+
return res.json();
|
|
2245
|
+
}).then((data) => {
|
|
2246
|
+
if (!cancelled) setDetail(data);
|
|
2247
|
+
}).catch((e) => {
|
|
2248
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
2249
|
+
}).finally(() => {
|
|
2250
|
+
if (!cancelled) setLoading(false);
|
|
2251
|
+
});
|
|
2252
|
+
return () => {
|
|
2253
|
+
cancelled = true;
|
|
2254
|
+
};
|
|
2255
|
+
}, [id]);
|
|
2256
|
+
const paymentStatus = ((_b = detail == null ? void 0 : detail.payment) == null ? void 0 : _b.status) ?? "—";
|
|
2257
|
+
const hasGatewayData = ((_c = detail == null ? void 0 : detail.payment) == null ? void 0 : _c.payment_data) && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
2258
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
2259
|
+
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2260
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
2261
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
2262
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
2263
|
+
] }) }),
|
|
2264
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
2265
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
2266
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
2267
|
+
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
2268
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2269
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
2270
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2271
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2272
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
2273
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
2274
|
+
] }),
|
|
2275
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2276
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
2277
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
2278
|
+
] }),
|
|
2279
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2280
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
2281
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
2282
|
+
] }),
|
|
2283
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2284
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
2285
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
2286
|
+
year: "numeric",
|
|
2287
|
+
month: "short",
|
|
2288
|
+
day: "numeric",
|
|
2289
|
+
hour: "numeric",
|
|
2290
|
+
minute: "2-digit",
|
|
2291
|
+
hour12: true
|
|
2292
|
+
}) })
|
|
2293
|
+
] }),
|
|
2294
|
+
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2295
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
2296
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
2297
|
+
] }) : null
|
|
2298
|
+
] })
|
|
2299
|
+
] }),
|
|
2300
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2301
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
2302
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2303
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2304
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
2305
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
2306
|
+
] }),
|
|
2307
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2308
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
2309
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
2310
|
+
] }),
|
|
2311
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2312
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
2313
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
2314
|
+
] }),
|
|
2315
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2316
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
2317
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
2318
|
+
] }),
|
|
2319
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2320
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
2321
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2322
|
+
ui.Badge,
|
|
2323
|
+
{
|
|
2324
|
+
size: "2xsmall",
|
|
2325
|
+
className: `uppercase ${getStatusBadgeClass$1(paymentStatus)}`,
|
|
2326
|
+
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
2327
|
+
}
|
|
2328
|
+
) })
|
|
2329
|
+
] }),
|
|
2330
|
+
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2331
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2332
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
2333
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
2334
|
+
] }),
|
|
2335
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2336
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
2337
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
2338
|
+
] }),
|
|
2339
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2340
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
2341
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
2342
|
+
detail.computed.refund_percentage.toFixed(1),
|
|
2343
|
+
"%"
|
|
2344
|
+
] })
|
|
2345
|
+
] })
|
|
2346
|
+
] }) : null
|
|
2347
|
+
] })
|
|
2348
|
+
] }),
|
|
2349
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2350
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
2351
|
+
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
2352
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2353
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
2354
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2355
|
+
ui.Button,
|
|
2356
|
+
{
|
|
2357
|
+
variant: "transparent",
|
|
2358
|
+
size: "small",
|
|
2359
|
+
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
2360
|
+
children: detail.order.order_number ?? detail.order.order_id
|
|
2361
|
+
}
|
|
2362
|
+
) })
|
|
2363
|
+
] }),
|
|
2364
|
+
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2365
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
2366
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
2367
|
+
] }) : null,
|
|
2368
|
+
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2369
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
2370
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
2371
|
+
] }) : null,
|
|
2372
|
+
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2373
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
2374
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
2375
|
+
] }) : null,
|
|
2376
|
+
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2377
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
2378
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
2379
|
+
] }) : null
|
|
2380
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
2381
|
+
] }),
|
|
2382
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
2383
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2384
|
+
"button",
|
|
2385
|
+
{
|
|
2386
|
+
type: "button",
|
|
2387
|
+
className: "flex w-full items-center justify-between text-left",
|
|
2388
|
+
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
2389
|
+
"aria-expanded": gatewayExpanded,
|
|
2390
|
+
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
2391
|
+
children: [
|
|
2392
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
2393
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
2394
|
+
]
|
|
2395
|
+
}
|
|
2396
|
+
),
|
|
2397
|
+
gatewayExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
|
|
2398
|
+
] })
|
|
2399
|
+
] }) : null
|
|
2400
|
+
] }) });
|
|
2401
|
+
};
|
|
2402
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
2403
|
+
label: "Refund details",
|
|
2404
|
+
icon: icons.Receipt
|
|
2405
|
+
});
|
|
2406
2406
|
const getStatusBadgeClass = (status) => {
|
|
2407
2407
|
const statusLower = status.toLowerCase();
|
|
2408
2408
|
if (statusLower === "requested") {
|
|
@@ -2699,14 +2699,14 @@ const routeModule = {
|
|
|
2699
2699
|
Component: PaymentsPage,
|
|
2700
2700
|
path: "/payments"
|
|
2701
2701
|
},
|
|
2702
|
-
{
|
|
2703
|
-
Component: RefundsPage,
|
|
2704
|
-
path: "/refunds"
|
|
2705
|
-
},
|
|
2706
2702
|
{
|
|
2707
2703
|
Component: ReturnsPage,
|
|
2708
2704
|
path: "/returns"
|
|
2709
2705
|
},
|
|
2706
|
+
{
|
|
2707
|
+
Component: RefundsPage,
|
|
2708
|
+
path: "/refunds"
|
|
2709
|
+
},
|
|
2710
2710
|
{
|
|
2711
2711
|
Component: SwapsPage,
|
|
2712
2712
|
path: "/swaps"
|
|
@@ -2715,14 +2715,14 @@ const routeModule = {
|
|
|
2715
2715
|
Component: PaymentDetailPage,
|
|
2716
2716
|
path: "/payments/:id"
|
|
2717
2717
|
},
|
|
2718
|
-
{
|
|
2719
|
-
Component: RefundDetailPage,
|
|
2720
|
-
path: "/refunds/:id"
|
|
2721
|
-
},
|
|
2722
2718
|
{
|
|
2723
2719
|
Component: ReturnDetailPage,
|
|
2724
2720
|
path: "/returns/:id"
|
|
2725
2721
|
},
|
|
2722
|
+
{
|
|
2723
|
+
Component: RefundDetailPage,
|
|
2724
|
+
path: "/refunds/:id"
|
|
2725
|
+
},
|
|
2726
2726
|
{
|
|
2727
2727
|
Component: SwapDetailPage,
|
|
2728
2728
|
path: "/swaps/:id"
|
|
@@ -2738,14 +2738,14 @@ const menuItemModule = {
|
|
|
2738
2738
|
nested: void 0
|
|
2739
2739
|
},
|
|
2740
2740
|
{
|
|
2741
|
-
label: config$
|
|
2742
|
-
icon: config$
|
|
2741
|
+
label: config$5.label,
|
|
2742
|
+
icon: config$5.icon,
|
|
2743
2743
|
path: "/refunds",
|
|
2744
2744
|
nested: void 0
|
|
2745
2745
|
},
|
|
2746
2746
|
{
|
|
2747
|
-
label: config$
|
|
2748
|
-
icon: config$
|
|
2747
|
+
label: config$6.label,
|
|
2748
|
+
icon: config$6.icon,
|
|
2749
2749
|
path: "/returns",
|
|
2750
2750
|
nested: void 0
|
|
2751
2751
|
},
|
|
@@ -2762,14 +2762,14 @@ const menuItemModule = {
|
|
|
2762
2762
|
nested: void 0
|
|
2763
2763
|
},
|
|
2764
2764
|
{
|
|
2765
|
-
label: config$
|
|
2766
|
-
icon: config$
|
|
2765
|
+
label: config$1.label,
|
|
2766
|
+
icon: config$1.icon,
|
|
2767
2767
|
path: "/refunds/:id",
|
|
2768
2768
|
nested: void 0
|
|
2769
2769
|
},
|
|
2770
2770
|
{
|
|
2771
|
-
label: config$
|
|
2772
|
-
icon: config$
|
|
2771
|
+
label: config$2.label,
|
|
2772
|
+
icon: config$2.icon,
|
|
2773
2773
|
path: "/returns/:id",
|
|
2774
2774
|
nested: void 0
|
|
2775
2775
|
},
|