aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/paths/instance/templates/qr
diff options
context:
space:
mode:
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/qr')
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx65
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx2
2 files changed, 61 insertions, 6 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
index 756909d15..66ac72ff5 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
@@ -31,8 +31,10 @@ import {
} from "../../../../components/form/FormProvider.js";
import { Input } from "../../../../components/form/Input.js";
import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { ConfirmModal } from "../../../../components/modal/index.js";
import { useBackendContext } from "../../../../context/backend.js";
import { useConfigContext } from "../../../../context/config.js";
+import { useInstanceContext } from "../../../../context/instance.js";
import { MerchantBackend } from "../../../../declaration.js";
type Entity = MerchantBackend.Template.UsingTemplateDetails;
@@ -46,7 +48,9 @@ interface Props {
export function QrPage({ template, id: templateId, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
const { url: backendUrl } = useBackendContext();
+ const { id: instanceId } = useInstanceContext();
const config = useConfigContext();
+ const [setupTOTP, setSetupTOTP] = useState(false);
const [state, setState] = useState<Partial<Entity>>({
amount: template.template_contract.amount,
@@ -82,8 +86,33 @@ export function QrPage({ template, id: templateId, onBack }: Props): VNode {
const payTemplateUri = `${talerProto}//pay-template/${merchantURL.hostname}/${templateId}${paramsStr}`;
+ const issuer = encodeURIComponent(
+ `${new URL(backendUrl).hostname}/${instanceId}`,
+ );
+ const oauthUri = !template.pos_algorithm
+ ? undefined
+ : template.pos_algorithm === 1
+ ? `otpauth://totp/${issuer}:${templateId}?secret=${template.pos_key}&issuer=${issuer}&algorithm=SHA1&digits=8&period=30`
+ : template.pos_algorithm === 2
+ ? `otpauth://totp/${issuer}:${templateId}?secret=${template.pos_key}&issuer=${issuer}&algorithm=SHA1&digits=8&period=30`
+ : undefined;
return (
<div>
+ {oauthUri && (
+ <ConfirmModal
+ description="Setup TOTP"
+ active={setupTOTP}
+ onConfirm={() => {
+ setSetupTOTP(false);
+ }}
+ >
+ <p>Scan this qr code with your TOTP device</p>
+ <QR text={oauthUri} />
+ <pre style={{ textAlign: "center" }}>
+ <a href={oauthUri}>{oauthUri}</a>
+ </pre>
+ </ConfirmModal>
+ )}
<section class="section is-main-section">
<div class="columns">
<div class="column" />
@@ -114,20 +143,48 @@ export function QrPage({ template, id: templateId, onBack }: Props): VNode {
<i18n.Translate>Cancel</i18n.Translate>
</button>
)}
- <button class="button is-info" onClick={onBack}>
+ <button
+ class="button is-info"
+ onClick={() => saveAsPDF(templateId)}
+ >
<i18n.Translate>Print</i18n.Translate>
</button>
+ {oauthUri && (
+ <button
+ class="button is-info"
+ onClick={() => setSetupTOTP(true)}
+ >
+ <i18n.Translate>Setup TOTP</i18n.Translate>
+ </button>
+ )}
</div>
</div>
<div class="column" />
</div>
</section>
- <section>
- <pre>
+ <section id="printThis">
+ <QR text={payTemplateUri} />
+ <pre style={{ textAlign: "center" }}>
<a href={payTemplateUri}>{payTemplateUri}</a>
</pre>
- <QR text={payTemplateUri} />
</section>
</div>
);
}
+
+function saveAsPDF(name: string): void {
+ const printWindow = window.open("", "", "height=400,width=800");
+ if (!printWindow) return;
+ const divContents = document.getElementById("printThis");
+ if (!divContents) return;
+ printWindow.document.write(
+ `<html><head><title>Order template for ${name}</title><style>`,
+ );
+ printWindow.document.write("</style></head><body>&nbsp;</body></html>");
+ printWindow.document.close();
+ printWindow.document.body.appendChild(divContents.cloneNode(true));
+ printWindow.addEventListener("load", () => {
+ printWindow.print();
+ printWindow.close();
+ });
+}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx
index 97d25b700..044cc7d79 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx
@@ -51,10 +51,8 @@ export default function TemplateQrPage({
onNotFound,
onUnauthorized,
}: Props): VNode {
- const { createOrderFromTemplate } = useTemplateAPI();
const result = useTemplateDetails(tid);
const [notif, setNotif] = useState<Notification | undefined>(undefined);
- const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();