@hszrdm/core 1.0.1 → 1.0.2
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.
|
@@ -1788,283 +1788,400 @@ const SystemMonitoringPage = () => /* @__PURE__ */ jsxRuntime.jsxs(ui.Container,
|
|
|
1788
1788
|
] }, item.href)) })
|
|
1789
1789
|
] });
|
|
1790
1790
|
const config$9 = adminSdk.defineRouteConfig({ label: "Rendszerfelügyelet" });
|
|
1791
|
-
const defaults$1 = {
|
|
1792
|
-
ARUKERESO_STOREFRONT_URL: "",
|
|
1793
|
-
ARUKERESO_PRODUCT_PATH_TEMPLATE: "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
1794
|
-
ARUKERESO_SALES_CHANNEL_ID: "",
|
|
1795
|
-
ARUKERESO_DEFAULT_MANUFACTURER: "",
|
|
1796
|
-
ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER: false,
|
|
1797
|
-
ARUKERESO_INCLUDE_OUT_OF_STOCK: true,
|
|
1798
|
-
ARUKERESO_DEFAULT_DELIVERY_TIME: "",
|
|
1799
|
-
ARUKERESO_DEFAULT_DELIVERY_COST: ""
|
|
1800
|
-
};
|
|
1801
1791
|
const backendUrl$a = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
1802
|
-
const
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
const [
|
|
1808
|
-
const [
|
|
1809
|
-
const [
|
|
1810
|
-
const
|
|
1811
|
-
|
|
1812
|
-
|
|
1792
|
+
const adminBase$5 = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
1793
|
+
function apiUrl$a(path) {
|
|
1794
|
+
return `${backendUrl$a}${path.startsWith("/") ? path : `/${path}`}`;
|
|
1795
|
+
}
|
|
1796
|
+
const BillingPage = () => {
|
|
1797
|
+
const [orders, setOrders] = React.useState([]);
|
|
1798
|
+
const [configuration, setConfiguration] = React.useState(null);
|
|
1799
|
+
const [selected, setSelected] = React.useState([]);
|
|
1800
|
+
const [query, setQuery] = React.useState("");
|
|
1801
|
+
const [loading, setLoading] = React.useState(null);
|
|
1802
|
+
const [listLoading, setListLoading] = React.useState(true);
|
|
1803
|
+
const [loadError, setLoadError] = React.useState(null);
|
|
1813
1804
|
const load = React.useCallback(async () => {
|
|
1814
|
-
|
|
1805
|
+
setListLoading(true);
|
|
1806
|
+
setLoadError(null);
|
|
1815
1807
|
try {
|
|
1816
|
-
const response = await fetch(apiUrl$a("/admin/
|
|
1808
|
+
const response = await fetch(apiUrl$a("/admin/billingo/orders"), {
|
|
1817
1809
|
credentials: "include"
|
|
1818
1810
|
});
|
|
1819
|
-
const
|
|
1820
|
-
if (!response.ok
|
|
1821
|
-
throw new Error(
|
|
1811
|
+
const payload = await response.json().catch(() => ({}));
|
|
1812
|
+
if (!response.ok) {
|
|
1813
|
+
throw new Error(payload.message || "A számlázási lista nem tölthető be.");
|
|
1822
1814
|
}
|
|
1823
|
-
const
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
ARUKERESO_DEFAULT_MANUFACTURER: values.ARUKERESO_DEFAULT_MANUFACTURER || "",
|
|
1830
|
-
ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER: values.ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER === "true",
|
|
1831
|
-
ARUKERESO_INCLUDE_OUT_OF_STOCK: values.ARUKERESO_INCLUDE_OUT_OF_STOCK !== "false",
|
|
1832
|
-
ARUKERESO_DEFAULT_DELIVERY_TIME: values.ARUKERESO_DEFAULT_DELIVERY_TIME || "",
|
|
1833
|
-
ARUKERESO_DEFAULT_DELIVERY_COST: values.ARUKERESO_DEFAULT_DELIVERY_COST || ""
|
|
1834
|
-
});
|
|
1815
|
+
const nextOrders = payload.orders || [];
|
|
1816
|
+
setOrders(nextOrders);
|
|
1817
|
+
setConfiguration(payload.configuration || null);
|
|
1818
|
+
setSelected(
|
|
1819
|
+
(current) => current.filter((id) => nextOrders.some((order) => order.id === id))
|
|
1820
|
+
);
|
|
1835
1821
|
} catch (error) {
|
|
1836
|
-
|
|
1822
|
+
setOrders([]);
|
|
1823
|
+
setLoadError(
|
|
1824
|
+
error instanceof Error ? error.message : "A számlázási lista nem tölthető be."
|
|
1825
|
+
);
|
|
1837
1826
|
} finally {
|
|
1838
|
-
|
|
1827
|
+
setListLoading(false);
|
|
1839
1828
|
}
|
|
1840
1829
|
}, []);
|
|
1841
1830
|
React.useEffect(() => {
|
|
1842
1831
|
void load();
|
|
1843
1832
|
}, [load]);
|
|
1844
|
-
const
|
|
1845
|
-
|
|
1833
|
+
const visible = React.useMemo(() => {
|
|
1834
|
+
const value = query.trim().toLowerCase();
|
|
1835
|
+
if (!value) return orders;
|
|
1836
|
+
return orders.filter(
|
|
1837
|
+
(order) => [
|
|
1838
|
+
order.display_id,
|
|
1839
|
+
order.email,
|
|
1840
|
+
order.invoice?.invoiceNumber,
|
|
1841
|
+
order.invoice?.modificationInvoiceNumber
|
|
1842
|
+
].some(
|
|
1843
|
+
(item) => String(item || "").toLowerCase().includes(value)
|
|
1844
|
+
)
|
|
1845
|
+
);
|
|
1846
|
+
}, [orders, query]);
|
|
1847
|
+
const selectedSet = React.useMemo(() => new Set(selected), [selected]);
|
|
1848
|
+
const toggle = (id) => {
|
|
1849
|
+
setSelected(
|
|
1850
|
+
(current) => current.includes(id) ? current.filter((item) => item !== id) : [...current, id]
|
|
1851
|
+
);
|
|
1852
|
+
};
|
|
1853
|
+
const bulkCreate = async () => {
|
|
1854
|
+
if (!selected.length) {
|
|
1855
|
+
ui.toast.error("Jelölj ki legalább egy rendelést.");
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
setLoading("bulk");
|
|
1846
1859
|
try {
|
|
1847
|
-
const response = await fetch(apiUrl$a("/admin/
|
|
1860
|
+
const response = await fetch(apiUrl$a("/admin/billingo/bulk/create"), {
|
|
1848
1861
|
method: "POST",
|
|
1849
1862
|
credentials: "include",
|
|
1850
1863
|
headers: { "Content-Type": "application/json" },
|
|
1851
|
-
body: JSON.stringify({
|
|
1864
|
+
body: JSON.stringify({ orderIds: selected })
|
|
1852
1865
|
});
|
|
1853
|
-
const
|
|
1854
|
-
if (!response.ok
|
|
1855
|
-
|
|
1856
|
-
|
|
1866
|
+
const payload = await response.json().catch(() => ({}));
|
|
1867
|
+
if (!response.ok && response.status !== 207) {
|
|
1868
|
+
throw new Error(payload.message || "A tömeges számlázás nem sikerült.");
|
|
1869
|
+
}
|
|
1870
|
+
const failed = payload.results?.filter((item) => !item.ok).length || 0;
|
|
1871
|
+
const created = payload.results?.filter(
|
|
1872
|
+
(item) => item.ok && !item.alreadyExisted
|
|
1873
|
+
).length || 0;
|
|
1874
|
+
if (failed) {
|
|
1875
|
+
ui.toast.error(`${failed} számla nem készült el; ${created} sikeres.`);
|
|
1876
|
+
} else {
|
|
1877
|
+
ui.toast.success(`${created} új számla elkészült.`);
|
|
1878
|
+
}
|
|
1857
1879
|
await load();
|
|
1858
1880
|
} catch (error) {
|
|
1859
|
-
ui.toast.error(
|
|
1881
|
+
ui.toast.error(
|
|
1882
|
+
error instanceof Error ? error.message : "A tömeges számlázás nem sikerült."
|
|
1883
|
+
);
|
|
1860
1884
|
} finally {
|
|
1861
|
-
|
|
1885
|
+
setLoading(null);
|
|
1862
1886
|
}
|
|
1863
1887
|
};
|
|
1864
|
-
const
|
|
1865
|
-
|
|
1888
|
+
const action = async (order, value) => {
|
|
1889
|
+
if (value === "cancel" && !confirm(
|
|
1890
|
+
`Biztosan sztornózod a(z) ${order.invoice?.invoiceNumber || order.invoice?.documentId} számlát?`
|
|
1891
|
+
)) {
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
if (value === "modify" && !confirm(
|
|
1895
|
+
`Biztosan teljes jóváíró/módosító bizonylatot készítesz a(z) ${order.invoice?.invoiceNumber || order.invoice?.documentId} számlához? Ez a teljes számla összegét jóváírja.`
|
|
1896
|
+
)) {
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
setLoading(`${order.id}:${value}`);
|
|
1900
|
+
try {
|
|
1901
|
+
const response = await fetch(apiUrl$a(`/admin/orders/${order.id}/billingo`), {
|
|
1902
|
+
method: "POST",
|
|
1903
|
+
credentials: "include",
|
|
1904
|
+
headers: { "Content-Type": "application/json" },
|
|
1905
|
+
body: JSON.stringify({ action: value })
|
|
1906
|
+
});
|
|
1907
|
+
const payload = await response.json().catch(() => ({}));
|
|
1908
|
+
if (!response.ok) {
|
|
1909
|
+
throw new Error(payload.message || "A Billingo művelet nem sikerült.");
|
|
1910
|
+
}
|
|
1911
|
+
const messages = {
|
|
1912
|
+
create: "A számla elkészült.",
|
|
1913
|
+
sync: "A számla frissítve.",
|
|
1914
|
+
send: "A számla elküldve.",
|
|
1915
|
+
cancel: "A számla sztornózva.",
|
|
1916
|
+
modify: "A teljes jóváíró/módosító bizonylat elkészült."
|
|
1917
|
+
};
|
|
1918
|
+
ui.toast.success(messages[value]);
|
|
1919
|
+
if (value === "modify" && payload.sendError) {
|
|
1920
|
+
ui.toast.error(`A jóváírás elkészült, de az e-mail küldése sikertelen: ${payload.sendError}`);
|
|
1921
|
+
}
|
|
1922
|
+
await load();
|
|
1923
|
+
} catch (error) {
|
|
1924
|
+
ui.toast.error(
|
|
1925
|
+
error instanceof Error ? error.message : "A Billingo művelet nem sikerült."
|
|
1926
|
+
);
|
|
1927
|
+
} finally {
|
|
1928
|
+
setLoading(null);
|
|
1929
|
+
}
|
|
1930
|
+
};
|
|
1931
|
+
const testConnection = async () => {
|
|
1932
|
+
setLoading("connection");
|
|
1866
1933
|
try {
|
|
1867
|
-
const response = await fetch(apiUrl$a("/admin/
|
|
1934
|
+
const response = await fetch(apiUrl$a("/admin/billingo/connection"), {
|
|
1935
|
+
method: "POST",
|
|
1868
1936
|
credentials: "include"
|
|
1869
1937
|
});
|
|
1870
|
-
const
|
|
1871
|
-
if (!response.ok)
|
|
1872
|
-
|
|
1873
|
-
|
|
1938
|
+
const payload = await response.json().catch(() => ({}));
|
|
1939
|
+
if (!response.ok) {
|
|
1940
|
+
throw new Error(payload.message || "A Billingo kapcsolat nem működik.");
|
|
1941
|
+
}
|
|
1942
|
+
ui.toast.success(payload.message || "A Billingo kapcsolat működik.");
|
|
1874
1943
|
} catch (error) {
|
|
1875
|
-
ui.toast.error(
|
|
1944
|
+
ui.toast.error(
|
|
1945
|
+
error instanceof Error ? error.message : "A Billingo kapcsolat nem működik."
|
|
1946
|
+
);
|
|
1876
1947
|
} finally {
|
|
1877
|
-
|
|
1948
|
+
setLoading(null);
|
|
1878
1949
|
}
|
|
1879
1950
|
};
|
|
1880
|
-
const feedUrl = apiUrl$a("/feeds/arukereso.xml");
|
|
1881
|
-
const d = preview?.diagnostics;
|
|
1882
1951
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
1883
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-
|
|
1952
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 border-b px-6 py-4", children: [
|
|
1884
1953
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1885
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "
|
|
1886
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "
|
|
1954
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Számlázás" }),
|
|
1955
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Billingo számlák, sztornók és teljes jóváírások kezelése a HSZRDM Commerce rendeléseiből." }),
|
|
1956
|
+
configuration?.autoInvoice ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
1957
|
+
"Az automatikus számlázás aktív",
|
|
1958
|
+
configuration.autoSend ? ", automatikus e-mail küldéssel" : "",
|
|
1959
|
+
"."
|
|
1960
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-warning", children: "Az automatikus számlázás ki van kapcsolva." })
|
|
1887
1961
|
] }),
|
|
1888
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1889
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 border-b px-6 py-5 md:grid-cols-2", children: [
|
|
1894
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "Storefront URL", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1895
|
-
ui.Input,
|
|
1896
|
-
{
|
|
1897
|
-
value: draft.ARUKERESO_STOREFRONT_URL,
|
|
1898
|
-
onChange: (e) => update("ARUKERESO_STOREFRONT_URL", e.target.value),
|
|
1899
|
-
placeholder: "https://shop.hu (üresen STOREFRONT_URL)"
|
|
1900
|
-
}
|
|
1901
|
-
) }),
|
|
1902
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Field$4, { label: "Termék URL sablon", children: [
|
|
1962
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1963
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { children: [
|
|
1964
|
+
selected.length,
|
|
1965
|
+
" kijelölve"
|
|
1966
|
+
] }),
|
|
1903
1967
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1904
|
-
ui.
|
|
1968
|
+
ui.Button,
|
|
1905
1969
|
{
|
|
1906
|
-
|
|
1907
|
-
|
|
1970
|
+
variant: "secondary",
|
|
1971
|
+
isLoading: loading === "connection",
|
|
1972
|
+
onClick: () => void testConnection(),
|
|
1973
|
+
children: "Kapcsolat tesztelése"
|
|
1908
1974
|
}
|
|
1909
|
-
)
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
"
|
|
1918
|
-
"
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
] })
|
|
1922
|
-
|
|
1975
|
+
)
|
|
1976
|
+
] })
|
|
1977
|
+
] }),
|
|
1978
|
+
configuration && !configuration.configured ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-ui-border-error bg-ui-bg-base px-6 py-4", children: [
|
|
1979
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-error", children: "A Billingo még nincs teljesen beállítva." }),
|
|
1980
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-subtle", children: [
|
|
1981
|
+
"Hiányzik: ",
|
|
1982
|
+
[
|
|
1983
|
+
!configuration.apiKey && "API kulcs",
|
|
1984
|
+
!configuration.documentBlockId && "számlatömb azonosító"
|
|
1985
|
+
].filter(Boolean).join(", "),
|
|
1986
|
+
". Állítsd be a Settings → Integrációk → Billingo oldalon, majd indítsd újra a backendet."
|
|
1987
|
+
] })
|
|
1988
|
+
] }) : null,
|
|
1989
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3 border-b px-6 py-4", children: [
|
|
1990
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1923
1991
|
ui.Input,
|
|
1924
1992
|
{
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1993
|
+
className: "max-w-sm",
|
|
1994
|
+
value: query,
|
|
1995
|
+
onChange: (event) => setQuery(event.target.value),
|
|
1996
|
+
placeholder: "Rendelés, e-mail vagy számlaszám keresése"
|
|
1928
1997
|
}
|
|
1929
|
-
)
|
|
1930
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1931
|
-
ui.
|
|
1932
|
-
{
|
|
1933
|
-
value: draft.ARUKERESO_DEFAULT_MANUFACTURER,
|
|
1934
|
-
onChange: (e) => update("ARUKERESO_DEFAULT_MANUFACTURER", e.target.value),
|
|
1935
|
-
placeholder: "Csak ha minden termékre tényleg igaz"
|
|
1936
|
-
}
|
|
1937
|
-
) }),
|
|
1938
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "SKU mint gyártói cikkszám", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
1939
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1940
|
-
ui.Switch,
|
|
1941
|
-
{
|
|
1942
|
-
checked: draft.ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER,
|
|
1943
|
-
onCheckedChange: (value) => update("ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER", value)
|
|
1944
|
-
}
|
|
1945
|
-
),
|
|
1946
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: draft.ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER ? "Igen" : "Nem" })
|
|
1947
|
-
] }) }),
|
|
1948
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "Készlethiányos termékek", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
1949
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1950
|
-
ui.Switch,
|
|
1951
|
-
{
|
|
1952
|
-
checked: draft.ARUKERESO_INCLUDE_OUT_OF_STOCK,
|
|
1953
|
-
onCheckedChange: (value) => update("ARUKERESO_INCLUDE_OUT_OF_STOCK", value)
|
|
1954
|
-
}
|
|
1955
|
-
),
|
|
1956
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: draft.ARUKERESO_INCLUDE_OUT_OF_STOCK ? "DeliveryTime=NO" : "Kimaradnak" })
|
|
1957
|
-
] }) }),
|
|
1958
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "Alap szállítási idő", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1959
|
-
ui.Input,
|
|
1998
|
+
),
|
|
1999
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2000
|
+
ui.Button,
|
|
1960
2001
|
{
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2002
|
+
disabled: Boolean(loading) || !configuration?.configured,
|
|
2003
|
+
isLoading: loading === "bulk",
|
|
2004
|
+
onClick: () => void bulkCreate(),
|
|
2005
|
+
children: "Kijelöltek számlázása"
|
|
1964
2006
|
}
|
|
1965
|
-
)
|
|
1966
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1967
|
-
ui.
|
|
2007
|
+
),
|
|
2008
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2009
|
+
ui.Button,
|
|
1968
2010
|
{
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2011
|
+
variant: "secondary",
|
|
2012
|
+
disabled: Boolean(loading),
|
|
2013
|
+
onClick: () => void load(),
|
|
2014
|
+
children: "Frissítés"
|
|
1972
2015
|
}
|
|
1973
|
-
)
|
|
1974
|
-
] }),
|
|
1975
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b px-6 py-4", children: [
|
|
1976
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1977
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Publikus feed URL" }),
|
|
1978
|
-
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "break-all text-ui-fg-interactive hover:underline", href: feedUrl, target: "_blank", rel: "noreferrer", children: feedUrl })
|
|
1979
|
-
] }),
|
|
1980
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
1981
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1982
|
-
ui.Button,
|
|
1983
|
-
{
|
|
1984
|
-
variant: "secondary",
|
|
1985
|
-
isLoading: previewing,
|
|
1986
|
-
disabled: !enabled || loading || saving || previewing,
|
|
1987
|
-
onClick: () => void runPreview(),
|
|
1988
|
-
children: "Feed ellenőrzése"
|
|
1989
|
-
}
|
|
1990
|
-
),
|
|
1991
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1992
|
-
ui.Button,
|
|
1993
|
-
{
|
|
1994
|
-
isLoading: saving,
|
|
1995
|
-
disabled: loading || saving || previewing,
|
|
1996
|
-
onClick: () => void save(),
|
|
1997
|
-
children: "Mentés"
|
|
1998
|
-
}
|
|
1999
|
-
)
|
|
2000
|
-
] })
|
|
2016
|
+
)
|
|
2001
2017
|
] }),
|
|
2002
|
-
|
|
2003
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
2004
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Termékek", value: d.productsScanned }),
|
|
2005
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Variantok", value: d.variantsScanned }),
|
|
2006
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Feed tételek", value: d.itemsEmitted }),
|
|
2007
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs gyártó", value: d.skippedNoManufacturer }),
|
|
2008
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs kategória", value: d.skippedNoCategory }),
|
|
2009
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs ár", value: d.skippedNoPrice }),
|
|
2010
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs ProductNumber", value: d.itemsMissingProductNumber }),
|
|
2011
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs kép", value: d.itemsMissingImage }),
|
|
2012
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Készlethiány miatt kimaradt", value: d.skippedOutOfStock }),
|
|
2013
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Sales channel hiba", value: d.skippedNoSalesChannel + d.skippedNotInSalesChannel }),
|
|
2014
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Hibás delivery time", value: d.invalidDeliveryTime }),
|
|
2015
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Hibás delivery cost", value: d.invalidDeliveryCost })
|
|
2016
|
-
] }),
|
|
2017
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
2018
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-x-auto", children: [
|
|
2019
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
2018
2020
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-b bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2019
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children:
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2021
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2022
|
+
ui.Checkbox,
|
|
2023
|
+
{
|
|
2024
|
+
checked: visible.length > 0 && visible.every((order) => selectedSet.has(order.id)),
|
|
2025
|
+
onCheckedChange: () => setSelected(
|
|
2026
|
+
visible.every((order) => selectedSet.has(order.id)) ? selected.filter(
|
|
2027
|
+
(id) => !visible.some((order) => order.id === id)
|
|
2028
|
+
) : [
|
|
2029
|
+
.../* @__PURE__ */ new Set([
|
|
2030
|
+
...selected,
|
|
2031
|
+
...visible.map((order) => order.id)
|
|
2032
|
+
])
|
|
2033
|
+
]
|
|
2034
|
+
)
|
|
2035
|
+
}
|
|
2036
|
+
) }),
|
|
2037
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Rendelés" }),
|
|
2038
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Fizetés" }),
|
|
2039
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Számla" }),
|
|
2040
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Billingo státusz" }),
|
|
2041
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Műveletek" })
|
|
2025
2042
|
] }) }),
|
|
2026
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children:
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2043
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: visible.map((order) => {
|
|
2044
|
+
const invoice = order.invoice;
|
|
2045
|
+
const last = order.operations?.at(-1);
|
|
2046
|
+
const modified = Boolean(invoice?.modificationDocumentId);
|
|
2047
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b align-top", children: [
|
|
2048
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2049
|
+
ui.Checkbox,
|
|
2050
|
+
{
|
|
2051
|
+
checked: selectedSet.has(order.id),
|
|
2052
|
+
onCheckedChange: () => toggle(order.id)
|
|
2053
|
+
}
|
|
2054
|
+
) }),
|
|
2055
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
2056
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2057
|
+
"a",
|
|
2058
|
+
{
|
|
2059
|
+
className: "text-ui-fg-interactive",
|
|
2060
|
+
href: `${adminBase$5}/orders/${order.id}`,
|
|
2061
|
+
children: [
|
|
2062
|
+
"#",
|
|
2063
|
+
order.display_id ?? order.id
|
|
2064
|
+
]
|
|
2065
|
+
}
|
|
2066
|
+
),
|
|
2067
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: order.email || "—" }),
|
|
2068
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: formatMoney(order.total, order.currency_code) })
|
|
2069
|
+
] }),
|
|
2070
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: order.payment_status === "captured" ? "Fizetve" : order.payment_status === "refunded" ? "Visszatérítve" : order.payment_status === "partially_refunded" ? "Részben visszatérítve" : order.payment_status || "—" }),
|
|
2071
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
2072
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: invoice?.invoiceNumber || (invoice ? `#${invoice.documentId}` : "Még nincs") }),
|
|
2073
|
+
invoice?.cancelled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-error", children: "Sztornózva" }) : null,
|
|
2074
|
+
modified ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-interactive", children: [
|
|
2075
|
+
"Jóváírva: ",
|
|
2076
|
+
invoice?.modificationInvoiceNumber || `#${invoice?.modificationDocumentId}`
|
|
2077
|
+
] }) : null,
|
|
2078
|
+
last?.status === "failed" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xs text-ui-fg-error", children: last.message }) : null
|
|
2079
|
+
] }),
|
|
2080
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: invoice ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2081
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: invoice.paymentStatus || "—" }),
|
|
2082
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-subtle", children: [
|
|
2083
|
+
"NAV: ",
|
|
2084
|
+
invoice.onlineSzamlaStatus || "—"
|
|
2085
|
+
] }),
|
|
2086
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-subtle", children: [
|
|
2087
|
+
"E-mail: ",
|
|
2088
|
+
invoice.notificationStatus || "—"
|
|
2089
|
+
] })
|
|
2090
|
+
] }) : "—" }),
|
|
2091
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-w-lg flex-wrap gap-2", children: !invoice ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2092
|
+
ui.Button,
|
|
2093
|
+
{
|
|
2094
|
+
size: "small",
|
|
2095
|
+
disabled: !configuration?.configured || Boolean(loading),
|
|
2096
|
+
isLoading: loading === `${order.id}:create`,
|
|
2097
|
+
onClick: () => void action(order, "create"),
|
|
2098
|
+
children: "Számla készítése"
|
|
2099
|
+
}
|
|
2100
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2101
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2102
|
+
ui.Button,
|
|
2103
|
+
{
|
|
2104
|
+
size: "small",
|
|
2105
|
+
variant: "secondary",
|
|
2106
|
+
disabled: Boolean(loading),
|
|
2107
|
+
isLoading: loading === `${order.id}:sync`,
|
|
2108
|
+
onClick: () => void action(order, "sync"),
|
|
2109
|
+
children: "Frissítés"
|
|
2110
|
+
}
|
|
2111
|
+
),
|
|
2112
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2113
|
+
"a",
|
|
2114
|
+
{
|
|
2115
|
+
href: apiUrl$a(`/admin/orders/${order.id}/billingo/pdf`),
|
|
2116
|
+
target: "_blank",
|
|
2117
|
+
rel: "noreferrer",
|
|
2118
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "PDF" })
|
|
2119
|
+
}
|
|
2120
|
+
),
|
|
2121
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2122
|
+
ui.Button,
|
|
2123
|
+
{
|
|
2124
|
+
size: "small",
|
|
2125
|
+
variant: "secondary",
|
|
2126
|
+
disabled: Boolean(loading) || invoice.cancelled,
|
|
2127
|
+
isLoading: loading === `${order.id}:send`,
|
|
2128
|
+
onClick: () => void action(order, "send"),
|
|
2129
|
+
children: "E-mail"
|
|
2130
|
+
}
|
|
2131
|
+
),
|
|
2132
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2133
|
+
ui.Button,
|
|
2134
|
+
{
|
|
2135
|
+
size: "small",
|
|
2136
|
+
variant: "secondary",
|
|
2137
|
+
disabled: Boolean(loading) || invoice.cancelled || modified,
|
|
2138
|
+
isLoading: loading === `${order.id}:modify`,
|
|
2139
|
+
onClick: () => void action(order, "modify"),
|
|
2140
|
+
children: "Teljes jóváírás"
|
|
2141
|
+
}
|
|
2142
|
+
),
|
|
2143
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2144
|
+
ui.Button,
|
|
2145
|
+
{
|
|
2146
|
+
size: "small",
|
|
2147
|
+
variant: "danger",
|
|
2148
|
+
disabled: Boolean(loading) || invoice.cancelled || modified,
|
|
2149
|
+
isLoading: loading === `${order.id}:cancel`,
|
|
2150
|
+
onClick: () => void action(order, "cancel"),
|
|
2151
|
+
children: "Sztornó"
|
|
2152
|
+
}
|
|
2153
|
+
)
|
|
2154
|
+
] }) }) })
|
|
2155
|
+
] }, order.id);
|
|
2156
|
+
}) })
|
|
2157
|
+
] }),
|
|
2158
|
+
listLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Számlázási rendelések betöltése…" }) }) : null,
|
|
2159
|
+
!listLoading && loadError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-6 flex items-center justify-between gap-4 rounded-lg border border-ui-border-error p-4", children: [
|
|
2160
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2161
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-error", children: "Betöltési hiba." }),
|
|
2162
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: loadError })
|
|
2163
|
+
] }),
|
|
2164
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => void load(), children: "Újrapróbálás" })
|
|
2165
|
+
] }) : null,
|
|
2166
|
+
!listLoading && !loadError && !visible.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Nincs megjeleníthető rendelés." }) }) : null
|
|
2167
|
+
] })
|
|
2051
2168
|
] });
|
|
2052
2169
|
};
|
|
2053
|
-
function
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-3", children: [
|
|
2061
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: label }),
|
|
2062
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: value })
|
|
2063
|
-
] });
|
|
2170
|
+
function formatMoney(value, currency) {
|
|
2171
|
+
if (typeof value !== "number") return "—";
|
|
2172
|
+
return new Intl.NumberFormat("hu-HU", {
|
|
2173
|
+
style: "currency",
|
|
2174
|
+
currency: (currency || "HUF").toUpperCase(),
|
|
2175
|
+
maximumFractionDigits: currency?.toUpperCase() === "HUF" ? 0 : 2
|
|
2176
|
+
}).format(value);
|
|
2064
2177
|
}
|
|
2065
|
-
const config$8 = adminSdk.defineRouteConfig({
|
|
2178
|
+
const config$8 = adminSdk.defineRouteConfig({
|
|
2179
|
+
label: "Számlázás",
|
|
2180
|
+
icon: Newspaper,
|
|
2181
|
+
rank: 36
|
|
2182
|
+
});
|
|
2066
2183
|
const backendUrl$9 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
2067
|
-
const adminBase$
|
|
2184
|
+
const adminBase$4 = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
2068
2185
|
const apiUrl$9 = (path) => `${backendUrl$9}${path.startsWith("/") ? path : `/${path}`}`;
|
|
2069
2186
|
const LegalPage = () => {
|
|
2070
2187
|
const [documents, setDocuments] = React.useState([]);
|
|
@@ -2219,7 +2336,7 @@ const LegalPage = () => {
|
|
|
2219
2336
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Feltöltött PDF-ek, verziók és checkout-elfogadások. A Fogyasztó Barát ettől külön, opcionális embed." })
|
|
2220
2337
|
] }),
|
|
2221
2338
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
2222
|
-
/* @__PURE__ */ jsxRuntime.jsx("a", { href: `${adminBase$
|
|
2339
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href: `${adminBase$4}/settings/integrations`, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", children: "Fogyasztó Barát embed" }) }),
|
|
2223
2340
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2224
2341
|
ui.Button,
|
|
2225
2342
|
{
|
|
@@ -2240,7 +2357,7 @@ const LegalPage = () => {
|
|
|
2240
2357
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Mindegy, honnan származik a PDF: a Core ugyanúgy verziózza és SHA-256 hash-sel rögzíti. Dokumentumonként külön állítható, hogy checkoutnál kötelező-e elfogadni." })
|
|
2241
2358
|
] }),
|
|
2242
2359
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 border-b px-6 py-5 md:grid-cols-2", children: [
|
|
2243
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$
|
|
2360
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "Dokumentum neve", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2244
2361
|
ui.Input,
|
|
2245
2362
|
{
|
|
2246
2363
|
value: title,
|
|
@@ -2248,7 +2365,7 @@ const LegalPage = () => {
|
|
|
2248
2365
|
placeholder: "Általános Szerződési Feltételek"
|
|
2249
2366
|
}
|
|
2250
2367
|
) }),
|
|
2251
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$
|
|
2368
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "Kulcs", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2252
2369
|
ui.Input,
|
|
2253
2370
|
{
|
|
2254
2371
|
value: key,
|
|
@@ -2256,7 +2373,7 @@ const LegalPage = () => {
|
|
|
2256
2373
|
placeholder: "terms"
|
|
2257
2374
|
}
|
|
2258
2375
|
) }),
|
|
2259
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$
|
|
2376
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$4, { label: "Típus", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2260
2377
|
"select",
|
|
2261
2378
|
{
|
|
2262
2379
|
className: "h-8 rounded-md border bg-ui-bg-field px-2 text-sm",
|
|
@@ -2270,7 +2387,7 @@ const LegalPage = () => {
|
|
|
2270
2387
|
]
|
|
2271
2388
|
}
|
|
2272
2389
|
) }),
|
|
2273
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Field$
|
|
2390
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Field$4, { label: "PDF fájl (max. 5 MB)", children: [
|
|
2274
2391
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2275
2392
|
"input",
|
|
2276
2393
|
{
|
|
@@ -2411,7 +2528,7 @@ const LegalPage = () => {
|
|
|
2411
2528
|
"a",
|
|
2412
2529
|
{
|
|
2413
2530
|
className: "text-ui-fg-interactive",
|
|
2414
|
-
href: `${adminBase$
|
|
2531
|
+
href: `${adminBase$4}/orders/${consent.orderId}`,
|
|
2415
2532
|
children: consent.orderId
|
|
2416
2533
|
}
|
|
2417
2534
|
) : "Még nincs rendelés" }),
|
|
@@ -2421,7 +2538,7 @@ const LegalPage = () => {
|
|
|
2421
2538
|
] }) })
|
|
2422
2539
|
] }) });
|
|
2423
2540
|
};
|
|
2424
|
-
function Field$
|
|
2541
|
+
function Field$4({
|
|
2425
2542
|
label,
|
|
2426
2543
|
children
|
|
2427
2544
|
}) {
|
|
@@ -2467,398 +2584,281 @@ const config$7 = adminSdk.defineRouteConfig({
|
|
|
2467
2584
|
icon: Newspaper,
|
|
2468
2585
|
rank: 40
|
|
2469
2586
|
});
|
|
2587
|
+
const defaults$1 = {
|
|
2588
|
+
ARUKERESO_STOREFRONT_URL: "",
|
|
2589
|
+
ARUKERESO_PRODUCT_PATH_TEMPLATE: "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
2590
|
+
ARUKERESO_SALES_CHANNEL_ID: "",
|
|
2591
|
+
ARUKERESO_DEFAULT_MANUFACTURER: "",
|
|
2592
|
+
ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER: false,
|
|
2593
|
+
ARUKERESO_INCLUDE_OUT_OF_STOCK: true,
|
|
2594
|
+
ARUKERESO_DEFAULT_DELIVERY_TIME: "",
|
|
2595
|
+
ARUKERESO_DEFAULT_DELIVERY_COST: ""
|
|
2596
|
+
};
|
|
2470
2597
|
const backendUrl$8 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
2471
|
-
const
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
const
|
|
2476
|
-
const [
|
|
2477
|
-
const [
|
|
2478
|
-
const [
|
|
2479
|
-
const
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
const [loadError, setLoadError] = React.useState(null);
|
|
2598
|
+
const apiUrl$8 = (path) => `${backendUrl$8}${path.startsWith("/") ? path : `/${path}`}`;
|
|
2599
|
+
const ArukeresoPage = () => {
|
|
2600
|
+
const [enabled, setEnabled] = React.useState(false);
|
|
2601
|
+
const [draft, setDraft] = React.useState(defaults$1);
|
|
2602
|
+
const [loading, setLoading] = React.useState(true);
|
|
2603
|
+
const [saving, setSaving] = React.useState(false);
|
|
2604
|
+
const [previewing, setPreviewing] = React.useState(false);
|
|
2605
|
+
const [preview, setPreview] = React.useState(null);
|
|
2606
|
+
const update = (key, value) => {
|
|
2607
|
+
setDraft((current) => ({ ...current, [key]: value }));
|
|
2608
|
+
};
|
|
2483
2609
|
const load = React.useCallback(async () => {
|
|
2484
|
-
|
|
2485
|
-
setLoadError(null);
|
|
2610
|
+
setLoading(true);
|
|
2486
2611
|
try {
|
|
2487
|
-
const response = await fetch(apiUrl$8("/admin/
|
|
2612
|
+
const response = await fetch(apiUrl$8("/admin/integrations/arukereso"), {
|
|
2488
2613
|
credentials: "include"
|
|
2489
2614
|
});
|
|
2490
|
-
const
|
|
2491
|
-
if (!response.ok) {
|
|
2492
|
-
throw new Error(
|
|
2615
|
+
const data = await response.json().catch(() => ({}));
|
|
2616
|
+
if (!response.ok || !data.integration) {
|
|
2617
|
+
throw new Error(data.message || "Az Árukereső beállítások nem tölthetők be.");
|
|
2493
2618
|
}
|
|
2494
|
-
const
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2619
|
+
const values = data.integration.values || {};
|
|
2620
|
+
setEnabled(Boolean(data.integration.enabled));
|
|
2621
|
+
setDraft({
|
|
2622
|
+
ARUKERESO_STOREFRONT_URL: values.ARUKERESO_STOREFRONT_URL || "",
|
|
2623
|
+
ARUKERESO_PRODUCT_PATH_TEMPLATE: values.ARUKERESO_PRODUCT_PATH_TEMPLATE || "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
2624
|
+
ARUKERESO_SALES_CHANNEL_ID: values.ARUKERESO_SALES_CHANNEL_ID || "",
|
|
2625
|
+
ARUKERESO_DEFAULT_MANUFACTURER: values.ARUKERESO_DEFAULT_MANUFACTURER || "",
|
|
2626
|
+
ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER: values.ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER === "true",
|
|
2627
|
+
ARUKERESO_INCLUDE_OUT_OF_STOCK: values.ARUKERESO_INCLUDE_OUT_OF_STOCK !== "false",
|
|
2628
|
+
ARUKERESO_DEFAULT_DELIVERY_TIME: values.ARUKERESO_DEFAULT_DELIVERY_TIME || "",
|
|
2629
|
+
ARUKERESO_DEFAULT_DELIVERY_COST: values.ARUKERESO_DEFAULT_DELIVERY_COST || ""
|
|
2630
|
+
});
|
|
2500
2631
|
} catch (error) {
|
|
2501
|
-
|
|
2502
|
-
setLoadError(
|
|
2503
|
-
error instanceof Error ? error.message : "A számlázási lista nem tölthető be."
|
|
2504
|
-
);
|
|
2632
|
+
ui.toast.error(error instanceof Error ? error.message : "Betöltési hiba.");
|
|
2505
2633
|
} finally {
|
|
2506
|
-
|
|
2634
|
+
setLoading(false);
|
|
2507
2635
|
}
|
|
2508
2636
|
}, []);
|
|
2509
2637
|
React.useEffect(() => {
|
|
2510
2638
|
void load();
|
|
2511
2639
|
}, [load]);
|
|
2512
|
-
const
|
|
2513
|
-
|
|
2514
|
-
if (!value) return orders;
|
|
2515
|
-
return orders.filter(
|
|
2516
|
-
(order) => [
|
|
2517
|
-
order.display_id,
|
|
2518
|
-
order.email,
|
|
2519
|
-
order.invoice?.invoiceNumber,
|
|
2520
|
-
order.invoice?.modificationInvoiceNumber
|
|
2521
|
-
].some(
|
|
2522
|
-
(item) => String(item || "").toLowerCase().includes(value)
|
|
2523
|
-
)
|
|
2524
|
-
);
|
|
2525
|
-
}, [orders, query]);
|
|
2526
|
-
const selectedSet = React.useMemo(() => new Set(selected), [selected]);
|
|
2527
|
-
const toggle = (id) => {
|
|
2528
|
-
setSelected(
|
|
2529
|
-
(current) => current.includes(id) ? current.filter((item) => item !== id) : [...current, id]
|
|
2530
|
-
);
|
|
2531
|
-
};
|
|
2532
|
-
const bulkCreate = async () => {
|
|
2533
|
-
if (!selected.length) {
|
|
2534
|
-
ui.toast.error("Jelölj ki legalább egy rendelést.");
|
|
2535
|
-
return;
|
|
2536
|
-
}
|
|
2537
|
-
setLoading("bulk");
|
|
2538
|
-
try {
|
|
2539
|
-
const response = await fetch(apiUrl$8("/admin/billingo/bulk/create"), {
|
|
2540
|
-
method: "POST",
|
|
2541
|
-
credentials: "include",
|
|
2542
|
-
headers: { "Content-Type": "application/json" },
|
|
2543
|
-
body: JSON.stringify({ orderIds: selected })
|
|
2544
|
-
});
|
|
2545
|
-
const payload = await response.json().catch(() => ({}));
|
|
2546
|
-
if (!response.ok && response.status !== 207) {
|
|
2547
|
-
throw new Error(payload.message || "A tömeges számlázás nem sikerült.");
|
|
2548
|
-
}
|
|
2549
|
-
const failed = payload.results?.filter((item) => !item.ok).length || 0;
|
|
2550
|
-
const created = payload.results?.filter(
|
|
2551
|
-
(item) => item.ok && !item.alreadyExisted
|
|
2552
|
-
).length || 0;
|
|
2553
|
-
if (failed) {
|
|
2554
|
-
ui.toast.error(`${failed} számla nem készült el; ${created} sikeres.`);
|
|
2555
|
-
} else {
|
|
2556
|
-
ui.toast.success(`${created} új számla elkészült.`);
|
|
2557
|
-
}
|
|
2558
|
-
await load();
|
|
2559
|
-
} catch (error) {
|
|
2560
|
-
ui.toast.error(
|
|
2561
|
-
error instanceof Error ? error.message : "A tömeges számlázás nem sikerült."
|
|
2562
|
-
);
|
|
2563
|
-
} finally {
|
|
2564
|
-
setLoading(null);
|
|
2565
|
-
}
|
|
2566
|
-
};
|
|
2567
|
-
const action = async (order, value) => {
|
|
2568
|
-
if (value === "cancel" && !confirm(
|
|
2569
|
-
`Biztosan sztornózod a(z) ${order.invoice?.invoiceNumber || order.invoice?.documentId} számlát?`
|
|
2570
|
-
)) {
|
|
2571
|
-
return;
|
|
2572
|
-
}
|
|
2573
|
-
if (value === "modify" && !confirm(
|
|
2574
|
-
`Biztosan teljes jóváíró/módosító bizonylatot készítesz a(z) ${order.invoice?.invoiceNumber || order.invoice?.documentId} számlához? Ez a teljes számla összegét jóváírja.`
|
|
2575
|
-
)) {
|
|
2576
|
-
return;
|
|
2577
|
-
}
|
|
2578
|
-
setLoading(`${order.id}:${value}`);
|
|
2640
|
+
const save = async () => {
|
|
2641
|
+
setSaving(true);
|
|
2579
2642
|
try {
|
|
2580
|
-
const response = await fetch(apiUrl$8(
|
|
2643
|
+
const response = await fetch(apiUrl$8("/admin/integrations/arukereso"), {
|
|
2581
2644
|
method: "POST",
|
|
2582
2645
|
credentials: "include",
|
|
2583
2646
|
headers: { "Content-Type": "application/json" },
|
|
2584
|
-
body: JSON.stringify({
|
|
2647
|
+
body: JSON.stringify({ enabled, values: draft })
|
|
2585
2648
|
});
|
|
2586
|
-
const
|
|
2587
|
-
if (!response.ok)
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
const messages = {
|
|
2591
|
-
create: "A számla elkészült.",
|
|
2592
|
-
sync: "A számla frissítve.",
|
|
2593
|
-
send: "A számla elküldve.",
|
|
2594
|
-
cancel: "A számla sztornózva.",
|
|
2595
|
-
modify: "A teljes jóváíró/módosító bizonylat elkészült."
|
|
2596
|
-
};
|
|
2597
|
-
ui.toast.success(messages[value]);
|
|
2598
|
-
if (value === "modify" && payload.sendError) {
|
|
2599
|
-
ui.toast.error(`A jóváírás elkészült, de az e-mail küldése sikertelen: ${payload.sendError}`);
|
|
2600
|
-
}
|
|
2649
|
+
const data = await response.json().catch(() => ({}));
|
|
2650
|
+
if (!response.ok) throw new Error(data.message || "A mentés nem sikerült.");
|
|
2651
|
+
ui.toast.success(data.message || "Árukereső beállítások mentve.");
|
|
2652
|
+
setPreview(null);
|
|
2601
2653
|
await load();
|
|
2602
2654
|
} catch (error) {
|
|
2603
|
-
ui.toast.error(
|
|
2604
|
-
error instanceof Error ? error.message : "A Billingo művelet nem sikerült."
|
|
2605
|
-
);
|
|
2655
|
+
ui.toast.error(error instanceof Error ? error.message : "A mentés nem sikerült.");
|
|
2606
2656
|
} finally {
|
|
2607
|
-
|
|
2657
|
+
setSaving(false);
|
|
2608
2658
|
}
|
|
2609
2659
|
};
|
|
2610
|
-
const
|
|
2611
|
-
|
|
2660
|
+
const runPreview = async () => {
|
|
2661
|
+
setPreviewing(true);
|
|
2612
2662
|
try {
|
|
2613
|
-
const response = await fetch(apiUrl$8("/admin/
|
|
2614
|
-
method: "POST",
|
|
2663
|
+
const response = await fetch(apiUrl$8("/admin/arukereso/preview"), {
|
|
2615
2664
|
credentials: "include"
|
|
2616
2665
|
});
|
|
2617
|
-
const
|
|
2618
|
-
if (!response.ok)
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
ui.toast.success(payload.message || "A Billingo kapcsolat működik.");
|
|
2666
|
+
const data = await response.json().catch(() => ({}));
|
|
2667
|
+
if (!response.ok) throw new Error(data.message || "A feed nem generálható.");
|
|
2668
|
+
setPreview(data);
|
|
2669
|
+
ui.toast.success("Az Árukereső feed ellenőrzése elkészült.");
|
|
2622
2670
|
} catch (error) {
|
|
2623
|
-
ui.toast.error(
|
|
2624
|
-
error instanceof Error ? error.message : "A Billingo kapcsolat nem működik."
|
|
2625
|
-
);
|
|
2671
|
+
ui.toast.error(error instanceof Error ? error.message : "A feed nem generálható.");
|
|
2626
2672
|
} finally {
|
|
2627
|
-
|
|
2673
|
+
setPreviewing(false);
|
|
2628
2674
|
}
|
|
2629
2675
|
};
|
|
2676
|
+
const feedUrl = apiUrl$8("/feeds/arukereso.xml");
|
|
2677
|
+
const d = preview?.diagnostics;
|
|
2630
2678
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
2631
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-
|
|
2679
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4 border-b px-6 py-4", children: [
|
|
2632
2680
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2633
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "
|
|
2634
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "
|
|
2635
|
-
configuration?.autoInvoice ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
2636
|
-
"Az automatikus számlázás aktív",
|
|
2637
|
-
configuration.autoSend ? ", automatikus e-mail küldéssel" : "",
|
|
2638
|
-
"."
|
|
2639
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-warning", children: "Az automatikus számlázás ki van kapcsolva." })
|
|
2681
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Árukereső.hu" }),
|
|
2682
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Árukereső XML feed a Medusa termék-, variant-, HU/HUF ár-, ÁFA- és készletadataiból." })
|
|
2640
2683
|
] }),
|
|
2641
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
2642
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
2685
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: enabled, onCheckedChange: setEnabled, disabled: loading }),
|
|
2686
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: enabled ? "Bekapcsolva" : "Kikapcsolva" })
|
|
2687
|
+
] })
|
|
2688
|
+
] }),
|
|
2689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 border-b px-6 py-5 md:grid-cols-2", children: [
|
|
2690
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "Storefront URL", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2691
|
+
ui.Input,
|
|
2692
|
+
{
|
|
2693
|
+
value: draft.ARUKERESO_STOREFRONT_URL,
|
|
2694
|
+
onChange: (e) => update("ARUKERESO_STOREFRONT_URL", e.target.value),
|
|
2695
|
+
placeholder: "https://shop.hu (üresen STOREFRONT_URL)"
|
|
2696
|
+
}
|
|
2697
|
+
) }),
|
|
2698
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Field$3, { label: "Termék URL sablon", children: [
|
|
2646
2699
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2647
|
-
ui.
|
|
2700
|
+
ui.Input,
|
|
2648
2701
|
{
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
onClick: () => void testConnection(),
|
|
2652
|
-
children: "Kapcsolat tesztelése"
|
|
2702
|
+
value: draft.ARUKERESO_PRODUCT_PATH_TEMPLATE,
|
|
2703
|
+
onChange: (e) => update("ARUKERESO_PRODUCT_PATH_TEMPLATE", e.target.value)
|
|
2653
2704
|
}
|
|
2654
|
-
)
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
] })
|
|
2667
|
-
|
|
2668
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3 border-b px-6 py-4", children: [
|
|
2669
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2705
|
+
),
|
|
2706
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-xs", children: [
|
|
2707
|
+
"Helyőrzők: ",
|
|
2708
|
+
"{country_code}",
|
|
2709
|
+
", ",
|
|
2710
|
+
"{currency_code}",
|
|
2711
|
+
", ",
|
|
2712
|
+
"{handle}",
|
|
2713
|
+
", ",
|
|
2714
|
+
"{variant_id}",
|
|
2715
|
+
"."
|
|
2716
|
+
] })
|
|
2717
|
+
] }),
|
|
2718
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "Sales Channel ID", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2670
2719
|
ui.Input,
|
|
2671
2720
|
{
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
placeholder: "Rendelés, e-mail vagy számlaszám keresése"
|
|
2721
|
+
value: draft.ARUKERESO_SALES_CHANNEL_ID,
|
|
2722
|
+
onChange: (e) => update("ARUKERESO_SALES_CHANNEL_ID", e.target.value),
|
|
2723
|
+
placeholder: "sc_... (opcionális)"
|
|
2676
2724
|
}
|
|
2677
|
-
),
|
|
2678
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2679
|
-
ui.
|
|
2725
|
+
) }),
|
|
2726
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "Alapértelmezett gyártó", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2727
|
+
ui.Input,
|
|
2680
2728
|
{
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
children: "Kijelöltek számlázása"
|
|
2729
|
+
value: draft.ARUKERESO_DEFAULT_MANUFACTURER,
|
|
2730
|
+
onChange: (e) => update("ARUKERESO_DEFAULT_MANUFACTURER", e.target.value),
|
|
2731
|
+
placeholder: "Csak ha minden termékre tényleg igaz"
|
|
2685
2732
|
}
|
|
2686
|
-
),
|
|
2687
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2688
|
-
|
|
2733
|
+
) }),
|
|
2734
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "SKU mint gyártói cikkszám", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
2735
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2736
|
+
ui.Switch,
|
|
2737
|
+
{
|
|
2738
|
+
checked: draft.ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER,
|
|
2739
|
+
onCheckedChange: (value) => update("ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER", value)
|
|
2740
|
+
}
|
|
2741
|
+
),
|
|
2742
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: draft.ARUKERESO_USE_SKU_AS_PRODUCT_NUMBER ? "Igen" : "Nem" })
|
|
2743
|
+
] }) }),
|
|
2744
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "Készlethiányos termékek", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
2745
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2746
|
+
ui.Switch,
|
|
2747
|
+
{
|
|
2748
|
+
checked: draft.ARUKERESO_INCLUDE_OUT_OF_STOCK,
|
|
2749
|
+
onCheckedChange: (value) => update("ARUKERESO_INCLUDE_OUT_OF_STOCK", value)
|
|
2750
|
+
}
|
|
2751
|
+
),
|
|
2752
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: draft.ARUKERESO_INCLUDE_OUT_OF_STOCK ? "DeliveryTime=NO" : "Kimaradnak" })
|
|
2753
|
+
] }) }),
|
|
2754
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "Alap szállítási idő", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2755
|
+
ui.Input,
|
|
2689
2756
|
{
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
children: "Frissítés"
|
|
2757
|
+
value: draft.ARUKERESO_DEFAULT_DELIVERY_TIME,
|
|
2758
|
+
onChange: (e) => update("ARUKERESO_DEFAULT_DELIVERY_TIME", e.target.value),
|
|
2759
|
+
placeholder: "1 vagy 3"
|
|
2694
2760
|
}
|
|
2695
|
-
)
|
|
2761
|
+
) }),
|
|
2762
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$3, { label: "Alap szállítási költség", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2763
|
+
ui.Input,
|
|
2764
|
+
{
|
|
2765
|
+
value: draft.ARUKERESO_DEFAULT_DELIVERY_COST,
|
|
2766
|
+
onChange: (e) => update("ARUKERESO_DEFAULT_DELIVERY_COST", e.target.value),
|
|
2767
|
+
placeholder: "1990 vagy FREE"
|
|
2768
|
+
}
|
|
2769
|
+
) })
|
|
2696
2770
|
] }),
|
|
2697
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2698
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
2699
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
className: "text-ui-fg-interactive",
|
|
2739
|
-
href: `${adminBase$4}/orders/${order.id}`,
|
|
2740
|
-
children: [
|
|
2741
|
-
"#",
|
|
2742
|
-
order.display_id ?? order.id
|
|
2743
|
-
]
|
|
2744
|
-
}
|
|
2745
|
-
),
|
|
2746
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: order.email || "—" }),
|
|
2747
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: formatMoney(order.total, order.currency_code) })
|
|
2748
|
-
] }),
|
|
2749
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: order.payment_status === "captured" ? "Fizetve" : order.payment_status === "refunded" ? "Visszatérítve" : order.payment_status === "partially_refunded" ? "Részben visszatérítve" : order.payment_status || "—" }),
|
|
2750
|
-
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
2751
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: invoice?.invoiceNumber || (invoice ? `#${invoice.documentId}` : "Még nincs") }),
|
|
2752
|
-
invoice?.cancelled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-error", children: "Sztornózva" }) : null,
|
|
2753
|
-
modified ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-interactive", children: [
|
|
2754
|
-
"Jóváírva: ",
|
|
2755
|
-
invoice?.modificationInvoiceNumber || `#${invoice?.modificationDocumentId}`
|
|
2756
|
-
] }) : null,
|
|
2757
|
-
last?.status === "failed" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xs text-ui-fg-error", children: last.message }) : null
|
|
2758
|
-
] }),
|
|
2759
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: invoice ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2760
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: invoice.paymentStatus || "—" }),
|
|
2761
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-subtle", children: [
|
|
2762
|
-
"NAV: ",
|
|
2763
|
-
invoice.onlineSzamlaStatus || "—"
|
|
2764
|
-
] }),
|
|
2765
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-subtle", children: [
|
|
2766
|
-
"E-mail: ",
|
|
2767
|
-
invoice.notificationStatus || "—"
|
|
2768
|
-
] })
|
|
2769
|
-
] }) : "—" }),
|
|
2770
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-w-lg flex-wrap gap-2", children: !invoice ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2771
|
-
ui.Button,
|
|
2772
|
-
{
|
|
2773
|
-
size: "small",
|
|
2774
|
-
disabled: !configuration?.configured || Boolean(loading),
|
|
2775
|
-
isLoading: loading === `${order.id}:create`,
|
|
2776
|
-
onClick: () => void action(order, "create"),
|
|
2777
|
-
children: "Számla készítése"
|
|
2778
|
-
}
|
|
2779
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2780
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2781
|
-
ui.Button,
|
|
2782
|
-
{
|
|
2783
|
-
size: "small",
|
|
2784
|
-
variant: "secondary",
|
|
2785
|
-
disabled: Boolean(loading),
|
|
2786
|
-
isLoading: loading === `${order.id}:sync`,
|
|
2787
|
-
onClick: () => void action(order, "sync"),
|
|
2788
|
-
children: "Frissítés"
|
|
2789
|
-
}
|
|
2790
|
-
),
|
|
2791
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2792
|
-
"a",
|
|
2793
|
-
{
|
|
2794
|
-
href: apiUrl$8(`/admin/orders/${order.id}/billingo/pdf`),
|
|
2795
|
-
target: "_blank",
|
|
2796
|
-
rel: "noreferrer",
|
|
2797
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "PDF" })
|
|
2798
|
-
}
|
|
2799
|
-
),
|
|
2800
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2801
|
-
ui.Button,
|
|
2802
|
-
{
|
|
2803
|
-
size: "small",
|
|
2804
|
-
variant: "secondary",
|
|
2805
|
-
disabled: Boolean(loading) || invoice.cancelled,
|
|
2806
|
-
isLoading: loading === `${order.id}:send`,
|
|
2807
|
-
onClick: () => void action(order, "send"),
|
|
2808
|
-
children: "E-mail"
|
|
2809
|
-
}
|
|
2810
|
-
),
|
|
2811
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2812
|
-
ui.Button,
|
|
2813
|
-
{
|
|
2814
|
-
size: "small",
|
|
2815
|
-
variant: "secondary",
|
|
2816
|
-
disabled: Boolean(loading) || invoice.cancelled || modified,
|
|
2817
|
-
isLoading: loading === `${order.id}:modify`,
|
|
2818
|
-
onClick: () => void action(order, "modify"),
|
|
2819
|
-
children: "Teljes jóváírás"
|
|
2820
|
-
}
|
|
2821
|
-
),
|
|
2822
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2823
|
-
ui.Button,
|
|
2824
|
-
{
|
|
2825
|
-
size: "small",
|
|
2826
|
-
variant: "danger",
|
|
2827
|
-
disabled: Boolean(loading) || invoice.cancelled || modified,
|
|
2828
|
-
isLoading: loading === `${order.id}:cancel`,
|
|
2829
|
-
onClick: () => void action(order, "cancel"),
|
|
2830
|
-
children: "Sztornó"
|
|
2831
|
-
}
|
|
2832
|
-
)
|
|
2833
|
-
] }) }) })
|
|
2834
|
-
] }, order.id);
|
|
2835
|
-
}) })
|
|
2771
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b px-6 py-4", children: [
|
|
2772
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2773
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Publikus feed URL" }),
|
|
2774
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "break-all text-ui-fg-interactive hover:underline", href: feedUrl, target: "_blank", rel: "noreferrer", children: feedUrl })
|
|
2775
|
+
] }),
|
|
2776
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
2777
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2778
|
+
ui.Button,
|
|
2779
|
+
{
|
|
2780
|
+
variant: "secondary",
|
|
2781
|
+
isLoading: previewing,
|
|
2782
|
+
disabled: !enabled || loading || saving || previewing,
|
|
2783
|
+
onClick: () => void runPreview(),
|
|
2784
|
+
children: "Feed ellenőrzése"
|
|
2785
|
+
}
|
|
2786
|
+
),
|
|
2787
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2788
|
+
ui.Button,
|
|
2789
|
+
{
|
|
2790
|
+
isLoading: saving,
|
|
2791
|
+
disabled: loading || saving || previewing,
|
|
2792
|
+
onClick: () => void save(),
|
|
2793
|
+
children: "Mentés"
|
|
2794
|
+
}
|
|
2795
|
+
)
|
|
2796
|
+
] })
|
|
2797
|
+
] }),
|
|
2798
|
+
d ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2799
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 border-b px-6 py-5 sm:grid-cols-2 lg:grid-cols-4", children: [
|
|
2800
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Termékek", value: d.productsScanned }),
|
|
2801
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Variantok", value: d.variantsScanned }),
|
|
2802
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Feed tételek", value: d.itemsEmitted }),
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs gyártó", value: d.skippedNoManufacturer }),
|
|
2804
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs kategória", value: d.skippedNoCategory }),
|
|
2805
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs ár", value: d.skippedNoPrice }),
|
|
2806
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs ProductNumber", value: d.itemsMissingProductNumber }),
|
|
2807
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Nincs kép", value: d.itemsMissingImage }),
|
|
2808
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Készlethiány miatt kimaradt", value: d.skippedOutOfStock }),
|
|
2809
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Sales channel hiba", value: d.skippedNoSalesChannel + d.skippedNotInSalesChannel }),
|
|
2810
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Hibás delivery time", value: d.invalidDeliveryTime }),
|
|
2811
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat$1, { label: "Hibás delivery cost", value: d.invalidDeliveryCost })
|
|
2836
2812
|
] }),
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2841
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2813
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
2814
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-b bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2815
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Identifier" }),
|
|
2816
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Termék" }),
|
|
2817
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Gyártó" }),
|
|
2818
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Kategória" }),
|
|
2819
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Bruttó / nettó" }),
|
|
2820
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Szállítás" })
|
|
2821
|
+
] }) }),
|
|
2822
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: (preview?.sample || []).map((item) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b", children: [
|
|
2823
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: item.identifier }) }),
|
|
2824
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
2825
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href: item.productUrl, target: "_blank", rel: "noreferrer", className: "text-ui-fg-interactive hover:underline", children: item.name }),
|
|
2826
|
+
item.productNumber ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-muted text-xs", children: [
|
|
2827
|
+
"PN: ",
|
|
2828
|
+
item.productNumber
|
|
2829
|
+
] }) : null
|
|
2830
|
+
] }),
|
|
2831
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.manufacturer }),
|
|
2832
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.category }),
|
|
2833
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
2834
|
+
item.price,
|
|
2835
|
+
" / ",
|
|
2836
|
+
item.netPrice,
|
|
2837
|
+
" HUF"
|
|
2838
|
+
] }),
|
|
2839
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
2840
|
+
item.deliveryTime || "—",
|
|
2841
|
+
" · ",
|
|
2842
|
+
item.deliveryCost || "—"
|
|
2843
|
+
] })
|
|
2844
|
+
] }, item.identifier)) })
|
|
2845
|
+
] }) })
|
|
2846
|
+
] }) : null
|
|
2847
2847
|
] });
|
|
2848
2848
|
};
|
|
2849
|
-
function
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
maximumFractionDigits: currency?.toUpperCase() === "HUF" ? 0 : 2
|
|
2855
|
-
}).format(value);
|
|
2849
|
+
function Field$3({ label, children }) {
|
|
2850
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
2851
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: label }),
|
|
2852
|
+
children
|
|
2853
|
+
] });
|
|
2856
2854
|
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
});
|
|
2855
|
+
function Stat$1({ label, value }) {
|
|
2856
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-3", children: [
|
|
2857
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: label }),
|
|
2858
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: value })
|
|
2859
|
+
] });
|
|
2860
|
+
}
|
|
2861
|
+
const config$6 = adminSdk.defineRouteConfig({ label: "Árukereső", rank: 42 });
|
|
2862
2862
|
const EMPTY_SEO = {
|
|
2863
2863
|
title: "",
|
|
2864
2864
|
description: "",
|
|
@@ -3124,251 +3124,60 @@ ${selectedPage.path}`)) return;
|
|
|
3124
3124
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-2 text-ui-fg-subtle", children: previewDescription })
|
|
3125
3125
|
] }),
|
|
3126
3126
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 border-t pt-5", children: [
|
|
3127
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { isLoading: saving, disabled: saving || deleting || mode === "page" && !pagePath.trim(), onClick: () => void save(), children: "Mentés" }),
|
|
3128
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", disabled: saving || deleting, onClick: () => setForm({ ...EMPTY_SEO }), children: "SEO felülírások ürítése" }),
|
|
3129
|
-
mode === "page" && selectedPage ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { className: "ml-auto", variant: "secondary", isLoading: deleting, disabled: saving || deleting, onClick: () => void removePage(), children: "Oldal törlése" }) : null
|
|
3130
|
-
] })
|
|
3131
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Válassz egy elemet a SEO szerkesztéséhez." }) })
|
|
3132
|
-
] })
|
|
3133
|
-
] });
|
|
3134
|
-
};
|
|
3135
|
-
const ModeButton = ({ active, onClick, children }) => /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: active ? "primary" : "secondary", onClick, children });
|
|
3136
|
-
const ListButton = ({ active, title, subtitle, onClick }) => /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick, className: `mb-2 w-full rounded-lg border p-3 text-left transition-colors hover:bg-ui-bg-subtle ${active ? "bg-ui-bg-subtle" : "bg-ui-bg-base"}`, children: [
|
|
3137
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: title }),
|
|
3138
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 truncate text-xs text-ui-fg-subtle", children: subtitle })
|
|
3139
|
-
] });
|
|
3140
|
-
const Field$2 = ({ label, help, children }) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
3141
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: label }),
|
|
3142
|
-
children,
|
|
3143
|
-
help ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-muted", children: help }) : null
|
|
3144
|
-
] });
|
|
3145
|
-
const Counter = ({ value, recommended }) => {
|
|
3146
|
-
const length = value.length;
|
|
3147
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: `text-xs ${length > recommended ? "text-ui-fg-warning" : "text-ui-fg-muted"}`, children: [
|
|
3148
|
-
length,
|
|
3149
|
-
" karakter",
|
|
3150
|
-
length > recommended ? ` · ajánlott maximum kb. ${recommended}` : ""
|
|
3151
|
-
] });
|
|
3152
|
-
};
|
|
3153
|
-
const ToggleCard = ({ label, description, checked, onCheckedChange }) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-start justify-between gap-4 rounded-lg border p-4", children: [
|
|
3154
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3155
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: label }),
|
|
3156
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-subtle", children: description })
|
|
3157
|
-
] }),
|
|
3158
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked, onCheckedChange })
|
|
3159
|
-
] });
|
|
3160
|
-
function normalizeSeo(value) {
|
|
3161
|
-
return {
|
|
3162
|
-
title: value?.title || "",
|
|
3163
|
-
description: value?.description || "",
|
|
3164
|
-
canonical: value?.canonical || "",
|
|
3165
|
-
noindex: Boolean(value?.noindex),
|
|
3166
|
-
nofollow: Boolean(value?.nofollow),
|
|
3167
|
-
ogTitle: value?.ogTitle || "",
|
|
3168
|
-
ogDescription: value?.ogDescription || "",
|
|
3169
|
-
ogImage: value?.ogImage || ""
|
|
3170
|
-
};
|
|
3171
|
-
}
|
|
3172
|
-
function normalizeEntity(value) {
|
|
3173
|
-
return { ...value, seo: normalizeSeo(value.seo) };
|
|
3174
|
-
}
|
|
3175
|
-
function normalizePage(value) {
|
|
3176
|
-
return { ...value, seo: normalizeSeo(value.seo) };
|
|
3177
|
-
}
|
|
3178
|
-
const defaults = {
|
|
3179
|
-
GOOGLE_MERCHANT_COUNTRY_CODE: "HU",
|
|
3180
|
-
GOOGLE_MERCHANT_CURRENCY_CODE: "HUF",
|
|
3181
|
-
GOOGLE_MERCHANT_STOREFRONT_URL: "",
|
|
3182
|
-
GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE: "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
3183
|
-
GOOGLE_MERCHANT_SALES_CHANNEL_ID: "",
|
|
3184
|
-
GOOGLE_MERCHANT_DEFAULT_BRAND: "",
|
|
3185
|
-
GOOGLE_MERCHANT_DEFAULT_CONDITION: "new",
|
|
3186
|
-
GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK: true,
|
|
3187
|
-
GOOGLE_MERCHANT_FEED_TITLE: "",
|
|
3188
|
-
GOOGLE_MERCHANT_FEED_DESCRIPTION: ""
|
|
3189
|
-
};
|
|
3190
|
-
const backendUrl$6 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
3191
|
-
const apiUrl$6 = (path) => `${backendUrl$6}${path.startsWith("/") ? path : `/${path}`}`;
|
|
3192
|
-
const GoogleMerchantPage = () => {
|
|
3193
|
-
const [enabled, setEnabled] = React.useState(false);
|
|
3194
|
-
const [draft, setDraft] = React.useState(defaults);
|
|
3195
|
-
const [loading, setLoading] = React.useState(true);
|
|
3196
|
-
const [saving, setSaving] = React.useState(false);
|
|
3197
|
-
const [previewing, setPreviewing] = React.useState(false);
|
|
3198
|
-
const [preview, setPreview] = React.useState(null);
|
|
3199
|
-
const update = (key, value) => {
|
|
3200
|
-
setDraft((current) => ({ ...current, [key]: value }));
|
|
3201
|
-
};
|
|
3202
|
-
const load = React.useCallback(async () => {
|
|
3203
|
-
setLoading(true);
|
|
3204
|
-
try {
|
|
3205
|
-
const response = await fetch(apiUrl$6("/admin/integrations/google-merchant"), {
|
|
3206
|
-
credentials: "include"
|
|
3207
|
-
});
|
|
3208
|
-
const data = await response.json().catch(() => ({}));
|
|
3209
|
-
if (!response.ok || !data.integration) {
|
|
3210
|
-
throw new Error(data.message || "A Google Merchant beállítások nem tölthetők be.");
|
|
3211
|
-
}
|
|
3212
|
-
const values = data.integration.values || {};
|
|
3213
|
-
setEnabled(Boolean(data.integration.enabled));
|
|
3214
|
-
setDraft({
|
|
3215
|
-
GOOGLE_MERCHANT_COUNTRY_CODE: values.GOOGLE_MERCHANT_COUNTRY_CODE || "HU",
|
|
3216
|
-
GOOGLE_MERCHANT_CURRENCY_CODE: values.GOOGLE_MERCHANT_CURRENCY_CODE || "HUF",
|
|
3217
|
-
GOOGLE_MERCHANT_STOREFRONT_URL: values.GOOGLE_MERCHANT_STOREFRONT_URL || "",
|
|
3218
|
-
GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE: values.GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE || "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
3219
|
-
GOOGLE_MERCHANT_SALES_CHANNEL_ID: values.GOOGLE_MERCHANT_SALES_CHANNEL_ID || "",
|
|
3220
|
-
GOOGLE_MERCHANT_DEFAULT_BRAND: values.GOOGLE_MERCHANT_DEFAULT_BRAND || "",
|
|
3221
|
-
GOOGLE_MERCHANT_DEFAULT_CONDITION: values.GOOGLE_MERCHANT_DEFAULT_CONDITION || "new",
|
|
3222
|
-
GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK: values.GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK !== "false",
|
|
3223
|
-
GOOGLE_MERCHANT_FEED_TITLE: values.GOOGLE_MERCHANT_FEED_TITLE || "",
|
|
3224
|
-
GOOGLE_MERCHANT_FEED_DESCRIPTION: values.GOOGLE_MERCHANT_FEED_DESCRIPTION || ""
|
|
3225
|
-
});
|
|
3226
|
-
} catch (error) {
|
|
3227
|
-
ui.toast.error(error instanceof Error ? error.message : "Betöltési hiba.");
|
|
3228
|
-
} finally {
|
|
3229
|
-
setLoading(false);
|
|
3230
|
-
}
|
|
3231
|
-
}, []);
|
|
3232
|
-
React.useEffect(() => {
|
|
3233
|
-
void load();
|
|
3234
|
-
}, [load]);
|
|
3235
|
-
const save = async () => {
|
|
3236
|
-
setSaving(true);
|
|
3237
|
-
try {
|
|
3238
|
-
const response = await fetch(apiUrl$6("/admin/integrations/google-merchant"), {
|
|
3239
|
-
method: "POST",
|
|
3240
|
-
credentials: "include",
|
|
3241
|
-
headers: { "Content-Type": "application/json" },
|
|
3242
|
-
body: JSON.stringify({ enabled, values: draft })
|
|
3243
|
-
});
|
|
3244
|
-
const data = await response.json().catch(() => ({}));
|
|
3245
|
-
if (!response.ok) throw new Error(data.message || "A mentés nem sikerült.");
|
|
3246
|
-
ui.toast.success(data.message || "Google Merchant beállítások mentve.");
|
|
3247
|
-
setPreview(null);
|
|
3248
|
-
await load();
|
|
3249
|
-
} catch (error) {
|
|
3250
|
-
ui.toast.error(error instanceof Error ? error.message : "A mentés nem sikerült.");
|
|
3251
|
-
} finally {
|
|
3252
|
-
setSaving(false);
|
|
3253
|
-
}
|
|
3254
|
-
};
|
|
3255
|
-
const runPreview = async () => {
|
|
3256
|
-
setPreviewing(true);
|
|
3257
|
-
try {
|
|
3258
|
-
const response = await fetch(apiUrl$6("/admin/google-merchant/preview"), {
|
|
3259
|
-
credentials: "include"
|
|
3260
|
-
});
|
|
3261
|
-
const data = await response.json().catch(() => ({}));
|
|
3262
|
-
if (!response.ok) throw new Error(data.message || "A feed nem generálható.");
|
|
3263
|
-
setPreview(data);
|
|
3264
|
-
ui.toast.success("A Merchant feed ellenőrzése elkészült.");
|
|
3265
|
-
} catch (error) {
|
|
3266
|
-
ui.toast.error(error instanceof Error ? error.message : "A feed nem generálható.");
|
|
3267
|
-
} finally {
|
|
3268
|
-
setPreviewing(false);
|
|
3269
|
-
}
|
|
3270
|
-
};
|
|
3271
|
-
const feedUrl = apiUrl$6("/feeds/google-merchant.xml");
|
|
3272
|
-
const d = preview?.diagnostics;
|
|
3273
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
3274
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4 border-b px-6 py-4", children: [
|
|
3275
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3276
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Google Merchant Center" }),
|
|
3277
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Google RSS 2.0 feed a Medusa termék-, variant-, régiós ár-, ÁFA- és készletadataiból." })
|
|
3278
|
-
] }),
|
|
3279
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
3280
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: enabled, onCheckedChange: setEnabled, disabled: loading }),
|
|
3281
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: enabled ? "Bekapcsolva" : "Kikapcsolva" })
|
|
3282
|
-
] })
|
|
3283
|
-
] }),
|
|
3284
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 border-b px-6 py-5 md:grid-cols-2", children: [
|
|
3285
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Célország", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_COUNTRY_CODE, onChange: (e) => update("GOOGLE_MERCHANT_COUNTRY_CODE", e.target.value.toUpperCase()), placeholder: "HU" }) }),
|
|
3286
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Pénznem", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_CURRENCY_CODE, onChange: (e) => update("GOOGLE_MERCHANT_CURRENCY_CODE", e.target.value.toUpperCase()), placeholder: "HUF" }) }),
|
|
3287
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Storefront URL", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_STOREFRONT_URL, onChange: (e) => update("GOOGLE_MERCHANT_STOREFRONT_URL", e.target.value), placeholder: "https://shop.hu (üresen STOREFRONT_URL)" }) }),
|
|
3288
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Field$1, { label: "Termék URL sablon", children: [
|
|
3289
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE, onChange: (e) => update("GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE", e.target.value) }),
|
|
3290
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-xs", children: [
|
|
3291
|
-
"Helyőrzők: ",
|
|
3292
|
-
"{country_code}",
|
|
3293
|
-
", ",
|
|
3294
|
-
"{currency_code}",
|
|
3295
|
-
", ",
|
|
3296
|
-
"{handle}",
|
|
3297
|
-
", ",
|
|
3298
|
-
"{variant_id}",
|
|
3299
|
-
"."
|
|
3127
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { isLoading: saving, disabled: saving || deleting || mode === "page" && !pagePath.trim(), onClick: () => void save(), children: "Mentés" }),
|
|
3128
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", disabled: saving || deleting, onClick: () => setForm({ ...EMPTY_SEO }), children: "SEO felülírások ürítése" }),
|
|
3129
|
+
mode === "page" && selectedPage ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { className: "ml-auto", variant: "secondary", isLoading: deleting, disabled: saving || deleting, onClick: () => void removePage(), children: "Oldal törlése" }) : null
|
|
3300
3130
|
] })
|
|
3301
|
-
] }),
|
|
3302
|
-
|
|
3303
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Alapértelmezett márka", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_DEFAULT_BRAND, onChange: (e) => update("GOOGLE_MERCHANT_DEFAULT_BRAND", e.target.value) }) }),
|
|
3304
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Alapértelmezett állapot", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { className: "h-8 rounded-md border bg-ui-bg-field px-2 text-sm", value: draft.GOOGLE_MERCHANT_DEFAULT_CONDITION, onChange: (e) => update("GOOGLE_MERCHANT_DEFAULT_CONDITION", e.target.value), children: [
|
|
3305
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "new", children: "Új" }),
|
|
3306
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "refurbished", children: "Felújított" }),
|
|
3307
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "used", children: "Használt" })
|
|
3308
|
-
] }) }),
|
|
3309
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Készlethiányos variantok", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
3310
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: draft.GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK, onCheckedChange: (value) => update("GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK", value) }),
|
|
3311
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: draft.GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK ? "Benne maradnak" : "Kimaradnak" })
|
|
3312
|
-
] }) }),
|
|
3313
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Feed neve", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_FEED_TITLE, onChange: (e) => update("GOOGLE_MERCHANT_FEED_TITLE", e.target.value), placeholder: "Üresen automatikus" }) }),
|
|
3314
|
-
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Feed leírása", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_FEED_DESCRIPTION, onChange: (e) => update("GOOGLE_MERCHANT_FEED_DESCRIPTION", e.target.value), placeholder: "Üresen automatikus" }) })
|
|
3315
|
-
] }),
|
|
3316
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b px-6 py-4", children: [
|
|
3317
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3318
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Publikus feed URL" }),
|
|
3319
|
-
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "break-all text-ui-fg-interactive hover:underline", href: feedUrl, target: "_blank", rel: "noreferrer", children: feedUrl })
|
|
3320
|
-
] }),
|
|
3321
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
3322
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: previewing, disabled: !enabled || loading || saving || previewing, onClick: () => void runPreview(), children: "Feed ellenőrzése" }),
|
|
3323
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { isLoading: saving, disabled: loading || saving || previewing, onClick: () => void save(), children: "Mentés" })
|
|
3324
|
-
] })
|
|
3325
|
-
] }),
|
|
3326
|
-
d ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3327
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 border-b px-6 py-5 sm:grid-cols-2 lg:grid-cols-4", children: [
|
|
3328
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Termékek", value: d.productsScanned }),
|
|
3329
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Variantok", value: d.variantsScanned }),
|
|
3330
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Feed tételek", value: d.itemsEmitted }),
|
|
3331
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Hiányzó identifier", value: d.itemsMissingIdentifiers }),
|
|
3332
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Nincs ár", value: d.skippedNoPrice }),
|
|
3333
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Nincs kép", value: d.skippedNoImage }),
|
|
3334
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Nincs sales channel", value: d.skippedNoSalesChannel + d.skippedNotInSalesChannel }),
|
|
3335
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Érvénytelen GTIN", value: d.invalidGtinsIgnored })
|
|
3336
|
-
] }),
|
|
3337
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
3338
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-b bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3339
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "ID" }),
|
|
3340
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Termék" }),
|
|
3341
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Ár" }),
|
|
3342
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Készlet" }),
|
|
3343
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Identifier" })
|
|
3344
|
-
] }) }),
|
|
3345
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: (preview?.sample || []).map((item) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b", children: [
|
|
3346
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: item.id }) }),
|
|
3347
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.link, target: "_blank", rel: "noreferrer", className: "text-ui-fg-interactive hover:underline", children: item.title }) }),
|
|
3348
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.salePrice ? `${item.salePrice} (${item.price})` : item.price }),
|
|
3349
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.availability }),
|
|
3350
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.gtin || item.mpn || item.brand || "—" })
|
|
3351
|
-
] }, item.id)) })
|
|
3352
|
-
] }) })
|
|
3353
|
-
] }) : null
|
|
3131
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Válassz egy elemet a SEO szerkesztéséhez." }) })
|
|
3132
|
+
] })
|
|
3354
3133
|
] });
|
|
3355
3134
|
};
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3135
|
+
const ModeButton = ({ active, onClick, children }) => /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: active ? "primary" : "secondary", onClick, children });
|
|
3136
|
+
const ListButton = ({ active, title, subtitle, onClick }) => /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", onClick, className: `mb-2 w-full rounded-lg border p-3 text-left transition-colors hover:bg-ui-bg-subtle ${active ? "bg-ui-bg-subtle" : "bg-ui-bg-base"}`, children: [
|
|
3137
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: title }),
|
|
3138
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 truncate text-xs text-ui-fg-subtle", children: subtitle })
|
|
3139
|
+
] });
|
|
3140
|
+
const Field$2 = ({ label, help, children }) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
3141
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: label }),
|
|
3142
|
+
children,
|
|
3143
|
+
help ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-muted", children: help }) : null
|
|
3144
|
+
] });
|
|
3145
|
+
const Counter = ({ value, recommended }) => {
|
|
3146
|
+
const length = value.length;
|
|
3147
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: `text-xs ${length > recommended ? "text-ui-fg-warning" : "text-ui-fg-muted"}`, children: [
|
|
3148
|
+
length,
|
|
3149
|
+
" karakter",
|
|
3150
|
+
length > recommended ? ` · ajánlott maximum kb. ${recommended}` : ""
|
|
3360
3151
|
] });
|
|
3152
|
+
};
|
|
3153
|
+
const ToggleCard = ({ label, description, checked, onCheckedChange }) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-start justify-between gap-4 rounded-lg border p-4", children: [
|
|
3154
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3155
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: label }),
|
|
3156
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-subtle", children: description })
|
|
3157
|
+
] }),
|
|
3158
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked, onCheckedChange })
|
|
3159
|
+
] });
|
|
3160
|
+
function normalizeSeo(value) {
|
|
3161
|
+
return {
|
|
3162
|
+
title: value?.title || "",
|
|
3163
|
+
description: value?.description || "",
|
|
3164
|
+
canonical: value?.canonical || "",
|
|
3165
|
+
noindex: Boolean(value?.noindex),
|
|
3166
|
+
nofollow: Boolean(value?.nofollow),
|
|
3167
|
+
ogTitle: value?.ogTitle || "",
|
|
3168
|
+
ogDescription: value?.ogDescription || "",
|
|
3169
|
+
ogImage: value?.ogImage || ""
|
|
3170
|
+
};
|
|
3361
3171
|
}
|
|
3362
|
-
function
|
|
3363
|
-
return
|
|
3364
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: label }),
|
|
3365
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: value })
|
|
3366
|
-
] });
|
|
3172
|
+
function normalizeEntity(value) {
|
|
3173
|
+
return { ...value, seo: normalizeSeo(value.seo) };
|
|
3367
3174
|
}
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3175
|
+
function normalizePage(value) {
|
|
3176
|
+
return { ...value, seo: normalizeSeo(value.seo) };
|
|
3177
|
+
}
|
|
3178
|
+
const backendUrl$6 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
3179
|
+
function apiUrl$6(path) {
|
|
3180
|
+
return `${backendUrl$6}${path.startsWith("/") ? path : `/${path}`}`;
|
|
3372
3181
|
}
|
|
3373
3182
|
const CoreAuditPage = () => {
|
|
3374
3183
|
const [logs, setLogs] = React.useState([]);
|
|
@@ -3386,7 +3195,7 @@ const CoreAuditPage = () => {
|
|
|
3386
3195
|
if (integration !== "all") params.set("integration", integration);
|
|
3387
3196
|
if (status !== "all") params.set("status", status);
|
|
3388
3197
|
const response = await fetch(
|
|
3389
|
-
apiUrl$
|
|
3198
|
+
apiUrl$6(`/admin/core-audit?${params.toString()}`),
|
|
3390
3199
|
{ credentials: "include" }
|
|
3391
3200
|
);
|
|
3392
3201
|
const payload = await response.json().catch(() => ({}));
|
|
@@ -3522,15 +3331,15 @@ function formatDate$3(value) {
|
|
|
3522
3331
|
timeStyle: "short"
|
|
3523
3332
|
}).format(date);
|
|
3524
3333
|
}
|
|
3525
|
-
const config$
|
|
3334
|
+
const config$5 = adminSdk.defineRouteConfig({
|
|
3526
3335
|
label: "Audit napló",
|
|
3527
3336
|
icon: Newspaper,
|
|
3528
3337
|
rank: 39
|
|
3529
3338
|
});
|
|
3530
|
-
const backendUrl$
|
|
3339
|
+
const backendUrl$5 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
3531
3340
|
const adminBase$3 = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
3532
|
-
function apiUrl$
|
|
3533
|
-
return `${backendUrl$
|
|
3341
|
+
function apiUrl$5(path) {
|
|
3342
|
+
return `${backendUrl$5}${path.startsWith("/") ? path : `/${path}`}`;
|
|
3534
3343
|
}
|
|
3535
3344
|
const IntegrationHealthPage = () => {
|
|
3536
3345
|
const [integrations, setIntegrations] = React.useState([]);
|
|
@@ -3543,8 +3352,8 @@ const IntegrationHealthPage = () => {
|
|
|
3543
3352
|
setLoadError(null);
|
|
3544
3353
|
try {
|
|
3545
3354
|
const [integrationsResponse, operationsResponse] = await Promise.all([
|
|
3546
|
-
fetch(apiUrl$
|
|
3547
|
-
fetch(apiUrl$
|
|
3355
|
+
fetch(apiUrl$5("/admin/integrations"), { credentials: "include" }),
|
|
3356
|
+
fetch(apiUrl$5("/admin/integration-operations?status=problems&limit=100"), {
|
|
3548
3357
|
credentials: "include"
|
|
3549
3358
|
})
|
|
3550
3359
|
]);
|
|
@@ -3608,7 +3417,7 @@ const IntegrationHealthPage = () => {
|
|
|
3608
3417
|
setTesting(integration.key);
|
|
3609
3418
|
try {
|
|
3610
3419
|
const response = await fetch(
|
|
3611
|
-
apiUrl$
|
|
3420
|
+
apiUrl$5(`/admin/integrations/${integration.key}/test`),
|
|
3612
3421
|
{
|
|
3613
3422
|
method: "POST",
|
|
3614
3423
|
credentials: "include"
|
|
@@ -3756,206 +3565,66 @@ function SummaryCard$1({
|
|
|
3756
3565
|
function formatDate$2(value) {
|
|
3757
3566
|
const date = new Date(value);
|
|
3758
3567
|
if (Number.isNaN(date.getTime())) return "—";
|
|
3759
|
-
return new Intl.DateTimeFormat("hu-HU", {
|
|
3760
|
-
dateStyle: "short",
|
|
3761
|
-
timeStyle: "short"
|
|
3762
|
-
}).format(date);
|
|
3763
|
-
}
|
|
3764
|
-
const config$
|
|
3765
|
-
label: "Integrációk állapota",
|
|
3766
|
-
icon: Newspaper,
|
|
3767
|
-
rank: 38
|
|
3768
|
-
});
|
|
3769
|
-
const
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
};
|
|
3781
|
-
const ProductionReadinessPage = () => {
|
|
3782
|
-
const [report, setReport] = React.useState(null);
|
|
3783
|
-
const [loading, setLoading] = React.useState(true);
|
|
3784
|
-
const [error, setError] = React.useState(null);
|
|
3785
|
-
const load = React.useCallback(async () => {
|
|
3786
|
-
setLoading(true);
|
|
3787
|
-
setError(null);
|
|
3788
|
-
try {
|
|
3789
|
-
const response = await fetch(apiUrl$3("/admin/production-readiness"), {
|
|
3790
|
-
credentials: "include"
|
|
3791
|
-
});
|
|
3792
|
-
const payload = await response.json().catch(() => ({}));
|
|
3793
|
-
if (!response.ok) {
|
|
3794
|
-
throw new Error(payload.message || "Az élesítési ellenőrzés nem tölthető be.");
|
|
3795
|
-
}
|
|
3796
|
-
setReport(payload);
|
|
3797
|
-
} catch (cause) {
|
|
3798
|
-
setReport(null);
|
|
3799
|
-
setError(
|
|
3800
|
-
cause instanceof Error ? cause.message : "Az élesítési ellenőrzés nem tölthető be."
|
|
3801
|
-
);
|
|
3802
|
-
} finally {
|
|
3803
|
-
setLoading(false);
|
|
3804
|
-
}
|
|
3805
|
-
}, []);
|
|
3806
|
-
React.useEffect(() => {
|
|
3807
|
-
void load();
|
|
3808
|
-
}, [load]);
|
|
3809
|
-
const groups = React.useMemo(() => {
|
|
3810
|
-
const result = /* @__PURE__ */ new Map();
|
|
3811
|
-
for (const item of report?.checks || []) {
|
|
3812
|
-
result.set(item.category, [...result.get(item.category) || [], item]);
|
|
3813
|
-
}
|
|
3814
|
-
return Array.from(result.entries());
|
|
3815
|
-
}, [report]);
|
|
3816
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
3817
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4 border-b px-6 py-5", children: [
|
|
3818
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3819
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Production readiness" }),
|
|
3820
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 text-ui-fg-subtle", children: "Élesítés előtti runtime ellenőrzés. A felület státuszokat mutat, secret értéket nem ad vissza." })
|
|
3821
|
-
] }),
|
|
3822
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: loading, onClick: () => void load(), children: "Újraellenőrzés" })
|
|
3823
|
-
] }),
|
|
3824
|
-
report ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3825
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 border-b p-6 sm:grid-cols-2 lg:grid-cols-4", children: [
|
|
3826
|
-
/* @__PURE__ */ jsxRuntime.jsx(Summary, { label: "Kész", value: report.score.ready, tone: "ready" }),
|
|
3827
|
-
/* @__PURE__ */ jsxRuntime.jsx(Summary, { label: "Figyelmeztetés", value: report.score.warning, tone: "warning" }),
|
|
3828
|
-
/* @__PURE__ */ jsxRuntime.jsx(Summary, { label: "Blokkoló", value: report.score.blocked, tone: "blocked" }),
|
|
3829
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
3830
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Élesítési döntés" }),
|
|
3831
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: report.ready ? "mt-1 text-xl font-semibold text-ui-fg-success" : "mt-1 text-xl font-semibold text-ui-fg-error", children: report.ready ? "Élesíthető" : "Még nem élesíthető" }),
|
|
3832
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-1 text-ui-fg-subtle", children: report.environment === "production" ? "Production szabályok" : "Nem-production szabályok" })
|
|
3833
|
-
] })
|
|
3834
|
-
] }),
|
|
3835
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b px-6 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
3836
|
-
"Utolsó ellenőrzés: ",
|
|
3837
|
-
formatDate$1(report.generated_at),
|
|
3838
|
-
". A sárga elemek nem blokkolják az élesítést, a piros elemek igen."
|
|
3839
|
-
] }) }),
|
|
3840
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6 p-6", children: groups.map(([category, checks]) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "overflow-hidden rounded-lg border", children: [
|
|
3841
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b bg-ui-bg-subtle px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: CATEGORY_LABELS[category] || category }) }),
|
|
3842
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y", children: checks.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 p-4 md:grid-cols-[180px_140px_minmax(0,1fr)_auto] md:items-center", children: [
|
|
3843
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: item.label }),
|
|
3844
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: item.status }),
|
|
3845
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: item.message }),
|
|
3846
|
-
item.action_href && item.action_label ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: normalizeAdminHref(item.action_href), children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: item.action_label }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", {})
|
|
3847
|
-
] }, item.key)) })
|
|
3848
|
-
] }, category)) })
|
|
3849
|
-
] }) : null,
|
|
3850
|
-
loading && !report ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Élesítési feltételek ellenőrzése…" }) }) : null,
|
|
3851
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-6 rounded-lg border border-ui-border-error p-4", children: [
|
|
3852
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-error", children: "Az ellenőrzés nem futott le." }),
|
|
3853
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: error })
|
|
3854
|
-
] }) : null
|
|
3855
|
-
] });
|
|
3856
|
-
};
|
|
3857
|
-
function StatusBadge({ status }) {
|
|
3858
|
-
const label = status === "ready" ? "Kész" : status === "warning" ? "Figyelmeztetés" : "Blokkoló";
|
|
3859
|
-
const className = status === "ready" ? "font-medium text-ui-fg-success" : status === "warning" ? "font-medium text-ui-fg-warning" : "font-medium text-ui-fg-error";
|
|
3860
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className, children: [
|
|
3861
|
-
status === "ready" ? "✅" : status === "warning" ? "🟡" : "🔴",
|
|
3862
|
-
" ",
|
|
3863
|
-
label
|
|
3864
|
-
] });
|
|
3865
|
-
}
|
|
3866
|
-
function Summary({ label, value, tone }) {
|
|
3867
|
-
const valueClass = tone === "ready" ? "text-ui-fg-success" : tone === "warning" ? "text-ui-fg-warning" : "text-ui-fg-error";
|
|
3868
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
3869
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: label }),
|
|
3870
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `mt-1 text-3xl font-semibold ${valueClass}`, children: value })
|
|
3871
|
-
] });
|
|
3872
|
-
}
|
|
3873
|
-
function normalizeAdminHref(path) {
|
|
3874
|
-
if (!path.startsWith("/app")) return path;
|
|
3875
|
-
return `${adminBase$2}${path.slice(4)}`;
|
|
3876
|
-
}
|
|
3877
|
-
function formatDate$1(value) {
|
|
3878
|
-
const date = new Date(value);
|
|
3879
|
-
if (Number.isNaN(date.getTime())) return "—";
|
|
3880
|
-
return new Intl.DateTimeFormat("hu-HU", { dateStyle: "short", timeStyle: "medium" }).format(date);
|
|
3881
|
-
}
|
|
3882
|
-
const config$2 = adminSdk.defineRouteConfig({
|
|
3883
|
-
label: "Production readiness",
|
|
3884
|
-
rank: 39
|
|
3885
|
-
});
|
|
3886
|
-
const backendUrl$2 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
3887
|
-
const adminBase$1 = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
3888
|
-
const apiUrl$2 = (path) => `${backendUrl$2}${path.startsWith("/") ? path : `/${path}`}`;
|
|
3889
|
-
const CATEGORY_ORDER = [
|
|
3890
|
-
"payment",
|
|
3891
|
-
"invoicing",
|
|
3892
|
-
"shipping",
|
|
3893
|
-
"notification",
|
|
3894
|
-
"legal",
|
|
3895
|
-
"marketing"
|
|
3896
|
-
];
|
|
3897
|
-
const CATEGORY_LABEL = {
|
|
3898
|
-
payment: "Fizetés",
|
|
3899
|
-
invoicing: "Számlázás",
|
|
3900
|
-
shipping: "Szállítás",
|
|
3901
|
-
notification: "Értesítés",
|
|
3902
|
-
legal: "Jogi integráció",
|
|
3903
|
-
marketing: "Marketing"
|
|
3568
|
+
return new Intl.DateTimeFormat("hu-HU", {
|
|
3569
|
+
dateStyle: "short",
|
|
3570
|
+
timeStyle: "short"
|
|
3571
|
+
}).format(date);
|
|
3572
|
+
}
|
|
3573
|
+
const config$4 = adminSdk.defineRouteConfig({
|
|
3574
|
+
label: "Integrációk állapota",
|
|
3575
|
+
icon: Newspaper,
|
|
3576
|
+
rank: 38
|
|
3577
|
+
});
|
|
3578
|
+
const defaults = {
|
|
3579
|
+
GOOGLE_MERCHANT_COUNTRY_CODE: "HU",
|
|
3580
|
+
GOOGLE_MERCHANT_CURRENCY_CODE: "HUF",
|
|
3581
|
+
GOOGLE_MERCHANT_STOREFRONT_URL: "",
|
|
3582
|
+
GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE: "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
3583
|
+
GOOGLE_MERCHANT_SALES_CHANNEL_ID: "",
|
|
3584
|
+
GOOGLE_MERCHANT_DEFAULT_BRAND: "",
|
|
3585
|
+
GOOGLE_MERCHANT_DEFAULT_CONDITION: "new",
|
|
3586
|
+
GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK: true,
|
|
3587
|
+
GOOGLE_MERCHANT_FEED_TITLE: "",
|
|
3588
|
+
GOOGLE_MERCHANT_FEED_DESCRIPTION: ""
|
|
3904
3589
|
};
|
|
3905
|
-
const
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
const [draft, setDraft] = React.useState({});
|
|
3909
|
-
const [clearSecrets, setClearSecrets] = React.useState([]);
|
|
3590
|
+
const backendUrl$4 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
3591
|
+
const apiUrl$4 = (path) => `${backendUrl$4}${path.startsWith("/") ? path : `/${path}`}`;
|
|
3592
|
+
const GoogleMerchantPage = () => {
|
|
3910
3593
|
const [enabled, setEnabled] = React.useState(false);
|
|
3594
|
+
const [draft, setDraft] = React.useState(defaults);
|
|
3911
3595
|
const [loading, setLoading] = React.useState(true);
|
|
3912
3596
|
const [saving, setSaving] = React.useState(false);
|
|
3913
|
-
const [
|
|
3914
|
-
const [
|
|
3915
|
-
const
|
|
3916
|
-
() =>
|
|
3917
|
-
|
|
3918
|
-
);
|
|
3919
|
-
const selected = React.useMemo(
|
|
3920
|
-
() => visibleItems.find((item) => item.key === selectedKey) || null,
|
|
3921
|
-
[visibleItems, selectedKey]
|
|
3922
|
-
);
|
|
3923
|
-
const hasUnsavedChanges = React.useMemo(() => {
|
|
3924
|
-
if (!selected) return false;
|
|
3925
|
-
if (enabled !== selected.enabled || clearSecrets.length > 0) return true;
|
|
3926
|
-
return selected.fields.some((field) => {
|
|
3927
|
-
const value = draft[field.name];
|
|
3928
|
-
if (field.type === "secret") {
|
|
3929
|
-
return Boolean(String(value || "").trim());
|
|
3930
|
-
}
|
|
3931
|
-
if (field.type === "boolean") {
|
|
3932
|
-
return Boolean(value) !== (selected.values[field.name] === "true");
|
|
3933
|
-
}
|
|
3934
|
-
return String(value || "").trim() !== String(selected.values[field.name] || "").trim();
|
|
3935
|
-
});
|
|
3936
|
-
}, [selected, enabled, draft, clearSecrets]);
|
|
3597
|
+
const [previewing, setPreviewing] = React.useState(false);
|
|
3598
|
+
const [preview, setPreview] = React.useState(null);
|
|
3599
|
+
const update = (key, value) => {
|
|
3600
|
+
setDraft((current) => ({ ...current, [key]: value }));
|
|
3601
|
+
};
|
|
3937
3602
|
const load = React.useCallback(async () => {
|
|
3938
3603
|
setLoading(true);
|
|
3939
3604
|
try {
|
|
3940
|
-
const response = await fetch(apiUrl$
|
|
3605
|
+
const response = await fetch(apiUrl$4("/admin/integrations/google-merchant"), {
|
|
3941
3606
|
credentials: "include"
|
|
3942
3607
|
});
|
|
3943
3608
|
const data = await response.json().catch(() => ({}));
|
|
3944
|
-
if (!response.ok) {
|
|
3945
|
-
throw new Error(data.message || "
|
|
3609
|
+
if (!response.ok || !data.integration) {
|
|
3610
|
+
throw new Error(data.message || "A Google Merchant beállítások nem tölthetők be.");
|
|
3946
3611
|
}
|
|
3947
|
-
const
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3612
|
+
const values = data.integration.values || {};
|
|
3613
|
+
setEnabled(Boolean(data.integration.enabled));
|
|
3614
|
+
setDraft({
|
|
3615
|
+
GOOGLE_MERCHANT_COUNTRY_CODE: values.GOOGLE_MERCHANT_COUNTRY_CODE || "HU",
|
|
3616
|
+
GOOGLE_MERCHANT_CURRENCY_CODE: values.GOOGLE_MERCHANT_CURRENCY_CODE || "HUF",
|
|
3617
|
+
GOOGLE_MERCHANT_STOREFRONT_URL: values.GOOGLE_MERCHANT_STOREFRONT_URL || "",
|
|
3618
|
+
GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE: values.GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE || "/{country_code}/products/{handle}?v_id={variant_id}",
|
|
3619
|
+
GOOGLE_MERCHANT_SALES_CHANNEL_ID: values.GOOGLE_MERCHANT_SALES_CHANNEL_ID || "",
|
|
3620
|
+
GOOGLE_MERCHANT_DEFAULT_BRAND: values.GOOGLE_MERCHANT_DEFAULT_BRAND || "",
|
|
3621
|
+
GOOGLE_MERCHANT_DEFAULT_CONDITION: values.GOOGLE_MERCHANT_DEFAULT_CONDITION || "new",
|
|
3622
|
+
GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK: values.GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK !== "false",
|
|
3623
|
+
GOOGLE_MERCHANT_FEED_TITLE: values.GOOGLE_MERCHANT_FEED_TITLE || "",
|
|
3624
|
+
GOOGLE_MERCHANT_FEED_DESCRIPTION: values.GOOGLE_MERCHANT_FEED_DESCRIPTION || ""
|
|
3625
|
+
});
|
|
3955
3626
|
} catch (error) {
|
|
3956
|
-
ui.toast.error(
|
|
3957
|
-
error instanceof Error ? error.message : "Az integrációk nem tölthetők be."
|
|
3958
|
-
);
|
|
3627
|
+
ui.toast.error(error instanceof Error ? error.message : "Betöltési hiba.");
|
|
3959
3628
|
} finally {
|
|
3960
3629
|
setLoading(false);
|
|
3961
3630
|
}
|
|
@@ -3963,641 +3632,972 @@ const IntegrationsPage = () => {
|
|
|
3963
3632
|
React.useEffect(() => {
|
|
3964
3633
|
void load();
|
|
3965
3634
|
}, [load]);
|
|
3966
|
-
React.useEffect(() => {
|
|
3967
|
-
if (!selected) return;
|
|
3968
|
-
const next = {};
|
|
3969
|
-
for (const field of selected.fields) {
|
|
3970
|
-
if (field.type === "secret") next[field.name] = "";
|
|
3971
|
-
else if (field.type === "boolean") {
|
|
3972
|
-
next[field.name] = selected.values[field.name] === "true";
|
|
3973
|
-
} else {
|
|
3974
|
-
next[field.name] = selected.values[field.name] || "";
|
|
3975
|
-
}
|
|
3976
|
-
}
|
|
3977
|
-
setDraft(next);
|
|
3978
|
-
setClearSecrets([]);
|
|
3979
|
-
setEnabled(selected.enabled);
|
|
3980
|
-
setRestartNotice(false);
|
|
3981
|
-
}, [selected?.key, selected?.values, selected?.enabled]);
|
|
3982
3635
|
const save = async () => {
|
|
3983
|
-
if (!selected) return;
|
|
3984
3636
|
setSaving(true);
|
|
3985
3637
|
try {
|
|
3986
|
-
const
|
|
3987
|
-
for (const field of selected.fields) {
|
|
3988
|
-
const value = draft[field.name];
|
|
3989
|
-
if (field.type === "secret" && !String(value || "").trim()) continue;
|
|
3990
|
-
values[field.name] = value;
|
|
3991
|
-
}
|
|
3992
|
-
const response = await fetch(apiUrl$2(`/admin/integrations/${selected.key}`), {
|
|
3638
|
+
const response = await fetch(apiUrl$4("/admin/integrations/google-merchant"), {
|
|
3993
3639
|
method: "POST",
|
|
3994
3640
|
credentials: "include",
|
|
3995
3641
|
headers: { "Content-Type": "application/json" },
|
|
3996
|
-
body: JSON.stringify({
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
3642
|
+
body: JSON.stringify({ enabled, values: draft })
|
|
3643
|
+
});
|
|
3644
|
+
const data = await response.json().catch(() => ({}));
|
|
3645
|
+
if (!response.ok) throw new Error(data.message || "A mentés nem sikerült.");
|
|
3646
|
+
ui.toast.success(data.message || "Google Merchant beállítások mentve.");
|
|
3647
|
+
setPreview(null);
|
|
3648
|
+
await load();
|
|
3649
|
+
} catch (error) {
|
|
3650
|
+
ui.toast.error(error instanceof Error ? error.message : "A mentés nem sikerült.");
|
|
3651
|
+
} finally {
|
|
3652
|
+
setSaving(false);
|
|
3653
|
+
}
|
|
3654
|
+
};
|
|
3655
|
+
const runPreview = async () => {
|
|
3656
|
+
setPreviewing(true);
|
|
3657
|
+
try {
|
|
3658
|
+
const response = await fetch(apiUrl$4("/admin/google-merchant/preview"), {
|
|
3659
|
+
credentials: "include"
|
|
3660
|
+
});
|
|
3661
|
+
const data = await response.json().catch(() => ({}));
|
|
3662
|
+
if (!response.ok) throw new Error(data.message || "A feed nem generálható.");
|
|
3663
|
+
setPreview(data);
|
|
3664
|
+
ui.toast.success("A Merchant feed ellenőrzése elkészült.");
|
|
3665
|
+
} catch (error) {
|
|
3666
|
+
ui.toast.error(error instanceof Error ? error.message : "A feed nem generálható.");
|
|
3667
|
+
} finally {
|
|
3668
|
+
setPreviewing(false);
|
|
3669
|
+
}
|
|
3670
|
+
};
|
|
3671
|
+
const feedUrl = apiUrl$4("/feeds/google-merchant.xml");
|
|
3672
|
+
const d = preview?.diagnostics;
|
|
3673
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
3674
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4 border-b px-6 py-4", children: [
|
|
3675
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3676
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Google Merchant Center" }),
|
|
3677
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Google RSS 2.0 feed a Medusa termék-, variant-, régiós ár-, ÁFA- és készletadataiból." })
|
|
3678
|
+
] }),
|
|
3679
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
3680
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: enabled, onCheckedChange: setEnabled, disabled: loading }),
|
|
3681
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: enabled ? "Bekapcsolva" : "Kikapcsolva" })
|
|
3682
|
+
] })
|
|
3683
|
+
] }),
|
|
3684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 border-b px-6 py-5 md:grid-cols-2", children: [
|
|
3685
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Célország", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_COUNTRY_CODE, onChange: (e) => update("GOOGLE_MERCHANT_COUNTRY_CODE", e.target.value.toUpperCase()), placeholder: "HU" }) }),
|
|
3686
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Pénznem", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_CURRENCY_CODE, onChange: (e) => update("GOOGLE_MERCHANT_CURRENCY_CODE", e.target.value.toUpperCase()), placeholder: "HUF" }) }),
|
|
3687
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Storefront URL", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_STOREFRONT_URL, onChange: (e) => update("GOOGLE_MERCHANT_STOREFRONT_URL", e.target.value), placeholder: "https://shop.hu (üresen STOREFRONT_URL)" }) }),
|
|
3688
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Field$1, { label: "Termék URL sablon", children: [
|
|
3689
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE, onChange: (e) => update("GOOGLE_MERCHANT_PRODUCT_PATH_TEMPLATE", e.target.value) }),
|
|
3690
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-xs", children: [
|
|
3691
|
+
"Helyőrzők: ",
|
|
3692
|
+
"{country_code}",
|
|
3693
|
+
", ",
|
|
3694
|
+
"{currency_code}",
|
|
3695
|
+
", ",
|
|
3696
|
+
"{handle}",
|
|
3697
|
+
", ",
|
|
3698
|
+
"{variant_id}",
|
|
3699
|
+
"."
|
|
3700
|
+
] })
|
|
3701
|
+
] }),
|
|
3702
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Sales Channel ID", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_SALES_CHANNEL_ID, onChange: (e) => update("GOOGLE_MERCHANT_SALES_CHANNEL_ID", e.target.value), placeholder: "sc_... (opcionális)" }) }),
|
|
3703
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Alapértelmezett márka", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_DEFAULT_BRAND, onChange: (e) => update("GOOGLE_MERCHANT_DEFAULT_BRAND", e.target.value) }) }),
|
|
3704
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Alapértelmezett állapot", children: /* @__PURE__ */ jsxRuntime.jsxs("select", { className: "h-8 rounded-md border bg-ui-bg-field px-2 text-sm", value: draft.GOOGLE_MERCHANT_DEFAULT_CONDITION, onChange: (e) => update("GOOGLE_MERCHANT_DEFAULT_CONDITION", e.target.value), children: [
|
|
3705
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "new", children: "Új" }),
|
|
3706
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "refurbished", children: "Felújított" }),
|
|
3707
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "used", children: "Használt" })
|
|
3708
|
+
] }) }),
|
|
3709
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Készlethiányos variantok", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
3710
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: draft.GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK, onCheckedChange: (value) => update("GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK", value) }),
|
|
3711
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: draft.GOOGLE_MERCHANT_INCLUDE_OUT_OF_STOCK ? "Benne maradnak" : "Kimaradnak" })
|
|
3712
|
+
] }) }),
|
|
3713
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Feed neve", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_FEED_TITLE, onChange: (e) => update("GOOGLE_MERCHANT_FEED_TITLE", e.target.value), placeholder: "Üresen automatikus" }) }),
|
|
3714
|
+
/* @__PURE__ */ jsxRuntime.jsx(Field$1, { label: "Feed leírása", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { value: draft.GOOGLE_MERCHANT_FEED_DESCRIPTION, onChange: (e) => update("GOOGLE_MERCHANT_FEED_DESCRIPTION", e.target.value), placeholder: "Üresen automatikus" }) })
|
|
3715
|
+
] }),
|
|
3716
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b px-6 py-4", children: [
|
|
3717
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3718
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Publikus feed URL" }),
|
|
3719
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "break-all text-ui-fg-interactive hover:underline", href: feedUrl, target: "_blank", rel: "noreferrer", children: feedUrl })
|
|
3720
|
+
] }),
|
|
3721
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
3722
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: previewing, disabled: !enabled || loading || saving || previewing, onClick: () => void runPreview(), children: "Feed ellenőrzése" }),
|
|
3723
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { isLoading: saving, disabled: loading || saving || previewing, onClick: () => void save(), children: "Mentés" })
|
|
3724
|
+
] })
|
|
3725
|
+
] }),
|
|
3726
|
+
d ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3727
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 border-b px-6 py-5 sm:grid-cols-2 lg:grid-cols-4", children: [
|
|
3728
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Termékek", value: d.productsScanned }),
|
|
3729
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Variantok", value: d.variantsScanned }),
|
|
3730
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Feed tételek", value: d.itemsEmitted }),
|
|
3731
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Hiányzó identifier", value: d.itemsMissingIdentifiers }),
|
|
3732
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Nincs ár", value: d.skippedNoPrice }),
|
|
3733
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Nincs kép", value: d.skippedNoImage }),
|
|
3734
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Nincs sales channel", value: d.skippedNoSalesChannel + d.skippedNotInSalesChannel }),
|
|
3735
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stat, { label: "Érvénytelen GTIN", value: d.invalidGtinsIgnored })
|
|
3736
|
+
] }),
|
|
3737
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
3738
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-b bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3739
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "ID" }),
|
|
3740
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Termék" }),
|
|
3741
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Ár" }),
|
|
3742
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Készlet" }),
|
|
3743
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Identifier" })
|
|
3744
|
+
] }) }),
|
|
3745
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: (preview?.sample || []).map((item) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b", children: [
|
|
3746
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: item.id }) }),
|
|
3747
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.link, target: "_blank", rel: "noreferrer", className: "text-ui-fg-interactive hover:underline", children: item.title }) }),
|
|
3748
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.salePrice ? `${item.salePrice} (${item.price})` : item.price }),
|
|
3749
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.availability }),
|
|
3750
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: item.gtin || item.mpn || item.brand || "—" })
|
|
3751
|
+
] }, item.id)) })
|
|
3752
|
+
] }) })
|
|
3753
|
+
] }) : null
|
|
3754
|
+
] });
|
|
3755
|
+
};
|
|
3756
|
+
function Field$1({ label, children }) {
|
|
3757
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
3758
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: label }),
|
|
3759
|
+
children
|
|
3760
|
+
] });
|
|
3761
|
+
}
|
|
3762
|
+
function Stat({ label, value }) {
|
|
3763
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-3", children: [
|
|
3764
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: label }),
|
|
3765
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: value })
|
|
3766
|
+
] });
|
|
3767
|
+
}
|
|
3768
|
+
const config$3 = adminSdk.defineRouteConfig({ label: "Google Merchant", rank: 41 });
|
|
3769
|
+
const backendUrl$3 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
3770
|
+
const adminBase$2 = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
3771
|
+
function apiUrl$3(path) {
|
|
3772
|
+
return `${backendUrl$3}${path.startsWith("/") ? path : `/${path}`}`;
|
|
3773
|
+
}
|
|
3774
|
+
const IntegrationOperationsPage = () => {
|
|
3775
|
+
const [operations, setOperations] = React.useState([]);
|
|
3776
|
+
const [summary, setSummary] = React.useState({
|
|
3777
|
+
failed: 0,
|
|
3778
|
+
needsReconciliation: 0,
|
|
3779
|
+
processing: 0
|
|
3780
|
+
});
|
|
3781
|
+
const [count, setCount] = React.useState(0);
|
|
3782
|
+
const [status, setStatus] = React.useState("problems");
|
|
3783
|
+
const [provider, setProvider] = React.useState("all");
|
|
3784
|
+
const [query, setQuery] = React.useState("");
|
|
3785
|
+
const [loading, setLoading] = React.useState(false);
|
|
3786
|
+
const [actionLoading, setActionLoading] = React.useState(null);
|
|
3787
|
+
const [loadError, setLoadError] = React.useState(null);
|
|
3788
|
+
const load = React.useCallback(async () => {
|
|
3789
|
+
setLoading(true);
|
|
3790
|
+
setLoadError(null);
|
|
3791
|
+
try {
|
|
3792
|
+
const params = new URLSearchParams({
|
|
3793
|
+
limit: "100",
|
|
3794
|
+
status
|
|
4001
3795
|
});
|
|
4002
|
-
|
|
3796
|
+
if (provider !== "all") params.set("provider", provider);
|
|
3797
|
+
const response = await fetch(
|
|
3798
|
+
apiUrl$3(`/admin/integration-operations?${params.toString()}`),
|
|
3799
|
+
{ credentials: "include" }
|
|
3800
|
+
);
|
|
3801
|
+
const payload = await response.json().catch(() => ({}));
|
|
4003
3802
|
if (!response.ok) {
|
|
4004
|
-
throw new Error(
|
|
3803
|
+
throw new Error(
|
|
3804
|
+
payload.message || "Az integrációs műveletek nem tölthetők be."
|
|
3805
|
+
);
|
|
4005
3806
|
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
3807
|
+
setOperations(payload.operations || []);
|
|
3808
|
+
setCount(payload.count || 0);
|
|
3809
|
+
setSummary(
|
|
3810
|
+
payload.summary || {
|
|
3811
|
+
failed: 0,
|
|
3812
|
+
needsReconciliation: 0,
|
|
3813
|
+
processing: 0
|
|
3814
|
+
}
|
|
3815
|
+
);
|
|
4010
3816
|
} catch (error) {
|
|
4011
|
-
|
|
3817
|
+
setOperations([]);
|
|
3818
|
+
setLoadError(
|
|
3819
|
+
error instanceof Error ? error.message : "Az integrációs műveletek nem tölthetők be."
|
|
3820
|
+
);
|
|
4012
3821
|
} finally {
|
|
4013
|
-
|
|
3822
|
+
setLoading(false);
|
|
4014
3823
|
}
|
|
4015
|
-
};
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
3824
|
+
}, [provider, status]);
|
|
3825
|
+
React.useEffect(() => {
|
|
3826
|
+
void load();
|
|
3827
|
+
}, [load]);
|
|
3828
|
+
const visible = React.useMemo(() => {
|
|
3829
|
+
const value = query.trim().toLowerCase();
|
|
3830
|
+
if (!value) return operations;
|
|
3831
|
+
return operations.filter(
|
|
3832
|
+
(operation) => [
|
|
3833
|
+
operation.provider,
|
|
3834
|
+
operation.operation_type,
|
|
3835
|
+
operation.entity_type,
|
|
3836
|
+
operation.entity_id,
|
|
3837
|
+
operation.external_id,
|
|
3838
|
+
operation.error_summary
|
|
3839
|
+
].some(
|
|
3840
|
+
(item) => String(item || "").toLowerCase().includes(value)
|
|
3841
|
+
)
|
|
3842
|
+
);
|
|
3843
|
+
}, [operations, query]);
|
|
3844
|
+
const reconcile = async (operation, decision) => {
|
|
3845
|
+
const confirmed = confirm(
|
|
3846
|
+
decision === "confirmed_succeeded" ? "Megerősíted, hogy a külső szolgáltatónál ez a művelet valóban sikeresen megtörtént?" : "Megerősíted, hogy a külső szolgáltatónál ez a művelet biztosan NEM történt meg? Ez engedélyezi a normál művelet későbbi újrapróbálását."
|
|
3847
|
+
);
|
|
3848
|
+
if (!confirmed) return;
|
|
3849
|
+
let externalId = operation.external_id || void 0;
|
|
3850
|
+
if (decision === "confirmed_succeeded" && !externalId) {
|
|
3851
|
+
externalId = prompt(
|
|
3852
|
+
"Add meg a külső szolgáltató azonosítóját (pl. Billingo document ID vagy shipment ID):"
|
|
3853
|
+
)?.trim() || void 0;
|
|
3854
|
+
if (!externalId) {
|
|
3855
|
+
ui.toast.error("A sikeres lezáráshoz külső azonosító szükséges.");
|
|
3856
|
+
return;
|
|
4028
3857
|
}
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
3858
|
+
}
|
|
3859
|
+
const note = prompt(
|
|
3860
|
+
"Opcionális megjegyzés az egyeztetéshez:",
|
|
3861
|
+
""
|
|
3862
|
+
)?.trim();
|
|
3863
|
+
setActionLoading(operation.id);
|
|
3864
|
+
try {
|
|
3865
|
+
const response = await fetch(
|
|
3866
|
+
apiUrl$3(`/admin/integration-operations/${operation.id}/reconcile`),
|
|
3867
|
+
{
|
|
3868
|
+
method: "POST",
|
|
3869
|
+
credentials: "include",
|
|
3870
|
+
headers: { "Content-Type": "application/json" },
|
|
3871
|
+
body: JSON.stringify({ decision, externalId, note })
|
|
3872
|
+
}
|
|
3873
|
+
);
|
|
3874
|
+
const payload = await response.json().catch(() => ({}));
|
|
3875
|
+
if (!response.ok) {
|
|
3876
|
+
throw new Error(
|
|
3877
|
+
payload.message || "Az egyeztetés lezárása nem sikerült."
|
|
3878
|
+
);
|
|
4033
3879
|
}
|
|
3880
|
+
ui.toast.success(
|
|
3881
|
+
decision === "confirmed_succeeded" ? "A művelet sikeresként lezárva." : "A művelet újrapróbálhatóvá téve."
|
|
3882
|
+
);
|
|
3883
|
+
await load();
|
|
4034
3884
|
} catch (error) {
|
|
4035
3885
|
ui.toast.error(
|
|
4036
|
-
error instanceof Error ? error.message : "
|
|
3886
|
+
error instanceof Error ? error.message : "Az egyeztetés lezárása nem sikerült."
|
|
4037
3887
|
);
|
|
4038
|
-
void load();
|
|
4039
3888
|
} finally {
|
|
4040
|
-
|
|
3889
|
+
setActionLoading(null);
|
|
4041
3890
|
}
|
|
4042
3891
|
};
|
|
4043
|
-
const replaceIntegration = (integration) => {
|
|
4044
|
-
setItems(
|
|
4045
|
-
(current) => current.map(
|
|
4046
|
-
(item) => item.key === integration.key ? integration : item
|
|
4047
|
-
)
|
|
4048
|
-
);
|
|
4049
|
-
};
|
|
4050
|
-
const detailHref = selected ? detailPageForIntegration(selected.key) : null;
|
|
4051
|
-
const connection = selected ? connectionPresentation(selected) : null;
|
|
4052
3892
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
4053
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b px-6 py-
|
|
4054
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4055
|
-
|
|
3893
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 border-b px-6 py-4", children: [
|
|
3894
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3895
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Integrációs műveletek" }),
|
|
3896
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Külső API műveletek, hibák és kézi reconciliation kezelése." })
|
|
3897
|
+
] }),
|
|
3898
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3899
|
+
ui.Button,
|
|
3900
|
+
{
|
|
3901
|
+
variant: "secondary",
|
|
3902
|
+
isLoading: loading,
|
|
3903
|
+
onClick: () => void load(),
|
|
3904
|
+
children: "Frissítés"
|
|
3905
|
+
}
|
|
3906
|
+
)
|
|
4056
3907
|
] }),
|
|
4057
|
-
|
|
4058
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
}) })
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.
|
|
4094
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.
|
|
3908
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 border-b px-6 py-4 md:grid-cols-3", children: [
|
|
3909
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3910
|
+
SummaryCard,
|
|
3911
|
+
{
|
|
3912
|
+
label: "Egyeztetést igényel",
|
|
3913
|
+
value: summary.needsReconciliation,
|
|
3914
|
+
danger: summary.needsReconciliation > 0
|
|
3915
|
+
}
|
|
3916
|
+
),
|
|
3917
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3918
|
+
SummaryCard,
|
|
3919
|
+
{
|
|
3920
|
+
label: "Sikertelen",
|
|
3921
|
+
value: summary.failed,
|
|
3922
|
+
danger: summary.failed > 0
|
|
3923
|
+
}
|
|
3924
|
+
),
|
|
3925
|
+
/* @__PURE__ */ jsxRuntime.jsx(SummaryCard, { label: "Folyamatban", value: summary.processing })
|
|
3926
|
+
] }),
|
|
3927
|
+
summary.needsReconciliation > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-ui-border-warning bg-ui-bg-base px-6 py-4", children: [
|
|
3928
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium text-ui-fg-warning", children: [
|
|
3929
|
+
summary.needsReconciliation,
|
|
3930
|
+
" műveletnél nem dönthető el automatikusan, hogy a külső szolgáltató végrehajtotta-e a kérést."
|
|
3931
|
+
] }),
|
|
3932
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Ellenőrizd a szolgáltatónál, majd csak ezután jelöld sikeresnek vagy újrapróbálhatónak. Így elkerülhető a duplikált számla, csomag vagy fizetés." })
|
|
3933
|
+
] }) : null,
|
|
3934
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-end gap-3 border-b px-6 py-4", children: [
|
|
3935
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3936
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Státusz" }),
|
|
3937
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: status, onValueChange: setStatus, children: [
|
|
3938
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { className: "w-52", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
3939
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
3940
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "problems", children: "Hibák + egyeztetés" }),
|
|
3941
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "needs_reconciliation", children: "Egyeztetést igényel" }),
|
|
3942
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "failed", children: "Sikertelen" }),
|
|
3943
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "processing", children: "Folyamatban" }),
|
|
3944
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "pending", children: "Várakozik" }),
|
|
3945
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "succeeded", children: "Sikeres" }),
|
|
3946
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "all", children: "Összes" })
|
|
3947
|
+
] })
|
|
3948
|
+
] })
|
|
3949
|
+
] }),
|
|
3950
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3951
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Provider" }),
|
|
3952
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: provider, onValueChange: setProvider, children: [
|
|
3953
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { className: "w-44", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
3954
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
3955
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "all", children: "Összes" }),
|
|
3956
|
+
[
|
|
3957
|
+
"stripe",
|
|
3958
|
+
"simplepay",
|
|
3959
|
+
"billingo",
|
|
3960
|
+
"foxpost",
|
|
3961
|
+
"gls",
|
|
3962
|
+
"packeta",
|
|
3963
|
+
"dpd",
|
|
3964
|
+
"mpl"
|
|
3965
|
+
].map((item) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: item, children: providerLabel(item) }, item))
|
|
3966
|
+
] })
|
|
3967
|
+
] })
|
|
3968
|
+
] }),
|
|
3969
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3970
|
+
ui.Input,
|
|
3971
|
+
{
|
|
3972
|
+
className: "max-w-sm",
|
|
3973
|
+
value: query,
|
|
3974
|
+
onChange: (event) => setQuery(event.target.value),
|
|
3975
|
+
placeholder: "Keresés művelet, rendelés, külső ID vagy hiba alapján"
|
|
3976
|
+
}
|
|
3977
|
+
),
|
|
3978
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
3979
|
+
count,
|
|
3980
|
+
" találat"
|
|
3981
|
+
] })
|
|
3982
|
+
] }),
|
|
3983
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-x-auto", children: [
|
|
3984
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
3985
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-b bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3986
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Státusz" }),
|
|
3987
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Provider / művelet" }),
|
|
3988
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Entitás" }),
|
|
3989
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Külső ID" }),
|
|
3990
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Próbálkozás" }),
|
|
3991
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Hiba / idő" }),
|
|
3992
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Műveletek" })
|
|
3993
|
+
] }) }),
|
|
3994
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: visible.map((operation) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b align-top", children: [
|
|
3995
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(StatusText, { status: operation.status }) }),
|
|
3996
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
3997
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: providerLabel(operation.provider) }),
|
|
3998
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: operation.operation_type })
|
|
4095
3999
|
] }),
|
|
4096
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
4097
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Konfigurálva", value: selected.configured ? "Igen" : "Nem", state: selected.configured ? "success" : "neutral" }),
|
|
4107
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Aktív", value: selected.enabled ? "Igen" : "Nem", state: selected.enabled ? "success" : "neutral" }),
|
|
4108
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Kapcsolat", value: connection.label, state: connection.state })
|
|
4109
|
-
] }),
|
|
4110
|
-
selected.category === "shipping" ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "HSZRDM Commerce provider hozzárendelés", children: "Mentés és backend restart után a providert a HSZRDM Commerce Admin Settings → Locations & Shipping alatt rendeld locationhöz." }) : null,
|
|
4111
|
-
selected.category === "legal" ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "Fogyasztó Barát EMBED", children: "Ez csak az opcionális Fogyasztó Barát embed konfigurációja. A PDF-ek és checkout elfogadások a főoldali Jogi dokumentumok menüpontban kezelhetők." }) : null,
|
|
4112
|
-
selected.category === "marketing" ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "Marketing feed", children: "Itt az integráció alapbeállításait módosítod. A feed előnézet, diagnosztika és publikus URL a főoldali Marketing menüpontban található." }) : null,
|
|
4113
|
-
restartNotice ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "Újraindítás szükséges", children: "A beállítások elmentve. Indítsd újra a HSZRDM Commerce backendet az új provider-konfiguráció betöltéséhez." }) : null,
|
|
4114
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4115
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Beállítások" }),
|
|
4116
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 grid gap-4 sm:grid-cols-2", children: selected.fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4117
|
-
FieldEditor,
|
|
4118
|
-
{
|
|
4119
|
-
field,
|
|
4120
|
-
value: draft[field.name],
|
|
4121
|
-
hasSecret: Boolean(selected.secrets[field.name]),
|
|
4122
|
-
clearPending: clearSecrets.includes(field.name),
|
|
4123
|
-
onChange: (value) => {
|
|
4124
|
-
setDraft((current) => ({ ...current, [field.name]: value }));
|
|
4125
|
-
if (field.type === "secret" && String(value || "").trim()) {
|
|
4126
|
-
setClearSecrets(
|
|
4127
|
-
(current) => current.filter((name) => name !== field.name)
|
|
4128
|
-
);
|
|
4129
|
-
}
|
|
4130
|
-
},
|
|
4131
|
-
onClearSecret: () => {
|
|
4132
|
-
setDraft((current) => ({ ...current, [field.name]: "" }));
|
|
4133
|
-
setClearSecrets(
|
|
4134
|
-
(current) => current.includes(field.name) ? current : [...current, field.name]
|
|
4135
|
-
);
|
|
4136
|
-
},
|
|
4137
|
-
onRestoreSecret: () => setClearSecrets(
|
|
4138
|
-
(current) => current.filter((name) => name !== field.name)
|
|
4139
|
-
)
|
|
4140
|
-
},
|
|
4141
|
-
field.name
|
|
4142
|
-
)) })
|
|
4143
|
-
] }),
|
|
4144
|
-
selected.last_test_message ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
4145
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
4146
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Utolsó kapcsolat-teszt" }),
|
|
4147
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: connectionTextClass(connection.state), children: connection.label })
|
|
4000
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
4001
|
+
operation.entity_type === "order" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4002
|
+
"a",
|
|
4003
|
+
{
|
|
4004
|
+
href: `${adminBase$2}/orders/${operation.entity_id}`,
|
|
4005
|
+
className: "text-ui-fg-interactive",
|
|
4006
|
+
children: operation.entity_id
|
|
4007
|
+
}
|
|
4008
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: operation.entity_id }),
|
|
4009
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: operation.entity_type })
|
|
4148
4010
|
] }),
|
|
4149
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4011
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: operation.external_id || "—" }),
|
|
4012
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: operation.attempts }),
|
|
4013
|
+
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "max-w-md p-4", children: [
|
|
4014
|
+
operation.error_summary ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-error", children: operation.error_summary }) : null,
|
|
4015
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: formatDate$1(operation.updated_at) })
|
|
4016
|
+
] }),
|
|
4017
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-52 flex-wrap gap-2", children: operation.status === "needs_reconciliation" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4154
4018
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4155
4019
|
ui.Button,
|
|
4156
4020
|
{
|
|
4157
|
-
|
|
4158
|
-
disabled:
|
|
4159
|
-
|
|
4160
|
-
|
|
4021
|
+
size: "small",
|
|
4022
|
+
disabled: Boolean(actionLoading),
|
|
4023
|
+
isLoading: actionLoading === operation.id,
|
|
4024
|
+
onClick: () => void reconcile(operation, "confirmed_succeeded"),
|
|
4025
|
+
children: "Megtörtént"
|
|
4161
4026
|
}
|
|
4162
4027
|
),
|
|
4163
4028
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4164
4029
|
ui.Button,
|
|
4165
4030
|
{
|
|
4031
|
+
size: "small",
|
|
4166
4032
|
variant: "secondary",
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
children: "Kapcsolat tesztelése"
|
|
4033
|
+
disabled: Boolean(actionLoading),
|
|
4034
|
+
onClick: () => void reconcile(operation, "confirmed_not_executed"),
|
|
4035
|
+
children: "Nem történt meg"
|
|
4171
4036
|
}
|
|
4172
|
-
)
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4037
|
+
)
|
|
4038
|
+
] }) : operation.status === "failed" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "A normál rendelési művelet újraindítható." }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "—" }) }) })
|
|
4039
|
+
] }, operation.id)) })
|
|
4040
|
+
] }),
|
|
4041
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Műveletek betöltése…" }) }) : null,
|
|
4042
|
+
!loading && loadError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-6 rounded-lg border border-ui-border-error p-4", children: [
|
|
4043
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-error", children: "Az integrációs műveletek nem tölthetők be." }),
|
|
4044
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: loadError })
|
|
4045
|
+
] }) : null,
|
|
4046
|
+
!loading && !loadError && !visible.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Nincs a szűrésnek megfelelő integrációs művelet." }) }) : null
|
|
4178
4047
|
] })
|
|
4179
4048
|
] });
|
|
4180
4049
|
};
|
|
4181
|
-
function
|
|
4182
|
-
|
|
4183
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: title }),
|
|
4184
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children })
|
|
4185
|
-
] });
|
|
4186
|
-
}
|
|
4187
|
-
function FieldEditor({
|
|
4188
|
-
field,
|
|
4050
|
+
function SummaryCard({
|
|
4051
|
+
label,
|
|
4189
4052
|
value,
|
|
4190
|
-
|
|
4191
|
-
clearPending,
|
|
4192
|
-
onChange,
|
|
4193
|
-
onClearSecret,
|
|
4194
|
-
onRestoreSecret
|
|
4053
|
+
danger = false
|
|
4195
4054
|
}) {
|
|
4196
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
4197
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4055
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
4056
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: label }),
|
|
4057
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: danger ? "text-ui-fg-error text-2xl font-semibold" : "text-2xl font-semibold", children: value })
|
|
4058
|
+
] });
|
|
4059
|
+
}
|
|
4060
|
+
function StatusText({ status }) {
|
|
4061
|
+
const labels = {
|
|
4062
|
+
pending: "Várakozik",
|
|
4063
|
+
processing: "Folyamatban",
|
|
4064
|
+
succeeded: "Sikeres",
|
|
4065
|
+
failed: "Sikertelen",
|
|
4066
|
+
needs_reconciliation: "Egyeztetést igényel"
|
|
4067
|
+
};
|
|
4068
|
+
const className = status === "failed" || status === "needs_reconciliation" ? "font-medium text-ui-fg-error" : status === "succeeded" ? "font-medium text-ui-fg-success" : "font-medium";
|
|
4069
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: labels[status] });
|
|
4070
|
+
}
|
|
4071
|
+
function providerLabel(value) {
|
|
4072
|
+
const labels = {
|
|
4073
|
+
stripe: "Stripe",
|
|
4074
|
+
simplepay: "SimplePay",
|
|
4075
|
+
billingo: "Billingo",
|
|
4076
|
+
foxpost: "FOXPOST",
|
|
4077
|
+
gls: "GLS",
|
|
4078
|
+
packeta: "Packeta",
|
|
4079
|
+
dpd: "DPD",
|
|
4080
|
+
mpl: "MPL"
|
|
4081
|
+
};
|
|
4082
|
+
return labels[value] || value;
|
|
4083
|
+
}
|
|
4084
|
+
function formatDate$1(value) {
|
|
4085
|
+
if (!value) return "—";
|
|
4086
|
+
const date = new Date(value);
|
|
4087
|
+
if (Number.isNaN(date.getTime())) return "—";
|
|
4088
|
+
return new Intl.DateTimeFormat("hu-HU", {
|
|
4089
|
+
dateStyle: "short",
|
|
4090
|
+
timeStyle: "short"
|
|
4091
|
+
}).format(date);
|
|
4092
|
+
}
|
|
4093
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
4094
|
+
label: "Integrációs műveletek",
|
|
4095
|
+
icon: Newspaper,
|
|
4096
|
+
rank: 37
|
|
4097
|
+
});
|
|
4098
|
+
const backendUrl$2 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
4099
|
+
const adminBase$1 = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
4100
|
+
const apiUrl$2 = (path) => `${backendUrl$2}${path.startsWith("/") ? path : `/${path}`}`;
|
|
4101
|
+
const CATEGORY_LABELS = {
|
|
4102
|
+
infrastructure: "Infrastruktúra",
|
|
4103
|
+
security: "Biztonság",
|
|
4104
|
+
store: "Storefront alapok",
|
|
4105
|
+
commerce: "Kereskedelem",
|
|
4106
|
+
communication: "Kommunikáció",
|
|
4107
|
+
compliance: "Jogi megfelelés",
|
|
4108
|
+
marketing: "Mérés és SEO"
|
|
4109
|
+
};
|
|
4110
|
+
const ProductionReadinessPage = () => {
|
|
4111
|
+
const [report, setReport] = React.useState(null);
|
|
4112
|
+
const [loading, setLoading] = React.useState(true);
|
|
4113
|
+
const [error, setError] = React.useState(null);
|
|
4114
|
+
const load = React.useCallback(async () => {
|
|
4115
|
+
setLoading(true);
|
|
4116
|
+
setError(null);
|
|
4117
|
+
try {
|
|
4118
|
+
const response = await fetch(apiUrl$2("/admin/production-readiness"), {
|
|
4119
|
+
credentials: "include"
|
|
4120
|
+
});
|
|
4121
|
+
const payload = await response.json().catch(() => ({}));
|
|
4122
|
+
if (!response.ok) {
|
|
4123
|
+
throw new Error(payload.message || "Az élesítési ellenőrzés nem tölthető be.");
|
|
4222
4124
|
}
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
"
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4125
|
+
setReport(payload);
|
|
4126
|
+
} catch (cause) {
|
|
4127
|
+
setReport(null);
|
|
4128
|
+
setError(
|
|
4129
|
+
cause instanceof Error ? cause.message : "Az élesítési ellenőrzés nem tölthető be."
|
|
4130
|
+
);
|
|
4131
|
+
} finally {
|
|
4132
|
+
setLoading(false);
|
|
4133
|
+
}
|
|
4134
|
+
}, []);
|
|
4135
|
+
React.useEffect(() => {
|
|
4136
|
+
void load();
|
|
4137
|
+
}, [load]);
|
|
4138
|
+
const groups = React.useMemo(() => {
|
|
4139
|
+
const result = /* @__PURE__ */ new Map();
|
|
4140
|
+
for (const item of report?.checks || []) {
|
|
4141
|
+
result.set(item.category, [...result.get(item.category) || [], item]);
|
|
4142
|
+
}
|
|
4143
|
+
return Array.from(result.entries());
|
|
4144
|
+
}, [report]);
|
|
4145
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
4146
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4 border-b px-6 py-5", children: [
|
|
4147
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4148
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Production readiness" }),
|
|
4149
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 text-ui-fg-subtle", children: "Élesítés előtti runtime ellenőrzés. A felület státuszokat mutat, secret értéket nem ad vissza." })
|
|
4150
|
+
] }),
|
|
4151
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: loading, onClick: () => void load(), children: "Újraellenőrzés" })
|
|
4152
|
+
] }),
|
|
4153
|
+
report ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4154
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 border-b p-6 sm:grid-cols-2 lg:grid-cols-4", children: [
|
|
4155
|
+
/* @__PURE__ */ jsxRuntime.jsx(Summary, { label: "Kész", value: report.score.ready, tone: "ready" }),
|
|
4156
|
+
/* @__PURE__ */ jsxRuntime.jsx(Summary, { label: "Figyelmeztetés", value: report.score.warning, tone: "warning" }),
|
|
4157
|
+
/* @__PURE__ */ jsxRuntime.jsx(Summary, { label: "Blokkoló", value: report.score.blocked, tone: "blocked" }),
|
|
4158
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
4159
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Élesítési döntés" }),
|
|
4160
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: report.ready ? "mt-1 text-xl font-semibold text-ui-fg-success" : "mt-1 text-xl font-semibold text-ui-fg-error", children: report.ready ? "Élesíthető" : "Még nem élesíthető" }),
|
|
4161
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-1 text-ui-fg-subtle", children: report.environment === "production" ? "Production szabályok" : "Nem-production szabályok" })
|
|
4162
|
+
] })
|
|
4163
|
+
] }),
|
|
4164
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b px-6 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4165
|
+
"Utolsó ellenőrzés: ",
|
|
4166
|
+
formatDate(report.generated_at),
|
|
4167
|
+
". A sárga elemek nem blokkolják az élesítést, a piros elemek igen."
|
|
4168
|
+
] }) }),
|
|
4169
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6 p-6", children: groups.map(([category, checks]) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "overflow-hidden rounded-lg border", children: [
|
|
4170
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b bg-ui-bg-subtle px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: CATEGORY_LABELS[category] || category }) }),
|
|
4171
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y", children: checks.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 p-4 md:grid-cols-[180px_140px_minmax(0,1fr)_auto] md:items-center", children: [
|
|
4172
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: item.label }),
|
|
4173
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: item.status }),
|
|
4174
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: item.message }),
|
|
4175
|
+
item.action_href && item.action_label ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: normalizeAdminHref(item.action_href), children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: item.action_label }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", {})
|
|
4176
|
+
] }, item.key)) })
|
|
4177
|
+
] }, category)) })
|
|
4178
|
+
] }) : null,
|
|
4179
|
+
loading && !report ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Élesítési feltételek ellenőrzése…" }) }) : null,
|
|
4180
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-6 rounded-lg border border-ui-border-error p-4", children: [
|
|
4181
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-error", children: "Az ellenőrzés nem futott le." }),
|
|
4182
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: error })
|
|
4183
|
+
] }) : null
|
|
4236
4184
|
] });
|
|
4237
|
-
}
|
|
4238
|
-
function
|
|
4239
|
-
label
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: connectionTextClass(state), children: value })
|
|
4185
|
+
};
|
|
4186
|
+
function StatusBadge({ status }) {
|
|
4187
|
+
const label = status === "ready" ? "Kész" : status === "warning" ? "Figyelmeztetés" : "Blokkoló";
|
|
4188
|
+
const className = status === "ready" ? "font-medium text-ui-fg-success" : status === "warning" ? "font-medium text-ui-fg-warning" : "font-medium text-ui-fg-error";
|
|
4189
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className, children: [
|
|
4190
|
+
status === "ready" ? "✅" : status === "warning" ? "🟡" : "🔴",
|
|
4191
|
+
" ",
|
|
4192
|
+
label
|
|
4246
4193
|
] });
|
|
4247
4194
|
}
|
|
4248
|
-
function
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4195
|
+
function Summary({ label, value, tone }) {
|
|
4196
|
+
const valueClass = tone === "ready" ? "text-ui-fg-success" : tone === "warning" ? "text-ui-fg-warning" : "text-ui-fg-error";
|
|
4197
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
4198
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: label }),
|
|
4199
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `mt-1 text-3xl font-semibold ${valueClass}`, children: value })
|
|
4200
|
+
] });
|
|
4252
4201
|
}
|
|
4253
|
-
function
|
|
4254
|
-
if (
|
|
4255
|
-
|
|
4256
|
-
}
|
|
4257
|
-
if (item.last_test_status === "error") {
|
|
4258
|
-
return { label: "Hiba", state: "error" };
|
|
4259
|
-
}
|
|
4260
|
-
if (item.last_test_at) {
|
|
4261
|
-
return { label: "Részleges ellenőrzés", state: "warning" };
|
|
4262
|
-
}
|
|
4263
|
-
return { label: "Nem ellenőrzött", state: "neutral" };
|
|
4202
|
+
function normalizeAdminHref(path) {
|
|
4203
|
+
if (!path.startsWith("/app")) return path;
|
|
4204
|
+
return `${adminBase$1}${path.slice(4)}`;
|
|
4264
4205
|
}
|
|
4265
|
-
function
|
|
4266
|
-
|
|
4267
|
-
if (
|
|
4268
|
-
|
|
4269
|
-
return "font-medium";
|
|
4206
|
+
function formatDate(value) {
|
|
4207
|
+
const date = new Date(value);
|
|
4208
|
+
if (Number.isNaN(date.getTime())) return "—";
|
|
4209
|
+
return new Intl.DateTimeFormat("hu-HU", { dateStyle: "short", timeStyle: "medium" }).format(date);
|
|
4270
4210
|
}
|
|
4271
|
-
const config$1 = adminSdk.defineRouteConfig({
|
|
4211
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
4212
|
+
label: "Production readiness",
|
|
4213
|
+
rank: 39
|
|
4214
|
+
});
|
|
4272
4215
|
const backendUrl$1 = (__BACKEND_URL__ || "").replace(/\/+$/, "");
|
|
4273
4216
|
const adminBase = (__BASE__ || "/app").replace(/\/+$/, "");
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4217
|
+
const apiUrl$1 = (path) => `${backendUrl$1}${path.startsWith("/") ? path : `/${path}`}`;
|
|
4218
|
+
const CATEGORY_ORDER = [
|
|
4219
|
+
"payment",
|
|
4220
|
+
"invoicing",
|
|
4221
|
+
"shipping",
|
|
4222
|
+
"notification",
|
|
4223
|
+
"legal",
|
|
4224
|
+
"marketing"
|
|
4225
|
+
];
|
|
4226
|
+
const CATEGORY_LABEL = {
|
|
4227
|
+
payment: "Fizetés",
|
|
4228
|
+
invoicing: "Számlázás",
|
|
4229
|
+
shipping: "Szállítás",
|
|
4230
|
+
notification: "Értesítés",
|
|
4231
|
+
legal: "Jogi integráció",
|
|
4232
|
+
marketing: "Marketing"
|
|
4233
|
+
};
|
|
4234
|
+
const IntegrationsPage = () => {
|
|
4235
|
+
const [items, setItems] = React.useState([]);
|
|
4236
|
+
const [selectedKey, setSelectedKey] = React.useState(null);
|
|
4237
|
+
const [draft, setDraft] = React.useState({});
|
|
4238
|
+
const [clearSecrets, setClearSecrets] = React.useState([]);
|
|
4239
|
+
const [enabled, setEnabled] = React.useState(false);
|
|
4240
|
+
const [loading, setLoading] = React.useState(true);
|
|
4241
|
+
const [saving, setSaving] = React.useState(false);
|
|
4242
|
+
const [testing, setTesting] = React.useState(false);
|
|
4243
|
+
const [restartNotice, setRestartNotice] = React.useState(false);
|
|
4244
|
+
const visibleItems = React.useMemo(
|
|
4245
|
+
() => items.filter((item) => CATEGORY_ORDER.includes(item.category)),
|
|
4246
|
+
[items]
|
|
4247
|
+
);
|
|
4248
|
+
const selected = React.useMemo(
|
|
4249
|
+
() => visibleItems.find((item) => item.key === selectedKey) || null,
|
|
4250
|
+
[visibleItems, selectedKey]
|
|
4251
|
+
);
|
|
4252
|
+
const hasUnsavedChanges = React.useMemo(() => {
|
|
4253
|
+
if (!selected) return false;
|
|
4254
|
+
if (enabled !== selected.enabled || clearSecrets.length > 0) return true;
|
|
4255
|
+
return selected.fields.some((field) => {
|
|
4256
|
+
const value = draft[field.name];
|
|
4257
|
+
if (field.type === "secret") {
|
|
4258
|
+
return Boolean(String(value || "").trim());
|
|
4259
|
+
}
|
|
4260
|
+
if (field.type === "boolean") {
|
|
4261
|
+
return Boolean(value) !== (selected.values[field.name] === "true");
|
|
4262
|
+
}
|
|
4263
|
+
return String(value || "").trim() !== String(selected.values[field.name] || "").trim();
|
|
4264
|
+
});
|
|
4265
|
+
}, [selected, enabled, draft, clearSecrets]);
|
|
4291
4266
|
const load = React.useCallback(async () => {
|
|
4292
4267
|
setLoading(true);
|
|
4293
|
-
setLoadError(null);
|
|
4294
4268
|
try {
|
|
4295
|
-
const
|
|
4296
|
-
|
|
4297
|
-
status
|
|
4269
|
+
const response = await fetch(apiUrl$1("/admin/integrations"), {
|
|
4270
|
+
credentials: "include"
|
|
4298
4271
|
});
|
|
4299
|
-
|
|
4300
|
-
const response = await fetch(
|
|
4301
|
-
apiUrl$1(`/admin/integration-operations?${params.toString()}`),
|
|
4302
|
-
{ credentials: "include" }
|
|
4303
|
-
);
|
|
4304
|
-
const payload = await response.json().catch(() => ({}));
|
|
4272
|
+
const data = await response.json().catch(() => ({}));
|
|
4305
4273
|
if (!response.ok) {
|
|
4306
|
-
throw new Error(
|
|
4307
|
-
payload.message || "Az integrációs műveletek nem tölthetők be."
|
|
4308
|
-
);
|
|
4274
|
+
throw new Error(data.message || "Az integrációk nem tölthetők be.");
|
|
4309
4275
|
}
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
}
|
|
4276
|
+
const integrations = data.integrations || [];
|
|
4277
|
+
setItems(integrations);
|
|
4278
|
+
const eligible = integrations.filter(
|
|
4279
|
+
(item) => CATEGORY_ORDER.includes(item.category)
|
|
4280
|
+
);
|
|
4281
|
+
setSelectedKey(
|
|
4282
|
+
(current) => current && eligible.some((item) => item.key === current) ? current : eligible[0]?.key || null
|
|
4318
4283
|
);
|
|
4319
4284
|
} catch (error) {
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
error instanceof Error ? error.message : "Az integrációs műveletek nem tölthetők be."
|
|
4285
|
+
ui.toast.error(
|
|
4286
|
+
error instanceof Error ? error.message : "Az integrációk nem tölthetők be."
|
|
4323
4287
|
);
|
|
4324
4288
|
} finally {
|
|
4325
4289
|
setLoading(false);
|
|
4326
4290
|
}
|
|
4327
|
-
}, [
|
|
4291
|
+
}, []);
|
|
4328
4292
|
React.useEffect(() => {
|
|
4329
4293
|
void load();
|
|
4330
4294
|
}, [load]);
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
(
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
);
|
|
4346
|
-
}, [
|
|
4347
|
-
const
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4295
|
+
React.useEffect(() => {
|
|
4296
|
+
if (!selected) return;
|
|
4297
|
+
const next = {};
|
|
4298
|
+
for (const field of selected.fields) {
|
|
4299
|
+
if (field.type === "secret") next[field.name] = "";
|
|
4300
|
+
else if (field.type === "boolean") {
|
|
4301
|
+
next[field.name] = selected.values[field.name] === "true";
|
|
4302
|
+
} else {
|
|
4303
|
+
next[field.name] = selected.values[field.name] || "";
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
setDraft(next);
|
|
4307
|
+
setClearSecrets([]);
|
|
4308
|
+
setEnabled(selected.enabled);
|
|
4309
|
+
setRestartNotice(false);
|
|
4310
|
+
}, [selected?.key, selected?.values, selected?.enabled]);
|
|
4311
|
+
const save = async () => {
|
|
4312
|
+
if (!selected) return;
|
|
4313
|
+
setSaving(true);
|
|
4314
|
+
try {
|
|
4315
|
+
const values = {};
|
|
4316
|
+
for (const field of selected.fields) {
|
|
4317
|
+
const value = draft[field.name];
|
|
4318
|
+
if (field.type === "secret" && !String(value || "").trim()) continue;
|
|
4319
|
+
values[field.name] = value;
|
|
4320
|
+
}
|
|
4321
|
+
const response = await fetch(apiUrl$1(`/admin/integrations/${selected.key}`), {
|
|
4322
|
+
method: "POST",
|
|
4323
|
+
credentials: "include",
|
|
4324
|
+
headers: { "Content-Type": "application/json" },
|
|
4325
|
+
body: JSON.stringify({
|
|
4326
|
+
enabled,
|
|
4327
|
+
values,
|
|
4328
|
+
clear_secrets: clearSecrets
|
|
4329
|
+
})
|
|
4330
|
+
});
|
|
4331
|
+
const data = await response.json().catch(() => ({}));
|
|
4332
|
+
if (!response.ok) {
|
|
4333
|
+
throw new Error(data.message || "A mentés nem sikerült.");
|
|
4360
4334
|
}
|
|
4335
|
+
if (data.integration) replaceIntegration(data.integration);
|
|
4336
|
+
setClearSecrets([]);
|
|
4337
|
+
setRestartNotice(Boolean(data.integration?.restart_required));
|
|
4338
|
+
ui.toast.success(data.message || "Beállítások mentve.");
|
|
4339
|
+
} catch (error) {
|
|
4340
|
+
ui.toast.error(error instanceof Error ? error.message : "A mentés nem sikerült.");
|
|
4341
|
+
} finally {
|
|
4342
|
+
setSaving(false);
|
|
4361
4343
|
}
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
setActionLoading(operation.id);
|
|
4344
|
+
};
|
|
4345
|
+
const test = async () => {
|
|
4346
|
+
if (!selected || hasUnsavedChanges) return;
|
|
4347
|
+
setTesting(true);
|
|
4367
4348
|
try {
|
|
4368
|
-
const response = await fetch(
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
);
|
|
4349
|
+
const response = await fetch(apiUrl$1(`/admin/integrations/${selected.key}/test`), {
|
|
4350
|
+
method: "POST",
|
|
4351
|
+
credentials: "include"
|
|
4352
|
+
});
|
|
4353
|
+
const data = await response.json().catch(() => ({}));
|
|
4354
|
+
if (data.integration) replaceIntegration(data.integration);
|
|
4355
|
+
if (!response.ok || !data.ok) {
|
|
4356
|
+
throw new Error(data.message || "A kapcsolat tesztelése nem sikerült.");
|
|
4357
|
+
}
|
|
4358
|
+
if (data.verified) {
|
|
4359
|
+
ui.toast.success(data.message || "Kapcsolat ellenőrizve.");
|
|
4360
|
+
} else {
|
|
4361
|
+
ui.toast.success(data.message || "Részleges ellenőrzés sikeres.");
|
|
4382
4362
|
}
|
|
4383
|
-
ui.toast.success(
|
|
4384
|
-
decision === "confirmed_succeeded" ? "A művelet sikeresként lezárva." : "A művelet újrapróbálhatóvá téve."
|
|
4385
|
-
);
|
|
4386
|
-
await load();
|
|
4387
4363
|
} catch (error) {
|
|
4388
4364
|
ui.toast.error(
|
|
4389
|
-
error instanceof Error ? error.message : "
|
|
4365
|
+
error instanceof Error ? error.message : "A kapcsolat tesztelése nem sikerült."
|
|
4390
4366
|
);
|
|
4367
|
+
void load();
|
|
4391
4368
|
} finally {
|
|
4392
|
-
|
|
4369
|
+
setTesting(false);
|
|
4393
4370
|
}
|
|
4394
4371
|
};
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Külső API műveletek, hibák és kézi reconciliation kezelése." })
|
|
4400
|
-
] }),
|
|
4401
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4402
|
-
ui.Button,
|
|
4403
|
-
{
|
|
4404
|
-
variant: "secondary",
|
|
4405
|
-
isLoading: loading,
|
|
4406
|
-
onClick: () => void load(),
|
|
4407
|
-
children: "Frissítés"
|
|
4408
|
-
}
|
|
4372
|
+
const replaceIntegration = (integration) => {
|
|
4373
|
+
setItems(
|
|
4374
|
+
(current) => current.map(
|
|
4375
|
+
(item) => item.key === integration.key ? integration : item
|
|
4409
4376
|
)
|
|
4377
|
+
);
|
|
4378
|
+
};
|
|
4379
|
+
const detailHref = selected ? detailPageForIntegration(selected.key) : null;
|
|
4380
|
+
const connection = selected ? connectionPresentation(selected) : null;
|
|
4381
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-0", children: [
|
|
4382
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b px-6 py-5", children: [
|
|
4383
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Integrációk" }),
|
|
4384
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 text-ui-fg-subtle", children: "Külső szolgáltatások és provider kapcsolatok központi beállítása. A secret értékek nem kerülnek vissza a böngészőbe, a provider-hozzárendelés pedig továbbra is a HSZRDM Commerce Admin natív felületein történik." })
|
|
4410
4385
|
] }),
|
|
4411
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4412
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
label: "Sikertelen",
|
|
4424
|
-
value: summary.failed,
|
|
4425
|
-
danger: summary.failed > 0
|
|
4426
|
-
}
|
|
4427
|
-
),
|
|
4428
|
-
/* @__PURE__ */ jsxRuntime.jsx(SummaryCard, { label: "Folyamatban", value: summary.processing })
|
|
4429
|
-
] }),
|
|
4430
|
-
summary.needsReconciliation > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-ui-border-warning bg-ui-bg-base px-6 py-4", children: [
|
|
4431
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium text-ui-fg-warning", children: [
|
|
4432
|
-
summary.needsReconciliation,
|
|
4433
|
-
" műveletnél nem dönthető el automatikusan, hogy a külső szolgáltató végrehajtotta-e a kérést."
|
|
4434
|
-
] }),
|
|
4435
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Ellenőrizd a szolgáltatónál, majd csak ezután jelöld sikeresnek vagy újrapróbálhatónak. Így elkerülhető a duplikált számla, csomag vagy fizetés." })
|
|
4436
|
-
] }) : null,
|
|
4437
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-end gap-3 border-b px-6 py-4", children: [
|
|
4438
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4439
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Státusz" }),
|
|
4440
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: status, onValueChange: setStatus, children: [
|
|
4441
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { className: "w-52", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
4442
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
4443
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "problems", children: "Hibák + egyeztetés" }),
|
|
4444
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "needs_reconciliation", children: "Egyeztetést igényel" }),
|
|
4445
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "failed", children: "Sikertelen" }),
|
|
4446
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "processing", children: "Folyamatban" }),
|
|
4447
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "pending", children: "Várakozik" }),
|
|
4448
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "succeeded", children: "Sikeres" }),
|
|
4449
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "all", children: "Összes" })
|
|
4450
|
-
] })
|
|
4451
|
-
] })
|
|
4452
|
-
] }),
|
|
4453
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4454
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Provider" }),
|
|
4455
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: provider, onValueChange: setProvider, children: [
|
|
4456
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { className: "w-44", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
4457
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
4458
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "all", children: "Összes" }),
|
|
4459
|
-
[
|
|
4460
|
-
"stripe",
|
|
4461
|
-
"simplepay",
|
|
4462
|
-
"billingo",
|
|
4463
|
-
"foxpost",
|
|
4464
|
-
"gls",
|
|
4465
|
-
"packeta",
|
|
4466
|
-
"dpd",
|
|
4467
|
-
"mpl"
|
|
4468
|
-
].map((item) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: item, children: providerLabel(item) }, item))
|
|
4469
|
-
] })
|
|
4470
|
-
] })
|
|
4471
|
-
] }),
|
|
4472
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4473
|
-
ui.Input,
|
|
4474
|
-
{
|
|
4475
|
-
className: "max-w-sm",
|
|
4476
|
-
value: query,
|
|
4477
|
-
onChange: (event) => setQuery(event.target.value),
|
|
4478
|
-
placeholder: "Keresés művelet, rendelés, külső ID vagy hiba alapján"
|
|
4479
|
-
}
|
|
4480
|
-
),
|
|
4481
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
4482
|
-
count,
|
|
4483
|
-
" találat"
|
|
4484
|
-
] })
|
|
4485
|
-
] }),
|
|
4486
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-x-auto", children: [
|
|
4487
|
-
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
|
|
4488
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-b bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
4489
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Státusz" }),
|
|
4490
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Provider / művelet" }),
|
|
4491
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Entitás" }),
|
|
4492
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Külső ID" }),
|
|
4493
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Próbálkozás" }),
|
|
4494
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Hiba / idő" }),
|
|
4495
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "p-4", children: "Műveletek" })
|
|
4496
|
-
] }) }),
|
|
4497
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: visible.map((operation) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b align-top", children: [
|
|
4498
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(StatusText, { status: operation.status }) }),
|
|
4499
|
-
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
4500
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: providerLabel(operation.provider) }),
|
|
4501
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: operation.operation_type })
|
|
4502
|
-
] }),
|
|
4503
|
-
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "p-4", children: [
|
|
4504
|
-
operation.entity_type === "order" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4505
|
-
"a",
|
|
4386
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Betöltés…" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid lg:grid-cols-[320px_minmax(0,1fr)]", children: [
|
|
4387
|
+
/* @__PURE__ */ jsxRuntime.jsx("aside", { className: "border-r p-4", children: CATEGORY_ORDER.map((category) => {
|
|
4388
|
+
const categoryItems = visibleItems.filter(
|
|
4389
|
+
(item) => item.category === category
|
|
4390
|
+
);
|
|
4391
|
+
if (!categoryItems.length) return null;
|
|
4392
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 last:mb-0", children: [
|
|
4393
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-2 px-1 text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: CATEGORY_LABEL[category] }),
|
|
4394
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: categoryItems.map((item) => {
|
|
4395
|
+
const itemConnection = connectionPresentation(item);
|
|
4396
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4397
|
+
"button",
|
|
4506
4398
|
{
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4399
|
+
type: "button",
|
|
4400
|
+
onClick: () => setSelectedKey(item.key),
|
|
4401
|
+
className: `rounded-lg border p-3 text-left transition-colors hover:bg-ui-bg-subtle ${selectedKey === item.key ? "bg-ui-bg-subtle" : "bg-ui-bg-base"}`,
|
|
4402
|
+
children: [
|
|
4403
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
4404
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: item.label }),
|
|
4405
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: item.enabled ? "text-xs font-medium text-ui-fg-success" : "text-xs text-ui-fg-muted", children: item.enabled ? "Aktív" : "Kikapcsolva" })
|
|
4406
|
+
] }),
|
|
4407
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 text-xs text-ui-fg-subtle", children: [
|
|
4408
|
+
item.configured ? "Konfigurálva" : "Beállítás szükséges",
|
|
4409
|
+
" · ",
|
|
4410
|
+
itemConnection.label
|
|
4411
|
+
] })
|
|
4412
|
+
]
|
|
4413
|
+
},
|
|
4414
|
+
item.key
|
|
4415
|
+
);
|
|
4416
|
+
}) })
|
|
4417
|
+
] }, category);
|
|
4418
|
+
}) }),
|
|
4419
|
+
/* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 p-6", children: selected && connection ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-w-4xl flex-col gap-6", children: [
|
|
4420
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
4421
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
4422
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: selected.label }),
|
|
4423
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 text-ui-fg-subtle", children: selected.description })
|
|
4513
4424
|
] }),
|
|
4514
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4425
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end gap-1", children: [
|
|
4426
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2", children: [
|
|
4427
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: enabled, onCheckedChange: setEnabled }),
|
|
4428
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: enabled ? "Bekapcsolva" : "Kikapcsolva" })
|
|
4429
|
+
] }),
|
|
4430
|
+
hasUnsavedChanges ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-warning", children: "Nem mentett módosítások" }) : null
|
|
4431
|
+
] })
|
|
4432
|
+
] }),
|
|
4433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-4", children: [
|
|
4434
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Telepítve", value: selected.installed ? "Igen" : "Nem", state: selected.installed ? "success" : "neutral" }),
|
|
4435
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Konfigurálva", value: selected.configured ? "Igen" : "Nem", state: selected.configured ? "success" : "neutral" }),
|
|
4436
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Aktív", value: selected.enabled ? "Igen" : "Nem", state: selected.enabled ? "success" : "neutral" }),
|
|
4437
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusBox, { label: "Kapcsolat", value: connection.label, state: connection.state })
|
|
4438
|
+
] }),
|
|
4439
|
+
selected.category === "shipping" ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "HSZRDM Commerce provider hozzárendelés", children: "Mentés és backend restart után a providert a HSZRDM Commerce Admin Settings → Locations & Shipping alatt rendeld locationhöz." }) : null,
|
|
4440
|
+
selected.category === "legal" ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "Fogyasztó Barát EMBED", children: "Ez csak az opcionális Fogyasztó Barát embed konfigurációja. A PDF-ek és checkout elfogadások a főoldali Jogi dokumentumok menüpontban kezelhetők." }) : null,
|
|
4441
|
+
selected.category === "marketing" ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "Marketing feed", children: "Itt az integráció alapbeállításait módosítod. A feed előnézet, diagnosztika és publikus URL a főoldali Marketing menüpontban található." }) : null,
|
|
4442
|
+
restartNotice ? /* @__PURE__ */ jsxRuntime.jsx(Notice, { title: "Újraindítás szükséges", children: "A beállítások elmentve. Indítsd újra a HSZRDM Commerce backendet az új provider-konfiguráció betöltéséhez." }) : null,
|
|
4443
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4444
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Beállítások" }),
|
|
4445
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 grid gap-4 sm:grid-cols-2", children: selected.fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4446
|
+
FieldEditor,
|
|
4447
|
+
{
|
|
4448
|
+
field,
|
|
4449
|
+
value: draft[field.name],
|
|
4450
|
+
hasSecret: Boolean(selected.secrets[field.name]),
|
|
4451
|
+
clearPending: clearSecrets.includes(field.name),
|
|
4452
|
+
onChange: (value) => {
|
|
4453
|
+
setDraft((current) => ({ ...current, [field.name]: value }));
|
|
4454
|
+
if (field.type === "secret" && String(value || "").trim()) {
|
|
4455
|
+
setClearSecrets(
|
|
4456
|
+
(current) => current.filter((name) => name !== field.name)
|
|
4457
|
+
);
|
|
4458
|
+
}
|
|
4459
|
+
},
|
|
4460
|
+
onClearSecret: () => {
|
|
4461
|
+
setDraft((current) => ({ ...current, [field.name]: "" }));
|
|
4462
|
+
setClearSecrets(
|
|
4463
|
+
(current) => current.includes(field.name) ? current : [...current, field.name]
|
|
4464
|
+
);
|
|
4465
|
+
},
|
|
4466
|
+
onRestoreSecret: () => setClearSecrets(
|
|
4467
|
+
(current) => current.filter((name) => name !== field.name)
|
|
4468
|
+
)
|
|
4469
|
+
},
|
|
4470
|
+
field.name
|
|
4471
|
+
)) })
|
|
4472
|
+
] }),
|
|
4473
|
+
selected.last_test_message ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
4474
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
4475
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Utolsó kapcsolat-teszt" }),
|
|
4476
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: connectionTextClass(connection.state), children: connection.label })
|
|
4519
4477
|
] }),
|
|
4520
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4478
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 text-ui-fg-subtle", children: selected.last_test_message }),
|
|
4479
|
+
selected.last_test_at ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 text-xs text-ui-fg-muted", children: new Date(selected.last_test_at).toLocaleString("hu-HU") }) : null
|
|
4480
|
+
] }) : null,
|
|
4481
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t pt-5", children: [
|
|
4482
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4521
4483
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4522
4484
|
ui.Button,
|
|
4523
4485
|
{
|
|
4524
|
-
|
|
4525
|
-
disabled:
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
children: "Megtörtént"
|
|
4486
|
+
isLoading: saving,
|
|
4487
|
+
disabled: saving || testing || !hasUnsavedChanges,
|
|
4488
|
+
onClick: () => void save(),
|
|
4489
|
+
children: "Mentés"
|
|
4529
4490
|
}
|
|
4530
4491
|
),
|
|
4531
4492
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4532
4493
|
ui.Button,
|
|
4533
4494
|
{
|
|
4534
|
-
size: "small",
|
|
4535
4495
|
variant: "secondary",
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4496
|
+
isLoading: testing,
|
|
4497
|
+
disabled: saving || testing || hasUnsavedChanges || !selected.configured || !selected.enabled,
|
|
4498
|
+
onClick: () => void test(),
|
|
4499
|
+
children: "Kapcsolat tesztelése"
|
|
4539
4500
|
}
|
|
4540
|
-
)
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-error", children: "Az integrációs műveletek nem tölthetők be." }),
|
|
4547
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: loadError })
|
|
4548
|
-
] }) : null,
|
|
4549
|
-
!loading && !loadError && !visible.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Nincs a szűrésnek megfelelő integrációs művelet." }) }) : null
|
|
4501
|
+
),
|
|
4502
|
+
detailHref ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: detailHref, className: "ml-auto", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", children: "Részletes nézet" }) }) : null
|
|
4503
|
+
] }),
|
|
4504
|
+
hasUnsavedChanges ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-2 text-xs text-ui-fg-warning", children: "A kapcsolat-teszt mindig a mentett konfigurációt használja. Mentsd a módosításokat a teszt előtt." }) : !selected.enabled ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-2 text-xs text-ui-fg-muted", children: "Kapcsolat-teszt csak bekapcsolt integráción futtatható." }) : !selected.configured ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-2 text-xs text-ui-fg-muted", children: "Töltsd ki a kötelező mezőket és mentsd az integrációt a teszteléshez." }) : null
|
|
4505
|
+
] })
|
|
4506
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Nincs kiválasztott integráció." }) })
|
|
4550
4507
|
] })
|
|
4551
4508
|
] });
|
|
4552
4509
|
};
|
|
4553
|
-
function
|
|
4510
|
+
function Notice({ title, children }) {
|
|
4511
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border bg-ui-bg-subtle p-4", children: [
|
|
4512
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: title }),
|
|
4513
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children })
|
|
4514
|
+
] });
|
|
4515
|
+
}
|
|
4516
|
+
function FieldEditor({
|
|
4517
|
+
field,
|
|
4518
|
+
value,
|
|
4519
|
+
hasSecret,
|
|
4520
|
+
clearPending,
|
|
4521
|
+
onChange,
|
|
4522
|
+
onClearSecret,
|
|
4523
|
+
onRestoreSecret
|
|
4524
|
+
}) {
|
|
4525
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
4526
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium", children: [
|
|
4527
|
+
field.label,
|
|
4528
|
+
field.required ? " *" : ""
|
|
4529
|
+
] }),
|
|
4530
|
+
field.type === "boolean" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-2", children: [
|
|
4531
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: Boolean(value), onCheckedChange: onChange }),
|
|
4532
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: value ? "Igen" : "Nem" })
|
|
4533
|
+
] }) : field.type === "select" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4534
|
+
"select",
|
|
4535
|
+
{
|
|
4536
|
+
className: "h-8 rounded-md border bg-ui-bg-field px-2 text-sm",
|
|
4537
|
+
value: String(value || ""),
|
|
4538
|
+
onChange: (event) => onChange(event.target.value),
|
|
4539
|
+
children: [
|
|
4540
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "—" }),
|
|
4541
|
+
(field.options || []).map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value))
|
|
4542
|
+
]
|
|
4543
|
+
}
|
|
4544
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4545
|
+
ui.Input,
|
|
4546
|
+
{
|
|
4547
|
+
type: field.type === "secret" ? "password" : field.type === "number" ? "number" : "text",
|
|
4548
|
+
value: String(value || ""),
|
|
4549
|
+
placeholder: field.type === "secret" && hasSecret && !clearPending ? "•••••••• (beállítva – hagyd üresen a megtartáshoz)" : field.help,
|
|
4550
|
+
onChange: (event) => onChange(event.target.value)
|
|
4551
|
+
}
|
|
4552
|
+
),
|
|
4553
|
+
field.type === "secret" && hasSecret ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
4554
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: `text-xs ${clearPending ? "text-ui-fg-error" : "text-ui-fg-muted"}`, children: clearPending ? "A mentett titok a következő mentéskor törlődik." : "Titkos érték beállítva." }),
|
|
4555
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4556
|
+
"button",
|
|
4557
|
+
{
|
|
4558
|
+
type: "button",
|
|
4559
|
+
className: "shrink-0 text-xs font-medium text-ui-fg-interactive hover:underline",
|
|
4560
|
+
onClick: clearPending ? onRestoreSecret : onClearSecret,
|
|
4561
|
+
children: clearPending ? "Törlés visszavonása" : "Titok törlése"
|
|
4562
|
+
}
|
|
4563
|
+
)
|
|
4564
|
+
] }) : field.help ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-muted", children: field.help }) : null
|
|
4565
|
+
] });
|
|
4566
|
+
}
|
|
4567
|
+
function StatusBox({
|
|
4554
4568
|
label,
|
|
4555
4569
|
value,
|
|
4556
|
-
|
|
4570
|
+
state
|
|
4557
4571
|
}) {
|
|
4558
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-
|
|
4559
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, {
|
|
4560
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4572
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border p-3", children: [
|
|
4573
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-ui-fg-muted", children: label }),
|
|
4574
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: connectionTextClass(state), children: value })
|
|
4561
4575
|
] });
|
|
4562
4576
|
}
|
|
4563
|
-
function
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
succeeded: "Sikeres",
|
|
4568
|
-
failed: "Sikertelen",
|
|
4569
|
-
needs_reconciliation: "Egyeztetést igényel"
|
|
4570
|
-
};
|
|
4571
|
-
const className = status === "failed" || status === "needs_reconciliation" ? "font-medium text-ui-fg-error" : status === "succeeded" ? "font-medium text-ui-fg-success" : "font-medium";
|
|
4572
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: labels[status] });
|
|
4577
|
+
function detailPageForIntegration(key) {
|
|
4578
|
+
if (key === "google-merchant") return `${adminBase}/marketing/google-merchant`;
|
|
4579
|
+
if (key === "arukereso") return `${adminBase}/marketing/arukereso`;
|
|
4580
|
+
return null;
|
|
4573
4581
|
}
|
|
4574
|
-
function
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
};
|
|
4585
|
-
return labels[value] || value;
|
|
4582
|
+
function connectionPresentation(item) {
|
|
4583
|
+
if (item.last_test_status === "ok") {
|
|
4584
|
+
return { label: "Ellenőrizve", state: "success" };
|
|
4585
|
+
}
|
|
4586
|
+
if (item.last_test_status === "error") {
|
|
4587
|
+
return { label: "Hiba", state: "error" };
|
|
4588
|
+
}
|
|
4589
|
+
if (item.last_test_at) {
|
|
4590
|
+
return { label: "Részleges ellenőrzés", state: "warning" };
|
|
4591
|
+
}
|
|
4592
|
+
return { label: "Nem ellenőrzött", state: "neutral" };
|
|
4586
4593
|
}
|
|
4587
|
-
function
|
|
4588
|
-
if (
|
|
4589
|
-
|
|
4590
|
-
if (
|
|
4591
|
-
return
|
|
4592
|
-
dateStyle: "short",
|
|
4593
|
-
timeStyle: "short"
|
|
4594
|
-
}).format(date);
|
|
4594
|
+
function connectionTextClass(state) {
|
|
4595
|
+
if (state === "success") return "font-medium text-ui-fg-success";
|
|
4596
|
+
if (state === "warning") return "font-medium text-ui-fg-warning";
|
|
4597
|
+
if (state === "error") return "font-medium text-ui-fg-error";
|
|
4598
|
+
return "font-medium";
|
|
4595
4599
|
}
|
|
4596
|
-
const config = adminSdk.defineRouteConfig({
|
|
4597
|
-
label: "Integrációs műveletek",
|
|
4598
|
-
icon: Newspaper,
|
|
4599
|
-
rank: 37
|
|
4600
|
-
});
|
|
4600
|
+
const config = adminSdk.defineRouteConfig({ label: "Integrációk" });
|
|
4601
4601
|
const EMPTY = {
|
|
4602
4602
|
sourcePath: "",
|
|
4603
4603
|
targetPath: "",
|
|
@@ -4934,8 +4934,8 @@ const routeModule = {
|
|
|
4934
4934
|
handle: { label: config$9.label, translationNs: config$9.translationNs }
|
|
4935
4935
|
},
|
|
4936
4936
|
{
|
|
4937
|
-
Component:
|
|
4938
|
-
path: "/
|
|
4937
|
+
Component: BillingPage,
|
|
4938
|
+
path: "/billing",
|
|
4939
4939
|
handle: { label: config$8.label, translationNs: config$8.translationNs }
|
|
4940
4940
|
},
|
|
4941
4941
|
{
|
|
@@ -4944,42 +4944,42 @@ const routeModule = {
|
|
|
4944
4944
|
handle: { label: config$7.label, translationNs: config$7.translationNs }
|
|
4945
4945
|
},
|
|
4946
4946
|
{
|
|
4947
|
-
Component:
|
|
4948
|
-
path: "/
|
|
4947
|
+
Component: ArukeresoPage,
|
|
4948
|
+
path: "/marketing/arukereso",
|
|
4949
4949
|
handle: { label: config$6.label, translationNs: config$6.translationNs }
|
|
4950
4950
|
},
|
|
4951
4951
|
{
|
|
4952
4952
|
Component: SeoAdminPage,
|
|
4953
4953
|
path: "/marketing/seo"
|
|
4954
4954
|
},
|
|
4955
|
-
{
|
|
4956
|
-
Component: GoogleMerchantPage,
|
|
4957
|
-
path: "/marketing/google-merchant",
|
|
4958
|
-
handle: { label: config$5.label, translationNs: config$5.translationNs }
|
|
4959
|
-
},
|
|
4960
4955
|
{
|
|
4961
4956
|
Component: CoreAuditPage,
|
|
4962
4957
|
path: "/system-monitoring/audit",
|
|
4963
|
-
handle: { label: config$
|
|
4958
|
+
handle: { label: config$5.label, translationNs: config$5.translationNs }
|
|
4964
4959
|
},
|
|
4965
4960
|
{
|
|
4966
4961
|
Component: IntegrationHealthPage,
|
|
4967
4962
|
path: "/system-monitoring/health",
|
|
4963
|
+
handle: { label: config$4.label, translationNs: config$4.translationNs }
|
|
4964
|
+
},
|
|
4965
|
+
{
|
|
4966
|
+
Component: GoogleMerchantPage,
|
|
4967
|
+
path: "/marketing/google-merchant",
|
|
4968
4968
|
handle: { label: config$3.label, translationNs: config$3.translationNs }
|
|
4969
4969
|
},
|
|
4970
4970
|
{
|
|
4971
|
-
Component:
|
|
4972
|
-
path: "/system-monitoring/
|
|
4971
|
+
Component: IntegrationOperationsPage,
|
|
4972
|
+
path: "/system-monitoring/operations",
|
|
4973
4973
|
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
4974
4974
|
},
|
|
4975
4975
|
{
|
|
4976
|
-
Component:
|
|
4977
|
-
path: "/
|
|
4976
|
+
Component: ProductionReadinessPage,
|
|
4977
|
+
path: "/system-monitoring/readiness",
|
|
4978
4978
|
handle: { label: config$1.label, translationNs: config$1.translationNs }
|
|
4979
4979
|
},
|
|
4980
4980
|
{
|
|
4981
|
-
Component:
|
|
4982
|
-
path: "/
|
|
4981
|
+
Component: IntegrationsPage,
|
|
4982
|
+
path: "/settings/integrations",
|
|
4983
4983
|
handle: { label: config.label, translationNs: config.translationNs }
|
|
4984
4984
|
},
|
|
4985
4985
|
{
|
|
@@ -4999,8 +4999,8 @@ const menuItemModule = {
|
|
|
4999
4999
|
translationNs: void 0
|
|
5000
5000
|
},
|
|
5001
5001
|
{
|
|
5002
|
-
label: config$
|
|
5003
|
-
icon: config$
|
|
5002
|
+
label: config$8.label,
|
|
5003
|
+
icon: config$8.icon,
|
|
5004
5004
|
path: "/billing",
|
|
5005
5005
|
nested: void 0,
|
|
5006
5006
|
rank: 36,
|
|
@@ -5022,6 +5022,14 @@ const menuItemModule = {
|
|
|
5022
5022
|
rank: void 0,
|
|
5023
5023
|
translationNs: void 0
|
|
5024
5024
|
},
|
|
5025
|
+
{
|
|
5026
|
+
label: config$a.label,
|
|
5027
|
+
icon: config$a.icon,
|
|
5028
|
+
path: "/shipping",
|
|
5029
|
+
nested: void 0,
|
|
5030
|
+
rank: 35,
|
|
5031
|
+
translationNs: void 0
|
|
5032
|
+
},
|
|
5025
5033
|
{
|
|
5026
5034
|
label: config$9.label,
|
|
5027
5035
|
icon: void 0,
|
|
@@ -5031,23 +5039,23 @@ const menuItemModule = {
|
|
|
5031
5039
|
translationNs: void 0
|
|
5032
5040
|
},
|
|
5033
5041
|
{
|
|
5034
|
-
label: config
|
|
5035
|
-
icon:
|
|
5036
|
-
path: "/
|
|
5042
|
+
label: config.label,
|
|
5043
|
+
icon: void 0,
|
|
5044
|
+
path: "/settings/integrations",
|
|
5037
5045
|
nested: void 0,
|
|
5038
|
-
rank:
|
|
5046
|
+
rank: void 0,
|
|
5039
5047
|
translationNs: void 0
|
|
5040
5048
|
},
|
|
5041
5049
|
{
|
|
5042
|
-
label: config$
|
|
5050
|
+
label: config$3.label,
|
|
5043
5051
|
icon: void 0,
|
|
5044
|
-
path: "/
|
|
5052
|
+
path: "/marketing/google-merchant",
|
|
5045
5053
|
nested: void 0,
|
|
5046
|
-
rank:
|
|
5054
|
+
rank: 41,
|
|
5047
5055
|
translationNs: void 0
|
|
5048
5056
|
},
|
|
5049
5057
|
{
|
|
5050
|
-
label: config$
|
|
5058
|
+
label: config$6.label,
|
|
5051
5059
|
icon: void 0,
|
|
5052
5060
|
path: "/marketing/arukereso",
|
|
5053
5061
|
nested: void 0,
|
|
@@ -5056,43 +5064,35 @@ const menuItemModule = {
|
|
|
5056
5064
|
},
|
|
5057
5065
|
{
|
|
5058
5066
|
label: config$5.label,
|
|
5059
|
-
icon:
|
|
5060
|
-
path: "/
|
|
5067
|
+
icon: config$5.icon,
|
|
5068
|
+
path: "/system-monitoring/audit",
|
|
5061
5069
|
nested: void 0,
|
|
5062
|
-
rank:
|
|
5070
|
+
rank: 39,
|
|
5063
5071
|
translationNs: void 0
|
|
5064
5072
|
},
|
|
5065
5073
|
{
|
|
5066
5074
|
label: config$4.label,
|
|
5067
5075
|
icon: config$4.icon,
|
|
5068
|
-
path: "/system-monitoring/
|
|
5076
|
+
path: "/system-monitoring/health",
|
|
5069
5077
|
nested: void 0,
|
|
5070
|
-
rank:
|
|
5078
|
+
rank: 38,
|
|
5071
5079
|
translationNs: void 0
|
|
5072
5080
|
},
|
|
5073
5081
|
{
|
|
5074
|
-
label: config.label,
|
|
5075
|
-
icon: config.icon,
|
|
5082
|
+
label: config$2.label,
|
|
5083
|
+
icon: config$2.icon,
|
|
5076
5084
|
path: "/system-monitoring/operations",
|
|
5077
5085
|
nested: void 0,
|
|
5078
5086
|
rank: 37,
|
|
5079
5087
|
translationNs: void 0
|
|
5080
5088
|
},
|
|
5081
5089
|
{
|
|
5082
|
-
label: config$
|
|
5090
|
+
label: config$1.label,
|
|
5083
5091
|
icon: void 0,
|
|
5084
5092
|
path: "/system-monitoring/readiness",
|
|
5085
5093
|
nested: void 0,
|
|
5086
5094
|
rank: 39,
|
|
5087
5095
|
translationNs: void 0
|
|
5088
|
-
},
|
|
5089
|
-
{
|
|
5090
|
-
label: config$3.label,
|
|
5091
|
-
icon: config$3.icon,
|
|
5092
|
-
path: "/system-monitoring/health",
|
|
5093
|
-
nested: void 0,
|
|
5094
|
-
rank: 38,
|
|
5095
|
-
translationNs: void 0
|
|
5096
5096
|
}
|
|
5097
5097
|
]
|
|
5098
5098
|
};
|