@koda-plus/medusa-plugin-subiekt-nexo 0.2.0 → 0.3.0
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 +2027 -1225
- package/.medusa/server/src/admin/index.mjs +2030 -1228
- package/.medusa/server/src/api/admin/subiekt/check/route.d.ts +9 -0
- package/.medusa/server/src/api/admin/subiekt/documents/route.d.ts +8 -0
- package/.medusa/server/src/api/admin/subiekt/helpers.d.ts +23 -0
- package/.medusa/server/src/api/admin/subiekt/helpers.js +4 -4
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/check/route.d.ts +10 -0
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/check/route.js +33 -0
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/documents/route.d.ts +12 -0
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/link/route.d.ts +10 -0
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/link/route.js +40 -0
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/subiekt/orders/[id]/send/route.d.ts +8 -0
- package/.medusa/server/src/api/admin/subiekt/products/release/route.d.ts +9 -0
- package/.medusa/server/src/api/admin/subiekt/products/route.d.ts +9 -0
- package/.medusa/server/src/api/admin/subiekt/route.d.ts +8 -0
- package/.medusa/server/src/api/admin/subiekt/runs/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/subiekt/sync/route.d.ts +9 -0
- package/.medusa/server/src/api/admin/subiekt/sync/route.js +6 -4
- package/.medusa/server/src/api/admin/subiekt/tasks/[id]/retry/route.d.ts +9 -0
- package/.medusa/server/src/api/admin/subiekt/tasks/route.d.ts +8 -0
- package/.medusa/server/src/api/admin/subiekt/writers/route.d.ts +9 -0
- package/.medusa/server/src/api/hooks/subiekt/route.d.ts +11 -0
- package/.medusa/server/src/api/middlewares.d.ts +6 -0
- package/.medusa/server/src/jobs/subiekt-catch-up.d.ts +12 -0
- package/.medusa/server/src/jobs/subiekt-catch-up.js +26 -0
- package/.medusa/server/src/jobs/subiekt-process-tasks.d.ts +12 -0
- package/.medusa/server/src/jobs/subiekt-pull-events.d.ts +12 -0
- package/.medusa/server/src/jobs/subiekt-sync-products.d.ts +11 -0
- package/.medusa/server/src/jobs/subiekt-sync-stock.d.ts +11 -0
- package/.medusa/server/src/modules/subiekt/index.d.ts +113 -0
- package/.medusa/server/src/modules/subiekt/lib/backoff.d.ts +23 -0
- package/.medusa/server/src/modules/subiekt/lib/bridge-client.d.ts +86 -0
- package/.medusa/server/src/modules/subiekt/lib/capabilities.d.ts +24 -0
- package/.medusa/server/src/modules/subiekt/lib/catch-up.d.ts +47 -0
- package/.medusa/server/src/modules/subiekt/lib/catch-up.js +79 -0
- package/.medusa/server/src/modules/subiekt/lib/constants.d.ts +111 -0
- package/.medusa/server/src/modules/subiekt/lib/constants.js +15 -3
- package/.medusa/server/src/modules/subiekt/lib/contract.d.ts +560 -0
- package/.medusa/server/src/modules/subiekt/lib/demo.d.ts +95 -0
- package/.medusa/server/src/modules/subiekt/lib/demo.js +1 -1
- package/.medusa/server/src/modules/subiekt/lib/diagnostics.d.ts +15 -0
- package/.medusa/server/src/modules/subiekt/lib/documents.d.ts +35 -0
- package/.medusa/server/src/modules/subiekt/lib/dto.d.ts +81 -0
- package/.medusa/server/src/modules/subiekt/lib/guide.d.ts +19 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-contract.d.ts +186 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-contract.js +144 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-guards.d.ts +12 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-guards.js +90 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-meta.d.ts +8 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-meta.js +13 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-routes.d.ts +156 -0
- package/.medusa/server/src/modules/subiekt/lib/kit-routes.js +409 -0
- package/.medusa/server/src/modules/subiekt/lib/nip.d.ts +44 -0
- package/.medusa/server/src/modules/subiekt/lib/numbers.d.ts +9 -0
- package/.medusa/server/src/modules/subiekt/lib/options.d.ts +133 -0
- package/.medusa/server/src/modules/subiekt/lib/options.js +4 -3
- package/.medusa/server/src/modules/subiekt/lib/order-payload.d.ts +137 -0
- package/.medusa/server/src/modules/subiekt/lib/order-payload.js +24 -12
- package/.medusa/server/src/modules/subiekt/lib/payment.d.ts +54 -0
- package/.medusa/server/src/modules/subiekt/lib/products.d.ts +121 -0
- package/.medusa/server/src/modules/subiekt/lib/reconcile.d.ts +47 -0
- package/.medusa/server/src/modules/subiekt/lib/reconcile.js +83 -0
- package/.medusa/server/src/modules/subiekt/lib/signature.d.ts +53 -0
- package/.medusa/server/src/modules/subiekt/lib/stock.d.ts +83 -0
- package/.medusa/server/src/modules/subiekt/lib/writers.d.ts +29 -0
- package/.medusa/server/src/modules/subiekt/migrations/Migration20261004180000.d.ts +9 -0
- package/.medusa/server/src/modules/subiekt/migrations/Migration20261006120000.d.ts +11 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-catalog-change.d.ts +36 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-catalog-quarantine.d.ts +17 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-connection.d.ts +25 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-document.d.ts +31 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-sync-run.d.ts +19 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-task.d.ts +39 -0
- package/.medusa/server/src/modules/subiekt/models/subiekt-writer.d.ts +17 -0
- package/.medusa/server/src/modules/subiekt/service.d.ts +133 -0
- package/.medusa/server/src/subscribers/subiekt-fulfillment-created.d.ts +13 -0
- package/.medusa/server/src/subscribers/subiekt-order-canceled.d.ts +9 -0
- package/.medusa/server/src/subscribers/subiekt-order-placed.d.ts +18 -0
- package/.medusa/server/src/subscribers/subiekt-order-placed.js +8 -13
- package/.medusa/server/src/subscribers/subiekt-payment-captured.d.ts +11 -0
- package/.medusa/server/src/workflows/index.d.ts +20 -0
- package/.medusa/server/src/workflows/subiekt/cancel-order-in-subiekt.d.ts +13 -0
- package/.medusa/server/src/workflows/subiekt/catalog.d.ts +89 -0
- package/.medusa/server/src/workflows/subiekt/catch-up.d.ts +45 -0
- package/.medusa/server/src/workflows/subiekt/catch-up.js +163 -0
- package/.medusa/server/src/workflows/subiekt/check-subiekt-connection.d.ts +8 -0
- package/.medusa/server/src/workflows/subiekt/create-subiekt-wz.d.ts +14 -0
- package/.medusa/server/src/workflows/subiekt/events.d.ts +30 -0
- package/.medusa/server/src/workflows/subiekt/health.d.ts +20 -0
- package/.medusa/server/src/workflows/subiekt/issue-subiekt-document.d.ts +23 -0
- package/.medusa/server/src/workflows/subiekt/orders.d.ts +70 -0
- package/.medusa/server/src/workflows/subiekt/process-subiekt-tasks.d.ts +8 -0
- package/.medusa/server/src/workflows/subiekt/pull-subiekt-events.d.ts +8 -0
- package/.medusa/server/src/workflows/subiekt/queue.d.ts +34 -0
- package/.medusa/server/src/workflows/subiekt/reconcile-order.d.ts +26 -0
- package/.medusa/server/src/workflows/subiekt/reconcile-order.js +95 -0
- package/.medusa/server/src/workflows/subiekt/runtime.d.ts +52 -0
- package/.medusa/server/src/workflows/subiekt/runtime.js +38 -1
- package/.medusa/server/src/workflows/subiekt/sales-documents.d.ts +35 -0
- package/.medusa/server/src/workflows/subiekt/send-order-to-subiekt.d.ts +45 -0
- package/.medusa/server/src/workflows/subiekt/stock-plan.d.ts +17 -0
- package/.medusa/server/src/workflows/subiekt/sync-subiekt-products.d.ts +17 -0
- package/.medusa/server/src/workflows/subiekt/sync-subiekt-stock.d.ts +23 -0
- package/.medusa/server/src/workflows/subiekt/tasks.d.ts +43 -0
- package/.medusa/server/src/workflows/subiekt/writers.d.ts +18 -0
- package/CHANGELOG.md +55 -0
- package/README.md +66 -19
- package/contract/examples/events.response.json +1 -1
- package/contract/openapi.yaml +1 -1
- package/package.json +30 -2
- package/.medusa/server/src/modules/subiekt/lib/references.js +0 -135
|
@@ -3,14 +3,15 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
const jsxRuntime = require("react/jsx-runtime");
|
|
6
|
+
const react = require("react");
|
|
6
7
|
const reactI18next = require("react-i18next");
|
|
7
8
|
const adminSdk = require("@medusajs/admin-sdk");
|
|
9
|
+
const icons = require("@medusajs/icons");
|
|
8
10
|
const ui = require("@medusajs/ui");
|
|
9
11
|
const reactQuery = require("@tanstack/react-query");
|
|
10
12
|
const reactRouterDom = require("react-router-dom");
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
function backendUrl() {
|
|
13
|
+
const reactDom = require("react-dom");
|
|
14
|
+
function backendUrl$1() {
|
|
14
15
|
try {
|
|
15
16
|
if (typeof __BACKEND_URL__ !== "undefined" && __BACKEND_URL__) return String(__BACKEND_URL__).replace(/\/+$/, "");
|
|
16
17
|
} catch {
|
|
@@ -27,7 +28,7 @@ class SubiektRequestError extends Error {
|
|
|
27
28
|
}
|
|
28
29
|
async function subiektFetch(path, init) {
|
|
29
30
|
const hasBody = (init == null ? void 0 : init.body) !== void 0;
|
|
30
|
-
const res = await fetch(`${backendUrl()}${path}`, {
|
|
31
|
+
const res = await fetch(`${backendUrl$1()}${path}`, {
|
|
31
32
|
method: (init == null ? void 0 : init.method) ?? "GET",
|
|
32
33
|
credentials: "include",
|
|
33
34
|
headers: { Accept: "application/json", ...hasBody ? { "Content-Type": "application/json" } : {} },
|
|
@@ -82,6 +83,7 @@ function useSubiektTasks(filter, q, offset, limit, poll) {
|
|
|
82
83
|
function useSubiektDocuments(kind, q, offset, limit, poll) {
|
|
83
84
|
const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
|
|
84
85
|
if (kind && kind !== "all") params.set("kind", kind);
|
|
86
|
+
if (q) params.set("q", q);
|
|
85
87
|
return reactQuery.useQuery({
|
|
86
88
|
queryKey: subiektKeys.documents(kind, q, offset, limit),
|
|
87
89
|
queryFn: () => subiektFetch(`/admin/subiekt/documents?${params.toString()}`),
|
|
@@ -166,502 +168,240 @@ function useSubiektSendOrder(orderId) {
|
|
|
166
168
|
onSuccess: () => client.invalidateQueries({ queryKey: subiektKeys.order(orderId) })
|
|
167
169
|
});
|
|
168
170
|
}
|
|
169
|
-
function
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
function useSubiektOrderCheck(orderId) {
|
|
172
|
+
return reactQuery.useMutation({
|
|
173
|
+
mutationFn: () => subiektFetch(`/admin/subiekt/orders/${encodeURIComponent(orderId)}/check`, { method: "POST", body: {} })
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function useSubiektLinkDocument(orderId) {
|
|
177
|
+
const client = reactQuery.useQueryClient();
|
|
178
|
+
return reactQuery.useMutation({
|
|
179
|
+
mutationFn: (body) => subiektFetch(`/admin/subiekt/orders/${encodeURIComponent(orderId)}/link`, { method: "POST", body }),
|
|
180
|
+
onSuccess: () => client.invalidateQueries({ queryKey: subiektKeys.all })
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function backendUrl() {
|
|
173
184
|
try {
|
|
174
|
-
|
|
185
|
+
if (typeof __BACKEND_URL__ !== "undefined" && __BACKEND_URL__ && __BACKEND_URL__ !== "/") return String(__BACKEND_URL__).replace(/\/+$/, "");
|
|
175
186
|
} catch {
|
|
176
|
-
return d.toISOString().slice(0, 16).replace("T", " ");
|
|
177
187
|
}
|
|
188
|
+
return "";
|
|
178
189
|
}
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
return ms < 1e4 ? `${(ms / 1e3).toFixed(1)} s` : `${Math.round(ms / 1e3)} s`;
|
|
182
|
-
}
|
|
183
|
-
function fmtNumber(value, lang) {
|
|
184
|
-
const n = typeof value === "number" ? value : Number(value);
|
|
185
|
-
if (!Number.isFinite(n)) return "0";
|
|
190
|
+
function authHeaders() {
|
|
191
|
+
let type = "session";
|
|
186
192
|
try {
|
|
187
|
-
|
|
193
|
+
if (typeof __AUTH_TYPE__ !== "undefined" && __AUTH_TYPE__) type = String(__AUTH_TYPE__);
|
|
188
194
|
} catch {
|
|
189
|
-
return String(n);
|
|
190
195
|
}
|
|
196
|
+
if (type !== "jwt") return {};
|
|
197
|
+
let key = "medusa_auth_token";
|
|
198
|
+
try {
|
|
199
|
+
if (typeof __JWT_TOKEN_STORAGE_KEY__ !== "undefined" && __JWT_TOKEN_STORAGE_KEY__) key = String(__JWT_TOKEN_STORAGE_KEY__);
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
let token = null;
|
|
203
|
+
try {
|
|
204
|
+
token = window.localStorage.getItem(key) ?? window.sessionStorage.getItem(key);
|
|
205
|
+
} catch {
|
|
206
|
+
token = null;
|
|
207
|
+
}
|
|
208
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
191
209
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: TASK_TONE[status] ?? "grey", children: t(`tasks.statuses.${status}`) });
|
|
204
|
-
}
|
|
205
|
-
const RUN_TONE = { success: "green", partial: "orange", error: "red", skipped: "grey" };
|
|
206
|
-
function RunStatusBadge({ status }) {
|
|
207
|
-
const { t } = reactI18next.useTranslation("subiekt");
|
|
208
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: RUN_TONE[status] ?? "grey", children: t(`runs.statuses.${status}`) });
|
|
209
|
-
}
|
|
210
|
-
function DocumentStatusBadge({ status }) {
|
|
211
|
-
const { t } = reactI18next.useTranslation("subiekt");
|
|
212
|
-
const tone = status === "canceled" ? "grey" : status === "completed" ? "green" : "blue";
|
|
213
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: tone, children: t(`documents.statuses.${status}`, { defaultValue: status }) });
|
|
214
|
-
}
|
|
215
|
-
const CATALOG_TONE = {
|
|
216
|
-
planned: "blue",
|
|
217
|
-
applied: "green",
|
|
218
|
-
simulated: "purple",
|
|
219
|
-
over_cap: "grey",
|
|
220
|
-
stale: "orange",
|
|
221
|
-
failed: "red",
|
|
222
|
-
quarantined: "red",
|
|
223
|
-
skipped: "grey"
|
|
224
|
-
};
|
|
225
|
-
function CatalogStatusBadge({ status }) {
|
|
226
|
-
const { t } = reactI18next.useTranslation("subiekt");
|
|
227
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: CATALOG_TONE[status] ?? "grey", children: t(`products.statuses.${status}`, { defaultValue: status }) });
|
|
228
|
-
}
|
|
229
|
-
function SampleList({ label, items }) {
|
|
230
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
231
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: label }),
|
|
232
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", className: "font-mono", children: item }, item)) })
|
|
233
|
-
] });
|
|
234
|
-
}
|
|
235
|
-
function RichText({ text }) {
|
|
236
|
-
const parts = text.split("`");
|
|
237
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts.map(
|
|
238
|
-
(part, i) => i % 2 === 1 ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "txt-compact-xsmall rounded border border-ui-border-base bg-ui-bg-subtle px-1 font-mono text-ui-fg-base", children: part }, i) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: part }, i)
|
|
239
|
-
) });
|
|
210
|
+
class KitRequestError extends Error {
|
|
211
|
+
constructor(status, message, code, body) {
|
|
212
|
+
super(message);
|
|
213
|
+
__publicField(this, "status");
|
|
214
|
+
__publicField(this, "code");
|
|
215
|
+
__publicField(this, "body");
|
|
216
|
+
this.name = "KitRequestError";
|
|
217
|
+
this.status = status;
|
|
218
|
+
this.code = code;
|
|
219
|
+
this.body = body;
|
|
220
|
+
}
|
|
240
221
|
}
|
|
241
|
-
function
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
222
|
+
function kitRequestInit(init = {}) {
|
|
223
|
+
const method = init.method ?? "GET";
|
|
224
|
+
const write = method !== "GET";
|
|
225
|
+
const hasBody = init.body !== void 0;
|
|
226
|
+
return {
|
|
227
|
+
method,
|
|
228
|
+
credentials: "include",
|
|
229
|
+
signal: init.signal,
|
|
230
|
+
headers: {
|
|
231
|
+
Accept: "application/json",
|
|
232
|
+
...write ? { "Content-Type": "application/json", "x-koda-request": "1" } : {},
|
|
233
|
+
...authHeaders(),
|
|
234
|
+
...init.headers ?? {}
|
|
235
|
+
},
|
|
236
|
+
body: write ? JSON.stringify(hasBody ? init.body : {}) : void 0
|
|
237
|
+
};
|
|
250
238
|
}
|
|
251
|
-
function
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
|
|
239
|
+
async function kitFetch(path, init = {}) {
|
|
240
|
+
const res = await fetch(`${backendUrl()}${path}`, kitRequestInit(init));
|
|
241
|
+
const text = await res.text();
|
|
242
|
+
let json = null;
|
|
243
|
+
try {
|
|
244
|
+
json = text ? JSON.parse(text) : null;
|
|
245
|
+
} catch {
|
|
246
|
+
json = null;
|
|
247
|
+
}
|
|
248
|
+
if (!res.ok) {
|
|
249
|
+
const body = json && typeof json === "object" ? json : {};
|
|
250
|
+
throw new KitRequestError(res.status, typeof body.message === "string" ? body.message : `HTTP ${res.status}`, typeof body.code === "string" ? body.code : null, json);
|
|
251
|
+
}
|
|
252
|
+
return json;
|
|
255
253
|
}
|
|
256
|
-
function
|
|
257
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
{
|
|
262
|
-
size: "xlarge",
|
|
263
|
-
weight: "plus",
|
|
264
|
-
leading: "compact",
|
|
265
|
-
className: ui.clx("tabular-nums", tone === "attention" ? "text-ui-tag-red-text" : tone === "muted" ? "text-ui-fg-muted" : "text-ui-fg-base"),
|
|
266
|
-
children: value
|
|
267
|
-
}
|
|
268
|
-
)
|
|
254
|
+
function WidgetFrame({ embedded, header, children, className }) {
|
|
255
|
+
if (embedded) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.clx("divide-y divide-ui-border-base", className), children });
|
|
256
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: ui.clx("divide-y p-0", className), children: [
|
|
257
|
+
header,
|
|
258
|
+
children
|
|
269
259
|
] });
|
|
270
260
|
}
|
|
271
|
-
function
|
|
272
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
273
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
274
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
261
|
+
function KitLoading({ label, className }) {
|
|
262
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "status", "aria-live": "polite", className: ui.clx("flex min-h-[8rem] flex-col items-center justify-center gap-y-2 px-6 py-8", className), children: [
|
|
263
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-5 animate-spin rounded-full border-2 border-ui-border-base border-t-ui-fg-interactive" }),
|
|
264
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-small text-ui-fg-subtle", children: label }) : null
|
|
275
265
|
] });
|
|
276
266
|
}
|
|
277
|
-
function
|
|
278
|
-
return /* @__PURE__ */ jsxRuntime.jsx("
|
|
279
|
-
"button",
|
|
280
|
-
{
|
|
281
|
-
type: "button",
|
|
282
|
-
onClick: () => onChange(o.value),
|
|
283
|
-
className: ui.clx(
|
|
284
|
-
"txt-compact-small-plus rounded-full border px-3 py-1 transition-colors",
|
|
285
|
-
value === o.value ? "border-ui-border-interactive bg-ui-bg-highlight text-ui-fg-interactive" : "border-ui-border-base text-ui-fg-subtle hover:bg-ui-bg-base-hover"
|
|
286
|
-
),
|
|
287
|
-
children: [
|
|
288
|
-
o.label,
|
|
289
|
-
typeof o.count === "number" && o.count > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", className: "ml-2", children: o.count }) : null
|
|
290
|
-
]
|
|
291
|
-
},
|
|
292
|
-
o.value
|
|
293
|
-
)) });
|
|
267
|
+
function KitSkeletonRows({ cols, rows = 6 }) {
|
|
268
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: rows }, (_, r) => /* @__PURE__ */ jsxRuntime.jsx("tr", { "aria-hidden": true, className: "border-b border-ui-border-base last:border-b-0", children: Array.from({ length: cols }, (_2, c) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block h-3 animate-pulse rounded bg-ui-bg-component", style: { width: `${45 + (r * 7 + c * 13) % 45}%` } }) }, c)) }, r)) });
|
|
294
269
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
270
|
+
const KIT_META = {
|
|
271
|
+
pkg: "@koda-plus/medusa-plugin-subiekt-nexo",
|
|
272
|
+
version: "0.3.0"
|
|
273
|
+
};
|
|
274
|
+
const NBSP = " ";
|
|
275
|
+
const NBHY = "‑";
|
|
276
|
+
const SHORT = /(^|[\s("„])(oraz|albo|lub|ale|że|bo|czy|gdy|aby|by|więc|jak|na|do|za|ze|we|od|po|to|[aiouwze])[ \t]+/gi;
|
|
277
|
+
function nb(text) {
|
|
278
|
+
let out = text;
|
|
279
|
+
for (let k = 0; k < 2; k++) out = out.replace(SHORT, `$1$2${NBSP}`);
|
|
280
|
+
out = out.replace(/(\d) (?=\d{3}\b)/g, `$1${NBSP}`);
|
|
281
|
+
out = out.replace(/\b([eE])-(?=mail)/g, `$1${NBHY}`);
|
|
282
|
+
return out.replace(/(\d) (zł|€|Kč|EUR|USD|PLN|CZK|mln|tys\.|cm|mm|m²|%)/g, `$1${NBSP}$2`);
|
|
305
283
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
const changes = num(s.toUpdate) + num(s.toCreate);
|
|
312
|
-
return t(run.dryRun ? "runs.summary.stockDry" : "runs.summary.stock", { changes, unchanged: num(s.unchanged) });
|
|
313
|
-
}
|
|
314
|
-
if (run.kind === "tasks") {
|
|
315
|
-
const vars = { succeeded: num(s.succeeded), retry: num(s.retry), failed: num(s.failed) };
|
|
316
|
-
return t(vars.retry || vars.failed ? "runs.summary.tasksIssues" : "runs.summary.tasks", vars);
|
|
317
|
-
}
|
|
318
|
-
if (run.kind === "events") return num(s.read) > 0 ? t("runs.summary.events", { applied: num(s.applied) }) : t("runs.summary.eventsNone");
|
|
319
|
-
if (run.kind === "health" && run.status === "success") return t("runs.summary.health");
|
|
320
|
-
if (run.kind === "products") {
|
|
321
|
-
const applied = num(s.applied) + num(s.simulated);
|
|
322
|
-
return t(run.dryRun ? "runs.summary.productsPlan" : "runs.summary.productsApplied", {
|
|
323
|
-
prices: num(s.priceChanges),
|
|
324
|
-
creates: num(s.toCreate),
|
|
325
|
-
applied,
|
|
326
|
-
failed: num(s.failed)
|
|
327
|
-
});
|
|
284
|
+
function typeset(value) {
|
|
285
|
+
if (typeof value === "string") return nb(value);
|
|
286
|
+
if (Array.isArray(value)) return value.map((v) => typeset(v));
|
|
287
|
+
if (value && typeof value === "object") {
|
|
288
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, typeset(v)]));
|
|
328
289
|
}
|
|
329
|
-
return
|
|
290
|
+
return value;
|
|
330
291
|
}
|
|
331
|
-
function
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
292
|
+
function usePageNav(tabs) {
|
|
293
|
+
const [params, setParams] = reactRouterDom.useSearchParams();
|
|
294
|
+
const raw = params.get("view");
|
|
295
|
+
const view = raw === "guide" || raw === "settings" ? raw : "panel";
|
|
296
|
+
const asked = params.get("tab") ?? "";
|
|
297
|
+
const tab = tabs.includes(asked) ? asked : tabs[0];
|
|
298
|
+
const go = (next, nextTab) => {
|
|
299
|
+
const p = new URLSearchParams(params);
|
|
300
|
+
if (next === "panel") p.delete("view");
|
|
301
|
+
else p.set("view", next);
|
|
302
|
+
if (next === "settings") p.set("tab", nextTab ?? tab);
|
|
303
|
+
else p.delete("tab");
|
|
304
|
+
setParams(p, { replace: true });
|
|
305
|
+
};
|
|
306
|
+
return { view, tab, go };
|
|
338
307
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return
|
|
308
|
+
const VIEWS = ["panel", "guide", "settings"];
|
|
309
|
+
const VIEW_ICON = { panel: /* @__PURE__ */ jsxRuntime.jsx(icons.ChartBar, {}), guide: /* @__PURE__ */ jsxRuntime.jsx(icons.BookOpen, {}), settings: /* @__PURE__ */ jsxRuntime.jsx(icons.CogSixTooth, {}) };
|
|
310
|
+
function PageTabs({ value, onChange, labels }) {
|
|
311
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", className: "flex flex-wrap items-center gap-1", children: VIEWS.map((v) => {
|
|
312
|
+
const on = v === value;
|
|
313
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
314
|
+
"button",
|
|
315
|
+
{
|
|
316
|
+
type: "button",
|
|
317
|
+
role: "tab",
|
|
318
|
+
"aria-selected": on,
|
|
319
|
+
onClick: () => onChange(v),
|
|
320
|
+
className: ui.clx(
|
|
321
|
+
"txt-compact-small-plus inline-flex items-center gap-x-1.5 rounded-md px-2.5 py-1.5 outline-none transition-fg focus-visible:shadow-borders-focus",
|
|
322
|
+
on ? "bg-ui-bg-base text-ui-fg-base shadow-borders-base" : "text-ui-fg-subtle hover:bg-ui-bg-base-hover hover:text-ui-fg-base"
|
|
323
|
+
),
|
|
324
|
+
children: [
|
|
325
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("flex", on ? "text-ui-fg-interactive" : "text-ui-fg-muted"), children: VIEW_ICON[v] }),
|
|
326
|
+
labels[v]
|
|
327
|
+
]
|
|
328
|
+
},
|
|
329
|
+
v
|
|
330
|
+
);
|
|
331
|
+
}) });
|
|
343
332
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
function
|
|
352
|
-
const
|
|
353
|
-
if (!
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
return new Intl.DateTimeFormat(lang, { month: "long", year: "numeric", timeZone: "UTC" }).format(new Date(Date.UTC(year, month - 1, 15)));
|
|
359
|
-
} catch {
|
|
360
|
-
return since;
|
|
361
|
-
}
|
|
333
|
+
const POINT_TONE = {
|
|
334
|
+
grey: "border-ui-border-base bg-ui-bg-subtle text-ui-fg-subtle",
|
|
335
|
+
green: "border-ui-tag-green-border bg-ui-tag-green-bg text-ui-tag-green-text",
|
|
336
|
+
orange: "border-ui-tag-orange-border bg-ui-tag-orange-bg text-ui-tag-orange-text",
|
|
337
|
+
red: "border-ui-tag-red-border bg-ui-tag-red-bg text-ui-tag-red-text",
|
|
338
|
+
blue: "border-ui-tag-blue-border bg-ui-tag-blue-bg text-ui-tag-blue-text"
|
|
339
|
+
};
|
|
340
|
+
function KeyPoints({ items, label, className }) {
|
|
341
|
+
const shown = items.filter((p) => Boolean(p));
|
|
342
|
+
if (!shown.length) return null;
|
|
343
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": label, title: label, className: ui.clx("flex min-w-0 flex-nowrap items-center gap-1.5 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", className), children: shown.map((p, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { title: p.title, className: ui.clx("txt-compact-xsmall-plus inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded-full border px-2 py-0.5", POINT_TONE[p.tone ?? "grey"]), children: [
|
|
344
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "flex shrink-0 [&_svg]:size-3.5", children: p.icon }),
|
|
345
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: p.text })
|
|
346
|
+
] }, i)) });
|
|
362
347
|
}
|
|
363
|
-
function
|
|
364
|
-
return (
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
description: resolveText(r.description, lang),
|
|
369
|
-
since: r.since,
|
|
370
|
-
metrics: r.metrics.map((m) => ({ label: resolveText(m.label, lang) ?? "", value: m.value })).filter((m) => m.label),
|
|
371
|
-
links: r.links.map((l) => ({ label: resolveText(l.label, lang) ?? l.url, url: l.url })),
|
|
372
|
-
review: r.review ? { ...r.review, quote: resolveText(r.review.quote ?? void 0, lang) } : null
|
|
373
|
-
}));
|
|
348
|
+
function OtherActions({ items }) {
|
|
349
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: a.loading, disabled: a.disabled, onClick: a.onClick, className: "whitespace-nowrap", children: [
|
|
350
|
+
a.icon,
|
|
351
|
+
a.label
|
|
352
|
+
] }, a.key)) });
|
|
374
353
|
}
|
|
375
|
-
function
|
|
354
|
+
function isWhiteLabel() {
|
|
355
|
+
var _a;
|
|
376
356
|
try {
|
|
377
|
-
return
|
|
357
|
+
return Boolean((_a = globalThis.__KODA_KIT__) == null ? void 0 : _a.whiteLabel);
|
|
378
358
|
} catch {
|
|
379
|
-
return
|
|
359
|
+
return false;
|
|
380
360
|
}
|
|
381
361
|
}
|
|
382
|
-
function
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
]
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
399
|
-
/* @__PURE__ */ jsxRuntime.
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
/* @__PURE__ */ jsxRuntime.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
title: displayId ? `#${displayId}` : orderId,
|
|
426
|
-
mono: displayId ? orderId : null,
|
|
427
|
-
monoTitle: orderId,
|
|
428
|
-
action: t("store.openOrder")
|
|
429
|
-
}
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
function SubiektIcon({ width = 15, height = 15, ...props }) {
|
|
433
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
434
|
-
"svg",
|
|
435
|
-
{
|
|
436
|
-
width,
|
|
437
|
-
height,
|
|
438
|
-
viewBox: "0 0 192 192",
|
|
439
|
-
fill: "none",
|
|
440
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
441
|
-
"aria-hidden": "true",
|
|
442
|
-
...props,
|
|
443
|
-
children: [
|
|
444
|
-
/* @__PURE__ */ jsxRuntime.jsx("rect", { width: "192", height: "192", rx: "40", fill: "#0071B8" }),
|
|
445
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
446
|
-
"path",
|
|
447
|
-
{
|
|
448
|
-
fill: "#FFFFFF",
|
|
449
|
-
d: "M38.4 134.71L38.4 123.08Q40.4 124.84 43.19 126.25 45.98 127.66 49.06 128.63 52.15 129.6 55.26 130.13 58.37 130.66 61.02 130.66 70.12 130.66 74.62 127.28 79.11 123.9 79.11 117.56 79.11 114.15 77.61 111.63 76.12 109.1 73.47 107.02 70.83 104.93 67.21 103.02 63.6 101.11 59.43 99 55.03 96.76 51.21 94.47 47.39 92.18 44.57 89.42 41.75 86.66 40.13 83.16 38.52 79.67 38.52 74.97 38.52 69.21 41.04 64.95 43.57 60.69 47.68 57.93 51.79 55.17 57.05 53.82 62.31 52.47 67.77 52.47 80.23 52.47 85.93 55.47L85.93 66.57Q78.46 61.4 66.77 61.4 63.54 61.4 60.31 62.07 57.08 62.75 54.56 64.28 52.03 65.8 50.44 68.21 48.86 70.62 48.86 74.09 48.86 77.32 50.06 79.67 51.27 82.02 53.62 83.96 55.97 85.9 59.34 87.72 62.72 89.54 67.13 91.71 71.65 93.94 75.7 96.41 79.76 98.88 82.81 101.87 85.87 104.87 87.66 108.51 89.45 112.15 89.45 116.85 89.45 123.08 87.01 127.4 84.57 131.72 80.43 134.42 76.29 137.12 70.89 138.33 65.48 139.53 59.49 139.53 57.49 139.53 54.56 139.21 51.62 138.88 48.56 138.27 45.51 137.65 42.78 136.74 40.04 135.83 38.4 134.71M153.6 77.96L153.6 138.12 143.97 138.12 143.97 128.6 143.73 128.6Q137.74 139.53 125.17 139.53 103.67 139.53 103.67 113.92L103.67 77.96 113.24 77.96 113.24 112.39Q113.24 131.42 127.81 131.42 134.86 131.42 139.41 126.22 143.97 121.03 143.97 112.63L143.97 77.96"
|
|
450
|
-
}
|
|
451
|
-
)
|
|
452
|
-
]
|
|
453
|
-
}
|
|
454
|
-
);
|
|
455
|
-
}
|
|
456
|
-
const SubiektOrderWidget = ({ data }) => {
|
|
457
|
-
var _a, _b, _c, _d;
|
|
458
|
-
const { t, i18n } = reactI18next.useTranslation("subiekt");
|
|
459
|
-
const lang = i18n.language || "en";
|
|
460
|
-
const q = useSubiektOrder(data.id);
|
|
461
|
-
const send = useSubiektSendOrder(data.id);
|
|
462
|
-
const issue = useSubiektIssueDocument(data.id);
|
|
463
|
-
const retry = useSubiektRetry();
|
|
464
|
-
const documents = ((_a = q.data) == null ? void 0 : _a.documents) ?? [];
|
|
465
|
-
const tasks = ((_b = q.data) == null ? void 0 : _b.tasks) ?? [];
|
|
466
|
-
const sales = (_c = q.data) == null ? void 0 : _c.salesDocument;
|
|
467
|
-
const create = tasks.find((task) => task.kind === "order.create");
|
|
468
|
-
const documentTask = tasks.find((task) => task.kind === "order.document");
|
|
469
|
-
const hasZk = documents.some((d) => d.kind === "ZK" && d.status !== "canceled");
|
|
470
|
-
const hasSales = documents.some((d) => (d.kind === "FS" || d.kind === "PA") && d.status !== "canceled");
|
|
471
|
-
const busy = (create == null ? void 0 : create.status) === "pending" || (create == null ? void 0 : create.status) === "running";
|
|
472
|
-
const documentBusy = documentTask ? ["pending", "running", "unknown"].includes(documentTask.status) : false;
|
|
473
|
-
const canceled = data.status === "canceled";
|
|
474
|
-
const offerIssue = Boolean(sales && sales.option !== "none" && sales.supported && hasZk && !hasSales && !documentBusy && !canceled);
|
|
475
|
-
const onSend = async () => {
|
|
476
|
-
try {
|
|
477
|
-
await send.mutateAsync();
|
|
478
|
-
ui.toast.success(t("widget.sent"));
|
|
479
|
-
} catch (err) {
|
|
480
|
-
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
const onIssue = async (kind) => {
|
|
484
|
-
try {
|
|
485
|
-
await issue.mutateAsync(kind);
|
|
486
|
-
ui.toast.success(t("widget.issued"));
|
|
487
|
-
} catch (err) {
|
|
488
|
-
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
489
|
-
}
|
|
490
|
-
};
|
|
491
|
-
const onRetry = async (id) => {
|
|
492
|
-
try {
|
|
493
|
-
await retry.mutateAsync(id);
|
|
494
|
-
ui.toast.success(t("toast.retried"));
|
|
495
|
-
void q.refetch();
|
|
496
|
-
} catch (err) {
|
|
497
|
-
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
501
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
|
|
502
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
503
|
-
/* @__PURE__ */ jsxRuntime.jsx(SubiektIcon, { width: 18, height: 18, className: "shrink-0" }),
|
|
504
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t("widget.title") }),
|
|
505
|
-
((_d = q.data) == null ? void 0 : _d.mode) === "demo" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "purple", children: t("widget.demo") }) : null
|
|
506
|
-
] }),
|
|
507
|
-
/* @__PURE__ */ jsxRuntime.jsx("a", { href: "/app/subiekt", className: "txt-compact-small text-ui-fg-interactive hover:text-ui-fg-interactive-hover", children: t("widget.more") })
|
|
508
|
-
] }),
|
|
509
|
-
q.isLoading ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
510
|
-
documents.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-2 px-6 py-4", children: documents.map((d) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-x-2", children: [
|
|
511
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
512
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "font-mono", children: d.number }),
|
|
513
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
514
|
-
fmtDateTime(d.issuedAt, lang),
|
|
515
|
-
", ",
|
|
516
|
-
t(`documents.sources.${d.source}`, { defaultValue: d.source })
|
|
517
|
-
] }),
|
|
518
|
-
d.kind === "FS" && d.status !== "canceled" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: d.ksefNumber ? "break-all font-mono text-ui-fg-subtle" : "text-ui-fg-muted", children: d.ksefNumber ? t("widget.ksef", { number: d.ksefNumber }) : t("widget.ksefWaiting") }) : null
|
|
519
|
-
] }),
|
|
520
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocumentStatusBadge, { status: d.status })
|
|
521
|
-
] }, d.id)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: (create == null ? void 0 : create.status) === "waiting" ? t("widget.waiting") : t("widget.none") }) }),
|
|
522
|
-
tasks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
523
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-2", children: [
|
|
524
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: task.kind === "order.document" && (task.documentKind === "fs" || task.documentKind === "pa") ? t(`tasks.documentKinds.${task.documentKind}`) : t(`tasks.kinds.${task.kind}`) }),
|
|
525
|
-
/* @__PURE__ */ jsxRuntime.jsx(TaskStatusBadge, { status: task.status })
|
|
526
|
-
] }),
|
|
527
|
-
task.buyer ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: task.buyer.source === "retail" ? t("tasks.buyer.retail") : t(`tasks.buyer.${task.buyer.source}`, { name: task.buyer.name ?? task.buyer.symbol ?? "?", nip: task.buyer.nip ?? "?" }) }) : null,
|
|
528
|
-
task.warnings.map((w) => /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: w }, w)),
|
|
529
|
-
task.lastError && task.status !== "succeeded" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: task.status === "failed" ? "text-ui-tag-red-text" : "text-ui-fg-muted", children: task.lastError }) : null,
|
|
530
|
-
task.status === "unknown" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: t("tasks.unknownHint") }) : null,
|
|
531
|
-
task.manualAction ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: t("tasks.manual") }) : null,
|
|
532
|
-
task.status === "failed" ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", isLoading: retry.isPending && retry.variables === task.id, onClick: () => onRetry(task.id), children: t("actions.retry") }) }) : null
|
|
533
|
-
] }, task.id)) }) : null,
|
|
534
|
-
!hasZk && !busy && !canceled && (create == null ? void 0 : create.status) !== "failed" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", isLoading: send.isPending, onClick: onSend, children: t("widget.send") }) }) : null,
|
|
535
|
-
offerIssue && sales ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2 px-6 py-4", children: [
|
|
536
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: sales.writerActive ? t("widget.autoOn", { after: sales.after.toUpperCase() }) : t("widget.autoOff") }),
|
|
537
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
538
|
-
sales.option === "fs" || sales.option === "auto" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", isLoading: issue.isPending && issue.variables === "fs", onClick: () => onIssue("fs"), children: t("widget.issueFs") }) : null,
|
|
539
|
-
sales.option === "pa" || sales.option === "auto" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", isLoading: issue.isPending && issue.variables === "pa", onClick: () => onIssue("pa"), children: t("widget.issuePa") }) : null
|
|
540
|
-
] })
|
|
541
|
-
] }) : null
|
|
542
|
-
] })
|
|
543
|
-
] });
|
|
544
|
-
};
|
|
545
|
-
adminSdk.defineWidgetConfig({
|
|
546
|
-
zone: "order.details.side.after"
|
|
547
|
-
});
|
|
548
|
-
const NBSP = " ";
|
|
549
|
-
const NBHY = "‑";
|
|
550
|
-
const SHORT = /(^|[\s("„])(oraz|albo|lub|ale|że|bo|czy|gdy|aby|by|więc|jak|na|do|za|ze|we|od|po|to|[aiouwze])[ \t]+/gi;
|
|
551
|
-
function nb(text) {
|
|
552
|
-
let out = text;
|
|
553
|
-
for (let k = 0; k < 2; k++) out = out.replace(SHORT, `$1$2${NBSP}`);
|
|
554
|
-
out = out.replace(/(\d) (?=\d{3}\b)/g, `$1${NBSP}`);
|
|
555
|
-
out = out.replace(/\b([eE])-(?=mail)/g, `$1${NBHY}`);
|
|
556
|
-
return out.replace(/(\d) (zł|€|Kč|EUR|USD|PLN|CZK|mln|tys\.|cm|mm|m²|%)/g, `$1${NBSP}$2`);
|
|
557
|
-
}
|
|
558
|
-
function typeset(value) {
|
|
559
|
-
if (typeof value === "string") return nb(value);
|
|
560
|
-
if (Array.isArray(value)) return value.map((v) => typeset(v));
|
|
561
|
-
if (value && typeof value === "object") {
|
|
562
|
-
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, typeset(v)]));
|
|
563
|
-
}
|
|
564
|
-
return value;
|
|
565
|
-
}
|
|
566
|
-
function usePageNav(tabs) {
|
|
567
|
-
const [params, setParams] = reactRouterDom.useSearchParams();
|
|
568
|
-
const raw = params.get("view");
|
|
569
|
-
const view = raw === "guide" || raw === "settings" ? raw : "panel";
|
|
570
|
-
const asked = params.get("tab") ?? "";
|
|
571
|
-
const tab = tabs.includes(asked) ? asked : tabs[0];
|
|
572
|
-
const go = (next, nextTab) => {
|
|
573
|
-
const p = new URLSearchParams(params);
|
|
574
|
-
if (next === "panel") p.delete("view");
|
|
575
|
-
else p.set("view", next);
|
|
576
|
-
if (next === "settings") p.set("tab", nextTab ?? tab);
|
|
577
|
-
else p.delete("tab");
|
|
578
|
-
setParams(p, { replace: true });
|
|
579
|
-
};
|
|
580
|
-
return { view, tab, go };
|
|
581
|
-
}
|
|
582
|
-
const VIEWS = ["panel", "guide", "settings"];
|
|
583
|
-
const VIEW_ICON = { panel: /* @__PURE__ */ jsxRuntime.jsx(icons.ChartBar, {}), guide: /* @__PURE__ */ jsxRuntime.jsx(icons.BookOpen, {}), settings: /* @__PURE__ */ jsxRuntime.jsx(icons.CogSixTooth, {}) };
|
|
584
|
-
function PageTabs({ value, onChange, labels }) {
|
|
585
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", className: "flex flex-wrap items-center gap-1", children: VIEWS.map((v) => {
|
|
586
|
-
const on = v === value;
|
|
587
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
588
|
-
"button",
|
|
589
|
-
{
|
|
590
|
-
type: "button",
|
|
591
|
-
role: "tab",
|
|
592
|
-
"aria-selected": on,
|
|
593
|
-
onClick: () => onChange(v),
|
|
594
|
-
className: ui.clx(
|
|
595
|
-
"txt-compact-small-plus inline-flex items-center gap-x-1.5 rounded-md px-2.5 py-1.5 outline-none transition-fg focus-visible:shadow-borders-focus",
|
|
596
|
-
on ? "bg-ui-bg-base text-ui-fg-base shadow-borders-base" : "text-ui-fg-subtle hover:bg-ui-bg-base-hover hover:text-ui-fg-base"
|
|
597
|
-
),
|
|
598
|
-
children: [
|
|
599
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("flex", on ? "text-ui-fg-interactive" : "text-ui-fg-muted"), children: VIEW_ICON[v] }),
|
|
600
|
-
labels[v]
|
|
601
|
-
]
|
|
602
|
-
},
|
|
603
|
-
v
|
|
604
|
-
);
|
|
605
|
-
}) });
|
|
606
|
-
}
|
|
607
|
-
function OtherActions({ items, label }) {
|
|
608
|
-
if (items.length === 1) {
|
|
609
|
-
const a = items[0];
|
|
610
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: a.loading, disabled: a.disabled, onClick: a.onClick, children: [
|
|
611
|
-
a.icon,
|
|
612
|
-
a.label
|
|
613
|
-
] });
|
|
614
|
-
}
|
|
615
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
|
|
616
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", children: [
|
|
617
|
-
label,
|
|
618
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, {})
|
|
619
|
-
] }) }),
|
|
620
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Content, { align: "end", children: items.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Item, { disabled: a.disabled || a.loading, onClick: a.onClick, className: "gap-x-2", children: [
|
|
621
|
-
a.icon,
|
|
622
|
-
a.label
|
|
623
|
-
] }, a.key)) })
|
|
624
|
-
] });
|
|
625
|
-
}
|
|
626
|
-
function IntegrationHeader({
|
|
627
|
-
icon,
|
|
628
|
-
title,
|
|
629
|
-
by,
|
|
630
|
-
badges,
|
|
631
|
-
description,
|
|
632
|
-
social,
|
|
633
|
-
help,
|
|
634
|
-
view,
|
|
635
|
-
onView,
|
|
636
|
-
labels,
|
|
637
|
-
primary,
|
|
638
|
-
actions = []
|
|
639
|
-
}) {
|
|
640
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
641
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 pb-5 pt-5", children: [
|
|
642
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
643
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2.5 gap-y-1.5", children: [
|
|
644
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0", children: icon }),
|
|
645
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: title }),
|
|
646
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: by }),
|
|
647
|
-
badges ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-1.5", children: badges }) : null
|
|
648
|
-
] }),
|
|
649
|
-
help ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0", children: help }) : null
|
|
650
|
-
] }),
|
|
651
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-3xl text-ui-fg-subtle", children: description }),
|
|
652
|
-
social ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2 pt-0.5", children: social }) : null
|
|
653
|
-
] }),
|
|
654
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 border-t border-ui-border-base bg-ui-bg-subtle px-6 py-2.5 md:flex-row md:items-center md:justify-between", children: [
|
|
655
|
-
/* @__PURE__ */ jsxRuntime.jsx(PageTabs, { value: view, onChange: onView, labels }),
|
|
656
|
-
primary || actions.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
657
|
-
actions.length ? /* @__PURE__ */ jsxRuntime.jsx(OtherActions, { items: actions, label: labels.more }) : null,
|
|
658
|
-
primary ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "primary", isLoading: primary.loading, disabled: primary.disabled, onClick: primary.onClick, children: [
|
|
659
|
-
primary.icon,
|
|
660
|
-
primary.label
|
|
661
|
-
] }) : null
|
|
662
|
-
] }) : null
|
|
663
|
-
] })
|
|
664
|
-
] });
|
|
362
|
+
function IntegrationHeader({
|
|
363
|
+
icon,
|
|
364
|
+
title,
|
|
365
|
+
badges,
|
|
366
|
+
featured,
|
|
367
|
+
description,
|
|
368
|
+
points,
|
|
369
|
+
social,
|
|
370
|
+
help,
|
|
371
|
+
view,
|
|
372
|
+
onView,
|
|
373
|
+
labels,
|
|
374
|
+
primary,
|
|
375
|
+
actions = []
|
|
376
|
+
}) {
|
|
377
|
+
const plain2 = isWhiteLabel();
|
|
378
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
379
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 pb-5 pt-5", children: [
|
|
380
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
381
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2.5 gap-y-1.5", children: [
|
|
382
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0", children: icon }),
|
|
383
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: title }),
|
|
384
|
+
featured && !plain2 || badges ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
385
|
+
featured && !plain2 ? /* @__PURE__ */ jsxRuntime.jsx(FeaturedBadge, { url: featured.url, labels: featured.labels }) : null,
|
|
386
|
+
badges
|
|
387
|
+
] }) : null
|
|
388
|
+
] }),
|
|
389
|
+
help && !plain2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0", children: help }) : null
|
|
390
|
+
] }),
|
|
391
|
+
points && points.some(Boolean) ? /* @__PURE__ */ jsxRuntime.jsx(KeyPoints, { items: points, label: description }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-3xl text-ui-fg-subtle", children: description }),
|
|
392
|
+
social && !plain2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2 pt-0.5", children: social }) : null
|
|
393
|
+
] }),
|
|
394
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 border-t border-ui-border-base bg-ui-bg-subtle px-6 py-2.5 md:flex-row md:items-center md:justify-between", children: [
|
|
395
|
+
/* @__PURE__ */ jsxRuntime.jsx(PageTabs, { value: view, onChange: onView, labels }),
|
|
396
|
+
primary || actions.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
397
|
+
actions.length ? /* @__PURE__ */ jsxRuntime.jsx(OtherActions, { items: actions, label: labels.more }) : null,
|
|
398
|
+
primary ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "primary", isLoading: primary.loading, disabled: primary.disabled, onClick: primary.onClick, children: [
|
|
399
|
+
primary.icon,
|
|
400
|
+
primary.label
|
|
401
|
+
] }) : null
|
|
402
|
+
] }) : null
|
|
403
|
+
] })
|
|
404
|
+
] });
|
|
665
405
|
}
|
|
666
406
|
function ModeBadge({ color, label, title, children }) {
|
|
667
407
|
if (!children) return /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color, children: label });
|
|
@@ -676,130 +416,31 @@ function ModeBadge({ color, label, title, children }) {
|
|
|
676
416
|
] })
|
|
677
417
|
] });
|
|
678
418
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
if (!review.icon) {
|
|
697
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", weight: "plus", className: "text-ui-fg-subtle", children: review.source });
|
|
698
|
-
}
|
|
699
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0 items-center rounded-full bg-white px-2 py-1 shadow-borders-base", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: review.icon, alt: review.source, style: { height, width: "auto" } }) });
|
|
700
|
-
}
|
|
701
|
-
function StoreIcon({ reference, size }) {
|
|
702
|
-
const box = { width: size, height: size };
|
|
703
|
-
return reference.icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: reference.icon, alt: "", width: size, height: size, style: box, className: "shrink-0 rounded-md bg-white object-contain shadow-borders-base" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: box, className: "txt-compact-xsmall-plus flex shrink-0 items-center justify-center rounded-md bg-ui-bg-base text-ui-fg-base shadow-borders-base", children: reference.name.slice(0, 1).toUpperCase() });
|
|
704
|
-
}
|
|
705
|
-
function meanRating(items) {
|
|
706
|
-
const reviews = items.map((r) => r.review).filter((r) => Boolean(r));
|
|
707
|
-
if (reviews.length === 0) return null;
|
|
708
|
-
const value = reviews.reduce((sum, r) => sum + r.rating / (r.scale || 5) * 5, 0) / reviews.length;
|
|
709
|
-
return { value: Math.round(value * 10) / 10, first: reviews[0] };
|
|
710
|
-
}
|
|
711
|
-
function ReferencesBadge({ items, labels }) {
|
|
712
|
-
if (items.length === 0) return null;
|
|
713
|
-
const mean = meanRating(items);
|
|
714
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
|
|
715
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
716
|
-
"button",
|
|
717
|
-
{
|
|
718
|
-
type: "button",
|
|
719
|
-
className: "inline-flex h-9 max-w-full items-center gap-x-3 rounded-full border border-ui-border-base bg-ui-bg-component py-1 pl-1.5 pr-3 outline-none transition-fg hover:bg-ui-bg-component-hover focus-visible:shadow-borders-focus",
|
|
720
|
-
children: [
|
|
721
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center", children: items.slice(0, 3).map((r, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("rounded-md", i > 0 && "-ml-2"), children: /* @__PURE__ */ jsxRuntime.jsx(StoreIcon, { reference: r, size: 24 }) }, r.url)) }),
|
|
722
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-small-plus truncate text-ui-fg-base", children: labels.count }),
|
|
723
|
-
mean ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-x-2 border-l border-ui-border-base pl-3", children: [
|
|
724
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: mean.value, size: 13 }),
|
|
725
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-small-plus tabular-nums text-ui-fg-base", children: labels.rating(mean.value) }),
|
|
726
|
-
/* @__PURE__ */ jsxRuntime.jsx(SourceMark, { review: mean.first, height: 10 })
|
|
727
|
-
] }) : null,
|
|
728
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, { className: "-ml-1 shrink-0 text-ui-fg-muted" })
|
|
729
|
-
]
|
|
730
|
-
}
|
|
731
|
-
) }),
|
|
732
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Popover.Content, { align: "start", sideOffset: 8, className: "w-[min(460px,calc(100vw-32px))] p-0", children: [
|
|
733
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-0.5 border-b border-ui-border-base px-4 py-3", children: [
|
|
734
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-base", children: labels.title }),
|
|
735
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: labels.subtitle })
|
|
736
|
-
] }),
|
|
737
|
-
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex max-h-[60vh] flex-col divide-y divide-ui-border-base overflow-y-auto", children: items.map((r) => {
|
|
738
|
-
var _a, _b;
|
|
739
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex flex-col gap-y-2 px-4 py-3", children: [
|
|
740
|
-
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: r.url, target: "_blank", rel: "noreferrer", className: "group flex items-center gap-x-3", children: [
|
|
741
|
-
/* @__PURE__ */ jsxRuntime.jsx(StoreIcon, { reference: r, size: 32 }),
|
|
742
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
743
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "truncate text-ui-fg-base", children: r.name }),
|
|
744
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "truncate text-ui-fg-interactive group-hover:text-ui-fg-interactive-hover", children: host(r.url) })
|
|
745
|
-
] }),
|
|
746
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "ml-auto shrink-0 text-ui-fg-muted group-hover:text-ui-fg-interactive" })
|
|
747
|
-
] }),
|
|
748
|
-
r.review ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
749
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: r.review.rating, scale: r.review.scale }),
|
|
750
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-xsmall-plus tabular-nums text-ui-fg-base", children: labels.rating(r.review.rating / (r.review.scale || 5) * 5) }),
|
|
751
|
-
/* @__PURE__ */ jsxRuntime.jsx(SourceMark, { review: r.review }),
|
|
752
|
-
r.review.url ? /* @__PURE__ */ jsxRuntime.jsxs("a", { href: r.review.url, target: "_blank", rel: "noreferrer", className: "txt-compact-xsmall-plus inline-flex items-center gap-x-0.5 text-ui-fg-interactive hover:text-ui-fg-interactive-hover", children: [
|
|
753
|
-
labels.review,
|
|
754
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "h-3.5 w-3.5" })
|
|
755
|
-
] }) : null
|
|
756
|
-
] }) : null,
|
|
757
|
-
((_a = r.review) == null ? void 0 : _a.quote) ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "border-l-2 border-ui-border-strong pl-2 italic text-ui-fg-subtle", children: [
|
|
758
|
-
nb(r.review.quote),
|
|
759
|
-
r.review.author ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "not-italic text-ui-fg-muted", children: [
|
|
760
|
-
" ",
|
|
761
|
-
r.review.author
|
|
762
|
-
] }) : null
|
|
763
|
-
] }) : null,
|
|
764
|
-
r.description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: nb(r.description) }) : null,
|
|
765
|
-
((_b = r.metrics) == null ? void 0 : _b.length) || r.since ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
766
|
-
(r.metrics ?? []).map((m) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "2xsmall", color: "green", children: [
|
|
767
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: m.value }),
|
|
768
|
-
" ",
|
|
769
|
-
m.label
|
|
770
|
-
] }, m.label)),
|
|
771
|
-
r.since ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "grey", children: labels.since(r.since) }) : null
|
|
772
|
-
] }) : null,
|
|
773
|
-
(r.links ?? []).length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-x-3 gap-y-1", children: (r.links ?? []).map((l) => /* @__PURE__ */ jsxRuntime.jsxs("a", { href: l.url, target: "_blank", rel: "noreferrer", className: "txt-compact-xsmall-plus inline-flex items-center gap-x-0.5 text-ui-fg-interactive hover:text-ui-fg-interactive-hover", children: [
|
|
774
|
-
l.label,
|
|
775
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "h-3.5 w-3.5" })
|
|
776
|
-
] }, l.url)) }) : null
|
|
777
|
-
] }, r.url);
|
|
778
|
-
}) })
|
|
779
|
-
] })
|
|
780
|
-
] });
|
|
419
|
+
function FeaturedBadge({ url, labels }) {
|
|
420
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
421
|
+
"a",
|
|
422
|
+
{
|
|
423
|
+
href: url,
|
|
424
|
+
target: "_blank",
|
|
425
|
+
rel: "noopener noreferrer",
|
|
426
|
+
title: labels.title,
|
|
427
|
+
"aria-label": `${labels.badge}. ${labels.title}`,
|
|
428
|
+
className: "inline-flex rounded-full outline-none transition-fg hover:opacity-80 focus-visible:shadow-borders-focus",
|
|
429
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "2xsmall", rounded: "full", color: "green", className: "cursor-pointer gap-x-1", children: [
|
|
430
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Medusa, { className: "h-3 w-3" }),
|
|
431
|
+
labels.badge,
|
|
432
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "h-3 w-3 opacity-70" })
|
|
433
|
+
] })
|
|
434
|
+
}
|
|
435
|
+
);
|
|
781
436
|
}
|
|
782
|
-
const KODA_DISCORD = "https://
|
|
437
|
+
const KODA_DISCORD = "https://koda.plus/discord";
|
|
783
438
|
const KODA_EMAIL = "hello@koda.plus";
|
|
784
439
|
const KODA_DEMO = "https://medusa.koda.plus";
|
|
785
440
|
const plain = (text) => text.split(NBSP).join(" ");
|
|
786
|
-
function communityLabels(t,
|
|
441
|
+
function communityLabels(t, _integration) {
|
|
787
442
|
const k = (key, options) => t(`community.${key}`, options);
|
|
788
443
|
return {
|
|
789
|
-
addStore: {
|
|
790
|
-
button: k("addStore.button"),
|
|
791
|
-
title: k("addStore.title"),
|
|
792
|
-
text: k("addStore.text"),
|
|
793
|
-
name: k("addStore.name"),
|
|
794
|
-
url: k("addStore.url"),
|
|
795
|
-
note: k("addStore.note"),
|
|
796
|
-
send: k("addStore.send"),
|
|
797
|
-
copy: k("addStore.copy"),
|
|
798
|
-
copied: k("addStore.copied"),
|
|
799
|
-
hint: k("addStore.hint", { email: KODA_EMAIL }),
|
|
800
|
-
subject: k("addStore.subject", { integration }),
|
|
801
|
-
greeting: k("addStore.greeting", { integration })
|
|
802
|
-
},
|
|
803
444
|
prompt: {
|
|
804
445
|
button: k("prompt.button"),
|
|
805
446
|
title: k("prompt.title"),
|
|
@@ -808,87 +449,23 @@ function communityLabels(t, integration) {
|
|
|
808
449
|
copied: k("prompt.copied"),
|
|
809
450
|
failed: k("prompt.failed")
|
|
810
451
|
},
|
|
811
|
-
discord: { button: k("discord.button"), title: k("discord.title") }
|
|
452
|
+
discord: { button: k("discord.button"), title: k("discord.title") },
|
|
453
|
+
featured: { badge: k("featured.badge"), title: k("featured.title") }
|
|
812
454
|
};
|
|
813
455
|
}
|
|
814
|
-
function AddStoreButton({ labels }) {
|
|
815
|
-
const [name, setName] = react.useState("");
|
|
816
|
-
const [url, setUrl] = react.useState("");
|
|
817
|
-
const [note, setNote] = react.useState("");
|
|
818
|
-
const ready = name.trim() !== "" && url.trim() !== "";
|
|
819
|
-
const subject = plain(labels.subject);
|
|
820
|
-
const body = plain(
|
|
821
|
-
[labels.greeting, "", `${labels.name}: ${name.trim()}`, `${labels.url}: ${url.trim()}`, ...note.trim() ? ["", note.trim()] : []].join("\n")
|
|
822
|
-
);
|
|
823
|
-
const send = () => {
|
|
824
|
-
window.location.href = `mailto:${KODA_EMAIL}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
825
|
-
};
|
|
826
|
-
const copy = async () => {
|
|
827
|
-
try {
|
|
828
|
-
await navigator.clipboard.writeText(`${KODA_EMAIL}
|
|
829
|
-
${subject}
|
|
830
|
-
|
|
831
|
-
${body}`);
|
|
832
|
-
ui.toast.success(labels.copied);
|
|
833
|
-
} catch {
|
|
834
|
-
ui.toast.error(KODA_EMAIL);
|
|
835
|
-
}
|
|
836
|
-
};
|
|
837
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
|
|
838
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
839
|
-
"button",
|
|
840
|
-
{
|
|
841
|
-
type: "button",
|
|
842
|
-
className: "txt-compact-small-plus inline-flex h-9 items-center gap-x-1.5 rounded-full px-3 text-ui-fg-subtle outline-none transition-fg hover:bg-ui-bg-base-hover hover:text-ui-fg-base focus-visible:shadow-borders-focus",
|
|
843
|
-
children: [
|
|
844
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.PlusMini, {}),
|
|
845
|
-
labels.button
|
|
846
|
-
]
|
|
847
|
-
}
|
|
848
|
-
) }),
|
|
849
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Popover.Content, { align: "start", sideOffset: 8, className: "w-[min(420px,calc(100vw-32px))] p-0", children: [
|
|
850
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1 border-b border-ui-border-base px-4 py-3", children: [
|
|
851
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-base", children: labels.title }),
|
|
852
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: labels.text })
|
|
853
|
-
] }),
|
|
854
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-4 py-4", children: [
|
|
855
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1.5", children: [
|
|
856
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "xsmall", weight: "plus", htmlFor: "koda-add-store-name", children: labels.name }),
|
|
857
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { id: "koda-add-store-name", size: "small", value: name, onChange: (e) => setName(e.target.value) })
|
|
858
|
-
] }),
|
|
859
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1.5", children: [
|
|
860
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "xsmall", weight: "plus", htmlFor: "koda-add-store-url", children: labels.url }),
|
|
861
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { id: "koda-add-store-url", size: "small", type: "url", placeholder: "https://", value: url, onChange: (e) => setUrl(e.target.value) })
|
|
862
|
-
] }),
|
|
863
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1.5", children: [
|
|
864
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "xsmall", weight: "plus", htmlFor: "koda-add-store-note", children: labels.note }),
|
|
865
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Textarea, { id: "koda-add-store-note", rows: 3, value: note, onChange: (e) => setNote(e.target.value) })
|
|
866
|
-
] })
|
|
867
|
-
] }),
|
|
868
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 border-t border-ui-border-base px-4 py-3", children: [
|
|
869
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: labels.hint }),
|
|
870
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [
|
|
871
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", disabled: !ready, onClick: () => void copy(), children: [
|
|
872
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.SquareTwoStack, {}),
|
|
873
|
-
labels.copy
|
|
874
|
-
] }),
|
|
875
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "primary", disabled: !ready, onClick: send, children: [
|
|
876
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.PaperPlane, {}),
|
|
877
|
-
labels.send
|
|
878
|
-
] })
|
|
879
|
-
] })
|
|
880
|
-
] })
|
|
881
|
-
] })
|
|
882
|
-
] });
|
|
883
|
-
}
|
|
884
456
|
function envNames(code) {
|
|
885
457
|
const names = /* @__PURE__ */ new Set();
|
|
886
458
|
for (const m of code.matchAll(/process\.env\.([A-Z][A-Z0-9_]*)/g)) names.add(m[1]);
|
|
887
459
|
for (const m of code.matchAll(/^([A-Z][A-Z0-9_]*)=/gm)) names.add(m[1]);
|
|
888
460
|
return [...names];
|
|
889
461
|
}
|
|
462
|
+
function pinnedPackage(spec) {
|
|
463
|
+
const version = spec.version ?? (spec.pkg === KIT_META.pkg ? KIT_META.version : null);
|
|
464
|
+
return version && /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/.test(version) ? `${spec.pkg}@${version}` : spec.pkg;
|
|
465
|
+
}
|
|
890
466
|
function buildSetupPrompt(spec, lang) {
|
|
891
467
|
const code = (text) => "`" + text + "`";
|
|
468
|
+
const pinned = pinnedPackage(spec);
|
|
892
469
|
const env = envNames(`${spec.config}
|
|
893
470
|
${spec.demo}`).map(code).join(", ");
|
|
894
471
|
const needs = spec.needs.map((n) => `- ${plain(n)}`);
|
|
@@ -909,16 +486,16 @@ ${spec.demo}`).map(code).join(", ");
|
|
|
909
486
|
"",
|
|
910
487
|
"## Kroki",
|
|
911
488
|
"1. Zanim cokolwiek zmienisz, sprawdź projekt: Medusa 2.12 albo nowsza (tego wymagają strony i tłumaczenia panelu we wtyczce), menedżer pakietów projektu i medusa-config.ts. Jeśli coś blokuje instalację, zatrzymaj się i napisz mi, co.",
|
|
912
|
-
`2. Zainstaluj wtyczkę menedżerem pakietów projektu, na przykład ${code(`npm install ${spec.pkg}`)}. Jeśli rejestr jej nie znajduje
|
|
489
|
+
`2. Zainstaluj wtyczkę w tej wersji menedżerem pakietów projektu, na przykład ${code(`npm install ${pinned}`)}. Potem sprawdź pochodzenie paczki: ${code(`npm view ${spec.pkg} dist-tags.latest`)} i ${code("npm audit signatures")}. Jeśli rejestr jej nie znajduje albo podpisy się nie zgadzają, zatrzymaj się i daj mi znać: pomaga Koda Plus (${KODA_EMAIL}, Discord ${KODA_DISCORD}).`,
|
|
913
490
|
"3. Zarejestruj wtyczkę w medusa-config.ts, nie ruszając tego, co już tam jest. Użyj konfiguracji z Przewodnika wdrożenia:",
|
|
914
491
|
"",
|
|
915
492
|
...config2,
|
|
916
493
|
"",
|
|
917
|
-
`4. Dodaj do opcji przełącznik trybu demo, tak jak w sklepie demo: ${code(spec.demo)}.
|
|
494
|
+
`4. Dodaj do opcji przełącznik trybu demo, tak jak w sklepie demo: ${code(spec.demo)}. Tryb demo działa tylko po jawnym włączeniu: wtedy moduł pracuje na przykładowych danych i nie łączy się z ${service}; bez niego i bez kluczy mówi „nieskonfigurowane” i nic nie robi.`,
|
|
918
495
|
`5. Wpisz zmienne do .env i do środowiska hostingu, nigdy do kodu ani do gita: ${env}. Jeśli nie podałem Ci wartości, zostaw ją pustą i wypisz mi ją na końcu.`,
|
|
919
|
-
`6. Uruchom migracje bazy (${code("npx medusa db:migrate")}), potem sklep, i otwórz ${spec.route} w panelu admina. Sprawdź, czy Panel, Przewodnik wdrożenia i Ustawienia otwierają się bez błędów w konsoli przeglądarki i w logu serwera.`,
|
|
920
|
-
`7. Nie włączaj żadnego zapisu, czyli niczego, co zmienia dane w ${service} albo w sklepie. Każdy zapis uzbraja człowiek w Ustawieniach, po próbie na sucho; opcje tylko na to pozwalają.`,
|
|
921
|
-
`8.
|
|
496
|
+
spec.migrations === false ? `6. Uruchom sklep i otwórz ${spec.route} w panelu admina (ta wtyczka nie ma własnych tabel, migracje nie są potrzebne). Sprawdź, czy Panel, Przewodnik wdrożenia i Ustawienia otwierają się bez błędów w konsoli przeglądarki i w logu serwera.` : `6. Uruchom migracje bazy (${code("npx medusa db:migrate")}), potem sklep, i otwórz ${spec.route} w panelu admina. Sprawdź, czy Panel, Przewodnik wdrożenia i Ustawienia otwierają się bez błędów w konsoli przeglądarki i w logu serwera.`,
|
|
497
|
+
spec.readOnly ? `7. Ta integracja tylko czyta z ${service}: nie ma zapisów do uzbrajania. Użyj klucza tylko do odczytu, jeśli ${service} go oferuje.` : `7. Nie włączaj żadnego zapisu, czyli niczego, co zmienia dane w ${service} albo w sklepie. Każdy zapis uzbraja człowiek w Ustawieniach, po próbie na sucho; opcje tylko na to pozwalają.`,
|
|
498
|
+
`8. Zaproponuj sekcję o tej integracji do notatek projektu dla agentów AI (CLAUDE.md albo AGENTS.md, zależnie od tego, czego używa projekt; jeśli nie ma żadnego, zaproponuj CLAUDE.md) i pokaż mi jej treść, zanim ją zapiszesz: pakiet i jego wersja, gdzie są jego opcje w medusa-config.ts, zmienne środowiskowe, przełącznik demo, to, że zapisy uzbraja człowiek w Ustawieniach, że wdrożenie krok po kroku jest w panelu w Przewodniku wdrożenia, że pomoc jest na Discordzie (${KODA_DISCORD}) i że wtyczka zmienia się aktualizacją pakietu, nigdy edycją node_modules.`,
|
|
922
499
|
"",
|
|
923
500
|
"Na koniec napisz mi, co zmieniłeś i co zostało po mojej stronie: konta i klucze, pierwsze połączenie w Ustawieniach i uzbrojenie zapisów."
|
|
924
501
|
].join("\n");
|
|
@@ -936,16 +513,16 @@ ${spec.demo}`).map(code).join(", ");
|
|
|
936
513
|
"",
|
|
937
514
|
"## Steps",
|
|
938
515
|
"1. Before you change anything, check the project: Medusa 2.12 or newer (the plugin's admin pages and translations need it), the project's package manager and medusa-config.ts. If something blocks the install, stop and tell me what.",
|
|
939
|
-
`2. Install the plugin with the project's package manager, for example ${code(`npm install ${spec.pkg}`)}. If the registry cannot find it, stop and tell me: Koda Plus
|
|
516
|
+
`2. Install this version of the plugin with the project's package manager, for example ${code(`npm install ${pinned}`)}. Then check where the package comes from: ${code(`npm view ${spec.pkg} dist-tags.latest`)} and ${code("npm audit signatures")}. If the registry cannot find it or the signatures do not verify, stop and tell me: Koda Plus helps (${KODA_EMAIL}, Discord ${KODA_DISCORD}).`,
|
|
940
517
|
"3. Register the plugin in medusa-config.ts without touching what is already there. Use the setup from the Setup guide:",
|
|
941
518
|
"",
|
|
942
519
|
...config2,
|
|
943
520
|
"",
|
|
944
|
-
`4. Add the demo switch to the options, as the demo store has it: ${code(spec.demo)}.
|
|
521
|
+
`4. Add the demo switch to the options, as the demo store has it: ${code(spec.demo)}. Demo mode runs only when switched on: then the module works on sample data and never calls ${service}; without it and without keys it says "Not configured" and does nothing.`,
|
|
945
522
|
`5. Put the variables in .env and in the hosting's environment, never in code or in git: ${env}. If I did not give you a value, leave it empty and list it for me at the end.`,
|
|
946
|
-
`6. Run the database migrations (${code("npx medusa db:migrate")}), then the store, and open ${spec.route} in the admin. Check that the Panel, the Setup guide and Settings open with no errors in the browser console or the server log.`,
|
|
947
|
-
`7. Do not turn on any writer, that is anything that changes data in ${service} or in the store. A person arms each writer in Settings, after a dry run; the options only allow it.`,
|
|
948
|
-
`8.
|
|
523
|
+
spec.migrations === false ? `6. Start the store and open ${spec.route} in the admin (this plugin has no tables of its own, no migrations needed). Check that the Panel, the Setup guide and Settings open with no errors in the browser console or the server log.` : `6. Run the database migrations (${code("npx medusa db:migrate")}), then the store, and open ${spec.route} in the admin. Check that the Panel, the Setup guide and Settings open with no errors in the browser console or the server log.`,
|
|
524
|
+
spec.readOnly ? `7. This integration only reads from ${service}: there are no writers to arm. Use a read-only key if ${service} offers one.` : `7. Do not turn on any writer, that is anything that changes data in ${service} or in the store. A person arms each writer in Settings, after a dry run; the options only allow it.`,
|
|
525
|
+
`8. Propose a section about this integration for the project's notes for AI agents (CLAUDE.md or AGENTS.md, whichever the project uses; if neither exists, propose CLAUDE.md) and show me its text before you save it: the package and its version, where its options sit in medusa-config.ts, the environment variables, the demo switch, that a person arms writers in Settings, that the step by step setup is in the admin under Setup guide, that help is on Discord (${KODA_DISCORD}), and that the plugin changes through package updates, never through edits in node_modules.`,
|
|
949
526
|
"",
|
|
950
527
|
"When you are done, tell me what you changed and what is left for me: accounts and keys, the first connection in Settings and arming the writers."
|
|
951
528
|
].join("\n");
|
|
@@ -962,7 +539,7 @@ function PromptButton({ spec, lang, labels }) {
|
|
|
962
539
|
}
|
|
963
540
|
};
|
|
964
541
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
|
|
965
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", onClick: () =>
|
|
542
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", onClick: () => setState("idle"), children: [
|
|
966
543
|
/* @__PURE__ */ jsxRuntime.jsx(icons.Sparkles, {}),
|
|
967
544
|
labels.button
|
|
968
545
|
] }) }),
|
|
@@ -1046,56 +623,6 @@ function SettingsView({
|
|
|
1046
623
|
children
|
|
1047
624
|
] });
|
|
1048
625
|
}
|
|
1049
|
-
function References({ items, title, subtitle, openLabel, sinceLabel, reviewLabel, ratingLabel }) {
|
|
1050
|
-
if (items.length === 0) return null;
|
|
1051
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
1052
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1 px-6 py-4", children: [
|
|
1053
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: title }),
|
|
1054
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: subtitle })
|
|
1055
|
-
] }),
|
|
1056
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-3 px-6 py-4 md:grid-cols-2 xl:grid-cols-3", children: items.map((r) => {
|
|
1057
|
-
var _a;
|
|
1058
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 rounded-lg border border-ui-border-base bg-ui-bg-component px-4 py-3", children: [
|
|
1059
|
-
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: r.url, target: "_blank", rel: "noreferrer", className: "group flex items-center gap-x-3", children: [
|
|
1060
|
-
r.icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: r.icon, alt: "", width: 36, height: 36, className: "h-9 w-9 shrink-0 rounded-md bg-white object-contain shadow-borders-base" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-medium-plus flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-ui-bg-base text-ui-fg-base shadow-borders-base", children: r.name.slice(0, 1).toUpperCase() }),
|
|
1061
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
1062
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "truncate text-ui-fg-base", children: r.name }),
|
|
1063
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "truncate text-ui-fg-interactive group-hover:text-ui-fg-interactive-hover", children: host(r.url) })
|
|
1064
|
-
] }),
|
|
1065
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "ml-auto shrink-0 text-ui-fg-muted group-hover:text-ui-fg-interactive" })
|
|
1066
|
-
] }),
|
|
1067
|
-
r.review ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1068
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: r.review.rating, scale: r.review.scale }),
|
|
1069
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-xsmall-plus tabular-nums text-ui-fg-base", children: (ratingLabel ?? ((v) => v.toFixed(1)))(r.review.rating / (r.review.scale || 5) * 5) }),
|
|
1070
|
-
/* @__PURE__ */ jsxRuntime.jsx(SourceMark, { review: r.review }),
|
|
1071
|
-
r.review.url && reviewLabel ? /* @__PURE__ */ jsxRuntime.jsxs("a", { href: r.review.url, target: "_blank", rel: "noreferrer", className: "txt-compact-xsmall-plus inline-flex items-center gap-x-0.5 text-ui-fg-interactive hover:text-ui-fg-interactive-hover", children: [
|
|
1072
|
-
reviewLabel,
|
|
1073
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "h-3.5 w-3.5" })
|
|
1074
|
-
] }) : null
|
|
1075
|
-
] }) : null,
|
|
1076
|
-
r.description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: nb(r.description) }) : null,
|
|
1077
|
-
((_a = r.metrics) == null ? void 0 : _a.length) || r.since ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1078
|
-
(r.metrics ?? []).map((m) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Badge, { size: "2xsmall", color: "green", children: [
|
|
1079
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: m.value }),
|
|
1080
|
-
" ",
|
|
1081
|
-
m.label
|
|
1082
|
-
] }, m.label)),
|
|
1083
|
-
r.since ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "grey", children: sinceLabel(r.since) }) : null
|
|
1084
|
-
] }) : null,
|
|
1085
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto flex flex-col gap-y-1 border-t border-ui-border-base pt-2", children: [
|
|
1086
|
-
(r.links ?? []).map((l) => /* @__PURE__ */ jsxRuntime.jsxs("a", { href: l.url, target: "_blank", rel: "noreferrer", className: "txt-compact-small inline-flex w-fit items-center gap-x-1 text-ui-fg-interactive hover:text-ui-fg-interactive-hover", children: [
|
|
1087
|
-
l.label,
|
|
1088
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "shrink-0" })
|
|
1089
|
-
] }, l.url)),
|
|
1090
|
-
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: r.url, target: "_blank", rel: "noreferrer", className: "txt-compact-small-plus inline-flex w-fit items-center gap-x-1 text-ui-fg-interactive hover:text-ui-fg-interactive-hover", children: [
|
|
1091
|
-
openLabel,
|
|
1092
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, { className: "shrink-0" })
|
|
1093
|
-
] })
|
|
1094
|
-
] })
|
|
1095
|
-
] }, r.url);
|
|
1096
|
-
}) })
|
|
1097
|
-
] });
|
|
1098
|
-
}
|
|
1099
626
|
function GuideIntro({ title, text, time, needs, needsLabel, timeLabel }) {
|
|
1100
627
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
1101
628
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2 px-6 py-4", children: [
|
|
@@ -1261,6 +788,830 @@ function GuideFaq({ title, items }) {
|
|
|
1261
788
|
] }, it.q))
|
|
1262
789
|
] });
|
|
1263
790
|
}
|
|
791
|
+
const TEXT$1 = {
|
|
792
|
+
en: {
|
|
793
|
+
search: "Search",
|
|
794
|
+
empty: "Nothing here yet",
|
|
795
|
+
now: "Now",
|
|
796
|
+
next: "In a moment",
|
|
797
|
+
counted: "Done",
|
|
798
|
+
stopped: "Stopped",
|
|
799
|
+
queued: "Waiting for a free slot on the server",
|
|
800
|
+
ready: "Ready",
|
|
801
|
+
error: "Error",
|
|
802
|
+
pctDone: "done",
|
|
803
|
+
pctError: "error",
|
|
804
|
+
pctQueued: "queued",
|
|
805
|
+
pctRunning: "working",
|
|
806
|
+
running: (time) => `running ${time}`,
|
|
807
|
+
left: (time) => `about ${time} left`,
|
|
808
|
+
clean: "no errors",
|
|
809
|
+
of: "of",
|
|
810
|
+
waiting: "waiting",
|
|
811
|
+
log: "Log",
|
|
812
|
+
retry: "Try again"
|
|
813
|
+
},
|
|
814
|
+
pl: {
|
|
815
|
+
search: "Szukaj",
|
|
816
|
+
empty: "Na razie pusto",
|
|
817
|
+
now: "Teraz",
|
|
818
|
+
next: "Za chwilę",
|
|
819
|
+
counted: "Gotowe",
|
|
820
|
+
stopped: "Przerwane",
|
|
821
|
+
queued: "Czekam na wolne miejsce na serwerze",
|
|
822
|
+
ready: "Gotowe",
|
|
823
|
+
error: "Błąd",
|
|
824
|
+
pctDone: "gotowe",
|
|
825
|
+
pctError: "błąd",
|
|
826
|
+
pctQueued: "w kolejce",
|
|
827
|
+
pctRunning: "liczę",
|
|
828
|
+
running: (time) => `trwa ${time}`,
|
|
829
|
+
left: (time) => nb(`zostało ok. ${time}`),
|
|
830
|
+
clean: "bez błędów",
|
|
831
|
+
of: "z",
|
|
832
|
+
waiting: "czeka",
|
|
833
|
+
log: "Przebieg",
|
|
834
|
+
retry: "Spróbuj ponownie"
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
function useKitText() {
|
|
838
|
+
const { i18n } = reactI18next.useTranslation();
|
|
839
|
+
const pl2 = String((i18n == null ? void 0 : i18n.language) ?? "en").startsWith("pl");
|
|
840
|
+
return { text: pl2 ? TEXT$1.pl : TEXT$1.en, locale: pl2 ? "pl-PL" : "en-GB" };
|
|
841
|
+
}
|
|
842
|
+
const DOT = {
|
|
843
|
+
green: "bg-ui-tag-green-icon",
|
|
844
|
+
orange: "bg-ui-tag-orange-icon",
|
|
845
|
+
red: "bg-ui-tag-red-icon",
|
|
846
|
+
blue: "bg-ui-tag-blue-icon",
|
|
847
|
+
grey: "bg-ui-tag-neutral-icon",
|
|
848
|
+
purple: "bg-ui-tag-purple-icon"
|
|
849
|
+
};
|
|
850
|
+
const ICON = {
|
|
851
|
+
green: "text-ui-tag-green-icon",
|
|
852
|
+
orange: "text-ui-tag-orange-icon",
|
|
853
|
+
red: "text-ui-tag-red-icon",
|
|
854
|
+
blue: "text-ui-tag-blue-icon",
|
|
855
|
+
grey: "text-ui-fg-muted",
|
|
856
|
+
purple: "text-ui-tag-purple-icon"
|
|
857
|
+
};
|
|
858
|
+
function ToneBadge({ tone = "grey", children, icon, dot = false, title, size = "2xsmall" }) {
|
|
859
|
+
if (dot) {
|
|
860
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { title, className: "txt-compact-small inline-flex items-center gap-x-1.5 whitespace-nowrap text-ui-fg-subtle", children: [
|
|
861
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: ui.clx("size-1.5 shrink-0 rounded-full", DOT[tone]) }),
|
|
862
|
+
children
|
|
863
|
+
] });
|
|
864
|
+
}
|
|
865
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size, color: tone, title, className: "whitespace-nowrap", children: icon ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-x-1 [&_svg]:size-3 [&_svg]:shrink-0", children: [
|
|
866
|
+
icon,
|
|
867
|
+
children
|
|
868
|
+
] }) : children });
|
|
869
|
+
}
|
|
870
|
+
function FilterBar({ children, className }) {
|
|
871
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.clx("flex flex-wrap items-center gap-2 bg-ui-bg-subtle px-6 py-2.5", className), children });
|
|
872
|
+
}
|
|
873
|
+
function FilterButton({
|
|
874
|
+
icon,
|
|
875
|
+
label,
|
|
876
|
+
count,
|
|
877
|
+
active,
|
|
878
|
+
attention,
|
|
879
|
+
onClick,
|
|
880
|
+
title,
|
|
881
|
+
disabled
|
|
882
|
+
}) {
|
|
883
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: active ? "primary" : "secondary", "aria-pressed": active, onClick, title, disabled, className: "shrink-0 gap-x-1.5 whitespace-nowrap [&_svg]:size-4", children: [
|
|
884
|
+
icon,
|
|
885
|
+
label,
|
|
886
|
+
typeof count === "number" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
887
|
+
"span",
|
|
888
|
+
{
|
|
889
|
+
className: ui.clx(
|
|
890
|
+
"txt-compact-xsmall-plus rounded-full px-1.5 tabular-nums",
|
|
891
|
+
active ? "bg-white/20" : attention && count > 0 ? "bg-ui-tag-orange-bg text-ui-tag-orange-text" : "bg-ui-bg-component text-ui-fg-muted"
|
|
892
|
+
),
|
|
893
|
+
children: count
|
|
894
|
+
}
|
|
895
|
+
) : null
|
|
896
|
+
] });
|
|
897
|
+
}
|
|
898
|
+
function FilterDivider() {
|
|
899
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mx-1 h-4 w-px shrink-0 bg-ui-border-base" });
|
|
900
|
+
}
|
|
901
|
+
function useDebouncedValue(value, ms = 300) {
|
|
902
|
+
const [out, setOut] = react.useState(value);
|
|
903
|
+
react.useEffect(() => {
|
|
904
|
+
const t = setTimeout(() => setOut(value), ms);
|
|
905
|
+
return () => clearTimeout(t);
|
|
906
|
+
}, [value, ms]);
|
|
907
|
+
return out;
|
|
908
|
+
}
|
|
909
|
+
function SearchInput({ value, onChange, placeholder, className, autoFocus, label }) {
|
|
910
|
+
const { text } = useKitText();
|
|
911
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
912
|
+
ui.Input,
|
|
913
|
+
{
|
|
914
|
+
size: "small",
|
|
915
|
+
type: "search",
|
|
916
|
+
autoFocus,
|
|
917
|
+
"aria-label": label ?? placeholder ?? text.search,
|
|
918
|
+
placeholder: placeholder ?? text.search,
|
|
919
|
+
value,
|
|
920
|
+
onChange: (e) => onChange(e.target.value),
|
|
921
|
+
className: ui.clx("w-full sm:w-64", className)
|
|
922
|
+
}
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
function RowActions({ actions, className }) {
|
|
926
|
+
const shown = actions.filter((a) => !a.hidden);
|
|
927
|
+
if (!shown.length) return null;
|
|
928
|
+
const stop = (e) => e.stopPropagation();
|
|
929
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("inline-flex items-center justify-end gap-0.5", className), onClick: stop, children: shown.map((a) => {
|
|
930
|
+
const icon = a.loading ? /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, { className: "animate-spin" }) : a.icon;
|
|
931
|
+
const tone = a.danger ? "text-ui-tag-red-icon" : "text-ui-fg-subtle";
|
|
932
|
+
if (a.href && !a.disabled) {
|
|
933
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
934
|
+
"a",
|
|
935
|
+
{
|
|
936
|
+
href: a.href,
|
|
937
|
+
title: a.label,
|
|
938
|
+
"aria-label": a.label,
|
|
939
|
+
...a.external ? { target: "_blank", rel: "noreferrer" } : {},
|
|
940
|
+
className: ui.clx("inline-flex size-7 items-center justify-center rounded-md outline-none transition-fg hover:bg-ui-bg-base-hover focus-visible:shadow-borders-focus", tone),
|
|
941
|
+
children: icon
|
|
942
|
+
},
|
|
943
|
+
a.key
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "small", variant: "transparent", title: a.label, "aria-label": a.label, disabled: a.disabled || a.loading, onClick: () => {
|
|
947
|
+
var _a;
|
|
948
|
+
return (_a = a.onClick) == null ? void 0 : _a.call(a);
|
|
949
|
+
}, className: tone, children: icon }, a.key);
|
|
950
|
+
}) });
|
|
951
|
+
}
|
|
952
|
+
function EmptyState({ icon, title, points, action, compact = false, className }) {
|
|
953
|
+
const { text } = useKitText();
|
|
954
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.clx("flex flex-col items-center justify-center gap-y-2 px-6 text-center", compact ? "py-5" : "py-10", className), children: [
|
|
955
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-9 items-center justify-center rounded-lg border border-ui-border-base bg-ui-bg-component text-ui-fg-muted shadow-elevation-card-rest [&_svg]:size-5", children: icon }) : null,
|
|
956
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: title ?? text.empty }),
|
|
957
|
+
points ? /* @__PURE__ */ jsxRuntime.jsx(KeyPoints, { items: points, className: "max-w-full justify-center" }) : null,
|
|
958
|
+
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-1", children: action }) : null
|
|
959
|
+
] });
|
|
960
|
+
}
|
|
961
|
+
function EmptyTableRow({ cols, ...props }) {
|
|
962
|
+
return /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: cols, children: /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { compact: true, ...props }) }) });
|
|
963
|
+
}
|
|
964
|
+
function Section({
|
|
965
|
+
id,
|
|
966
|
+
icon,
|
|
967
|
+
title,
|
|
968
|
+
badges,
|
|
969
|
+
points,
|
|
970
|
+
pointsLabel,
|
|
971
|
+
description,
|
|
972
|
+
actions,
|
|
973
|
+
children,
|
|
974
|
+
className
|
|
975
|
+
}) {
|
|
976
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { id, className: ui.clx("scroll-mt-4 divide-y p-0", className), children: [
|
|
977
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3 px-6 py-4", children: [
|
|
978
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-y-1.5", children: [
|
|
979
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
980
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 text-ui-fg-subtle [&_svg]:size-[18px]", children: icon }) : null,
|
|
981
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: title }),
|
|
982
|
+
badges ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-1.5", children: badges }) : null
|
|
983
|
+
] }),
|
|
984
|
+
points ? /* @__PURE__ */ jsxRuntime.jsx(KeyPoints, { items: points, label: pointsLabel }) : null,
|
|
985
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-small min-w-0 text-ui-fg-subtle", children: description }) : null
|
|
986
|
+
] }),
|
|
987
|
+
actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", children: actions }) : null
|
|
988
|
+
] }),
|
|
989
|
+
children
|
|
990
|
+
] });
|
|
991
|
+
}
|
|
992
|
+
const GRID = {
|
|
993
|
+
2: "md:grid-cols-2",
|
|
994
|
+
3: "md:grid-cols-3",
|
|
995
|
+
4: "md:grid-cols-4",
|
|
996
|
+
5: "md:grid-cols-3 xl:grid-cols-5",
|
|
997
|
+
6: "md:grid-cols-3 xl:grid-cols-6",
|
|
998
|
+
7: "md:grid-cols-4 xl:grid-cols-7"
|
|
999
|
+
};
|
|
1000
|
+
function StatTiles({ children, columns = 4, className }) {
|
|
1001
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.clx("grid grid-cols-2 gap-3 px-6 py-4", GRID[columns], className), children });
|
|
1002
|
+
}
|
|
1003
|
+
function StatTile({
|
|
1004
|
+
label,
|
|
1005
|
+
value,
|
|
1006
|
+
hint,
|
|
1007
|
+
tone = "grey",
|
|
1008
|
+
icon,
|
|
1009
|
+
active = false,
|
|
1010
|
+
onClick,
|
|
1011
|
+
title
|
|
1012
|
+
}) {
|
|
1013
|
+
const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1014
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-x-2", children: [
|
|
1015
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("flex shrink-0 [&_svg]:size-3.5", ICON[tone]), children: icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: ui.clx("size-1.5 shrink-0 rounded-full", DOT[tone]) }),
|
|
1016
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "truncate text-ui-fg-subtle", children: label })
|
|
1017
|
+
] }),
|
|
1018
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-xlarge-plus max-w-full break-words tabular-nums text-ui-fg-base", children: value }),
|
|
1019
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: hint }) : null
|
|
1020
|
+
] });
|
|
1021
|
+
const cls = ui.clx(
|
|
1022
|
+
"flex h-full min-w-0 flex-col items-start gap-y-1 rounded-lg border px-4 py-3 text-left transition-fg",
|
|
1023
|
+
active ? "border-ui-border-interactive bg-ui-bg-base shadow-borders-interactive-with-active" : "border-ui-border-base bg-ui-bg-subtle"
|
|
1024
|
+
);
|
|
1025
|
+
return onClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-pressed": active, title, onClick, className: ui.clx(cls, !active && "hover:bg-ui-bg-base-hover"), children: body }) : /* @__PURE__ */ jsxRuntime.jsx("div", { title, className: cls, children: body });
|
|
1026
|
+
}
|
|
1027
|
+
function runFromSteps(steps, startedAt, log = []) {
|
|
1028
|
+
var _a;
|
|
1029
|
+
const all = Object.values(steps);
|
|
1030
|
+
const status = all.some((s) => s.status === "error") ? "error" : all.some((s) => s.status === "running") ? "running" : all.length && all.every((s) => s.status === "done") ? "done" : all.some((s) => s.status === "done") ? "running" : "queued";
|
|
1031
|
+
return {
|
|
1032
|
+
status,
|
|
1033
|
+
started_at: new Date(startedAt).toISOString(),
|
|
1034
|
+
finished_at: status === "done" || status === "error" ? (/* @__PURE__ */ new Date()).toISOString() : null,
|
|
1035
|
+
steps,
|
|
1036
|
+
log,
|
|
1037
|
+
error: ((_a = all.find((s) => s.status === "error")) == null ? void 0 : _a.note) ?? null
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
function formatDuration(ms) {
|
|
1041
|
+
const s = Math.max(0, Math.round(ms / 1e3));
|
|
1042
|
+
return s >= 60 ? `${Math.floor(s / 60)} min ${String(s % 60).padStart(2, "0")} s` : `${s} s`;
|
|
1043
|
+
}
|
|
1044
|
+
const GRID_STAGES = {
|
|
1045
|
+
3: "grid-cols-3",
|
|
1046
|
+
4: "grid-cols-2 sm:grid-cols-4",
|
|
1047
|
+
5: "grid-cols-3 lg:grid-cols-5",
|
|
1048
|
+
6: "grid-cols-3 lg:grid-cols-6"
|
|
1049
|
+
};
|
|
1050
|
+
function StagedLoader({ run, stages, doneTitle, columns = 6, onRetry }) {
|
|
1051
|
+
const { text, locale } = useKitText();
|
|
1052
|
+
const [openLog, setOpenLog] = react.useState(false);
|
|
1053
|
+
const [now, setNow] = react.useState(Date.now());
|
|
1054
|
+
const live = run.status === "running" || run.status === "queued";
|
|
1055
|
+
react.useEffect(() => {
|
|
1056
|
+
if (!live) return;
|
|
1057
|
+
const t = setInterval(() => setNow(Date.now()), 500);
|
|
1058
|
+
return () => clearInterval(t);
|
|
1059
|
+
}, [live]);
|
|
1060
|
+
const share = (key) => {
|
|
1061
|
+
const s = run.steps[key] ?? { status: "queued" };
|
|
1062
|
+
if (s.status === "done" || s.status === "error") return 1;
|
|
1063
|
+
if (s.status === "running") return s.total ? Math.min(1, (s.done ?? 0) / s.total) : 0.3;
|
|
1064
|
+
return 0;
|
|
1065
|
+
};
|
|
1066
|
+
const weights = stages.reduce((sum, e) => sum + e.weight, 0) || 1;
|
|
1067
|
+
const pct = Math.round(stages.reduce((sum, e) => sum + e.weight * share(e.key), 0) / weights * 100);
|
|
1068
|
+
const start = new Date(run.started_at).getTime();
|
|
1069
|
+
const end = run.finished_at ? new Date(run.finished_at).getTime() : now;
|
|
1070
|
+
const elapsed = Math.max(0, end - start);
|
|
1071
|
+
const left = run.status === "running" && pct >= 5 && pct < 100 ? elapsed * (100 - pct) / pct : null;
|
|
1072
|
+
const current = stages.find((e) => {
|
|
1073
|
+
var _a;
|
|
1074
|
+
return ((_a = run.steps[e.key]) == null ? void 0 : _a.status) === "running";
|
|
1075
|
+
});
|
|
1076
|
+
const cs = current ? run.steps[current.key] : null;
|
|
1077
|
+
const log = run.log ?? [];
|
|
1078
|
+
const number = (n) => new Intl.NumberFormat(locale).format(n);
|
|
1079
|
+
const R = 46;
|
|
1080
|
+
const C = 2 * Math.PI * R;
|
|
1081
|
+
const ring = run.status === "error" ? "var(--tag-red-icon)" : run.status === "done" ? "var(--tag-green-icon)" : "var(--fg-interactive)";
|
|
1082
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "status", "aria-live": "polite", className: "flex flex-col gap-y-4 px-6 py-5", children: [
|
|
1083
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-6 rounded-xl border border-ui-border-base bg-ui-bg-subtle p-5 sm:flex-row", children: [
|
|
1084
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative size-32 shrink-0", children: [
|
|
1085
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 110 110", className: "size-32 -rotate-90", "aria-hidden": true, children: [
|
|
1086
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "55", cy: "55", r: R, fill: "none", stroke: "var(--border-base)", strokeWidth: "9" }),
|
|
1087
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "55", cy: "55", r: R, fill: "none", stroke: ring, strokeWidth: "9", strokeLinecap: "round", strokeDasharray: C, strokeDashoffset: C * (1 - pct / 100), style: { transition: "stroke-dashoffset .6s ease" } })
|
|
1088
|
+
] }),
|
|
1089
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: [
|
|
1090
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "txt-xlarge-plus tabular-nums text-ui-fg-base", children: [
|
|
1091
|
+
pct,
|
|
1092
|
+
"%"
|
|
1093
|
+
] }),
|
|
1094
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-xsmall text-ui-fg-muted", children: run.status === "done" ? text.pctDone : run.status === "error" ? text.pctError : run.status === "queued" ? text.pctQueued : text.pctRunning })
|
|
1095
|
+
] })
|
|
1096
|
+
] }),
|
|
1097
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-y-2", children: [
|
|
1098
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", weight: "plus", className: "uppercase tracking-wide text-ui-fg-muted", children: run.status === "running" ? text.now : run.status === "queued" ? text.next : run.status === "done" ? text.counted : text.stopped }),
|
|
1099
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2 [&_svg]:size-5", children: [
|
|
1100
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("flex shrink-0", run.status === "error" ? "text-ui-tag-red-icon" : run.status === "done" ? "text-ui-tag-green-icon" : "text-ui-fg-interactive"), children: current ? current.icon : run.status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(icons.XCircleSolid, {}) : run.status === "queued" ? /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircleSolid, {}) }),
|
|
1101
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "large", weight: "plus", className: "truncate", children: current ? current.name : run.status === "done" ? doneTitle ?? text.ready : run.status === "queued" ? text.queued : run.error ?? text.error })
|
|
1102
|
+
] }),
|
|
1103
|
+
(cs == null ? void 0 : cs.total) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1104
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 overflow-hidden rounded-full bg-ui-bg-component", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full rounded-full bg-ui-fg-interactive transition-all", style: { width: `${Math.min(100, Math.round((cs.done ?? 0) / cs.total * 100))}%` } }) }),
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "tabular-nums text-ui-fg-subtle", children: [
|
|
1106
|
+
number(cs.done ?? 0),
|
|
1107
|
+
" ",
|
|
1108
|
+
text.of,
|
|
1109
|
+
" ",
|
|
1110
|
+
number(cs.total),
|
|
1111
|
+
cs.note ? `, ${cs.note}` : ""
|
|
1112
|
+
] })
|
|
1113
|
+
] }) : (cs == null ? void 0 : cs.note) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: cs.note }) : null,
|
|
1114
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1115
|
+
KeyPoints,
|
|
1116
|
+
{
|
|
1117
|
+
items: [
|
|
1118
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), text: text.running(formatDuration(elapsed)) },
|
|
1119
|
+
left !== null && { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Sparkles, {}), text: text.left(formatDuration(left)), tone: "blue" },
|
|
1120
|
+
run.status === "done" && { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircleSolid, {}), text: text.clean, tone: "green" }
|
|
1121
|
+
]
|
|
1122
|
+
}
|
|
1123
|
+
)
|
|
1124
|
+
] })
|
|
1125
|
+
] }),
|
|
1126
|
+
/* @__PURE__ */ jsxRuntime.jsx("ol", { className: ui.clx("grid gap-2", GRID_STAGES[columns]), children: stages.map((e) => {
|
|
1127
|
+
const s = run.steps[e.key] ?? { status: "queued" };
|
|
1128
|
+
const p = s.total ? Math.min(100, Math.round((s.done ?? 0) / s.total * 100)) : s.status === "done" ? 100 : 0;
|
|
1129
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1130
|
+
"li",
|
|
1131
|
+
{
|
|
1132
|
+
className: ui.clx(
|
|
1133
|
+
"relative flex min-w-0 flex-col gap-1 overflow-hidden rounded-lg border px-3 py-2.5",
|
|
1134
|
+
s.status === "running" ? "border-ui-border-interactive bg-ui-bg-highlight shadow-borders-interactive-with-active" : s.status === "done" ? "border-ui-tag-green-border bg-ui-tag-green-bg" : s.status === "error" ? "border-ui-tag-red-border bg-ui-tag-red-bg" : "border-ui-border-base bg-ui-bg-base opacity-70"
|
|
1135
|
+
),
|
|
1136
|
+
children: [
|
|
1137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-between gap-1", children: [
|
|
1138
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("flex [&_svg]:size-4", s.status === "running" ? "text-ui-fg-interactive" : s.status === "done" ? "text-ui-tag-green-icon" : s.status === "error" ? "text-ui-tag-red-icon" : "text-ui-fg-muted"), children: e.icon }),
|
|
1139
|
+
s.status === "done" ? /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircleSolid, { className: "size-4 text-ui-tag-green-icon" }) : s.status === "running" ? /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, { className: "size-4 animate-spin text-ui-fg-interactive" }) : s.status === "error" ? /* @__PURE__ */ jsxRuntime.jsx(icons.XCircleSolid, { className: "size-4 text-ui-tag-red-icon" }) : null
|
|
1140
|
+
] }),
|
|
1141
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", weight: "plus", className: "truncate", children: e.short }),
|
|
1142
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "truncate tabular-nums text-ui-fg-subtle", children: s.total ? `${number(s.done ?? 0)} / ${number(s.total)}` : s.done !== void 0 ? number(s.done) : s.status === "queued" ? text.waiting : s.note ?? "" }),
|
|
1143
|
+
s.status === "running" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-x-0 bottom-0 h-0.5 bg-ui-fg-interactive transition-all", style: { width: `${p}%` } }) : null
|
|
1144
|
+
]
|
|
1145
|
+
},
|
|
1146
|
+
e.key
|
|
1147
|
+
);
|
|
1148
|
+
}) }),
|
|
1149
|
+
log.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base", children: [
|
|
1150
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", "aria-expanded": openLog, onClick: () => setOpenLog((v) => !v), className: "flex w-full items-center justify-between rounded-lg px-3 py-2 text-left hover:bg-ui-bg-base-hover", children: [
|
|
1151
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", weight: "plus", className: "uppercase tracking-wide text-ui-fg-muted", children: [
|
|
1152
|
+
text.log,
|
|
1153
|
+
" (",
|
|
1154
|
+
log.length,
|
|
1155
|
+
")"
|
|
1156
|
+
] }),
|
|
1157
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.TriangleRightMini, { className: ui.clx("text-ui-fg-muted transition-transform", openLog && "rotate-90") })
|
|
1158
|
+
] }),
|
|
1159
|
+
openLog ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-compact-xsmall flex max-h-56 flex-col gap-y-0.5 overflow-y-auto rounded-b-lg border-t border-ui-border-base bg-ui-bg-subtle px-3 py-2 font-mono text-ui-fg-subtle", children: log.map((l, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1160
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: new Date(l.at).toLocaleTimeString(locale) }),
|
|
1161
|
+
" ",
|
|
1162
|
+
l.text
|
|
1163
|
+
] }, i)) }) : null
|
|
1164
|
+
] }) : null,
|
|
1165
|
+
run.status === "error" && (run.error || onRetry) ? /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "error", label: text.error, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
1166
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: run.error }),
|
|
1167
|
+
onRetry ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", onClick: onRetry, children: [
|
|
1168
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
1169
|
+
text.retry
|
|
1170
|
+
] }) : null
|
|
1171
|
+
] }) }) : null
|
|
1172
|
+
] });
|
|
1173
|
+
}
|
|
1174
|
+
const TILE = '<rect width="192" height="192" rx="40" fill="#FFFFFF"/><rect x="0.75" y="0.75" width="190.5" height="190.5" rx="39.25" fill="none" stroke="#000000" stroke-opacity="0.1" stroke-width="1.5"/><image href="data:image/png;base64,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" x="24.00" y="77.25" width="144" height="37.49"/>';
|
|
1175
|
+
function SubiektIcon({ width = 15, height = 15, ...props }) {
|
|
1176
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1177
|
+
"svg",
|
|
1178
|
+
{
|
|
1179
|
+
width,
|
|
1180
|
+
height,
|
|
1181
|
+
viewBox: "0 0 192 192",
|
|
1182
|
+
fill: "none",
|
|
1183
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1184
|
+
"aria-hidden": "true",
|
|
1185
|
+
...props,
|
|
1186
|
+
dangerouslySetInnerHTML: { __html: TILE }
|
|
1187
|
+
}
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
function fmtDateTime(value, lang) {
|
|
1191
|
+
if (!value) return "";
|
|
1192
|
+
const d = new Date(value);
|
|
1193
|
+
if (!Number.isFinite(d.getTime())) return "";
|
|
1194
|
+
try {
|
|
1195
|
+
return new Intl.DateTimeFormat(lang, { dateStyle: "medium", timeStyle: "short" }).format(d);
|
|
1196
|
+
} catch {
|
|
1197
|
+
return d.toISOString().slice(0, 16).replace("T", " ");
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
function fmtDuration(ms) {
|
|
1201
|
+
if (!Number.isFinite(ms) || ms <= 0) return "0 s";
|
|
1202
|
+
return ms < 1e4 ? `${(ms / 1e3).toFixed(1)} s` : `${Math.round(ms / 1e3)} s`;
|
|
1203
|
+
}
|
|
1204
|
+
function fmtNumber(value, lang) {
|
|
1205
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
1206
|
+
if (!Number.isFinite(n)) return "0";
|
|
1207
|
+
try {
|
|
1208
|
+
return new Intl.NumberFormat(lang).format(n);
|
|
1209
|
+
} catch {
|
|
1210
|
+
return String(n);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
const TASK_TONE = {
|
|
1214
|
+
waiting: "grey",
|
|
1215
|
+
pending: "blue",
|
|
1216
|
+
running: "blue",
|
|
1217
|
+
unknown: "orange",
|
|
1218
|
+
succeeded: "green",
|
|
1219
|
+
failed: "red",
|
|
1220
|
+
canceled: "grey"
|
|
1221
|
+
};
|
|
1222
|
+
function taskTone(status) {
|
|
1223
|
+
return TASK_TONE[status] ?? "grey";
|
|
1224
|
+
}
|
|
1225
|
+
function TaskStatusBadge({ status, dot = false }) {
|
|
1226
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1227
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: taskTone(status), dot, children: t(`tasks.statuses.${status}`) });
|
|
1228
|
+
}
|
|
1229
|
+
const RUN_TONE = { success: "green", partial: "orange", error: "red", skipped: "grey" };
|
|
1230
|
+
function RunStatusBadge({ status, dot = false }) {
|
|
1231
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1232
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: RUN_TONE[status] ?? "grey", dot, children: t(`runs.statuses.${status}`) });
|
|
1233
|
+
}
|
|
1234
|
+
function DocumentStatusBadge({ status, dot = false }) {
|
|
1235
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1236
|
+
const tone = status === "canceled" ? "grey" : status === "completed" ? "green" : "blue";
|
|
1237
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone, dot, children: t(`documents.statuses.${status}`, { defaultValue: status }) });
|
|
1238
|
+
}
|
|
1239
|
+
const CATALOG_TONE = {
|
|
1240
|
+
planned: "blue",
|
|
1241
|
+
applied: "green",
|
|
1242
|
+
simulated: "blue",
|
|
1243
|
+
over_cap: "grey",
|
|
1244
|
+
stale: "orange",
|
|
1245
|
+
failed: "red",
|
|
1246
|
+
quarantined: "red",
|
|
1247
|
+
skipped: "grey"
|
|
1248
|
+
};
|
|
1249
|
+
function CatalogStatusBadge({ status, dot = false }) {
|
|
1250
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1251
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: CATALOG_TONE[status] ?? "grey", dot, children: t(`products.statuses.${status}`, { defaultValue: status }) });
|
|
1252
|
+
}
|
|
1253
|
+
function SampleList({ label, items }) {
|
|
1254
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
1255
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: label }),
|
|
1256
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: item }) }, item)) })
|
|
1257
|
+
] });
|
|
1258
|
+
}
|
|
1259
|
+
function RichText({ text }) {
|
|
1260
|
+
const parts = text.split("`");
|
|
1261
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts.map(
|
|
1262
|
+
(part, i) => i % 2 === 1 ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "txt-compact-xsmall rounded border border-ui-border-base bg-ui-bg-subtle px-1 font-mono text-ui-fg-base", children: part }, i) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: part }, i)
|
|
1263
|
+
) });
|
|
1264
|
+
}
|
|
1265
|
+
function connectionState(s) {
|
|
1266
|
+
var _a;
|
|
1267
|
+
if (!s) return { key: "unknown", tone: "grey" };
|
|
1268
|
+
if (s.mode === "demo") return { key: "demo", tone: "blue" };
|
|
1269
|
+
if (!s.configured) return { key: "notConfigured", tone: "orange" };
|
|
1270
|
+
if (!s.connection.checkedAt && !s.connection.lastErrorAt) return { key: "unknown", tone: "grey" };
|
|
1271
|
+
if (!s.connection.reachable) return { key: "unreachable", tone: "red" };
|
|
1272
|
+
if (s.connection.health && !((_a = s.connection.health.subiekt) == null ? void 0 : _a.connected)) return { key: "subiektDown", tone: "orange" };
|
|
1273
|
+
return { key: "connected", tone: "green" };
|
|
1274
|
+
}
|
|
1275
|
+
function ConnectionBadge({ status }) {
|
|
1276
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1277
|
+
const state = connectionState(status);
|
|
1278
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: state.tone, children: t(`mode.${state.key}`) });
|
|
1279
|
+
}
|
|
1280
|
+
function Field({ label, children }) {
|
|
1281
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(120px,1fr)_2fr] items-start gap-x-4 px-6 py-2", children: [
|
|
1282
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: label }),
|
|
1283
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-compact-small text-ui-fg-base min-w-0 break-words", children })
|
|
1284
|
+
] });
|
|
1285
|
+
}
|
|
1286
|
+
function Pager({ offset, limit, count, onChange }) {
|
|
1287
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1288
|
+
if (count <= limit) return null;
|
|
1289
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-3", children: [
|
|
1290
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle tabular-nums", children: t("tasks.page", { from: offset + 1, to: Math.min(offset + limit, count), count }) }),
|
|
1291
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-x-2", children: [
|
|
1292
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", disabled: offset === 0, onClick: () => onChange(Math.max(0, offset - limit)), children: t("tasks.prev") }),
|
|
1293
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", disabled: offset + limit >= count, onClick: () => onChange(offset + limit), children: t("tasks.next") })
|
|
1294
|
+
] })
|
|
1295
|
+
] });
|
|
1296
|
+
}
|
|
1297
|
+
const num$1 = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
1298
|
+
function runSummary(run, t) {
|
|
1299
|
+
const s = run.stats ?? {};
|
|
1300
|
+
if (run.status === "error" || run.status === "skipped" || !run.stats) return run.message ?? "";
|
|
1301
|
+
if (run.kind === "stock") {
|
|
1302
|
+
const changes = num$1(s.toUpdate) + num$1(s.toCreate);
|
|
1303
|
+
return t(run.dryRun ? "runs.summary.stockDry" : "runs.summary.stock", { changes, unchanged: num$1(s.unchanged) });
|
|
1304
|
+
}
|
|
1305
|
+
if (run.kind === "tasks") {
|
|
1306
|
+
const vars = { succeeded: num$1(s.succeeded), retry: num$1(s.retry), failed: num$1(s.failed) };
|
|
1307
|
+
return t(vars.retry || vars.failed ? "runs.summary.tasksIssues" : "runs.summary.tasks", vars);
|
|
1308
|
+
}
|
|
1309
|
+
if (run.kind === "events") return num$1(s.read) > 0 ? t("runs.summary.events", { applied: num$1(s.applied) }) : t("runs.summary.eventsNone");
|
|
1310
|
+
if (run.kind === "health" && run.status === "success") return t("runs.summary.health");
|
|
1311
|
+
if (run.kind === "products") {
|
|
1312
|
+
const applied = num$1(s.applied) + num$1(s.simulated);
|
|
1313
|
+
return t(run.dryRun ? "runs.summary.productsPlan" : "runs.summary.productsApplied", {
|
|
1314
|
+
prices: num$1(s.priceChanges),
|
|
1315
|
+
creates: num$1(s.toCreate),
|
|
1316
|
+
applied,
|
|
1317
|
+
failed: num$1(s.failed)
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
if (run.kind === "catchup") {
|
|
1321
|
+
const vars = { queued: num$1(s.queued) + num$1(s.waiting), released: num$1(s.released), errors: num$1(s.errors) };
|
|
1322
|
+
return t(vars.errors ? "runs.summary.catchupErrors" : "runs.summary.catchup", vars);
|
|
1323
|
+
}
|
|
1324
|
+
return run.message ?? "";
|
|
1325
|
+
}
|
|
1326
|
+
function fmtMoney(value, currency, lang) {
|
|
1327
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return "-";
|
|
1328
|
+
try {
|
|
1329
|
+
return new Intl.NumberFormat(lang, { style: "currency", currency: currency.toUpperCase() }).format(value);
|
|
1330
|
+
} catch {
|
|
1331
|
+
return `${value.toFixed(2)} ${currency.toUpperCase()}`;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
function fmtMs(ms) {
|
|
1335
|
+
if (typeof ms !== "number" || !Number.isFinite(ms)) return "-";
|
|
1336
|
+
const abs = Math.abs(ms);
|
|
1337
|
+
return abs < 1e3 ? `${Math.round(ms)} ms` : `${(ms / 1e3).toFixed(abs < 1e4 ? 1 : 0)} s`;
|
|
1338
|
+
}
|
|
1339
|
+
function MedusaMark({ className }) {
|
|
1340
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 36 38", fill: "none", "aria-hidden": true, className, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1341
|
+
"path",
|
|
1342
|
+
{
|
|
1343
|
+
d: "M30.85 6.16832L22.2453 1.21782C19.4299 -0.405941 15.9801 -0.405941 13.1648 1.21782L4.52043 6.16832C1.74473 7.79208 0 10.802 0 14.0099V23.9505C0 27.198 1.74473 30.1683 4.52043 31.7921L13.1251 36.7822C15.9405 38.4059 19.3903 38.4059 22.2056 36.7822L30.8103 31.7921C33.6257 30.1683 35.3307 27.198 35.3307 23.9505V14.0099C35.41 10.802 33.6653 7.79208 30.85 6.16832ZM17.6852 27.8317C12.8079 27.8317 8.8426 23.8713 8.8426 19C8.8426 14.1287 12.8079 10.1683 17.6852 10.1683C22.5625 10.1683 26.5674 14.1287 26.5674 19C26.5674 23.8713 22.6022 27.8317 17.6852 27.8317Z",
|
|
1344
|
+
fill: "currentColor"
|
|
1345
|
+
}
|
|
1346
|
+
) });
|
|
1347
|
+
}
|
|
1348
|
+
function StoreColumn({ label, hint }) {
|
|
1349
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-x-1.5", title: hint, children: [
|
|
1350
|
+
/* @__PURE__ */ jsxRuntime.jsx(MedusaMark, { className: "h-3.5 w-3.5 text-ui-fg-muted" }),
|
|
1351
|
+
label
|
|
1352
|
+
] });
|
|
1353
|
+
}
|
|
1354
|
+
function StoreLink({ to, title, mono, monoTitle, action }) {
|
|
1355
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Link, { to, className: "group flex items-center gap-x-2.5", title: action, children: [
|
|
1356
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-ui-bg-component shadow-borders-base transition-fg group-hover:bg-ui-bg-component-hover", children: /* @__PURE__ */ jsxRuntime.jsx(MedusaMark, { className: "h-4 w-4 text-ui-fg-base" }) }),
|
|
1357
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
1358
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-small-plus truncate text-ui-fg-base group-hover:text-ui-fg-interactive", children: title }),
|
|
1359
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-x-1.5", children: [
|
|
1360
|
+
mono ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-ui-fg-muted txt-compact-xsmall", title: monoTitle, children: mono }) : null,
|
|
1361
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "txt-compact-xsmall-plus inline-flex shrink-0 items-center gap-x-0.5 text-ui-fg-interactive", children: [
|
|
1362
|
+
action,
|
|
1363
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightMini, {})
|
|
1364
|
+
] })
|
|
1365
|
+
] })
|
|
1366
|
+
] })
|
|
1367
|
+
] });
|
|
1368
|
+
}
|
|
1369
|
+
function StoreUnlinked({ label, hint, mono }) {
|
|
1370
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-y-1", title: hint, children: [
|
|
1371
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "orange", children: label }),
|
|
1372
|
+
mono ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-ui-fg-muted txt-compact-xsmall", children: mono }) : null
|
|
1373
|
+
] });
|
|
1374
|
+
}
|
|
1375
|
+
function StoreOrderCell({ orderId, displayId }) {
|
|
1376
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1377
|
+
if (!orderId) return /* @__PURE__ */ jsxRuntime.jsx(StoreUnlinked, { label: t("store.noOrder"), hint: t("store.noOrderHint") });
|
|
1378
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1379
|
+
StoreLink,
|
|
1380
|
+
{
|
|
1381
|
+
to: `/orders/${orderId}`,
|
|
1382
|
+
title: displayId ? `#${displayId}` : orderId,
|
|
1383
|
+
mono: displayId ? orderId : null,
|
|
1384
|
+
monoTitle: orderId,
|
|
1385
|
+
action: t("store.openOrder")
|
|
1386
|
+
}
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1389
|
+
const BUSY = /* @__PURE__ */ new Set(["pending", "running", "unknown"]);
|
|
1390
|
+
function taskRun(task, hasDocument) {
|
|
1391
|
+
const s = task.status;
|
|
1392
|
+
const queue = s === "pending" && task.attempts === 0 ? { status: "running" } : { status: "done" };
|
|
1393
|
+
const bridge = s === "pending" && task.attempts === 0 ? { status: "queued" } : s === "failed" ? { status: "error", note: task.lastError ?? void 0 } : s === "succeeded" ? { status: "done" } : { status: "running", note: task.lastError ?? void 0 };
|
|
1394
|
+
const document2 = s === "succeeded" ? hasDocument ? { status: "done" } : { status: "running" } : { status: "queued" };
|
|
1395
|
+
return runFromSteps({ queue, bridge, document: document2 }, task.updatedAt ?? task.createdAt ?? Date.now());
|
|
1396
|
+
}
|
|
1397
|
+
function DocumentLine({ d, lang }) {
|
|
1398
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1399
|
+
const meta = [
|
|
1400
|
+
fmtDateTime(d.issuedAt, lang),
|
|
1401
|
+
t(`documents.sources.${d.source}`, { defaultValue: d.source }),
|
|
1402
|
+
d.warehouse ? t("widget.warehouse", { warehouse: d.warehouse }) : null
|
|
1403
|
+
].filter(Boolean);
|
|
1404
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-x-2", children: [
|
|
1405
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
1406
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t(`widget.kinds.${d.kind}`, { defaultValue: d.kind }) }),
|
|
1407
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "break-all font-mono", children: d.number }),
|
|
1408
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: meta.join(", ") }),
|
|
1409
|
+
d.related.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t("widget.related", { numbers: d.related.map((r) => r.number).join(", ") }) }) : null,
|
|
1410
|
+
d.kind === "ZK" && d.status === "completed" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t("widget.zkCompleted") }) : null,
|
|
1411
|
+
d.kind === "FS" && d.status !== "canceled" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: d.ksefNumber ? "break-all font-mono text-ui-fg-subtle" : "text-ui-fg-muted", children: d.ksefNumber ? t("widget.ksef", { number: d.ksefNumber }) : t("widget.ksefWaiting") }) : null
|
|
1412
|
+
] }),
|
|
1413
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocumentStatusBadge, { status: d.status })
|
|
1414
|
+
] });
|
|
1415
|
+
}
|
|
1416
|
+
const ENTRY_TONE = { missing: "orange", status_differs: "orange", same: "green", only_local: "grey" };
|
|
1417
|
+
function CheckResult({
|
|
1418
|
+
result,
|
|
1419
|
+
lang,
|
|
1420
|
+
linking,
|
|
1421
|
+
onLink
|
|
1422
|
+
}) {
|
|
1423
|
+
const { t } = reactI18next.useTranslation("subiekt");
|
|
1424
|
+
const status = (v) => t(`documents.statuses.${v ?? "open"}`, { defaultValue: v ?? "" });
|
|
1425
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: [
|
|
1426
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-2", children: [
|
|
1427
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: t("widget.check.title") }),
|
|
1428
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t("widget.check.at", { time: fmtDateTime(result.checkedAt, lang) }) })
|
|
1429
|
+
] }),
|
|
1430
|
+
result.entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t("widget.check.nothing") }) : result.entries.map((e) => {
|
|
1431
|
+
const key = `${e.kind}|${e.number}`;
|
|
1432
|
+
const where = e.state === "only_local" ? t("widget.check.notReported") : [t("widget.check.inSubiekt", { status: status(e.remoteStatus) }), e.issuedAt ? fmtDateTime(e.issuedAt, lang) : null].filter(Boolean).join(", ");
|
|
1433
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
1434
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-x-2", children: [
|
|
1435
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
1436
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "break-all font-mono", children: e.number }),
|
|
1437
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: where })
|
|
1438
|
+
] }),
|
|
1439
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: ENTRY_TONE[e.state], children: e.state === "status_differs" ? t("widget.check.states.status_differs", { status: status(e.localStatus) }) : t(`widget.check.states.${e.state}`) })
|
|
1440
|
+
] }),
|
|
1441
|
+
e.kind === "ZK" && e.remoteStatus === "completed" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t("widget.zkCompleted") }) : null,
|
|
1442
|
+
e.remoteStatus === "canceled" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t("widget.check.canceledThere") }) : null,
|
|
1443
|
+
e.state === "missing" || e.state === "status_differs" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
1444
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: linking === key, onClick: () => onLink(e), children: [
|
|
1445
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Link, {}),
|
|
1446
|
+
e.state === "missing" ? t("widget.check.link") : t("widget.check.update")
|
|
1447
|
+
] }) }),
|
|
1448
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: e.state === "missing" ? t("widget.check.linkHint") : t("widget.check.updateHint") })
|
|
1449
|
+
] }) : null
|
|
1450
|
+
] }, key);
|
|
1451
|
+
})
|
|
1452
|
+
] });
|
|
1453
|
+
}
|
|
1454
|
+
const SubiektOrderWidget = ({ data }) => {
|
|
1455
|
+
var _a, _b, _c, _d;
|
|
1456
|
+
const { t, i18n } = reactI18next.useTranslation("subiekt");
|
|
1457
|
+
const lang = i18n.language || "en";
|
|
1458
|
+
const q = useSubiektOrder(data.id);
|
|
1459
|
+
const send = useSubiektSendOrder(data.id);
|
|
1460
|
+
const issue = useSubiektIssueDocument(data.id);
|
|
1461
|
+
const retry = useSubiektRetry();
|
|
1462
|
+
const check = useSubiektOrderCheck(data.id);
|
|
1463
|
+
const link = useSubiektLinkDocument(data.id);
|
|
1464
|
+
const [checked, setChecked] = react.useState(null);
|
|
1465
|
+
const documents = ((_a = q.data) == null ? void 0 : _a.documents) ?? [];
|
|
1466
|
+
const tasks = ((_b = q.data) == null ? void 0 : _b.tasks) ?? [];
|
|
1467
|
+
const sales = (_c = q.data) == null ? void 0 : _c.salesDocument;
|
|
1468
|
+
const create = tasks.find((task) => task.kind === "order.create");
|
|
1469
|
+
const documentTask = tasks.find((task) => task.kind === "order.document");
|
|
1470
|
+
const hasZk = documents.some((d) => d.kind === "ZK" && d.status !== "canceled");
|
|
1471
|
+
const hasSales = documents.some((d) => (d.kind === "FS" || d.kind === "PA") && d.status !== "canceled");
|
|
1472
|
+
const busy = (create == null ? void 0 : create.status) === "pending" || (create == null ? void 0 : create.status) === "running";
|
|
1473
|
+
const documentBusy = documentTask ? BUSY.has(documentTask.status) : false;
|
|
1474
|
+
const canceled = data.status === "canceled";
|
|
1475
|
+
const offerIssue = Boolean(sales && sales.option !== "none" && sales.supported && hasZk && !hasSales && !documentBusy && !canceled);
|
|
1476
|
+
const inFlight = tasks.find((task) => (task.kind === "order.create" || task.kind === "order.document") && BUSY.has(task.status));
|
|
1477
|
+
const failed = tasks.some((task) => task.status === "failed");
|
|
1478
|
+
const state = failed ? { tone: "red", key: "attention" } : inFlight ? { tone: "blue", key: "sending" } : hasZk ? { tone: "green", key: "inSubiekt" } : (create == null ? void 0 : create.status) === "waiting" ? { tone: "grey", key: "waiting" } : { tone: "grey", key: "notSent" };
|
|
1479
|
+
const onSend = async () => {
|
|
1480
|
+
try {
|
|
1481
|
+
await send.mutateAsync();
|
|
1482
|
+
ui.toast.success(t("widget.sent"));
|
|
1483
|
+
} catch (err) {
|
|
1484
|
+
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
const onIssue = async (kind) => {
|
|
1488
|
+
try {
|
|
1489
|
+
await issue.mutateAsync(kind);
|
|
1490
|
+
ui.toast.success(t("widget.issued"));
|
|
1491
|
+
} catch (err) {
|
|
1492
|
+
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
1493
|
+
}
|
|
1494
|
+
};
|
|
1495
|
+
const onCheck = async () => {
|
|
1496
|
+
try {
|
|
1497
|
+
setChecked(await check.mutateAsync());
|
|
1498
|
+
} catch (err) {
|
|
1499
|
+
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
const onLink = async (e) => {
|
|
1503
|
+
try {
|
|
1504
|
+
const r = await link.mutateAsync({ kind: e.kind, number: e.number });
|
|
1505
|
+
setChecked(r.check);
|
|
1506
|
+
ui.toast.success(e.state === "missing" ? t("widget.check.linked", { number: e.number }) : t("widget.check.updated", { number: e.number }));
|
|
1507
|
+
} catch (err) {
|
|
1508
|
+
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
const onRetry = async (id) => {
|
|
1512
|
+
try {
|
|
1513
|
+
await retry.mutateAsync(id);
|
|
1514
|
+
ui.toast.success(t("toast.retried"));
|
|
1515
|
+
void q.refetch();
|
|
1516
|
+
} catch (err) {
|
|
1517
|
+
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
1518
|
+
}
|
|
1519
|
+
};
|
|
1520
|
+
const header = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-2 px-6 py-4", children: [
|
|
1521
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
|
|
1522
|
+
/* @__PURE__ */ jsxRuntime.jsx(SubiektIcon, { width: 18, height: 18, className: "shrink-0" }),
|
|
1523
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t("widget.title") }),
|
|
1524
|
+
q.data ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: state.tone, children: t(`widget.state.${state.key}`) }) : null,
|
|
1525
|
+
((_d = q.data) == null ? void 0 : _d.mode) === "demo" ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "blue", children: t("widget.demo") }) : null
|
|
1526
|
+
] }),
|
|
1527
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1528
|
+
"a",
|
|
1529
|
+
{
|
|
1530
|
+
href: `/app/subiekt?q=${encodeURIComponent(String(data.display_id ?? data.id))}`,
|
|
1531
|
+
className: "txt-compact-small inline-flex shrink-0 items-center gap-x-1 text-ui-fg-interactive hover:text-ui-fg-interactive-hover",
|
|
1532
|
+
children: [
|
|
1533
|
+
t("widget.more"),
|
|
1534
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpRightOnBox, {})
|
|
1535
|
+
]
|
|
1536
|
+
}
|
|
1537
|
+
)
|
|
1538
|
+
] });
|
|
1539
|
+
const sendingDocument = (inFlight == null ? void 0 : inFlight.kind) === "order.document";
|
|
1540
|
+
const inFlightHasDocument = sendingDocument ? hasSales : hasZk;
|
|
1541
|
+
return /* @__PURE__ */ jsxRuntime.jsx(WidgetFrame, { header, children: q.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(KitLoading, { className: "min-h-0 py-6" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1542
|
+
inFlight ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1543
|
+
StagedLoader,
|
|
1544
|
+
{
|
|
1545
|
+
run: taskRun(inFlight, inFlightHasDocument),
|
|
1546
|
+
columns: 3,
|
|
1547
|
+
doneTitle: t("widget.run.done"),
|
|
1548
|
+
stages: [
|
|
1549
|
+
{ key: "queue", name: t("widget.run.queue"), short: t("widget.run.queueShort"), icon: /* @__PURE__ */ jsxRuntime.jsx(icons.QueueList, {}), weight: 20 },
|
|
1550
|
+
{ key: "bridge", name: t("widget.run.bridge"), short: t("widget.run.bridgeShort"), icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ServerStack, {}), weight: 60 },
|
|
1551
|
+
{
|
|
1552
|
+
key: "document",
|
|
1553
|
+
name: t("widget.run.document"),
|
|
1554
|
+
short: t("widget.run.documentShort"),
|
|
1555
|
+
icon: sendingDocument ? /* @__PURE__ */ jsxRuntime.jsx(icons.Receipt, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, {}),
|
|
1556
|
+
weight: 20
|
|
1557
|
+
}
|
|
1558
|
+
]
|
|
1559
|
+
}
|
|
1560
|
+
) : null,
|
|
1561
|
+
documents.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-2 px-6 py-4", children: documents.map((d) => /* @__PURE__ */ jsxRuntime.jsx(DocumentLine, { d, lang }, d.id)) }) : inFlight ? null : /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { compact: true, icon: /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, {}), title: (create == null ? void 0 : create.status) === "waiting" ? t("widget.waiting") : t("widget.none") }),
|
|
1562
|
+
tasks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
1563
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-2", children: [
|
|
1564
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: task.kind === "order.document" && (task.documentKind === "fs" || task.documentKind === "pa") ? t(`tasks.documentKinds.${task.documentKind}`) : t(`tasks.kinds.${task.kind}`) }),
|
|
1565
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-x-1", children: [
|
|
1566
|
+
/* @__PURE__ */ jsxRuntime.jsx(TaskStatusBadge, { status: task.status }),
|
|
1567
|
+
task.status === "failed" ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: retry.isPending && retry.variables === task.id, onClick: () => onRetry(task.id), children: [
|
|
1568
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
1569
|
+
t("actions.retry")
|
|
1570
|
+
] }) : null
|
|
1571
|
+
] })
|
|
1572
|
+
] }),
|
|
1573
|
+
task.buyer ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: task.buyer.source === "retail" ? t("tasks.buyer.retail") : t(`tasks.buyer.${task.buyer.source}`, { name: task.buyer.name ?? task.buyer.symbol ?? "?", nip: task.buyer.nip ?? "?" }) }) : null,
|
|
1574
|
+
task.warnings.map((w) => /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: w }, w)),
|
|
1575
|
+
task.lastError && task.status !== "succeeded" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: task.status === "failed" ? "text-ui-tag-red-text" : "text-ui-fg-muted", children: task.lastError }) : null,
|
|
1576
|
+
task.status === "unknown" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: t("tasks.unknownHint") }) : null,
|
|
1577
|
+
task.manualAction ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: t("tasks.manual") }) : null
|
|
1578
|
+
] }, task.id)) }) : null,
|
|
1579
|
+
checked ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1580
|
+
CheckResult,
|
|
1581
|
+
{
|
|
1582
|
+
result: checked,
|
|
1583
|
+
lang,
|
|
1584
|
+
linking: link.isPending && link.variables ? `${link.variables.kind}|${link.variables.number}` : null,
|
|
1585
|
+
onLink: (e) => void onLink(e)
|
|
1586
|
+
}
|
|
1587
|
+
) : null,
|
|
1588
|
+
!inFlight || !hasZk && !busy && !canceled && (create == null ? void 0 : create.status) !== "failed" || offerIssue && sales ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2 px-6 py-4", children: [
|
|
1589
|
+
offerIssue && sales ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: sales.writerActive ? t("widget.autoOn", { after: sales.after.toUpperCase() }) : t("widget.autoOff") }) : null,
|
|
1590
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
1591
|
+
!hasZk && !busy && !canceled && (create == null ? void 0 : create.status) !== "failed" ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: send.isPending, onClick: onSend, children: [
|
|
1592
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.PaperPlane, {}),
|
|
1593
|
+
t("widget.send")
|
|
1594
|
+
] }) : null,
|
|
1595
|
+
offerIssue && sales && (sales.option === "fs" || sales.option === "auto") ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: issue.isPending && issue.variables === "fs", onClick: () => onIssue("fs"), children: [
|
|
1596
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, {}),
|
|
1597
|
+
t("widget.issueFs")
|
|
1598
|
+
] }) : null,
|
|
1599
|
+
offerIssue && sales && (sales.option === "pa" || sales.option === "auto") ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: issue.isPending && issue.variables === "pa", onClick: () => onIssue("pa"), children: [
|
|
1600
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.Receipt, {}),
|
|
1601
|
+
t("widget.issuePa")
|
|
1602
|
+
] }) : null,
|
|
1603
|
+
!inFlight ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", isLoading: check.isPending, onClick: () => void onCheck(), children: [
|
|
1604
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.MagnifyingGlass, {}),
|
|
1605
|
+
checked ? t("widget.check.again") : t("widget.check.button")
|
|
1606
|
+
] }) : null
|
|
1607
|
+
] }),
|
|
1608
|
+
!checked && !inFlight && (failed || !hasZk && !canceled) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t("widget.check.hint") }) : null
|
|
1609
|
+
] }) : null
|
|
1610
|
+
] }) });
|
|
1611
|
+
};
|
|
1612
|
+
adminSdk.defineWidgetConfig({
|
|
1613
|
+
zone: "order.details.side.after"
|
|
1614
|
+
});
|
|
1264
1615
|
const CLOCK_SKEW_WARN_SECONDS = 60;
|
|
1265
1616
|
const CLOCK_SKEW_LIMIT_SECONDS = 300;
|
|
1266
1617
|
function skewLevel(skewMs) {
|
|
@@ -1376,7 +1727,7 @@ function usePromptSpec() {
|
|
|
1376
1727
|
needs: Array.isArray(needs) ? needs : [],
|
|
1377
1728
|
config: `// medusa-config.ts, in plugins: [ ... ]
|
|
1378
1729
|
${MEDUSA_CODE}`,
|
|
1379
|
-
demo: 'demo: process.env.SUBIEKT_DEMO === "true"
|
|
1730
|
+
demo: 'demo: process.env.SUBIEKT_DEMO === "true",'
|
|
1380
1731
|
};
|
|
1381
1732
|
}, [t]);
|
|
1382
1733
|
}
|
|
@@ -1388,7 +1739,7 @@ maxProductsPerRun: 20,`;
|
|
|
1388
1739
|
const DOCUMENTS_CODE = `salesDocument: "auto",
|
|
1389
1740
|
salesDocumentAfter: "wz",
|
|
1390
1741
|
createContractors: true,`;
|
|
1391
|
-
function GuideView({ status
|
|
1742
|
+
function GuideView({ status }) {
|
|
1392
1743
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
1393
1744
|
function list(key) {
|
|
1394
1745
|
const value = t(key, { returnObjects: true });
|
|
@@ -1421,7 +1772,6 @@ function GuideView({ status, lang }) {
|
|
|
1421
1772
|
q: item.q,
|
|
1422
1773
|
a: (item.a ?? []).map((p, i) => /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsx(RichText, { text: p }) }, i))
|
|
1423
1774
|
}));
|
|
1424
|
-
const references = referencesFor(s.references, lang);
|
|
1425
1775
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3", children: [
|
|
1426
1776
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1427
1777
|
GuideIntro,
|
|
@@ -1465,31 +1815,249 @@ function GuideView({ status, lang }) {
|
|
|
1465
1815
|
}))
|
|
1466
1816
|
}
|
|
1467
1817
|
),
|
|
1468
|
-
/* @__PURE__ */ jsxRuntime.jsx(GuideFaq, { title: t("guide.faq.title"), items: faq })
|
|
1469
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1470
|
-
References,
|
|
1471
|
-
{
|
|
1472
|
-
items: references,
|
|
1473
|
-
title: t("references.title"),
|
|
1474
|
-
subtitle: t("references.subtitle"),
|
|
1475
|
-
openLabel: t("references.open"),
|
|
1476
|
-
sinceLabel: (since) => t("references.since", { date: monthYear(since, lang) }),
|
|
1477
|
-
reviewLabel: t("references.review"),
|
|
1478
|
-
ratingLabel: (value) => fmtRating(value, lang)
|
|
1479
|
-
}
|
|
1480
|
-
)
|
|
1818
|
+
/* @__PURE__ */ jsxRuntime.jsx(GuideFaq, { title: t("guide.faq.title"), items: faq })
|
|
1481
1819
|
] });
|
|
1482
1820
|
}
|
|
1483
|
-
const
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1821
|
+
const FIELDS = [
|
|
1822
|
+
"id",
|
|
1823
|
+
"currency_code",
|
|
1824
|
+
"items.id",
|
|
1825
|
+
"items.title",
|
|
1826
|
+
"items.product_title",
|
|
1827
|
+
"items.variant_title",
|
|
1828
|
+
"items.thumbnail",
|
|
1829
|
+
"items.quantity",
|
|
1830
|
+
"items.unit_price",
|
|
1831
|
+
"items.variant_sku",
|
|
1832
|
+
"items.variant_barcode",
|
|
1833
|
+
/* Totals come from the order module. Their relations in FULL (.*): with partial fields
|
|
1834
|
+
(e.g. adjustments.code alone) the module computes from incomplete rows. */
|
|
1835
|
+
"total",
|
|
1836
|
+
"shipping_total",
|
|
1837
|
+
"discount_total",
|
|
1838
|
+
"items.tax_lines.*",
|
|
1839
|
+
"items.adjustments.*",
|
|
1840
|
+
"shipping_methods.*",
|
|
1841
|
+
"shipping_methods.tax_lines.*",
|
|
1842
|
+
"shipping_methods.adjustments.*"
|
|
1843
|
+
].join(",");
|
|
1844
|
+
const TEXT = {
|
|
1845
|
+
en: { productsLine: "Products (before discount)", shippingLine: "Shipping (after its discount)", free: "free", discountLine: "Discount", codesLine: "Discount, codes", button: "View", show: "Show products", title: "Products", ofOrder: "of order", lines: "lines", pcs: "pcs", components: "components", close: "Close", showParts: "Show components", hideParts: "Hide components", empty: "This order has no items." },
|
|
1846
|
+
pl: { productsLine: "Produkty (przed rabatem)", shippingLine: "Dostawa (po rabacie na dostawę)", free: "gratis", discountLine: "Rabat", codesLine: "Rabat, kupony", button: "Zobacz", show: "Pokaż produkty", title: "Produkty", ofOrder: "zamówienia", lines: "poz.", pcs: "szt.", components: "składników", close: "Zamknij", showParts: "Pokaż składniki", hideParts: "Ukryj składniki", empty: "Zamówienie nie ma pozycji." }
|
|
1847
|
+
};
|
|
1848
|
+
function useText() {
|
|
1849
|
+
const { i18n } = reactI18next.useTranslation();
|
|
1850
|
+
return String((i18n == null ? void 0 : i18n.language) ?? "en").startsWith("pl") ? TEXT.pl : TEXT.en;
|
|
1851
|
+
}
|
|
1852
|
+
const num = (v) => {
|
|
1853
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
|
|
1854
|
+
return Number.isFinite(n) ? n : null;
|
|
1855
|
+
};
|
|
1856
|
+
function amountsOf(o) {
|
|
1857
|
+
const total = num(o.total);
|
|
1858
|
+
const shipping = num(o.shipping_total);
|
|
1859
|
+
const discount = num(o.discount_total) ?? 0;
|
|
1860
|
+
if (total == null || shipping == null) return null;
|
|
1861
|
+
const codes = /* @__PURE__ */ new Set();
|
|
1862
|
+
const adjustments = [...(o.items ?? []).flatMap((it) => it.adjustments ?? []), ...(o.shipping_methods ?? []).flatMap((sm) => sm.adjustments ?? [])];
|
|
1863
|
+
for (const a of adjustments) if (typeof (a == null ? void 0 : a.code) === "string" && a.code.trim()) codes.add(a.code.trim().toUpperCase());
|
|
1864
|
+
const r2 = (n) => Math.round(n * 100) / 100;
|
|
1865
|
+
return { total: r2(total), shipping: r2(shipping), discount: r2(discount), products: r2(total - shipping + discount), codes: [...codes] };
|
|
1866
|
+
}
|
|
1867
|
+
function itemOf(it) {
|
|
1868
|
+
const unitPrice = Number(it.unit_price ?? 0);
|
|
1869
|
+
return {
|
|
1870
|
+
id: it.id,
|
|
1871
|
+
title: it.product_title || it.title || "Product",
|
|
1872
|
+
variant: it.variant_title && it.variant_title !== "Default variant" ? it.variant_title : null,
|
|
1873
|
+
thumbnail: it.thumbnail ?? null,
|
|
1874
|
+
quantity: Number(it.quantity ?? 0),
|
|
1875
|
+
unitPrice,
|
|
1876
|
+
sku: it.variant_sku ?? null,
|
|
1877
|
+
barcode: it.variant_barcode ?? null,
|
|
1878
|
+
component: unitPrice <= 0.05
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
async function load(ids) {
|
|
1882
|
+
const out = {};
|
|
1883
|
+
for (let i = 0; i < ids.length; i += 100) {
|
|
1884
|
+
const batch = ids.slice(i, i + 100);
|
|
1885
|
+
const qs = [`fields=${encodeURIComponent(FIELDS)}`, `limit=${batch.length}`, ...batch.map((id) => `id=${encodeURIComponent(id)}`)].join("&");
|
|
1886
|
+
const r = await kitFetch(`/admin/orders?${qs}`);
|
|
1887
|
+
for (const o of r.orders ?? []) {
|
|
1888
|
+
out[o.id] = {
|
|
1889
|
+
currency: String(o.currency_code ?? "usd"),
|
|
1890
|
+
amounts: amountsOf(o),
|
|
1891
|
+
items: (o.items ?? []).map(itemOf)
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
return out;
|
|
1896
|
+
}
|
|
1897
|
+
function useKitOrderProducts(ids) {
|
|
1898
|
+
const unique = [...new Set(ids.filter((x) => typeof x === "string" && x.startsWith("order_")))].sort();
|
|
1899
|
+
return reactQuery.useQuery({
|
|
1900
|
+
queryKey: ["koda-kit-order-products", unique],
|
|
1901
|
+
queryFn: () => load(unique),
|
|
1902
|
+
enabled: unique.length > 0,
|
|
1903
|
+
staleTime: 6e4
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
function money(n, currency, lang) {
|
|
1907
|
+
try {
|
|
1908
|
+
return new Intl.NumberFormat(lang, { style: "currency", currency: currency.toUpperCase() }).format(n);
|
|
1909
|
+
} catch {
|
|
1910
|
+
return `${n.toFixed(2)} ${currency.toUpperCase()}`;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
function Thumb({ src, size, title }) {
|
|
1914
|
+
const [broken, setBroken] = react.useState(false);
|
|
1915
|
+
const style = { width: size, height: size };
|
|
1916
|
+
if (!src || broken)
|
|
1917
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style, className: "flex shrink-0 items-center justify-center rounded-lg border border-ui-border-base bg-ui-bg-component text-ui-fg-muted", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size * 0.5, height: size * 0.5, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" }) }) });
|
|
1918
|
+
return /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: title, title, style, loading: "lazy", onError: () => setBroken(true), className: "shrink-0 rounded-lg border border-ui-border-base bg-ui-bg-base object-cover" });
|
|
1919
|
+
}
|
|
1920
|
+
function Dialog({ data, displayId, onClose }) {
|
|
1921
|
+
const t = useText();
|
|
1922
|
+
const lang = t === TEXT.pl ? "pl-PL" : "en-GB";
|
|
1923
|
+
const [partsOpen, setPartsOpen] = react.useState(false);
|
|
1924
|
+
react.useEffect(() => {
|
|
1925
|
+
const k = (e) => e.key === "Escape" && onClose();
|
|
1926
|
+
window.addEventListener("keydown", k);
|
|
1927
|
+
return () => window.removeEventListener("keydown", k);
|
|
1928
|
+
}, [onClose]);
|
|
1929
|
+
const main = data.items.filter((p) => !p.component);
|
|
1930
|
+
const parts = data.items.filter((p) => p.component);
|
|
1931
|
+
const pcs = main.reduce((s, p) => s + p.quantity, 0);
|
|
1932
|
+
const value = data.items.reduce((s, p) => s + p.unitPrice * p.quantity, 0);
|
|
1933
|
+
return reactDom.createPortal(
|
|
1934
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/40 p-4", onClick: onClose, role: "presentation", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "dialog", "aria-modal": "true", "aria-label": `${t.title} ${displayId ? `#${displayId}` : ""}`, className: "flex max-h-[85vh] w-full max-w-2xl flex-col overflow-hidden rounded-xl border border-ui-border-base bg-ui-bg-base shadow-elevation-modal", onClick: (e) => e.stopPropagation(), children: [
|
|
1935
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-ui-border-base px-5 py-4", children: [
|
|
1936
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1937
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { weight: "plus", children: [
|
|
1938
|
+
t.title,
|
|
1939
|
+
displayId ? ` ${t.ofOrder} #${displayId}` : ""
|
|
1940
|
+
] }),
|
|
1941
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
1942
|
+
main.length,
|
|
1943
|
+
" ",
|
|
1944
|
+
t.lines,
|
|
1945
|
+
", ",
|
|
1946
|
+
pcs,
|
|
1947
|
+
" ",
|
|
1948
|
+
t.pcs,
|
|
1949
|
+
parts.length ? `, ${parts.length} ${t.components}` : "",
|
|
1950
|
+
", ",
|
|
1951
|
+
money(value, data.currency, lang)
|
|
1952
|
+
] })
|
|
1953
|
+
] }),
|
|
1954
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: onClose, children: t.close })
|
|
1955
|
+
] }),
|
|
1956
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto px-5 py-2", children: [
|
|
1957
|
+
main.map((p) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 border-b border-ui-border-base py-3 last:border-0", children: [
|
|
1958
|
+
/* @__PURE__ */ jsxRuntime.jsx(Thumb, { src: p.thumbnail, size: 48, title: p.title }),
|
|
1959
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1960
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "truncate", children: p.title }),
|
|
1961
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [p.variant, p.sku ? `SKU ${p.sku}` : null, p.barcode ? `EAN ${p.barcode}` : null].filter(Boolean).join(", ") || "-" })
|
|
1962
|
+
] }),
|
|
1963
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
1964
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", weight: "plus", className: "tabular-nums", children: [
|
|
1965
|
+
p.quantity,
|
|
1966
|
+
" × ",
|
|
1967
|
+
money(p.unitPrice, data.currency, lang)
|
|
1968
|
+
] }),
|
|
1969
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "tabular-nums text-ui-fg-subtle", children: money(p.unitPrice * p.quantity, data.currency, lang) })
|
|
1970
|
+
] })
|
|
1971
|
+
] }, p.id)),
|
|
1972
|
+
parts.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-3", children: [
|
|
1973
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "txt-small-plus text-ui-fg-interactive", onClick: () => setPartsOpen((v) => !v), children: [
|
|
1974
|
+
partsOpen ? t.hideParts : t.showParts,
|
|
1975
|
+
" (",
|
|
1976
|
+
parts.length,
|
|
1977
|
+
")"
|
|
1978
|
+
] }),
|
|
1979
|
+
partsOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 grid grid-cols-1 gap-x-4 gap-y-1 sm:grid-cols-2", children: parts.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [
|
|
1980
|
+
p.quantity,
|
|
1981
|
+
" × ",
|
|
1982
|
+
p.title,
|
|
1983
|
+
p.variant ? ` (${p.variant})` : ""
|
|
1984
|
+
] }, p.id)) }) : null
|
|
1985
|
+
] }) : null,
|
|
1986
|
+
!data.items.length ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "py-6 text-center text-ui-fg-subtle", children: t.empty }) : null
|
|
1987
|
+
] })
|
|
1988
|
+
] }) }),
|
|
1989
|
+
document.body
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
function KitOpenDialogIcon({ size = 14 }) {
|
|
1993
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1994
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "3" }),
|
|
1995
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 7h3v3" }),
|
|
1996
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M17 7l-4 4" }),
|
|
1997
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 17H7v-3" }),
|
|
1998
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 17l4-4" })
|
|
1999
|
+
] });
|
|
2000
|
+
}
|
|
2001
|
+
const SINGLE = 88;
|
|
2002
|
+
const CARD = 72;
|
|
2003
|
+
const MAX_CARDS = 4;
|
|
2004
|
+
function KitOrderProductsCell({ data, loading, displayId }) {
|
|
2005
|
+
const t = useText();
|
|
2006
|
+
const [open, setOpen] = react.useState(false);
|
|
2007
|
+
if (!data)
|
|
2008
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: loading ? "…" : "-" });
|
|
2009
|
+
const main = data.items.filter((p) => !p.component);
|
|
2010
|
+
const pool = main.length ? main : data.items;
|
|
2011
|
+
if (!pool.length)
|
|
2012
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "-" });
|
|
2013
|
+
const shown = pool.slice(0, pool.length > MAX_CARDS ? MAX_CARDS - 1 : MAX_CARDS);
|
|
2014
|
+
const rest = pool.length - shown.length;
|
|
2015
|
+
const size = pool.length === 1 ? SINGLE : CARD;
|
|
2016
|
+
const show = (e) => {
|
|
2017
|
+
e.stopPropagation();
|
|
2018
|
+
e.preventDefault();
|
|
2019
|
+
setOpen(true);
|
|
2020
|
+
};
|
|
2021
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-y-2", onClick: (e) => e.stopPropagation(), children: [
|
|
2022
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2023
|
+
"button",
|
|
2024
|
+
{
|
|
2025
|
+
type: "button",
|
|
2026
|
+
onClick: show,
|
|
2027
|
+
className: "inline-flex items-center gap-x-1 txt-compact-small-plus text-ui-fg-interactive underline-offset-2 transition-fg hover:text-ui-fg-interactive-hover hover:underline",
|
|
2028
|
+
title: t.show,
|
|
2029
|
+
children: [
|
|
2030
|
+
t.button,
|
|
2031
|
+
/* @__PURE__ */ jsxRuntime.jsx(KitOpenDialogIcon, {})
|
|
2032
|
+
]
|
|
2033
|
+
}
|
|
2034
|
+
),
|
|
2035
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick: show, className: "isolate flex items-center py-1", "aria-label": `${t.title}${displayId ? ` #${displayId}` : ""}: ${pool.length}`, children: [
|
|
2036
|
+
shown.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2037
|
+
"span",
|
|
2038
|
+
{
|
|
2039
|
+
style: { marginLeft: i ? -40 : 0, zIndex: i + 1 },
|
|
2040
|
+
className: "relative rounded-lg bg-ui-bg-base shadow-elevation-card-rest ring-2 ring-ui-bg-base transition-transform duration-200 ease-out hover:!z-30 hover:scale-[1.15]",
|
|
2041
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Thumb, { src: p.thumbnail, size, title: `${p.quantity} × ${p.title}${p.variant ? ` (${p.variant})` : ""}` })
|
|
2042
|
+
},
|
|
2043
|
+
p.id
|
|
2044
|
+
)),
|
|
2045
|
+
rest > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2046
|
+
"span",
|
|
2047
|
+
{
|
|
2048
|
+
style: { marginLeft: -40, zIndex: shown.length + 1, width: CARD, height: CARD },
|
|
2049
|
+
className: "relative flex items-center justify-end rounded-lg bg-ui-bg-component pr-3 shadow-elevation-card-rest ring-2 ring-ui-bg-base txt-compact-small-plus text-ui-fg-subtle",
|
|
2050
|
+
children: [
|
|
2051
|
+
"+",
|
|
2052
|
+
rest
|
|
2053
|
+
]
|
|
2054
|
+
}
|
|
2055
|
+
) : null
|
|
1489
2056
|
] }),
|
|
1490
|
-
|
|
2057
|
+
open ? /* @__PURE__ */ jsxRuntime.jsx(Dialog, { data, displayId: displayId ?? null, onClose: () => setOpen(false) }) : null
|
|
1491
2058
|
] });
|
|
1492
2059
|
}
|
|
2060
|
+
const PAGE_SIZE$1 = 15;
|
|
1493
2061
|
const LEVEL_TEXT = {
|
|
1494
2062
|
ok: "text-ui-fg-base",
|
|
1495
2063
|
warn: "text-ui-tag-orange-text",
|
|
@@ -1510,54 +2078,65 @@ function BridgeSection({ status, lang }) {
|
|
|
1510
2078
|
const licence = ((_a = h == null ? void 0 : h.subiekt) == null ? void 0 : _a.licence) === "ok" || ((_b = h == null ? void 0 : h.subiekt) == null ? void 0 : _b.licence) === "refused" ? h.subiekt.licence : "unknown";
|
|
1511
2079
|
const signatureTone = d.signature === "ok" ? LEVEL_TEXT.ok : d.signature === "unknown" ? LEVEL_TEXT.unknown : LEVEL_TEXT.error;
|
|
1512
2080
|
const rejectedLater = Boolean(d.webhook.rejectedAt && (!d.webhook.lastAt || d.webhook.rejectedAt > d.webhook.lastAt));
|
|
1513
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
hint
|
|
1554
|
-
"
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
2081
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2082
|
+
Section,
|
|
2083
|
+
{
|
|
2084
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ComputerDesktop, {}),
|
|
2085
|
+
title: t("bridge.title"),
|
|
2086
|
+
points: [
|
|
2087
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), text: t("bridge.points.last") },
|
|
2088
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ShieldCheck, {}), text: t("bridge.points.fresh") }
|
|
2089
|
+
],
|
|
2090
|
+
pointsLabel: t("bridge.subtitle"),
|
|
2091
|
+
children: [
|
|
2092
|
+
d.legacy ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "warning", label: t("bridge.title"), children: t("bridge.legacy") }) }) : null,
|
|
2093
|
+
status.mode === "live" && ((_c = h == null ? void 0 : h.bridge) == null ? void 0 : _c.mode) === "fake" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "warning", label: t("bridge.title"), children: t("bridge.fakeMode") }) }) : null,
|
|
2094
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-2", children: [
|
|
2095
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.versions"), children: t("bridge.versionsValue", { bridge: ((_d = h == null ? void 0 : h.bridge) == null ? void 0 : _d.version) ?? "?", contract: ((_e = h == null ? void 0 : h.bridge) == null ? void 0 : _e.contract) ?? "?", plugin: status.pluginVersion }) }),
|
|
2096
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.sdk"), children: h ? t("bridge.sdkValue", { sdk: ((_f = h.bridge) == null ? void 0 : _f.sdk_version) ?? none, db: ((_g = h.subiekt) == null ? void 0 : _g.database_version) ?? none }) : none }),
|
|
2097
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.licence"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: licence === "refused" ? LEVEL_TEXT.error : licence === "ok" ? LEVEL_TEXT.ok : LEVEL_TEXT.unknown, children: t(`bridge.licenceStates.${licence}`) }) }),
|
|
2098
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.started"), children: fmtDateTime((_h = h == null ? void 0 : h.bridge) == null ? void 0 : _h.started_at, lang) || none }),
|
|
2099
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.latency"), children: fmtMs(d.latencyMs) }),
|
|
2100
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.skew"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: LEVEL_TEXT[skew], children: t(`bridge.skewStates.${skew}`, { value: d.clockSkewMs === null ? "" : signedMs(d.clockSkewMs) }) }) }),
|
|
2101
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.signature"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: signatureTone, children: t(`bridge.signatureStates.${d.signature}`, { defaultValue: d.signature }) }) }),
|
|
2102
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.lastEvent"), children: (h == null ? void 0 : h.events) ? t("bridge.lastEventValue", { id: h.events.last_id, time: fmtDateTime(h.events.last_at, lang) || none }) : none }),
|
|
2103
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.queues"), children: (h == null ? void 0 : h.queues) ? t("bridge.queuesValue", { sfera: h.queues.sfera_pending, webhook: h.queues.webhook_pending }) : none }),
|
|
2104
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("bridge.webhook"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
2105
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: d.webhook.lastAt ? t("bridge.webhookValue", { time: fmtDateTime(d.webhook.lastAt, lang) }) : t("bridge.webhookNever") }),
|
|
2106
|
+
rejectedLater ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: LEVEL_TEXT.warn, children: t("bridge.webhookRejected", {
|
|
2107
|
+
time: fmtDateTime(d.webhook.rejectedAt, lang),
|
|
2108
|
+
reason: t(`bridge.webhookReasons.${d.webhook.rejectReason ?? "missing"}`, { defaultValue: d.webhook.rejectReason ?? "" })
|
|
2109
|
+
}) }) : null
|
|
2110
|
+
] }) }),
|
|
2111
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.checkedAt"), children: fmtDateTime(d.checkedAt, lang) || t("connection.never") })
|
|
2112
|
+
] }),
|
|
2113
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: [
|
|
2114
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
2115
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t("bridge.capabilities") }),
|
|
2116
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: d.capabilities.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: none }) : d.capabilities.map((c) => /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "green", children: t(`bridge.capabilityNames.${c}`, { defaultValue: c }) }, c)) })
|
|
2117
|
+
] }),
|
|
2118
|
+
d.missing.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
2119
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t("bridge.cannot") }),
|
|
2120
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-y-1", children: d.missing.map((m) => {
|
|
2121
|
+
const hint = m.reason === "bridge_config" ? t(`bridge.capabilityHints.${m.capability}`, { defaultValue: "" }) : "";
|
|
2122
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "txt-compact-small flex flex-wrap gap-x-1", children: [
|
|
2123
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-base", children: [
|
|
2124
|
+
t(`bridge.capabilityNames.${m.capability}`, { defaultValue: m.capability }),
|
|
2125
|
+
":"
|
|
2126
|
+
] }),
|
|
2127
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-subtle", children: t(`bridge.reasons.${m.reason}`, { defaultValue: m.reason }) }),
|
|
2128
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-ui-fg-muted", children: [
|
|
2129
|
+
"(",
|
|
2130
|
+
hint,
|
|
2131
|
+
")"
|
|
2132
|
+
] }) : null
|
|
2133
|
+
] }, m.capability);
|
|
2134
|
+
}) })
|
|
2135
|
+
] }) : null
|
|
2136
|
+
] })
|
|
2137
|
+
]
|
|
2138
|
+
}
|
|
2139
|
+
);
|
|
1561
2140
|
}
|
|
1562
2141
|
const WRITER_ORDER = ["documents", "contractors", "prices", "products"];
|
|
1563
2142
|
function WriterRow({ writer, status, lang }) {
|
|
@@ -1591,15 +2170,14 @@ function WriterRow({ writer, status, lang }) {
|
|
|
1591
2170
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
1592
2171
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1593
2172
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: "text-ui-fg-base", children: name }),
|
|
1594
|
-
writer.active ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1595
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1596
|
-
writer.allowed ? null : /* @__PURE__ */ jsxRuntime.jsx(icons.LockClosedSolid, {}),
|
|
2173
|
+
writer.active ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "green", children: t("writers.active") }) : writer.armed ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "orange", children: t("writers.blocked") }) : /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { children: t("writers.disarmed") }),
|
|
2174
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ToneBadge, { icon: writer.allowed ? void 0 : /* @__PURE__ */ jsxRuntime.jsx(icons.LockClosedSolid, {}), children: [
|
|
1597
2175
|
t("writers.option", { option: writer.option }),
|
|
1598
2176
|
" ",
|
|
1599
2177
|
writer.allowed ? t("writers.allowed") : t("writers.forbidden")
|
|
1600
|
-
] })
|
|
2178
|
+
] })
|
|
1601
2179
|
] }),
|
|
1602
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "
|
|
2180
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: description }),
|
|
1603
2181
|
writer.unsupported ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-orange-text", children: t("writers.unsupported") }) : null,
|
|
1604
2182
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: writer.changedAt ? t(writer.armed ? "writers.armedBy" : "writers.disarmedBy", { who: writer.changedBy ?? "?", time: fmtDateTime(writer.changedAt, lang) }) : t("writers.never") })
|
|
1605
2183
|
] }),
|
|
@@ -1609,13 +2187,34 @@ function WriterRow({ writer, status, lang }) {
|
|
|
1609
2187
|
function WritersSection({ status, lang }) {
|
|
1610
2188
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
1611
2189
|
const writers = WRITER_ORDER.map((k) => status.writers.find((w) => w.key === k)).filter((w) => Boolean(w));
|
|
1612
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
2190
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2191
|
+
Section,
|
|
2192
|
+
{
|
|
2193
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.LockClosedSolid, {}),
|
|
2194
|
+
title: t("writers.title"),
|
|
2195
|
+
badges: status.mode === "demo" ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "blue", title: t("writers.demoNote"), children: t("widget.demo") }) : null,
|
|
2196
|
+
points: [
|
|
2197
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {}), text: t("writers.points.option") },
|
|
2198
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.User, {}), text: t("writers.points.person") },
|
|
2199
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.LockClosedSolid, {}), text: t("writers.points.falseWins") }
|
|
2200
|
+
],
|
|
2201
|
+
pointsLabel: t("writers.subtitle"),
|
|
2202
|
+
children: writers.map((w) => /* @__PURE__ */ jsxRuntime.jsx(WriterRow, { writer: w, status, lang }, w.key))
|
|
2203
|
+
}
|
|
2204
|
+
);
|
|
1617
2205
|
}
|
|
1618
2206
|
const STATUS_FILTERS = ["planned", "applied", "simulated", "over_cap", "stale", "failed", "quarantined", "skipped"];
|
|
2207
|
+
const STATUS_ICON = {
|
|
2208
|
+
planned: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}),
|
|
2209
|
+
applied: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, {}),
|
|
2210
|
+
simulated: /* @__PURE__ */ jsxRuntime.jsx(icons.Beaker, {}),
|
|
2211
|
+
over_cap: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLongRight, {}),
|
|
2212
|
+
stale: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
2213
|
+
failed: /* @__PURE__ */ jsxRuntime.jsx(icons.XCircle, {}),
|
|
2214
|
+
quarantined: /* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, {}),
|
|
2215
|
+
skipped: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUturnLeft, {})
|
|
2216
|
+
};
|
|
2217
|
+
const STATUS_ATTENTION = /* @__PURE__ */ new Set(["failed", "quarantined", "stale"]);
|
|
1619
2218
|
function ChangeCell({ change, lang }) {
|
|
1620
2219
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
1621
2220
|
if (change.kind === "create") return /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("products.newProduct", { price: fmtMoney(change.to, change.currency, lang) }) });
|
|
@@ -1661,7 +2260,7 @@ function ProductsSection({ status, lang, poll, onAction }) {
|
|
|
1661
2260
|
const [filter, setFilter] = react.useState("all");
|
|
1662
2261
|
const [search, setSearch] = react.useState("");
|
|
1663
2262
|
const [offset, setOffset] = react.useState(0);
|
|
1664
|
-
const q = search.trim();
|
|
2263
|
+
const q = useDebouncedValue(search).trim();
|
|
1665
2264
|
const running = status.running.includes("products");
|
|
1666
2265
|
const products = useSubiektProducts(kind, filter, q, offset, PAGE_SIZE$1, poll || running);
|
|
1667
2266
|
const sync = useSubiektSync();
|
|
@@ -1710,112 +2309,147 @@ function ProductsSection({ status, lang, poll, onAction }) {
|
|
|
1710
2309
|
["unmatchedVariants", stats.unmatchedVariants, true],
|
|
1711
2310
|
["noPrice", stats.noPrice, true]
|
|
1712
2311
|
] : [];
|
|
1713
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1 px-6 py-3", children: [
|
|
1723
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: settings }),
|
|
1724
|
-
run ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
1725
|
-
runSummary(run, t),
|
|
1726
|
-
" ",
|
|
1727
|
-
fmtDateTime(run.startedAt, lang),
|
|
1728
|
-
", ",
|
|
1729
|
-
fmtDuration(run.durationMs)
|
|
1730
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t("products.never") })
|
|
1731
|
-
] }),
|
|
1732
|
-
!o.productSyncEnabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "info", label: t("products.title"), children: t("products.disabled") }) }) : !supported ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "warning", label: t("products.title"), children: t("products.unsupported") }) }) : null,
|
|
1733
|
-
(stats == null ? void 0 : stats.blocked) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "warning", label: t("products.title"), children: t(`products.blocked.${stats.blocked}`) }) }) : null,
|
|
1734
|
-
counters.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-x-4 gap-y-2 px-6 py-4 sm:grid-cols-4", children: counters.map(([key, value, warn]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
1735
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: t(`products.counters.${key}`) }),
|
|
1736
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", className: ui.clx("tabular-nums", warn && value ? "text-ui-tag-orange-text" : void 0), children: fmtNumber(value ?? 0, lang) })
|
|
1737
|
-
] }, key)) }) : null,
|
|
1738
|
-
(stats == null ? void 0 : stats.samples) && (((_a = stats.samples.conflicts) == null ? void 0 : _a.length) || ((_b = stats.samples.unmatchedVariants) == null ? void 0 : _b.length) || ((_c = stats.samples.noPrice) == null ? void 0 : _c.length)) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: [
|
|
1739
|
-
((_d = stats.samples.conflicts) == null ? void 0 : _d.length) ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("products.samples.conflicts"), items: stats.samples.conflicts }) : null,
|
|
1740
|
-
((_e = stats.samples.unmatchedVariants) == null ? void 0 : _e.length) ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("products.samples.unmatchedVariants"), items: stats.samples.unmatchedVariants }) : null,
|
|
1741
|
-
((_f = stats.samples.noPrice) == null ? void 0 : _f.length) ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("products.samples.noPrice"), items: stats.samples.noPrice }) : null
|
|
1742
|
-
] }) : null,
|
|
1743
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 px-6 py-3", children: [
|
|
1744
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1745
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1746
|
-
FilterPills,
|
|
1747
|
-
{
|
|
1748
|
-
value: kind,
|
|
1749
|
-
onChange: setKind,
|
|
1750
|
-
options: [
|
|
1751
|
-
{ value: "all", label: t("products.statuses.all") },
|
|
1752
|
-
{ value: "price", label: t("products.kinds.price") },
|
|
1753
|
-
{ value: "create", label: t("products.kinds.create") }
|
|
1754
|
-
]
|
|
1755
|
-
}
|
|
1756
|
-
),
|
|
1757
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full md:w-56", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { size: "small", type: "search", placeholder: t("products.search"), value: search, onChange: (e) => setSearch(e.target.value) }) })
|
|
2312
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2313
|
+
Section,
|
|
2314
|
+
{
|
|
2315
|
+
id: "subiekt-products",
|
|
2316
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Tag, {}),
|
|
2317
|
+
title: t("products.title"),
|
|
2318
|
+
badges: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2319
|
+
(run == null ? void 0 : run.dryRun) ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "blue", children: t("stock.dryRun") }) : null,
|
|
2320
|
+
run ? /* @__PURE__ */ jsxRuntime.jsx(RunStatusBadge, { status: run.status }) : null
|
|
1758
2321
|
] }),
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
{
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
] }),
|
|
1771
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
1772
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
1773
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.product") }),
|
|
1774
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.change") }),
|
|
1775
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: /* @__PURE__ */ jsxRuntime.jsx(StoreColumn, { label: t("products.columns.store"), hint: t("products.matching") }) }),
|
|
1776
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.status") }),
|
|
1777
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.details") })
|
|
1778
|
-
] }) }),
|
|
1779
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 5, className: "px-6 py-6 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: products.isLoading ? "" : t("products.empty") }) }) }) : rows.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "[&_td]:py-2.5", children: [
|
|
1780
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-[240px]", children: /* @__PURE__ */ jsxRuntime.jsx(SubiektProductCell, { change: c }) }),
|
|
1781
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ChangeCell, { change: c, lang }) }),
|
|
1782
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-[300px]", children: /* @__PURE__ */ jsxRuntime.jsx(StoreProductCell, { change: c }) }),
|
|
1783
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(CatalogStatusBadge, { status: c.status }) }),
|
|
1784
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { className: "max-w-md", children: [
|
|
1785
|
-
c.lastError ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: c.status === "failed" || c.status === "quarantined" ? "text-ui-tag-red-text" : "text-ui-fg-subtle", children: c.lastError }) : null,
|
|
1786
|
-
c.appliedAt ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: fmtDateTime(c.appliedAt, lang) }) : null
|
|
2322
|
+
points: [
|
|
2323
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListBullet, {}), text: t("products.points.plan") },
|
|
2324
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.MagnifyingGlass, {}), text: t("products.points.match"), title: t("products.matching") },
|
|
2325
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.LockClosedSolid, {}), text: t("products.points.writer") }
|
|
2326
|
+
],
|
|
2327
|
+
pointsLabel: t("products.subtitle"),
|
|
2328
|
+
actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2329
|
+
/* @__PURE__ */ jsxRuntime.jsx(SearchInput, { value: search, onChange: setSearch, placeholder: t("products.search") }),
|
|
2330
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", variant: "secondary", disabled: !ready || !supported || !o.productSyncEnabled || running, isLoading: sync.isPending, onClick: onRead, children: [
|
|
2331
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
2332
|
+
running ? t("actions.running") : t("actions.products")
|
|
1787
2333
|
] })
|
|
1788
|
-
] },
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t("products.quarantineHint") }),
|
|
1794
|
-
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col divide-y", children: data.quarantined.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start justify-between gap-x-4 py-2", children: [
|
|
1795
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
1796
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "font-mono", children: [
|
|
1797
|
-
t(`products.kinds.${item.kind}`),
|
|
1798
|
-
": ",
|
|
1799
|
-
item.key
|
|
1800
|
-
] }),
|
|
1801
|
-
item.lastError ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-red-text", children: item.lastError }) : null
|
|
2334
|
+
] }),
|
|
2335
|
+
children: [
|
|
2336
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1 px-6 py-3", children: [
|
|
2337
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: settings }),
|
|
2338
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: run ? `${runSummary(run, t)} ${fmtDateTime(run.startedAt, lang)}, ${fmtDuration(run.durationMs)}` : t("products.never") })
|
|
1802
2339
|
] }),
|
|
1803
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
2340
|
+
!o.productSyncEnabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "info", label: t("products.title"), children: t("products.disabled") }) }) : !supported ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "warning", label: t("products.title"), children: t("products.unsupported") }) }) : null,
|
|
2341
|
+
(stats == null ? void 0 : stats.blocked) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "warning", label: t("products.title"), children: t(`products.blocked.${stats.blocked}`) }) }) : null,
|
|
2342
|
+
counters.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(StatTiles, { columns: 4, children: counters.map(([key, value, warn]) => /* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t(`products.counters.${key}`), value: fmtNumber(value ?? 0, lang), tone: warn && value ? "orange" : "grey" }, key)) }) : null,
|
|
2343
|
+
(stats == null ? void 0 : stats.samples) && (((_a = stats.samples.conflicts) == null ? void 0 : _a.length) || ((_b = stats.samples.unmatchedVariants) == null ? void 0 : _b.length) || ((_c = stats.samples.noPrice) == null ? void 0 : _c.length)) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: [
|
|
2344
|
+
((_d = stats.samples.conflicts) == null ? void 0 : _d.length) ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("products.samples.conflicts"), items: stats.samples.conflicts }) : null,
|
|
2345
|
+
((_e = stats.samples.unmatchedVariants) == null ? void 0 : _e.length) ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("products.samples.unmatchedVariants"), items: stats.samples.unmatchedVariants }) : null,
|
|
2346
|
+
((_f = stats.samples.noPrice) == null ? void 0 : _f.length) ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("products.samples.noPrice"), items: stats.samples.noPrice }) : null
|
|
2347
|
+
] }) : null,
|
|
2348
|
+
/* @__PURE__ */ jsxRuntime.jsxs(FilterBar, { children: [
|
|
2349
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListBullet, {}), label: t("products.statuses.all"), count: summary == null ? void 0 : summary.total, active: kind === "all" && filter === "all", onClick: () => (setKind("all"), setFilter("all")) }),
|
|
2350
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Tag, {}), label: t("products.kinds.price"), active: kind === "price", onClick: () => setKind(kind === "price" ? "all" : "price") }),
|
|
2351
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), label: t("products.kinds.create"), active: kind === "create", onClick: () => setKind(kind === "create" ? "all" : "create") }),
|
|
2352
|
+
STATUS_FILTERS.some((st) => ((summary == null ? void 0 : summary[st]) ?? 0) > 0 || st === filter) ? /* @__PURE__ */ jsxRuntime.jsx(FilterDivider, {}) : null,
|
|
2353
|
+
STATUS_FILTERS.filter((st) => ((summary == null ? void 0 : summary[st]) ?? 0) > 0 || st === filter).map((st) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2354
|
+
FilterButton,
|
|
2355
|
+
{
|
|
2356
|
+
icon: STATUS_ICON[st],
|
|
2357
|
+
label: t(`products.statuses.${st}`),
|
|
2358
|
+
count: summary == null ? void 0 : summary[st],
|
|
2359
|
+
attention: STATUS_ATTENTION.has(st),
|
|
2360
|
+
active: filter === st,
|
|
2361
|
+
onClick: () => setFilter(filter === st ? "all" : st)
|
|
2362
|
+
},
|
|
2363
|
+
st
|
|
2364
|
+
))
|
|
2365
|
+
] }),
|
|
2366
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
2367
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2368
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.product") }),
|
|
2369
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.change") }),
|
|
2370
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: /* @__PURE__ */ jsxRuntime.jsx(StoreColumn, { label: t("products.columns.store"), hint: t("products.matching") }) }),
|
|
2371
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.status") }),
|
|
2372
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("products.columns.details") })
|
|
2373
|
+
] }) }),
|
|
2374
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: products.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(KitSkeletonRows, { cols: 5, rows: 4 }) : rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyTableRow, { cols: 5, icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Tag, {}), title: t("products.empty") }) : rows.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "[&_td]:py-2.5", children: [
|
|
2375
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-[240px]", children: /* @__PURE__ */ jsxRuntime.jsx(SubiektProductCell, { change: c }) }),
|
|
2376
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ChangeCell, { change: c, lang }) }),
|
|
2377
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-[300px]", children: /* @__PURE__ */ jsxRuntime.jsx(StoreProductCell, { change: c }) }),
|
|
2378
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(CatalogStatusBadge, { status: c.status, dot: true }) }),
|
|
2379
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { className: "max-w-md", children: [
|
|
2380
|
+
c.lastError ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: c.status === "failed" || c.status === "quarantined" ? "text-ui-tag-red-text" : "text-ui-fg-subtle", children: c.lastError }) : null,
|
|
2381
|
+
c.appliedAt ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: fmtDateTime(c.appliedAt, lang) }) : null
|
|
2382
|
+
] })
|
|
2383
|
+
] }, c.id)) })
|
|
2384
|
+
] }) }),
|
|
2385
|
+
/* @__PURE__ */ jsxRuntime.jsx(Pager, { offset, limit: PAGE_SIZE$1, count: (data == null ? void 0 : data.count) ?? 0, onChange: setOffset }),
|
|
2386
|
+
data && data.quarantined.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2 px-6 py-4", children: [
|
|
2387
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2388
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: t("products.quarantine") }),
|
|
2389
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2390
|
+
KeyPoints,
|
|
2391
|
+
{
|
|
2392
|
+
items: [
|
|
2393
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, {}), text: t("products.quarantinePoints.skipped"), tone: "orange" },
|
|
2394
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {}), text: t("products.quarantinePoints.fix") }
|
|
2395
|
+
],
|
|
2396
|
+
label: t("products.quarantineHint")
|
|
2397
|
+
}
|
|
2398
|
+
)
|
|
2399
|
+
] }),
|
|
2400
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col divide-y", children: data.quarantined.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start justify-between gap-x-4 py-2", children: [
|
|
2401
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2402
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "font-mono", children: [
|
|
2403
|
+
t(`products.kinds.${item.kind}`),
|
|
2404
|
+
": ",
|
|
2405
|
+
item.key
|
|
2406
|
+
] }),
|
|
2407
|
+
item.lastError ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-tag-red-text", children: item.lastError }) : null
|
|
2408
|
+
] }),
|
|
2409
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2410
|
+
RowActions,
|
|
2411
|
+
{
|
|
2412
|
+
actions: [
|
|
2413
|
+
{
|
|
2414
|
+
key: "release",
|
|
2415
|
+
label: t("actions.release"),
|
|
2416
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUturnLeft, {}),
|
|
2417
|
+
loading: release.isPending && release.variables === item.id,
|
|
2418
|
+
onClick: () => void onRelease(item.id)
|
|
2419
|
+
}
|
|
2420
|
+
]
|
|
2421
|
+
}
|
|
2422
|
+
)
|
|
2423
|
+
] }, item.id)) })
|
|
2424
|
+
] }) : null
|
|
2425
|
+
]
|
|
2426
|
+
}
|
|
2427
|
+
);
|
|
1807
2428
|
}
|
|
1808
2429
|
const PAGE_SIZE = 15;
|
|
1809
2430
|
const SETTINGS_TABS = ["connection", "bridge", "writers", "stock", "runs"];
|
|
2431
|
+
const TASK_FILTERS = ["attention", "open", "done", "all"];
|
|
2432
|
+
function scrollToSection(id) {
|
|
2433
|
+
requestAnimationFrame(() => {
|
|
2434
|
+
var _a;
|
|
2435
|
+
return (_a = document.getElementById(id)) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
1810
2438
|
const SubiektPage = () => {
|
|
1811
2439
|
const { t, i18n } = reactI18next.useTranslation("subiekt");
|
|
1812
2440
|
const lang = i18n.language || "en";
|
|
1813
2441
|
const client = reactQuery.useQueryClient();
|
|
1814
2442
|
const nav = usePageNav(SETTINGS_TABS);
|
|
2443
|
+
const [params] = reactRouterDom.useSearchParams();
|
|
1815
2444
|
const [pollUntil, setPollUntil] = react.useState(0);
|
|
1816
2445
|
const status = useSubiektStatus(pollUntil);
|
|
1817
2446
|
const s = status.data;
|
|
1818
2447
|
const polling = ((s == null ? void 0 : s.running.length) ?? 0) > 0 || Date.now() < pollUntil;
|
|
2448
|
+
const asked = params.get("filter") ?? "";
|
|
2449
|
+
const [taskFilter, setTaskFilter] = react.useState(TASK_FILTERS.includes(asked) ? asked : null);
|
|
2450
|
+
const [docKind, setDocKind] = react.useState("all");
|
|
2451
|
+
const initialQuery = (params.get("q") ?? "").slice(0, 80);
|
|
2452
|
+
const filter = taskFilter ?? (s && s.counts.failed > 0 ? "attention" : "all");
|
|
1819
2453
|
const runKey = JSON.stringify(Object.values((s == null ? void 0 : s.lastRuns) ?? {}).map((r) => (r == null ? void 0 : r.id) ?? ""));
|
|
1820
2454
|
const seen = react.useRef(void 0);
|
|
1821
2455
|
react.useEffect(() => {
|
|
@@ -1825,32 +2459,45 @@ const SubiektPage = () => {
|
|
|
1825
2459
|
seen.current = runKey;
|
|
1826
2460
|
}, [runKey, client]);
|
|
1827
2461
|
const poll = () => setPollUntil(Date.now() + 3e4);
|
|
2462
|
+
const toggleTasks = (f) => {
|
|
2463
|
+
setTaskFilter(filter === f ? "all" : f);
|
|
2464
|
+
scrollToSection("subiekt-tasks");
|
|
2465
|
+
};
|
|
2466
|
+
const toggleDocs = (k) => {
|
|
2467
|
+
setDocKind(docKind === k ? "all" : k);
|
|
2468
|
+
scrollToSection("subiekt-documents");
|
|
2469
|
+
};
|
|
2470
|
+
const c = s == null ? void 0 : s.counts;
|
|
2471
|
+
const queued = c ? c.pending + c.running + c.unknown : 0;
|
|
1828
2472
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3", children: [
|
|
1829
2473
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
1830
|
-
/* @__PURE__ */ jsxRuntime.jsx(Header, { status: s, loading: status.isLoading, lang, nav, onAction: poll }),
|
|
2474
|
+
/* @__PURE__ */ jsxRuntime.jsx(Header, { status: s, loading: status.isLoading, fetching: status.isFetching, lang, nav, onAction: poll }),
|
|
1831
2475
|
status.isError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineTip, { variant: "error", label: t("title"), children: errorMessage(status.error) }) }) : null,
|
|
1832
2476
|
s ? /* @__PURE__ */ jsxRuntime.jsx(Warnings, { status: s }) : null,
|
|
1833
|
-
|
|
1834
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.sent24h"), value: fmtNumber(
|
|
1835
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.waiting"), value: fmtNumber(
|
|
2477
|
+
c && nav.view === "panel" ? /* @__PURE__ */ jsxRuntime.jsxs(StatTiles, { columns: 7, children: [
|
|
2478
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.sent24h"), value: fmtNumber(c.succeeded24h, lang), tone: c.succeeded24h ? "green" : "grey", active: filter === "done", onClick: () => toggleTasks("done") }),
|
|
2479
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.waiting"), value: fmtNumber(c.waiting, lang), hint: c.waiting ? t("stats.hintWaiting") : void 0 }),
|
|
2480
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.queue"), value: fmtNumber(queued, lang), tone: queued ? "blue" : "grey", active: filter === "open", onClick: () => toggleTasks("open") }),
|
|
1836
2481
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1837
2482
|
StatTile,
|
|
1838
2483
|
{
|
|
1839
|
-
label: t("stats.
|
|
1840
|
-
value: fmtNumber(
|
|
1841
|
-
tone:
|
|
2484
|
+
label: t("stats.attention"),
|
|
2485
|
+
value: fmtNumber(c.failed, lang),
|
|
2486
|
+
tone: c.failed ? "red" : "grey",
|
|
2487
|
+
hint: c.failed ? t("stats.hintAttention") : void 0,
|
|
2488
|
+
active: filter === "attention",
|
|
2489
|
+
onClick: () => toggleTasks("attention")
|
|
1842
2490
|
}
|
|
1843
2491
|
),
|
|
1844
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.
|
|
1845
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.
|
|
1846
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.
|
|
1847
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.sales"), value: fmtNumber(s.counts.fs + s.counts.pa, lang), tone: s.counts.fs + s.counts.pa ? void 0 : "muted" })
|
|
2492
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.zk"), value: fmtNumber(c.zk, lang), active: docKind === "ZK", onClick: () => toggleDocs("ZK") }),
|
|
2493
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.wz"), value: fmtNumber(c.wz, lang), active: docKind === "WZ", onClick: () => toggleDocs("WZ") }),
|
|
2494
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t("stats.sales"), value: fmtNumber(c.fs + c.pa, lang) })
|
|
1848
2495
|
] }) : null
|
|
1849
2496
|
] }),
|
|
1850
|
-
s && nav.view === "guide" ? /* @__PURE__ */ jsxRuntime.jsx(GuideView, { status: s
|
|
2497
|
+
s && nav.view === "guide" ? /* @__PURE__ */ jsxRuntime.jsx(GuideView, { status: s }) : null,
|
|
1851
2498
|
nav.view === "panel" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1852
|
-
s ? /* @__PURE__ */ jsxRuntime.jsx(TasksSection, { status: s, lang, poll: polling, onAction: poll }) : null,
|
|
1853
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocumentsSection, { lang, poll: polling }),
|
|
2499
|
+
s ? /* @__PURE__ */ jsxRuntime.jsx(TasksSection, { status: s, lang, poll: polling, onAction: poll, filter, onFilter: setTaskFilter, initialQuery }) : null,
|
|
2500
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocumentsSection, { lang, poll: polling, kind: docKind, onKind: setDocKind, counts: c, initialQuery }),
|
|
1854
2501
|
s ? /* @__PURE__ */ jsxRuntime.jsx(ProductsSection, { status: s, lang, poll: polling, onAction: poll }) : null
|
|
1855
2502
|
] }) : null,
|
|
1856
2503
|
nav.view === "settings" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -1864,7 +2511,7 @@ const SubiektPage = () => {
|
|
|
1864
2511
|
{ id: "connection", label: t("settings.tab.connection") },
|
|
1865
2512
|
{ id: "bridge", label: t("settings.tab.bridge") },
|
|
1866
2513
|
{ id: "writers", label: t("settings.tab.writers"), badge: s == null ? void 0 : s.writers.filter((w) => w.active).length, tone: "orange" },
|
|
1867
|
-
{ id: "stock", label: t("settings.tab.stock"), badge: (s == null ? void 0 : s.options.stockDryRun) ? t("stock.dryRun") : null, tone: "
|
|
2514
|
+
{ id: "stock", label: t("settings.tab.stock"), badge: (s == null ? void 0 : s.options.stockDryRun) ? t("stock.dryRun") : null, tone: "blue" },
|
|
1868
2515
|
{ id: "runs", label: t("settings.tab.runs") }
|
|
1869
2516
|
],
|
|
1870
2517
|
children: [
|
|
@@ -1881,17 +2528,18 @@ const SubiektPage = () => {
|
|
|
1881
2528
|
function Header({
|
|
1882
2529
|
status,
|
|
1883
2530
|
loading,
|
|
2531
|
+
fetching,
|
|
1884
2532
|
lang,
|
|
1885
2533
|
nav,
|
|
1886
2534
|
onAction
|
|
1887
2535
|
}) {
|
|
1888
2536
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
2537
|
+
const client = reactQuery.useQueryClient();
|
|
1889
2538
|
const sync = useSubiektSync();
|
|
1890
2539
|
const check = useSubiektCheck();
|
|
1891
2540
|
const ready = Boolean(status && (status.mode === "demo" || status.configured));
|
|
1892
2541
|
const running = new Set((status == null ? void 0 : status.running) ?? []);
|
|
1893
2542
|
const state = connectionState(status);
|
|
1894
|
-
const references = status ? referencesFor(status.references, lang) : [];
|
|
1895
2543
|
const promptSpec = usePromptSpec();
|
|
1896
2544
|
const community = communityLabels((key, options) => t(key, options), `${t("title")} ${t("by")}`);
|
|
1897
2545
|
const start = async (what) => {
|
|
@@ -1915,33 +2563,30 @@ function Header({
|
|
|
1915
2563
|
}
|
|
1916
2564
|
};
|
|
1917
2565
|
const panel = nav.view !== "guide";
|
|
1918
|
-
const
|
|
2566
|
+
const refreshAction = {
|
|
2567
|
+
key: "refresh",
|
|
2568
|
+
label: t("actions.refresh"),
|
|
2569
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
2570
|
+
loading: fetching && !loading,
|
|
2571
|
+
onClick: () => void client.invalidateQueries({ queryKey: subiektKeys.all })
|
|
2572
|
+
};
|
|
2573
|
+
const checkAction = { key: "check", label: t("actions.check"), icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ShieldCheck, {}), loading: check.isPending, disabled: !ready, onClick: () => void onCheck() };
|
|
1919
2574
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1920
2575
|
IntegrationHeader,
|
|
1921
2576
|
{
|
|
1922
2577
|
icon: /* @__PURE__ */ jsxRuntime.jsx(SubiektIcon, { width: 28, height: 28 }),
|
|
1923
2578
|
title: t("title"),
|
|
1924
|
-
|
|
2579
|
+
featured: { url: "https://medusajs.com/integrations/@koda-plusmedusa-plugin-subiekt-nexo", labels: community.featured },
|
|
1925
2580
|
badges: !loading ? /* @__PURE__ */ jsxRuntime.jsx(ModeBadge, { color: state.tone, label: t(`mode.${state.key}`), title: t("demo.label"), children: (status == null ? void 0 : status.mode) === "demo" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("demo.text") }) : null }) : null,
|
|
1926
2581
|
description: t("subtitle"),
|
|
1927
|
-
|
|
1928
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
subtitle: t("references.subtitle"),
|
|
1936
|
-
open: t("references.open"),
|
|
1937
|
-
review: t("references.review"),
|
|
1938
|
-
since: (since) => t("references.since", { date: monthYear(since, lang) }),
|
|
1939
|
-
rating: (value) => fmtRating(value, lang)
|
|
1940
|
-
}
|
|
1941
|
-
}
|
|
1942
|
-
),
|
|
1943
|
-
/* @__PURE__ */ jsxRuntime.jsx(AddStoreButton, { labels: community.addStore })
|
|
1944
|
-
] }),
|
|
2582
|
+
points: [
|
|
2583
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ShoppingCart, {}), text: t("points.orders") },
|
|
2584
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArchiveBox, {}), text: t("points.wz") },
|
|
2585
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Receipt, {}), text: t("points.sales") },
|
|
2586
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CubeSolid, {}), text: t("points.stock") },
|
|
2587
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Tag, {}), text: t("points.prices") },
|
|
2588
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.LockClosedSolid, {}), text: t("points.safe"), tone: "green" }
|
|
2589
|
+
],
|
|
1945
2590
|
help: /* @__PURE__ */ jsxRuntime.jsx(HelpButtons, { spec: promptSpec, lang, labels: community }),
|
|
1946
2591
|
view: nav.view,
|
|
1947
2592
|
onView: (v) => nav.go(v),
|
|
@@ -1949,19 +2594,21 @@ function Header({
|
|
|
1949
2594
|
primary: panel ? {
|
|
1950
2595
|
key: "stock",
|
|
1951
2596
|
label: running.has("stock") ? t("actions.running") : t("actions.stock"),
|
|
1952
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.
|
|
2597
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CubeSolid, {}),
|
|
1953
2598
|
disabled: !ready || running.has("stock"),
|
|
1954
2599
|
onClick: () => void start("stock")
|
|
1955
2600
|
} : null,
|
|
1956
2601
|
actions: panel ? [
|
|
2602
|
+
refreshAction,
|
|
1957
2603
|
{
|
|
1958
2604
|
key: "events",
|
|
1959
2605
|
label: running.has("events") ? t("actions.running") : t("actions.events"),
|
|
2606
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownTray, {}),
|
|
1960
2607
|
disabled: !ready || running.has("events"),
|
|
1961
2608
|
onClick: () => void start("events")
|
|
1962
2609
|
},
|
|
1963
2610
|
checkAction
|
|
1964
|
-
] : [checkAction]
|
|
2611
|
+
] : [refreshAction, checkAction]
|
|
1965
2612
|
}
|
|
1966
2613
|
);
|
|
1967
2614
|
}
|
|
@@ -1977,39 +2624,48 @@ function ConnectionSection({ status, lang }) {
|
|
|
1977
2624
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
1978
2625
|
const c = status.connection;
|
|
1979
2626
|
const h = c.health;
|
|
1980
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
"
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2627
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2628
|
+
Section,
|
|
2629
|
+
{
|
|
2630
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Link, {}),
|
|
2631
|
+
title: t("connection.title"),
|
|
2632
|
+
badges: /* @__PURE__ */ jsxRuntime.jsx(ConnectionBadge, { status }),
|
|
2633
|
+
points: [
|
|
2634
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), text: t("connection.points.queue") },
|
|
2635
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), text: t("connection.points.documents") },
|
|
2636
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), text: t("connection.points.stock") },
|
|
2637
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), text: t("connection.points.products") }
|
|
2638
|
+
],
|
|
2639
|
+
children: [
|
|
2640
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-2", children: [
|
|
2641
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Field, { label: t("connection.bridge"), children: [
|
|
2642
|
+
h ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2643
|
+
(_a = h.bridge) == null ? void 0 : _a.name,
|
|
2644
|
+
" ",
|
|
2645
|
+
(_b = h.bridge) == null ? void 0 : _b.version,
|
|
2646
|
+
" ",
|
|
2647
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-muted", children: [
|
|
2648
|
+
"(",
|
|
2649
|
+
t("connection.contract", { version: (_c = h.bridge) == null ? void 0 : _c.contract }),
|
|
2650
|
+
")"
|
|
2651
|
+
] })
|
|
2652
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: status.bridgeHost ?? t("connection.none") }),
|
|
2653
|
+
status.bridgeHost && h ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-muted", children: status.bridgeHost }) : null
|
|
2654
|
+
] }),
|
|
2655
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.subiekt"), children: (h == null ? void 0 : h.subiekt) ? [h.subiekt.product, h.subiekt.version].filter(Boolean).join(" ") || t("connection.none") : t("connection.none") }),
|
|
2656
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.database"), children: ((_d = h == null ? void 0 : h.subiekt) == null ? void 0 : _d.database) ?? t("connection.none") }),
|
|
2657
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.company"), children: ((_e = h == null ? void 0 : h.subiekt) == null ? void 0 : _e.company) ?? t("connection.none") }),
|
|
2658
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.warehouse"), children: ((_f = h == null ? void 0 : h.subiekt) == null ? void 0 : _f.warehouse) ?? t("connection.none") }),
|
|
2659
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.checkedAt"), children: fmtDateTime(c.checkedAt, lang) || t("connection.never") }),
|
|
2660
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field, { label: t("connection.eventsReadAt"), children: fmtDateTime(c.eventsReadAt, lang) || t("connection.never") })
|
|
2661
|
+
] }),
|
|
2662
|
+
c.lastError && (!c.reachable || h && !((_g = h.subiekt) == null ? void 0 : _g.connected)) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "error", label: t("connection.lastError"), children: [
|
|
2663
|
+
c.lastError,
|
|
2664
|
+
c.consecutiveFailures > 1 ? ` (${t("connection.failures", { count: c.consecutiveFailures })})` : ""
|
|
2665
|
+
] }) }) : null
|
|
2666
|
+
]
|
|
2667
|
+
}
|
|
2668
|
+
);
|
|
2013
2669
|
}
|
|
2014
2670
|
function StockSection({ run, lang }) {
|
|
2015
2671
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
@@ -2025,44 +2681,45 @@ function StockSection({ run, lang }) {
|
|
|
2025
2681
|
["conflicts", stats.conflicts, true]
|
|
2026
2682
|
] : [];
|
|
2027
2683
|
const samples = stats == null ? void 0 : stats.samples;
|
|
2028
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
(run == null ? void 0 : run.dryRun) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "purple", children: t("stock.dryRun") }) : null,
|
|
2684
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2685
|
+
Section,
|
|
2686
|
+
{
|
|
2687
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CubeSolid, {}),
|
|
2688
|
+
title: t("stock.title"),
|
|
2689
|
+
badges: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2690
|
+
(run == null ? void 0 : run.dryRun) ? /* @__PURE__ */ jsxRuntime.jsx(ToneBadge, { tone: "blue", children: t("stock.dryRun") }) : null,
|
|
2036
2691
|
run ? /* @__PURE__ */ jsxRuntime.jsx(RunStatusBadge, { status: run.status }) : null
|
|
2037
|
-
] })
|
|
2038
|
-
] }),
|
|
2039
|
-
!run ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: t("stock.never") }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2040
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-3", children: [
|
|
2041
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: runSummary(run, t) }),
|
|
2042
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
2043
|
-
fmtDateTime(run.startedAt, lang),
|
|
2044
|
-
", ",
|
|
2045
|
-
fmtDuration(run.durationMs)
|
|
2046
|
-
] })
|
|
2047
2692
|
] }),
|
|
2048
|
-
|
|
2049
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2050
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2051
|
-
]
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
{
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2693
|
+
points: [
|
|
2694
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLongRight, {}), text: t("stock.points.direction") },
|
|
2695
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.MagnifyingGlass, {}), text: t("stock.points.match") }
|
|
2696
|
+
],
|
|
2697
|
+
pointsLabel: t("stock.subtitle"),
|
|
2698
|
+
children: !run ? /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CubeSolid, {}), title: t("stock.never"), compact: true }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2699
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-3", children: [
|
|
2700
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: runSummary(run, t) }),
|
|
2701
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
2702
|
+
fmtDateTime(run.startedAt, lang),
|
|
2703
|
+
", ",
|
|
2704
|
+
fmtDuration(run.durationMs)
|
|
2705
|
+
] })
|
|
2706
|
+
] }),
|
|
2707
|
+
counters.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(StatTiles, { columns: 4, children: counters.map(([key, value, warn]) => /* @__PURE__ */ jsxRuntime.jsx(StatTile, { label: t(`stock.counters.${key}`), value: fmtNumber(value ?? 0, lang), tone: warn && value ? "orange" : "grey" }, key)) }) : null,
|
|
2708
|
+
samples ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: [
|
|
2709
|
+
samples.changes && samples.changes.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2710
|
+
SampleList,
|
|
2711
|
+
{
|
|
2712
|
+
label: t("stock.samples.changes"),
|
|
2713
|
+
items: samples.changes.map((ch) => `${ch.sku ?? "?"}: ${ch.from === null ? "-" : fmtNumber(ch.from, lang)} → ${fmtNumber(ch.to, lang)}`)
|
|
2714
|
+
}
|
|
2715
|
+
) : null,
|
|
2716
|
+
samples.unmatchedVariants && samples.unmatchedVariants.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("stock.samples.unmatchedVariants"), items: samples.unmatchedVariants }) : null,
|
|
2717
|
+
samples.unmatchedSubiekt && samples.unmatchedSubiekt.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("stock.samples.unmatchedSubiekt"), items: samples.unmatchedSubiekt }) : null,
|
|
2718
|
+
samples.conflicts && samples.conflicts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(SampleList, { label: t("stock.samples.conflicts"), items: samples.conflicts }) : null
|
|
2719
|
+
] }) : null
|
|
2720
|
+
] })
|
|
2721
|
+
}
|
|
2722
|
+
);
|
|
2066
2723
|
}
|
|
2067
2724
|
function TaskDetails({ task, lang }) {
|
|
2068
2725
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
@@ -2083,17 +2740,26 @@ function TaskDetails({ task, lang }) {
|
|
|
2083
2740
|
(task.status === "pending" || task.status === "unknown") && task.nextAttemptAt && task.attempts > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: t("tasks.nextAttempt", { time: fmtDateTime(task.nextAttemptAt, lang) }) }) : null
|
|
2084
2741
|
] });
|
|
2085
2742
|
}
|
|
2086
|
-
function TasksSection({
|
|
2743
|
+
function TasksSection({
|
|
2744
|
+
status,
|
|
2745
|
+
lang,
|
|
2746
|
+
poll,
|
|
2747
|
+
onAction,
|
|
2748
|
+
filter,
|
|
2749
|
+
onFilter,
|
|
2750
|
+
initialQuery
|
|
2751
|
+
}) {
|
|
2087
2752
|
var _a, _b;
|
|
2088
2753
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
2089
|
-
const [
|
|
2090
|
-
const [search, setSearch] = react.useState("");
|
|
2754
|
+
const [search, setSearch] = react.useState(initialQuery);
|
|
2091
2755
|
const [offset, setOffset] = react.useState(0);
|
|
2092
|
-
const q = search.trim();
|
|
2093
|
-
const
|
|
2094
|
-
const
|
|
2756
|
+
const q = useDebouncedValue(search).trim();
|
|
2757
|
+
const c = status.counts;
|
|
2758
|
+
const open = c.waiting + c.pending + c.running + c.unknown;
|
|
2759
|
+
const tasks = useSubiektTasks(filter, q, offset, PAGE_SIZE, poll || c.pending + c.running + c.unknown > 0);
|
|
2095
2760
|
const retry = useSubiektRetry();
|
|
2096
2761
|
const rows = ((_a = tasks.data) == null ? void 0 : _a.tasks) ?? [];
|
|
2762
|
+
const products = useKitOrderProducts(rows.map((task) => task.orderId));
|
|
2097
2763
|
react.useEffect(() => setOffset(0), [filter, q]);
|
|
2098
2764
|
const onRetry = async (task) => {
|
|
2099
2765
|
try {
|
|
@@ -2104,139 +2770,249 @@ function TasksSection({ status, lang, poll, onAction }) {
|
|
|
2104
2770
|
ui.toast.error(t("toast.error", { error: errorMessage(err) }));
|
|
2105
2771
|
}
|
|
2106
2772
|
};
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
{
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2773
|
+
const pick = (f) => onFilter(filter === f && f !== "all" ? "all" : f);
|
|
2774
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2775
|
+
Section,
|
|
2776
|
+
{
|
|
2777
|
+
id: "subiekt-tasks",
|
|
2778
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.QueueList, {}),
|
|
2779
|
+
title: t("tasks.title"),
|
|
2780
|
+
points: [
|
|
2781
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListBullet, {}), text: t("tasks.points.order") },
|
|
2782
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}), text: t("tasks.points.retries") },
|
|
2783
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, {}), text: t("tasks.points.failed"), tone: c.failed ? "orange" : "grey" }
|
|
2784
|
+
],
|
|
2785
|
+
pointsLabel: t("tasks.subtitle"),
|
|
2786
|
+
actions: /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { value: search, onChange: setSearch, placeholder: t("tasks.search") }),
|
|
2787
|
+
children: [
|
|
2788
|
+
/* @__PURE__ */ jsxRuntime.jsxs(FilterBar, { children: [
|
|
2789
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListBullet, {}), label: t("tasks.filters.all"), active: filter === "all", onClick: () => pick("all") }),
|
|
2790
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterDivider, {}),
|
|
2791
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, {}), label: t("tasks.filters.attention"), count: c.failed, attention: true, active: filter === "attention", onClick: () => pick("attention") }),
|
|
2792
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), label: t("tasks.filters.open"), count: open, active: filter === "open", onClick: () => pick("open") }),
|
|
2793
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, {}), label: t("tasks.filters.done"), active: filter === "done", onClick: () => pick("done") })
|
|
2794
|
+
] }),
|
|
2795
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
2796
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2797
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: /* @__PURE__ */ jsxRuntime.jsx(StoreColumn, { label: t("tasks.columns.order"), hint: t("store.orderMatching") }) }),
|
|
2798
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("tasks.columns.products") }),
|
|
2799
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("tasks.columns.operation") }),
|
|
2800
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("tasks.columns.document") }),
|
|
2801
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("tasks.columns.status") }),
|
|
2802
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: t("tasks.columns.attempts") }),
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("tasks.columns.details") }),
|
|
2804
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, {})
|
|
2805
|
+
] }) }),
|
|
2806
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: tasks.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(KitSkeletonRows, { cols: 8, rows: 4 }) : rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyTableRow, { cols: 8, icon: filter === "attention" ? /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.QueueList, {}), title: t(`tasks.emptyBy.${filter}`) }) : rows.map((task) => {
|
|
2807
|
+
var _a2;
|
|
2808
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "[&_td]:py-2.5", children: [
|
|
2809
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-[260px]", children: /* @__PURE__ */ jsxRuntime.jsx(StoreOrderCell, { orderId: task.orderId, displayId: task.displayId }) }),
|
|
2810
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(KitOrderProductsCell, { data: (_a2 = products.data) == null ? void 0 : _a2[task.orderId], loading: products.isLoading, displayId: task.displayId }) }),
|
|
2811
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap", children: task.kind === "order.document" && (task.documentKind === "fs" || task.documentKind === "pa") ? t(`tasks.documentKinds.${task.documentKind}`) : t(`tasks.kinds.${task.kind}`) }),
|
|
2812
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap font-mono txt-compact-xsmall", children: task.documentNumber ?? "" }),
|
|
2813
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(TaskStatusBadge, { status: task.status, dot: true }) }),
|
|
2814
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right tabular-nums", children: task.attempts }),
|
|
2815
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-md", children: /* @__PURE__ */ jsxRuntime.jsx(TaskDetails, { task, lang }) }),
|
|
2816
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2817
|
+
RowActions,
|
|
2818
|
+
{
|
|
2819
|
+
actions: [
|
|
2820
|
+
{
|
|
2821
|
+
key: "send",
|
|
2822
|
+
label: task.status === "waiting" ? t("actions.send") : t("actions.retry"),
|
|
2823
|
+
icon: task.status === "waiting" ? /* @__PURE__ */ jsxRuntime.jsx(icons.PaperPlane, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
2824
|
+
loading: retry.isPending && retry.variables === task.id,
|
|
2825
|
+
hidden: !(task.status === "failed" || task.status === "unknown" || task.status === "pending" && task.attempts > 0 || task.status === "waiting"),
|
|
2826
|
+
onClick: () => void onRetry(task)
|
|
2827
|
+
}
|
|
2828
|
+
]
|
|
2829
|
+
}
|
|
2830
|
+
) })
|
|
2831
|
+
] }, task.id);
|
|
2832
|
+
}) })
|
|
2833
|
+
] }) }),
|
|
2834
|
+
/* @__PURE__ */ jsxRuntime.jsx(Pager, { offset, limit: PAGE_SIZE, count: ((_b = tasks.data) == null ? void 0 : _b.count) ?? 0, onChange: setOffset })
|
|
2835
|
+
]
|
|
2836
|
+
}
|
|
2837
|
+
);
|
|
2150
2838
|
}
|
|
2151
|
-
|
|
2839
|
+
const DOC_KINDS = [
|
|
2840
|
+
{ kind: "ZK", icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ShoppingCart, {}), count: (c) => c.zk },
|
|
2841
|
+
{ kind: "WZ", icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArchiveBox, {}), count: (c) => c.wz },
|
|
2842
|
+
{ kind: "FS", icon: /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, {}), count: (c) => c.fs },
|
|
2843
|
+
{ kind: "PA", icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Receipt, {}), count: (c) => c.pa }
|
|
2844
|
+
];
|
|
2845
|
+
function DocumentsSection({
|
|
2846
|
+
lang,
|
|
2847
|
+
poll,
|
|
2848
|
+
kind,
|
|
2849
|
+
onKind,
|
|
2850
|
+
counts,
|
|
2851
|
+
initialQuery
|
|
2852
|
+
}) {
|
|
2152
2853
|
var _a, _b;
|
|
2153
2854
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
2154
|
-
const [
|
|
2855
|
+
const [search, setSearch] = react.useState(initialQuery);
|
|
2856
|
+
const q = useDebouncedValue(search).trim();
|
|
2155
2857
|
const [offset, setOffset] = react.useState(0);
|
|
2156
|
-
const docs = useSubiektDocuments(kind,
|
|
2858
|
+
const docs = useSubiektDocuments(kind, q, offset, PAGE_SIZE, poll);
|
|
2157
2859
|
const rows = ((_a = docs.data) == null ? void 0 : _a.documents) ?? [];
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
{
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
)
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
d.related.map((r) => r.number).join(", ")
|
|
2189
|
-
] }) : null
|
|
2860
|
+
const products = useKitOrderProducts(rows.map((d) => d.orderId));
|
|
2861
|
+
react.useEffect(() => setOffset(0), [kind, q]);
|
|
2862
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2863
|
+
Section,
|
|
2864
|
+
{
|
|
2865
|
+
id: "subiekt-documents",
|
|
2866
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, {}),
|
|
2867
|
+
title: t("documents.title"),
|
|
2868
|
+
points: [
|
|
2869
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Link, {}), text: t("documents.points.tag") },
|
|
2870
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArchiveBox, {}), text: t("documents.points.warehouse") },
|
|
2871
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Receipt, {}), text: t("documents.points.ksef") }
|
|
2872
|
+
],
|
|
2873
|
+
pointsLabel: t("documents.subtitle"),
|
|
2874
|
+
actions: /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { value: search, onChange: setSearch, placeholder: t("documents.search") }),
|
|
2875
|
+
children: [
|
|
2876
|
+
/* @__PURE__ */ jsxRuntime.jsxs(FilterBar, { children: [
|
|
2877
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterButton, { icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListBullet, {}), label: t("documents.filters.all"), count: counts == null ? void 0 : counts.documents, active: kind === "all", onClick: () => onKind("all") }),
|
|
2878
|
+
/* @__PURE__ */ jsxRuntime.jsx(FilterDivider, {}),
|
|
2879
|
+
DOC_KINDS.map((d) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2880
|
+
FilterButton,
|
|
2881
|
+
{
|
|
2882
|
+
icon: d.icon,
|
|
2883
|
+
label: t(`documents.filters.${d.kind}`),
|
|
2884
|
+
count: counts ? d.count(counts) : void 0,
|
|
2885
|
+
active: kind === d.kind,
|
|
2886
|
+
onClick: () => onKind(kind === d.kind ? "all" : d.kind)
|
|
2887
|
+
},
|
|
2888
|
+
d.kind
|
|
2889
|
+
))
|
|
2190
2890
|
] }),
|
|
2191
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2891
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
2892
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2893
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("documents.columns.number") }),
|
|
2894
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: /* @__PURE__ */ jsxRuntime.jsx(StoreColumn, { label: t("documents.columns.order"), hint: t("store.orderMatching") }) }),
|
|
2895
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("documents.columns.products") }),
|
|
2896
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("documents.columns.issued") }),
|
|
2897
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("documents.columns.source") }),
|
|
2898
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("documents.columns.ksef") }),
|
|
2899
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("documents.columns.status") })
|
|
2900
|
+
] }) }),
|
|
2901
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: docs.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(KitSkeletonRows, { cols: 7, rows: 4 }) : rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyTableRow, { cols: 7, icon: /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentText, {}), title: t("documents.empty") }) : rows.map((d) => {
|
|
2902
|
+
var _a2;
|
|
2903
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "[&_td]:py-2.5", children: [
|
|
2904
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { className: "whitespace-nowrap font-mono txt-compact-xsmall", children: [
|
|
2905
|
+
d.number,
|
|
2906
|
+
d.related.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-muted", children: [
|
|
2907
|
+
" ← ",
|
|
2908
|
+
d.related.map((r) => r.number).join(", ")
|
|
2909
|
+
] }) : null
|
|
2910
|
+
] }),
|
|
2911
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-[260px]", children: /* @__PURE__ */ jsxRuntime.jsx(StoreOrderCell, { orderId: d.orderId, displayId: d.displayId }) }),
|
|
2912
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: d.orderId ? /* @__PURE__ */ jsxRuntime.jsx(KitOrderProductsCell, { data: (_a2 = products.data) == null ? void 0 : _a2[d.orderId], loading: products.isLoading, displayId: d.displayId }) : null }),
|
|
2913
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap", children: fmtDateTime(d.issuedAt, lang) }),
|
|
2914
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: t(`documents.sources.${d.source}`, { defaultValue: d.source }) }),
|
|
2915
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap font-mono txt-compact-xsmall", children: d.ksefNumber ? d.ksefNumber : d.kind === "FS" && d.status !== "canceled" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans text-ui-fg-muted", children: t("documents.ksefWaiting") }) : "" }),
|
|
2916
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatusBadge, { status: d.status, dot: true }) })
|
|
2917
|
+
] }, d.id);
|
|
2918
|
+
}) })
|
|
2919
|
+
] }) }),
|
|
2920
|
+
/* @__PURE__ */ jsxRuntime.jsx(Pager, { offset, limit: PAGE_SIZE, count: ((_b = docs.data) == null ? void 0 : _b.count) ?? 0, onChange: setOffset })
|
|
2921
|
+
]
|
|
2922
|
+
}
|
|
2923
|
+
);
|
|
2200
2924
|
}
|
|
2201
2925
|
function RunsSection({ lang, poll }) {
|
|
2202
2926
|
var _a;
|
|
2203
2927
|
const { t } = reactI18next.useTranslation("subiekt");
|
|
2204
2928
|
const runs = useSubiektRuns(poll);
|
|
2205
2929
|
const rows = ((_a = runs.data) == null ? void 0 : _a.runs) ?? [];
|
|
2206
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2213
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2930
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2931
|
+
Section,
|
|
2932
|
+
{
|
|
2933
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}),
|
|
2934
|
+
title: t("runs.title"),
|
|
2935
|
+
points: [
|
|
2936
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.BarsArrowDown, {}), text: t("runs.points.newest") },
|
|
2937
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Bolt, {}), text: t("runs.points.jobs") }
|
|
2938
|
+
],
|
|
2939
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
2940
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2941
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("runs.columns.kind") }),
|
|
2942
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("runs.columns.trigger") }),
|
|
2943
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("runs.columns.status") }),
|
|
2944
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("runs.columns.message") }),
|
|
2945
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: t("runs.columns.started") }),
|
|
2946
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: t("runs.columns.duration") })
|
|
2947
|
+
] }) }),
|
|
2948
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: runs.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(KitSkeletonRows, { cols: 6, rows: 4 }) : rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyTableRow, { cols: 6, icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, {}), title: t("runs.empty") }) : rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { className: "[&_td]:py-2.5", children: [
|
|
2949
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap", children: t(`runs.kinds.${r.kind}`) }),
|
|
2950
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap text-ui-fg-subtle", children: t(`runs.triggers.${r.trigger}`, { defaultValue: r.trigger }) }),
|
|
2951
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(RunStatusBadge, { status: r.status, dot: true }) }),
|
|
2952
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-lg", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: runSummary(r, t) }) }),
|
|
2953
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "whitespace-nowrap", children: fmtDateTime(r.startedAt, lang) }),
|
|
2954
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right tabular-nums", children: fmtDuration(r.durationMs) })
|
|
2955
|
+
] }, r.id)) })
|
|
2956
|
+
] }) })
|
|
2957
|
+
}
|
|
2958
|
+
);
|
|
2227
2959
|
}
|
|
2228
2960
|
const config = adminSdk.defineRouteConfig({
|
|
2229
2961
|
label: "Subiekt nexo",
|
|
2230
2962
|
icon: SubiektIcon
|
|
2231
2963
|
});
|
|
2964
|
+
const communityEn = {
|
|
2965
|
+
prompt: {
|
|
2966
|
+
button: "Copy prompt",
|
|
2967
|
+
title: "Add this integration to your store",
|
|
2968
|
+
text: "Paste it into Claude Code, Cursor or another AI agent opened in your Medusa project. The agent installs this version of the plugin, sets it up like here and shows you its notes before it saves them.",
|
|
2969
|
+
copy: "Copy",
|
|
2970
|
+
copied: "Prompt copied",
|
|
2971
|
+
failed: "Could not copy. Select the text and copy it by hand."
|
|
2972
|
+
},
|
|
2973
|
+
discord: {
|
|
2974
|
+
button: "Help on Discord",
|
|
2975
|
+
title: "Join the Koda Plus server on Discord"
|
|
2976
|
+
},
|
|
2977
|
+
featured: {
|
|
2978
|
+
badge: "Medusa featured integration",
|
|
2979
|
+
title: "Featured in the Medusa integrations catalog. Opens its page there in a new tab."
|
|
2980
|
+
}
|
|
2981
|
+
};
|
|
2982
|
+
const communityPl = {
|
|
2983
|
+
prompt: {
|
|
2984
|
+
button: "Kopiuj prompt",
|
|
2985
|
+
title: "Dodaj tę integrację do swojego sklepu",
|
|
2986
|
+
text: "Wklej go w Claude Code, Cursorze albo innym agencie AI otwartym w projekcie Twojej Medusy. Agent zainstaluje tę wersję wtyczki, ustawi ją tak jak tutaj i pokaże Ci notatki, zanim je zapisze.",
|
|
2987
|
+
copy: "Kopiuj",
|
|
2988
|
+
copied: "Prompt skopiowany",
|
|
2989
|
+
failed: "Nie udało się skopiować. Zaznacz tekst i skopiuj go ręcznie."
|
|
2990
|
+
},
|
|
2991
|
+
discord: {
|
|
2992
|
+
button: "Pomoc na Discordzie",
|
|
2993
|
+
title: "Dołącz do serwera Koda Plus na Discordzie"
|
|
2994
|
+
},
|
|
2995
|
+
featured: {
|
|
2996
|
+
badge: "Wyróżniona przez Medusę",
|
|
2997
|
+
title: "Wyróżniona w katalogu integracji Medusy. Otwiera jej stronę w katalogu w nowej karcie."
|
|
2998
|
+
}
|
|
2999
|
+
};
|
|
2232
3000
|
const en = {
|
|
2233
3001
|
title: "Subiekt nexo",
|
|
2234
3002
|
by: "by Koda Plus",
|
|
2235
3003
|
subtitle: "Orders become ZK documents in Subiekt nexo PRO, the WZ issued in the warehouse comes back to the order, sales documents carry their KSeF number, and stock and prices flow from Subiekt to Medusa.",
|
|
3004
|
+
points: {
|
|
3005
|
+
orders: "Order becomes a ZK",
|
|
3006
|
+
wz: "WZ back from the warehouse",
|
|
3007
|
+
sales: "Invoices with KSeF numbers",
|
|
3008
|
+
stock: "Stock from Subiekt",
|
|
3009
|
+
prices: "Prices as a plan first",
|
|
3010
|
+
safe: "Writes only once armed"
|
|
3011
|
+
},
|
|
2236
3012
|
view: { panel: "Panel", guide: "Setup guide" },
|
|
2237
3013
|
settings: {
|
|
2238
3014
|
title: "Settings",
|
|
2239
|
-
subtitle: "The technical side of the integration
|
|
3015
|
+
subtitle: "The technical side of the integration",
|
|
2240
3016
|
tab: {
|
|
2241
3017
|
connection: "Connection",
|
|
2242
3018
|
bridge: "Bridge",
|
|
@@ -2255,6 +3031,7 @@ const en = {
|
|
|
2255
3031
|
},
|
|
2256
3032
|
actions: {
|
|
2257
3033
|
moreActions: "More actions",
|
|
3034
|
+
refresh: "Refresh",
|
|
2258
3035
|
check: "Check connection",
|
|
2259
3036
|
checking: "Checking",
|
|
2260
3037
|
stock: "Sync stock",
|
|
@@ -2286,7 +3063,9 @@ const en = {
|
|
|
2286
3063
|
attention: "Need attention",
|
|
2287
3064
|
zk: "ZK documents",
|
|
2288
3065
|
wz: "WZ documents",
|
|
2289
|
-
sales: "FS and PA"
|
|
3066
|
+
sales: "FS and PA",
|
|
3067
|
+
hintAttention: "Send again below",
|
|
3068
|
+
hintWaiting: "Sent after payment"
|
|
2290
3069
|
},
|
|
2291
3070
|
store: {
|
|
2292
3071
|
openOrder: "Open order",
|
|
@@ -2314,11 +3093,12 @@ const en = {
|
|
|
2314
3093
|
never: "never",
|
|
2315
3094
|
none: "none",
|
|
2316
3095
|
eventsReadAt: "Documents read",
|
|
2317
|
-
|
|
3096
|
+
points: { queue: "Queue every minute", documents: "Documents every 2 min", stock: "Stock every 10 min", products: "Products every hour" }
|
|
2318
3097
|
},
|
|
2319
3098
|
bridge: {
|
|
2320
3099
|
title: "Bridge",
|
|
2321
3100
|
subtitle: "What the last check of the bridge said. Click Check connection for a fresh one.",
|
|
3101
|
+
points: { last: "From the last check", fresh: "Check connection reads again" },
|
|
2322
3102
|
versions: "Versions",
|
|
2323
3103
|
versionsValue: "bridge {{bridge}}, contract {{contract}}, plugin {{plugin}}",
|
|
2324
3104
|
sdk: "nexo SDK and database",
|
|
@@ -2397,6 +3177,7 @@ const en = {
|
|
|
2397
3177
|
writers: {
|
|
2398
3178
|
title: "Writers",
|
|
2399
3179
|
subtitle: "Every write added in 0.2.0 needs its option in medusa-config.ts and a person arming it here. An option set to false wins.",
|
|
3180
|
+
points: { option: "Option in medusa-config.ts", person: "Armed here by a person", falseWins: "Option false wins" },
|
|
2400
3181
|
demoNote: "Demo: armed writers only simulate. Nothing in this store changes.",
|
|
2401
3182
|
names: {
|
|
2402
3183
|
prices: "Prices from Subiekt",
|
|
@@ -2443,6 +3224,7 @@ const en = {
|
|
|
2443
3224
|
products: {
|
|
2444
3225
|
title: "Products from Subiekt",
|
|
2445
3226
|
subtitle: "Prices from Subiekt next to the store products they update, and Subiekt products the store does not sell yet. Everything is a plan first: nothing changes until someone switches its writer on in Settings.",
|
|
3227
|
+
points: { plan: "A plan first", match: "EAN first, then SKU", writer: "Changes after arming" },
|
|
2446
3228
|
matching: "Subiekt products are matched to store variants by EAN first, then by the SKU against the Subiekt symbol. A code used twice is a conflict and is never guessed.",
|
|
2447
3229
|
matchedKey: "Matched by {{by}}: {{code}}",
|
|
2448
3230
|
settings: "Prices from {{level}} ({{type}}) to {{target}}, in {{currency}}.",
|
|
@@ -2478,10 +3260,11 @@ const en = {
|
|
|
2478
3260
|
columns: { product: "Product in Subiekt", change: "Change", store: "Product in the store", matched: "Matched by", status: "Status", details: "Details" },
|
|
2479
3261
|
matchedBy: { ean: "EAN", sku: "SKU" },
|
|
2480
3262
|
newProduct: "new, {{price}}",
|
|
2481
|
-
empty: "Nothing in this plan
|
|
3263
|
+
empty: "Nothing in this plan",
|
|
2482
3264
|
search: "Symbol, SKU or EAN",
|
|
2483
3265
|
quarantine: "Quarantined after repeated failures",
|
|
2484
3266
|
quarantineHint: "The writer skips these until you release them. Fix the cause first (the last error says what failed).",
|
|
3267
|
+
quarantinePoints: { skipped: "Skipped until released", fix: "Fix the cause first" },
|
|
2485
3268
|
samples: { conflicts: "Conflicts, never guessed", unmatchedVariants: "Variants without a match (SKU)", noPrice: "Without a price in this level" },
|
|
2486
3269
|
blocked: {
|
|
2487
3270
|
currency_mismatch: "The price level is in another currency than priceCurrency: nothing was planned.",
|
|
@@ -2491,11 +3274,11 @@ const en = {
|
|
|
2491
3274
|
tasks: {
|
|
2492
3275
|
title: "Queue",
|
|
2493
3276
|
subtitle: "Orders on their way to Subiekt: every ZK, WZ, invoice or receipt the store asked for, and how it went. A send that failed waits here for you, with a Send again button.",
|
|
2494
|
-
|
|
3277
|
+
points: { order: "One row per call", retries: "Retries by itself", failed: "Failed waits for you" },
|
|
3278
|
+
emptyBy: { attention: "Nothing needs attention", open: "Nothing on its way", done: "Nothing sent yet", all: "Queue empty" },
|
|
2495
3279
|
filters: { attention: "Need attention", open: "Open", done: "Done", all: "All" },
|
|
2496
3280
|
search: "Order number",
|
|
2497
|
-
|
|
2498
|
-
columns: { order: "Order in the store", operation: "Operation", status: "Status", attempts: "Attempts", document: "Document in Subiekt", details: "Details", actions: "" },
|
|
3281
|
+
columns: { order: "Order in the store", products: "Products", operation: "Operation", status: "Status", attempts: "Attempts", document: "Document in Subiekt", details: "Details", actions: "" },
|
|
2499
3282
|
kinds: { "order.create": "Create ZK", "order.cancel": "Cancel ZK", "order.fulfill": "Issue WZ", "order.document": "Issue sales document" },
|
|
2500
3283
|
documentKinds: { fs: "Issue FS", pa: "Issue PA" },
|
|
2501
3284
|
statuses: {
|
|
@@ -2518,17 +3301,20 @@ const en = {
|
|
|
2518
3301
|
documents: {
|
|
2519
3302
|
title: "Documents",
|
|
2520
3303
|
subtitle: "What Subiekt issued for your orders: ZK, WZ, invoices and receipts, each next to its order in the store.",
|
|
3304
|
+
points: { tag: "Order tag in the notes", warehouse: "WZ from the warehouse", ksef: "KSeF number on FS" },
|
|
3305
|
+
search: "Document or order number",
|
|
2521
3306
|
filters: { all: "All", ZK: "ZK", WZ: "WZ", FS: "FS", PA: "PA" },
|
|
2522
|
-
empty: "No documents yet
|
|
2523
|
-
columns: { number: "Number", order: "Order in the store", issued: "Issued", source: "Source", status: "Status", ksef: "KSeF number" },
|
|
2524
|
-
sources: { bridge: "Medusa", subiekt: "Warehouse", demo: "Demo" },
|
|
3307
|
+
empty: "No documents yet",
|
|
3308
|
+
columns: { number: "Number", order: "Order in the store", products: "Products", issued: "Issued", source: "Source", status: "Status", ksef: "KSeF number" },
|
|
3309
|
+
sources: { bridge: "Medusa", subiekt: "Warehouse", demo: "Demo", linked: "Linked by hand" },
|
|
2525
3310
|
statuses: { open: "Open", canceled: "Canceled", completed: "Completed" },
|
|
2526
3311
|
ksefWaiting: "waiting for KSeF"
|
|
2527
3312
|
},
|
|
2528
3313
|
stock: {
|
|
2529
3314
|
title: "Stock",
|
|
2530
3315
|
subtitle: "Subiekt to Medusa, by EAN first, then SKU against the product symbol.",
|
|
2531
|
-
|
|
3316
|
+
points: { direction: "Subiekt to Medusa", match: "EAN first, then SKU" },
|
|
3317
|
+
never: "No stock sync yet",
|
|
2532
3318
|
dryRun: "Dry run",
|
|
2533
3319
|
counters: {
|
|
2534
3320
|
subiektProducts: "Products in Subiekt",
|
|
@@ -2549,9 +3335,10 @@ const en = {
|
|
|
2549
3335
|
},
|
|
2550
3336
|
runs: {
|
|
2551
3337
|
title: "History",
|
|
2552
|
-
empty: "No runs yet
|
|
3338
|
+
empty: "No runs yet",
|
|
3339
|
+
points: { newest: "Newest first", jobs: "Background jobs and clicks" },
|
|
2553
3340
|
columns: { kind: "Job", trigger: "Trigger", status: "Result", message: "Summary", started: "Started", duration: "Time" },
|
|
2554
|
-
kinds: { stock: "Stock", events: "Documents", tasks: "Queue", health: "Connection", products: "Products" },
|
|
3341
|
+
kinds: { stock: "Stock", events: "Documents", tasks: "Queue", health: "Connection", products: "Products", catchup: "Safety net" },
|
|
2555
3342
|
triggers: { schedule: "Schedule", manual: "Manual", webhook: "Webhook", event: "Event", auto: "Automatic" },
|
|
2556
3343
|
statuses: { success: "OK", partial: "Partial", error: "Error", skipped: "Skipped" },
|
|
2557
3344
|
summary: {
|
|
@@ -2563,15 +3350,27 @@ const en = {
|
|
|
2563
3350
|
eventsNone: "Nothing new.",
|
|
2564
3351
|
health: "Bridge and Subiekt answer.",
|
|
2565
3352
|
productsPlan: "Plan: {{prices}} price change(s), {{creates}} new product(s). No writer armed.",
|
|
2566
|
-
productsApplied: "{{prices}} price change(s), {{creates}} new product(s) planned, {{applied}} applied, {{failed}} failed."
|
|
3353
|
+
productsApplied: "{{prices}} price change(s), {{creates}} new product(s) planned, {{applied}} applied, {{failed}} failed.",
|
|
3354
|
+
catchup: "{{queued}} order(s) without a ZK task queued, {{released}} released after the payment.",
|
|
3355
|
+
catchupErrors: "{{queued}} order(s) without a ZK task queued, {{released}} released after the payment, {{errors}} error(s)."
|
|
2567
3356
|
}
|
|
2568
3357
|
},
|
|
2569
3358
|
widget: {
|
|
2570
3359
|
title: "Subiekt nexo",
|
|
2571
3360
|
demo: "Demo",
|
|
2572
3361
|
more: "Panel",
|
|
2573
|
-
none: "
|
|
2574
|
-
waiting: "
|
|
3362
|
+
none: "Not sent to Subiekt",
|
|
3363
|
+
waiting: "ZK after the payment capture",
|
|
3364
|
+
state: { notSent: "Not sent", waiting: "Waiting for payment", sending: "Sending", attention: "Needs attention", inSubiekt: "In Subiekt" },
|
|
3365
|
+
run: {
|
|
3366
|
+
queue: "Waiting in the Medusa queue",
|
|
3367
|
+
queueShort: "Queue",
|
|
3368
|
+
bridge: "The bridge issues the document",
|
|
3369
|
+
bridgeShort: "Bridge",
|
|
3370
|
+
document: "The number comes back",
|
|
3371
|
+
documentShort: "Number",
|
|
3372
|
+
done: "In Subiekt"
|
|
3373
|
+
},
|
|
2575
3374
|
send: "Send to Subiekt now",
|
|
2576
3375
|
sent: "Queued. The ZK appears here in a few seconds.",
|
|
2577
3376
|
ksef: "KSeF {{number}}",
|
|
@@ -2580,7 +3379,29 @@ const en = {
|
|
|
2580
3379
|
issuePa: "Issue receipt (PA)",
|
|
2581
3380
|
issued: "Queued. The document appears here in a few seconds.",
|
|
2582
3381
|
autoOff: "Automatic sales documents are off: arm the writer on the Subiekt page.",
|
|
2583
|
-
autoOn: "The sales document is issued automatically after the {{after}}."
|
|
3382
|
+
autoOn: "The sales document is issued automatically after the {{after}}.",
|
|
3383
|
+
kinds: { ZK: "Order from customer (ZK)", WZ: "Goods issue (WZ)", FS: "Invoice (FS)", PA: "Receipt (PA)" },
|
|
3384
|
+
warehouse: "warehouse {{warehouse}}",
|
|
3385
|
+
related: "From {{numbers}}",
|
|
3386
|
+
zkCompleted: "Realized in Subiekt: the goods were released.",
|
|
3387
|
+
check: {
|
|
3388
|
+
button: "Check in Subiekt",
|
|
3389
|
+
again: "Check again",
|
|
3390
|
+
hint: "No ZK here? Check in Subiekt: if it is already there, link it to the order.",
|
|
3391
|
+
title: "In Subiekt now",
|
|
3392
|
+
at: "checked {{time}}",
|
|
3393
|
+
nothing: "Subiekt has no document for this order.",
|
|
3394
|
+
inSubiekt: "In Subiekt: {{status}}",
|
|
3395
|
+
notReported: "Subiekt does not report it (deleted there, or another database)",
|
|
3396
|
+
canceledThere: "Canceled in Subiekt.",
|
|
3397
|
+
states: { missing: "Not in Medusa", status_differs: "Medusa shows {{status}}", same: "Recorded", only_local: "Only in Medusa" },
|
|
3398
|
+
link: "Link",
|
|
3399
|
+
update: "Update status",
|
|
3400
|
+
linkHint: "Records it in Medusa. Nothing changes in Subiekt, no second document.",
|
|
3401
|
+
updateHint: "Records the status Subiekt shows. Nothing changes in Subiekt.",
|
|
3402
|
+
linked: "{{number}} linked to the order.",
|
|
3403
|
+
updated: "{{number}} updated."
|
|
3404
|
+
}
|
|
2584
3405
|
},
|
|
2585
3406
|
toast: {
|
|
2586
3407
|
started: "Started. Results appear here in a moment.",
|
|
@@ -2591,43 +3412,7 @@ const en = {
|
|
|
2591
3412
|
released: "Released. The next run tries it again.",
|
|
2592
3413
|
error: "Something went wrong: {{error}}"
|
|
2593
3414
|
},
|
|
2594
|
-
|
|
2595
|
-
title: "Running in stores built by Koda Plus",
|
|
2596
|
-
subtitle: "Live stores implemented by Koda Plus that run on this integration every day.",
|
|
2597
|
-
open: "Open the store",
|
|
2598
|
-
since: "Since {{date}}",
|
|
2599
|
-
badgeOne: "Running in 1 store",
|
|
2600
|
-
badgeMany: "Running in {{count}} stores",
|
|
2601
|
-
review: "Read the review"
|
|
2602
|
-
},
|
|
2603
|
-
community: {
|
|
2604
|
-
addStore: {
|
|
2605
|
-
button: "Add your store",
|
|
2606
|
-
title: "Does your store run on this integration?",
|
|
2607
|
-
text: "Tell us about it. Once we check it, the store joins this list with a link and its rating.",
|
|
2608
|
-
name: "Store name",
|
|
2609
|
-
url: "Store address",
|
|
2610
|
-
note: "A few words about the setup (optional)",
|
|
2611
|
-
send: "Send the request",
|
|
2612
|
-
copy: "Copy the text",
|
|
2613
|
-
copied: "Request copied, paste it into a mail to hello@koda.plus",
|
|
2614
|
-
hint: "Your mail app opens with the message to {{email}} ready to send.",
|
|
2615
|
-
subject: "A store for {{integration}}",
|
|
2616
|
-
greeting: "Hello, my store runs on {{integration}}. Please add it to the list of stores."
|
|
2617
|
-
},
|
|
2618
|
-
prompt: {
|
|
2619
|
-
button: "Copy prompt",
|
|
2620
|
-
title: "Add this integration to your store",
|
|
2621
|
-
text: "Paste it into Claude Code, Cursor or another AI agent opened in your Medusa project. The agent installs the plugin, sets it up like here and leaves notes for further work.",
|
|
2622
|
-
copy: "Copy again",
|
|
2623
|
-
copied: "Prompt copied",
|
|
2624
|
-
failed: "Could not copy. Select the text and copy it by hand."
|
|
2625
|
-
},
|
|
2626
|
-
discord: {
|
|
2627
|
-
button: "Help on Discord",
|
|
2628
|
-
title: "Join the Koda Plus server on Discord"
|
|
2629
|
-
}
|
|
2630
|
-
},
|
|
3415
|
+
community: communityEn,
|
|
2631
3416
|
guide: {
|
|
2632
3417
|
intro: {
|
|
2633
3418
|
title: "Connect Medusa to Subiekt nexo PRO",
|
|
@@ -2889,10 +3674,18 @@ const pl$1 = {
|
|
|
2889
3674
|
title: "Subiekt nexo",
|
|
2890
3675
|
by: "by Koda Plus",
|
|
2891
3676
|
subtitle: "Zamówienia trafiają do Subiekta nexo PRO jako dokumenty ZK, WZ wystawione w magazynie wraca do zamówienia, dokumenty sprzedaży dostają numer KSeF, a stany i ceny płyną z Subiekta do Medusy.",
|
|
3677
|
+
points: {
|
|
3678
|
+
orders: "Zamówienie jako ZK",
|
|
3679
|
+
wz: "WZ wraca z magazynu",
|
|
3680
|
+
sales: "Faktury z numerem KSeF",
|
|
3681
|
+
stock: "Stany z Subiekta",
|
|
3682
|
+
prices: "Ceny najpierw jako plan",
|
|
3683
|
+
safe: "Zapis dopiero po włączeniu"
|
|
3684
|
+
},
|
|
2892
3685
|
view: { panel: "Panel", guide: "Przewodnik wdrożenia" },
|
|
2893
3686
|
settings: {
|
|
2894
3687
|
title: "Ustawienia",
|
|
2895
|
-
subtitle: "Techniczna strona integracji
|
|
3688
|
+
subtitle: "Techniczna strona integracji",
|
|
2896
3689
|
tab: {
|
|
2897
3690
|
connection: "Połączenie",
|
|
2898
3691
|
bridge: "Most",
|
|
@@ -2911,6 +3704,7 @@ const pl$1 = {
|
|
|
2911
3704
|
},
|
|
2912
3705
|
actions: {
|
|
2913
3706
|
moreActions: "Więcej akcji",
|
|
3707
|
+
refresh: "Odśwież",
|
|
2914
3708
|
check: "Sprawdź połączenie",
|
|
2915
3709
|
checking: "Sprawdzam",
|
|
2916
3710
|
stock: "Synchronizuj stany",
|
|
@@ -2942,7 +3736,9 @@ const pl$1 = {
|
|
|
2942
3736
|
attention: "Wymagają uwagi",
|
|
2943
3737
|
zk: "Dokumenty ZK",
|
|
2944
3738
|
wz: "Dokumenty WZ",
|
|
2945
|
-
sales: "FS i PA"
|
|
3739
|
+
sales: "FS i PA",
|
|
3740
|
+
hintAttention: "Wyślij ponownie niżej",
|
|
3741
|
+
hintWaiting: "Wysyłka po płatności"
|
|
2946
3742
|
},
|
|
2947
3743
|
store: {
|
|
2948
3744
|
openOrder: "Otwórz zamówienie",
|
|
@@ -2970,11 +3766,12 @@ const pl$1 = {
|
|
|
2970
3766
|
never: "nigdy",
|
|
2971
3767
|
none: "brak",
|
|
2972
3768
|
eventsReadAt: "Dokumenty pobrane",
|
|
2973
|
-
|
|
3769
|
+
points: { queue: "Kolejka co minutę", documents: "Dokumenty co 2 min", stock: "Stany co 10 min", products: "Produkty co godzinę" }
|
|
2974
3770
|
},
|
|
2975
3771
|
bridge: {
|
|
2976
3772
|
title: "Most",
|
|
2977
3773
|
subtitle: "Co powiedziało ostatnie sprawdzenie mostu. Świeży odczyt daje przycisk Sprawdź połączenie.",
|
|
3774
|
+
points: { last: "Z ostatniego sprawdzenia", fresh: "Sprawdź połączenie czyta od nowa" },
|
|
2978
3775
|
versions: "Wersje",
|
|
2979
3776
|
versionsValue: "most {{bridge}}, kontrakt {{contract}}, wtyczka {{plugin}}",
|
|
2980
3777
|
sdk: "nexo SDK i baza",
|
|
@@ -3053,6 +3850,7 @@ const pl$1 = {
|
|
|
3053
3850
|
writers: {
|
|
3054
3851
|
title: "Przełączniki zapisu",
|
|
3055
3852
|
subtitle: "Każdy zapis dodany w 0.2.0 wymaga swojej opcji w medusa-config.ts i osoby, która włączy go tutaj. Opcja ustawiona na false wygrywa.",
|
|
3853
|
+
points: { option: "Opcja w medusa-config.ts", person: "Włącza tu człowiek", falseWins: "Opcja false wygrywa" },
|
|
3056
3854
|
demoNote: "Demo: włączone zapisy tylko symulują. W tym sklepie nic się nie zmienia.",
|
|
3057
3855
|
names: {
|
|
3058
3856
|
prices: "Ceny z Subiekta",
|
|
@@ -3099,6 +3897,7 @@ const pl$1 = {
|
|
|
3099
3897
|
products: {
|
|
3100
3898
|
title: "Produkty z Subiekta",
|
|
3101
3899
|
subtitle: "Ceny z Subiekta obok produktów w sklepie, które aktualizują, oraz towary z Subiekta, których sklep jeszcze nie sprzedaje. Najpierw wszystko jest planem: nic się nie zmienia, dopóki ktoś nie włączy zapisu w Ustawieniach.",
|
|
3900
|
+
points: { plan: "Najpierw plan", match: "Najpierw EAN, potem SKU", writer: "Zmiany po włączeniu zapisu" },
|
|
3102
3901
|
matching: "Towary z Subiekta są dopasowywane do wariantów w sklepie najpierw po EAN, potem po SKU porównanym z symbolem w Subiekcie. Kod użyty dwa razy to konflikt i nigdy nie jest zgadywany.",
|
|
3103
3902
|
matchedKey: "Dopasowane po {{by}}: {{code}}",
|
|
3104
3903
|
settings: "Ceny z {{level}} ({{type}}) do: {{target}}, w walucie {{currency}}.",
|
|
@@ -3134,10 +3933,11 @@ const pl$1 = {
|
|
|
3134
3933
|
columns: { product: "Towar w Subiekcie", change: "Zmiana", store: "Produkt w sklepie", matched: "Dopasowanie", status: "Status", details: "Szczegóły" },
|
|
3135
3934
|
matchedBy: { ean: "EAN", sku: "SKU" },
|
|
3136
3935
|
newProduct: "nowy, {{price}}",
|
|
3137
|
-
empty: "Nic w tym planie
|
|
3936
|
+
empty: "Nic w tym planie",
|
|
3138
3937
|
search: "Symbol, SKU albo EAN",
|
|
3139
3938
|
quarantine: "W kwarantannie po kolejnych błędach",
|
|
3140
3939
|
quarantineHint: "Zapis pomija te pozycje, dopóki ich nie zwolnisz. Najpierw usuń przyczynę (ostatni błąd mówi, co poszło nie tak).",
|
|
3940
|
+
quarantinePoints: { skipped: "Pomijane do zwolnienia", fix: "Najpierw usuń przyczynę" },
|
|
3141
3941
|
samples: { conflicts: "Konflikty, nigdy nie zgadujemy", unmatchedVariants: "Warianty bez dopasowania (SKU)", noPrice: "Bez ceny w tym poziomie" },
|
|
3142
3942
|
blocked: {
|
|
3143
3943
|
currency_mismatch: "Poziom cen jest w innej walucie niż priceCurrency: nic nie zaplanowano.",
|
|
@@ -3147,11 +3947,11 @@ const pl$1 = {
|
|
|
3147
3947
|
tasks: {
|
|
3148
3948
|
title: "Kolejka",
|
|
3149
3949
|
subtitle: "Zamówienia w drodze do Subiekta: każde ZK, WZ, faktura albo paragon, o które poprosił sklep, i jak poszło. Wysyłka, która się nie udała, czeka tu na Ciebie z przyciskiem Wyślij ponownie.",
|
|
3150
|
-
|
|
3950
|
+
points: { order: "Wiersz na każde wywołanie", retries: "Ponawia sama", failed: "Nieudane czeka na Ciebie" },
|
|
3951
|
+
emptyBy: { attention: "Nic nie wymaga uwagi", open: "Nic nie jest w drodze", done: "Jeszcze nic nie wysłano", all: "Kolejka pusta" },
|
|
3151
3952
|
filters: { attention: "Wymagają uwagi", open: "Otwarte", done: "Zakończone", all: "Wszystkie" },
|
|
3152
3953
|
search: "Numer zamówienia",
|
|
3153
|
-
|
|
3154
|
-
columns: { order: "Zamówienie w sklepie", operation: "Operacja", status: "Status", attempts: "Próby", document: "Dokument w Subiekcie", details: "Szczegóły", actions: "" },
|
|
3954
|
+
columns: { order: "Zamówienie w sklepie", products: "Produkty", operation: "Operacja", status: "Status", attempts: "Próby", document: "Dokument w Subiekcie", details: "Szczegóły", actions: "" },
|
|
3155
3955
|
kinds: { "order.create": "Utwórz ZK", "order.cancel": "Anuluj ZK", "order.fulfill": "Wystaw WZ", "order.document": "Wystaw dokument sprzedaży" },
|
|
3156
3956
|
documentKinds: { fs: "Wystaw FS", pa: "Wystaw PA" },
|
|
3157
3957
|
statuses: {
|
|
@@ -3174,17 +3974,20 @@ const pl$1 = {
|
|
|
3174
3974
|
documents: {
|
|
3175
3975
|
title: "Dokumenty",
|
|
3176
3976
|
subtitle: "Co Subiekt wystawił do Twoich zamówień: ZK, WZ, faktury i paragony, każdy dokument obok swojego zamówienia w sklepie.",
|
|
3977
|
+
points: { tag: "Znacznik zamówienia w uwagach", warehouse: "WZ z magazynu", ksef: "Numer KSeF na FS" },
|
|
3978
|
+
search: "Numer dokumentu albo zamówienia",
|
|
3177
3979
|
filters: { all: "Wszystkie", ZK: "ZK", WZ: "WZ", FS: "FS", PA: "PA" },
|
|
3178
|
-
empty: "Jeszcze
|
|
3179
|
-
columns: { number: "Numer", order: "Zamówienie w sklepie", issued: "Wystawiono", source: "Źródło", status: "Status", ksef: "Numer KSeF" },
|
|
3180
|
-
sources: { bridge: "Medusa", subiekt: "Magazyn", demo: "Demo" },
|
|
3980
|
+
empty: "Jeszcze bez dokumentów",
|
|
3981
|
+
columns: { number: "Numer", order: "Zamówienie w sklepie", products: "Produkty", issued: "Wystawiono", source: "Źródło", status: "Status", ksef: "Numer KSeF" },
|
|
3982
|
+
sources: { bridge: "Medusa", subiekt: "Magazyn", demo: "Demo", linked: "Połączone ręcznie" },
|
|
3181
3983
|
statuses: { open: "Otwarty", canceled: "Anulowany", completed: "Zrealizowany" },
|
|
3182
3984
|
ksefWaiting: "czeka na KSeF"
|
|
3183
3985
|
},
|
|
3184
3986
|
stock: {
|
|
3185
3987
|
title: "Stany",
|
|
3186
3988
|
subtitle: "Z Subiekta do Medusy, najpierw po EAN, potem po SKU porównanym z symbolem towaru.",
|
|
3187
|
-
|
|
3989
|
+
points: { direction: "Z Subiekta do Medusy", match: "Najpierw EAN, potem SKU" },
|
|
3990
|
+
never: "Stany jeszcze nie synchronizowane",
|
|
3188
3991
|
dryRun: "Próba na sucho",
|
|
3189
3992
|
counters: {
|
|
3190
3993
|
subiektProducts: "Towary w Subiekcie",
|
|
@@ -3205,9 +4008,10 @@ const pl$1 = {
|
|
|
3205
4008
|
},
|
|
3206
4009
|
runs: {
|
|
3207
4010
|
title: "Historia",
|
|
3208
|
-
empty: "Jeszcze
|
|
4011
|
+
empty: "Jeszcze bez uruchomień",
|
|
4012
|
+
points: { newest: "Najnowsze na górze", jobs: "Zadania w tle i kliknięcia" },
|
|
3209
4013
|
columns: { kind: "Zadanie", trigger: "Wyzwalacz", status: "Wynik", message: "Podsumowanie", started: "Start", duration: "Czas" },
|
|
3210
|
-
kinds: { stock: "Stany", events: "Dokumenty", tasks: "Kolejka", health: "Połączenie", products: "Produkty" },
|
|
4014
|
+
kinds: { stock: "Stany", events: "Dokumenty", tasks: "Kolejka", health: "Połączenie", products: "Produkty", catchup: "Siatka bezpieczeństwa" },
|
|
3211
4015
|
triggers: { schedule: "Harmonogram", manual: "Ręcznie", webhook: "Webhook", event: "Zdarzenie", auto: "Automatycznie" },
|
|
3212
4016
|
statuses: { success: "OK", partial: "Częściowo", error: "Błąd", skipped: "Pominięto" },
|
|
3213
4017
|
summary: {
|
|
@@ -3219,15 +4023,27 @@ const pl$1 = {
|
|
|
3219
4023
|
eventsNone: "Nic nowego.",
|
|
3220
4024
|
health: "Most i Subiekt odpowiadają.",
|
|
3221
4025
|
productsPlan: "Plan: zmiany cen {{prices}}, nowe produkty {{creates}}. Żaden zapis nie jest włączony.",
|
|
3222
|
-
productsApplied: "Zaplanowane zmiany cen: {{prices}}, nowe produkty: {{creates}}, naniesione: {{applied}}, nieudane: {{failed}}."
|
|
4026
|
+
productsApplied: "Zaplanowane zmiany cen: {{prices}}, nowe produkty: {{creates}}, naniesione: {{applied}}, nieudane: {{failed}}.",
|
|
4027
|
+
catchup: "Zamówienia bez zadania ZK dodane do kolejki: {{queued}}, zwolnione po płatności: {{released}}.",
|
|
4028
|
+
catchupErrors: "Zamówienia bez zadania ZK dodane do kolejki: {{queued}}, zwolnione po płatności: {{released}}, błędy: {{errors}}."
|
|
3223
4029
|
}
|
|
3224
4030
|
},
|
|
3225
4031
|
widget: {
|
|
3226
4032
|
title: "Subiekt nexo",
|
|
3227
4033
|
demo: "Demo",
|
|
3228
4034
|
more: "Panel",
|
|
3229
|
-
none: "
|
|
3230
|
-
waiting: "ZK
|
|
4035
|
+
none: "Nie wysłano do Subiekta",
|
|
4036
|
+
waiting: "ZK po zaksięgowaniu płatności",
|
|
4037
|
+
state: { notSent: "Nie wysłano", waiting: "Czeka na płatność", sending: "Wysyłka", attention: "Wymaga uwagi", inSubiekt: "W Subiekcie" },
|
|
4038
|
+
run: {
|
|
4039
|
+
queue: "Czeka w kolejce Medusy",
|
|
4040
|
+
queueShort: "Kolejka",
|
|
4041
|
+
bridge: "Most wystawia dokument",
|
|
4042
|
+
bridgeShort: "Most",
|
|
4043
|
+
document: "Numer wraca do Medusy",
|
|
4044
|
+
documentShort: "Numer",
|
|
4045
|
+
done: "W Subiekcie"
|
|
4046
|
+
},
|
|
3231
4047
|
send: "Wyślij do Subiekta teraz",
|
|
3232
4048
|
sent: "W kolejce. ZK pojawi się tu za kilka sekund.",
|
|
3233
4049
|
ksef: "KSeF {{number}}",
|
|
@@ -3236,7 +4052,29 @@ const pl$1 = {
|
|
|
3236
4052
|
issuePa: "Wystaw paragon (PA)",
|
|
3237
4053
|
issued: "W kolejce. Dokument pojawi się tu za kilka sekund.",
|
|
3238
4054
|
autoOff: "Automatyczne dokumenty sprzedaży są wyłączone: włącz zapis na stronie Subiekta.",
|
|
3239
|
-
autoOn: "Dokument sprzedaży powstanie automatycznie po {{after}}."
|
|
4055
|
+
autoOn: "Dokument sprzedaży powstanie automatycznie po {{after}}.",
|
|
4056
|
+
kinds: { ZK: "Zamówienie od klienta (ZK)", WZ: "Wydanie zewnętrzne (WZ)", FS: "Faktura (FS)", PA: "Paragon (PA)" },
|
|
4057
|
+
warehouse: "magazyn {{warehouse}}",
|
|
4058
|
+
related: "Na podstawie {{numbers}}",
|
|
4059
|
+
zkCompleted: "Zrealizowane w Subiekcie: towar wydano.",
|
|
4060
|
+
check: {
|
|
4061
|
+
button: "Sprawdź w Subiekcie",
|
|
4062
|
+
again: "Sprawdź ponownie",
|
|
4063
|
+
hint: "Nie ma tu ZK? Sprawdź w Subiekcie: jeśli już tam jest, połącz je z zamówieniem.",
|
|
4064
|
+
title: "W Subiekcie teraz",
|
|
4065
|
+
at: "sprawdzono {{time}}",
|
|
4066
|
+
nothing: "Subiekt nie ma żadnego dokumentu do tego zamówienia.",
|
|
4067
|
+
inSubiekt: "W Subiekcie: {{status}}",
|
|
4068
|
+
notReported: "Subiekt go nie zgłasza (usunięty tam albo inna baza)",
|
|
4069
|
+
canceledThere: "Anulowany w Subiekcie.",
|
|
4070
|
+
states: { missing: "Brak w Medusie", status_differs: "Medusa pokazuje: {{status}}", same: "Zapisany", only_local: "Tylko w Medusie" },
|
|
4071
|
+
link: "Połącz",
|
|
4072
|
+
update: "Zaktualizuj status",
|
|
4073
|
+
linkHint: "Zapisuje go w Medusie. W Subiekcie nic się nie zmienia, drugi dokument nie powstanie.",
|
|
4074
|
+
updateHint: "Zapisuje status, który pokazuje Subiekt. W Subiekcie nic się nie zmienia.",
|
|
4075
|
+
linked: "{{number}} połączony z zamówieniem.",
|
|
4076
|
+
updated: "{{number}} zaktualizowany."
|
|
4077
|
+
}
|
|
3240
4078
|
},
|
|
3241
4079
|
toast: {
|
|
3242
4080
|
started: "Uruchomione. Wynik pojawi się tu za chwilę.",
|
|
@@ -3247,43 +4085,7 @@ const pl$1 = {
|
|
|
3247
4085
|
released: "Zwolnione. Następny przebieg spróbuje ponownie.",
|
|
3248
4086
|
error: "Coś poszło nie tak: {{error}}"
|
|
3249
4087
|
},
|
|
3250
|
-
|
|
3251
|
-
title: "Działa w sklepach wdrożonych przez Koda Plus",
|
|
3252
|
-
subtitle: "Prawdziwe sklepy z wdrożeniem Koda Plus, które pracują na tej integracji na co dzień.",
|
|
3253
|
-
open: "Otwórz sklep",
|
|
3254
|
-
since: "Od {{date}}",
|
|
3255
|
-
badgeOne: "Działa w 1 sklepie",
|
|
3256
|
-
badgeMany: "Działa w {{count}} sklepach",
|
|
3257
|
-
review: "Zobacz opinię"
|
|
3258
|
-
},
|
|
3259
|
-
community: {
|
|
3260
|
-
addStore: {
|
|
3261
|
-
button: "Dodaj swój sklep",
|
|
3262
|
-
title: "Twój sklep działa na tej integracji?",
|
|
3263
|
-
text: "Daj nam znać. Po sprawdzeniu dodamy go do tej listy z linkiem i oceną.",
|
|
3264
|
-
name: "Nazwa sklepu",
|
|
3265
|
-
url: "Adres sklepu",
|
|
3266
|
-
note: "Kilka słów o wdrożeniu (opcjonalnie)",
|
|
3267
|
-
send: "Wyślij zgłoszenie",
|
|
3268
|
-
copy: "Kopiuj treść",
|
|
3269
|
-
copied: "Treść skopiowana, wklej ją w mail do hello@koda.plus",
|
|
3270
|
-
hint: "Otworzy się Twoja poczta z gotową wiadomością do {{email}}.",
|
|
3271
|
-
subject: "Zgłoszenie sklepu: {{integration}}",
|
|
3272
|
-
greeting: "Dzień dobry, mój sklep działa na integracji {{integration}}. Proszę o dodanie go do listy sklepów."
|
|
3273
|
-
},
|
|
3274
|
-
prompt: {
|
|
3275
|
-
button: "Kopiuj prompt",
|
|
3276
|
-
title: "Dodaj tę integrację do swojego sklepu",
|
|
3277
|
-
text: "Wklej go w Claude Code, Cursorze albo innym agencie AI otwartym w projekcie Twojej Medusy. Agent zainstaluje wtyczkę, ustawi ją tak jak tutaj i zostawi notatki do dalszej pracy.",
|
|
3278
|
-
copy: "Kopiuj jeszcze raz",
|
|
3279
|
-
copied: "Prompt skopiowany",
|
|
3280
|
-
failed: "Nie udało się skopiować. Zaznacz tekst i skopiuj go ręcznie."
|
|
3281
|
-
},
|
|
3282
|
-
discord: {
|
|
3283
|
-
button: "Pomoc na Discordzie",
|
|
3284
|
-
title: "Dołącz do serwera Koda Plus na Discordzie"
|
|
3285
|
-
}
|
|
3286
|
-
},
|
|
4088
|
+
community: communityPl,
|
|
3287
4089
|
guide: {
|
|
3288
4090
|
intro: {
|
|
3289
4091
|
title: "Połącz Medusę z Subiektem nexo PRO",
|