first version

This commit is contained in:
Gerhard Scheikl
2026-04-28 21:56:11 +02:00
parent 0f75dbaccb
commit 5b2aa5d62b
50 changed files with 5514 additions and 481 deletions
@@ -0,0 +1,55 @@
import { render } from "preact";
import { useState } from "preact/hooks";
export default async () => {
render(<Extension />, document.body);
};
function Extension() {
const { close, data } = (globalThis as any).shopify;
const [busy, setBusy] = useState(false);
const [error, setError] = useState<string | null>(null);
const orderGid: string | undefined = data?.selected?.[0]?.id;
const orderId = orderGid ? orderGid.split("/").pop() : undefined;
async function trigger(action: "generate" | "cancel_reissue") {
if (!orderId) {
setError("No order selected");
return;
}
setBusy(true);
setError(null);
try {
const body = new URLSearchParams({ action });
const res = await fetch(`/api/orders/${orderId}/invoice`, {
method: "POST",
body,
});
if (!res.ok) {
const txt = await res.text();
throw new Error(`HTTP ${res.status}: ${txt.slice(0, 200)}`);
}
close();
} catch (e: any) {
setError(e?.message ?? "Failed");
} finally {
setBusy(false);
}
}
return (
<s-admin-action heading="Generate invoice" loading={busy}>
<s-stack gap="200">
<s-text>Create or regenerate the PDF invoice for this order. The file will be uploaded to Shopify Files and linked via order metafields.</s-text>
{error ? <s-banner tone="critical">{error}</s-banner> : null}
</s-stack>
<s-button slot="primary-action" onClick={() => trigger("generate")} disabled={busy}>
Generate / regenerate
</s-button>
<s-button slot="secondary-actions" tone="critical" onClick={() => trigger("cancel_reissue")} disabled={busy}>
Cancel &amp; reissue
</s-button>
</s-admin-action>
);
}