mirror of
https://github.com/temetro/temetro.git
synced 2026-07-26 11:58:14 +00:00
frontend: scan a patient's wallet code in Import from a patient app
Adds a Scan button beside the wallet-number field in the import dialog, reusing the BarcodeScanner. A scanned QR or 2D barcode from the patient's wallet app drops the wallet number straight into the field. i18n added to all locales. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Check, Loader2, QrCode, Smartphone, X } from "lucide-react";
|
import { Check, Loader2, QrCode, ScanLine, Smartphone, X } from "lucide-react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import QRCodeSvg from "react-qr-code";
|
import QRCodeSvg from "react-qr-code";
|
||||||
|
|
||||||
import { PatientFormDialog } from "@/components/chat/patient-form-dialog";
|
import { PatientFormDialog } from "@/components/chat/patient-form-dialog";
|
||||||
|
import { BarcodeScanner } from "@/components/scan/barcode-scanner";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -63,6 +64,15 @@ export function ImportFromWalletDialog({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [mode, setMode] = useState<Mode>("number");
|
const [mode, setMode] = useState<Mode>("number");
|
||||||
const [walletNumber, setWalletNumber] = useState("");
|
const [walletNumber, setWalletNumber] = useState("");
|
||||||
|
const [scanOpen, setScanOpen] = useState(false);
|
||||||
|
|
||||||
|
// Scanning the wallet code shown on the patient's phone (QR or 2D barcode)
|
||||||
|
// drops its wallet number straight into the field.
|
||||||
|
const handleScan = (value: string) => {
|
||||||
|
setScanOpen(false);
|
||||||
|
setMode("number");
|
||||||
|
setWalletNumber(value.trim());
|
||||||
|
};
|
||||||
const [temporary, setTemporary] = useState(false);
|
const [temporary, setTemporary] = useState(false);
|
||||||
const [durationHours, setDurationHours] = useState<number>(24);
|
const [durationHours, setDurationHours] = useState<number>(24);
|
||||||
const [phase, setPhase] = useState<Phase>("form");
|
const [phase, setPhase] = useState<Phase>("form");
|
||||||
@@ -302,13 +312,25 @@ export function ImportFromWalletDialog({
|
|||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-muted-foreground">
|
||||||
{t("patients.importApp.walletLabel")}
|
{t("patients.importApp.walletLabel")}
|
||||||
</span>
|
</span>
|
||||||
<Input
|
<div className="flex items-center gap-2">
|
||||||
autoFocus
|
<Input
|
||||||
disabled={phase === "requesting"}
|
autoFocus
|
||||||
onChange={(e) => setWalletNumber(e.target.value)}
|
disabled={phase === "requesting"}
|
||||||
placeholder={t("patients.importApp.walletPlaceholder")}
|
onChange={(e) => setWalletNumber(e.target.value)}
|
||||||
value={walletNumber}
|
placeholder={t("patients.importApp.walletPlaceholder")}
|
||||||
/>
|
value={walletNumber}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
aria-label={t("patients.importApp.scan")}
|
||||||
|
disabled={phase === "requesting"}
|
||||||
|
onClick={() => setScanOpen(true)}
|
||||||
|
size="icon"
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
<ScanLine className="size-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
@@ -411,6 +433,14 @@ export function ImportFromWalletDialog({
|
|||||||
patient={request.draft}
|
patient={request.draft}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
<BarcodeScanner
|
||||||
|
description={t("patients.importApp.scanHint")}
|
||||||
|
onDetected={handleScan}
|
||||||
|
onOpenChange={setScanOpen}
|
||||||
|
open={scanOpen}
|
||||||
|
title={t("patients.importApp.scan")}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,6 +302,8 @@
|
|||||||
"qrCaption": "امسح هذا في تطبيق المريض",
|
"qrCaption": "امسح هذا في تطبيق المريض",
|
||||||
"generateQr": "عرض رمز QR",
|
"generateQr": "عرض رمز QR",
|
||||||
"walletLabel": "رقم محفظة المريض",
|
"walletLabel": "رقم محفظة المريض",
|
||||||
|
"scan": "امسح رمز المريض",
|
||||||
|
"scanHint": "امسح رمز QR أو الباركود الظاهر في تطبيق محفظة المريض.",
|
||||||
"walletPlaceholder": "tmw_…",
|
"walletPlaceholder": "tmw_…",
|
||||||
"tempLabel": "مشاركة مؤقتة",
|
"tempLabel": "مشاركة مؤقتة",
|
||||||
"tempHint": "يُحذف السجل تلقائيًا من هذه العيادة عند انتهاء فترة المشاركة.",
|
"tempHint": "يُحذف السجل تلقائيًا من هذه العيادة عند انتهاء فترة المشاركة.",
|
||||||
|
|||||||
@@ -298,6 +298,8 @@
|
|||||||
"qrCaption": "Dies in der Patienten-App scannen",
|
"qrCaption": "Dies in der Patienten-App scannen",
|
||||||
"generateQr": "QR-Code anzeigen",
|
"generateQr": "QR-Code anzeigen",
|
||||||
"walletLabel": "Patienten-Wallet-Nummer",
|
"walletLabel": "Patienten-Wallet-Nummer",
|
||||||
|
"scan": "Code des Patienten scannen",
|
||||||
|
"scanHint": "Scanne den QR- oder Barcode aus der Wallet-App des Patienten.",
|
||||||
"walletPlaceholder": "tmw_…",
|
"walletPlaceholder": "tmw_…",
|
||||||
"tempLabel": "Temporär teilen",
|
"tempLabel": "Temporär teilen",
|
||||||
"tempHint": "Die Akte wird automatisch aus dieser Klinik gelöscht, wenn das Freigabefenster endet.",
|
"tempHint": "Die Akte wird automatisch aus dieser Klinik gelöscht, wenn das Freigabefenster endet.",
|
||||||
|
|||||||
@@ -298,6 +298,8 @@
|
|||||||
"qrCaption": "Scan this in the patient app",
|
"qrCaption": "Scan this in the patient app",
|
||||||
"generateQr": "Show QR code",
|
"generateQr": "Show QR code",
|
||||||
"walletLabel": "Patient wallet number",
|
"walletLabel": "Patient wallet number",
|
||||||
|
"scan": "Scan patient's code",
|
||||||
|
"scanHint": "Scan the QR or barcode shown in the patient's wallet app.",
|
||||||
"walletPlaceholder": "tmw_…",
|
"walletPlaceholder": "tmw_…",
|
||||||
"tempLabel": "Share temporarily",
|
"tempLabel": "Share temporarily",
|
||||||
"tempHint": "The record is automatically deleted from this clinic when the share window ends.",
|
"tempHint": "The record is automatically deleted from this clinic when the share window ends.",
|
||||||
|
|||||||
@@ -298,6 +298,8 @@
|
|||||||
"qrCaption": "Scannez ceci dans l'application patient",
|
"qrCaption": "Scannez ceci dans l'application patient",
|
||||||
"generateQr": "Afficher le code QR",
|
"generateQr": "Afficher le code QR",
|
||||||
"walletLabel": "Numéro de portefeuille du patient",
|
"walletLabel": "Numéro de portefeuille du patient",
|
||||||
|
"scan": "Scanner le code du patient",
|
||||||
|
"scanHint": "Scannez le QR code ou le code-barres affiché dans l'app portefeuille du patient.",
|
||||||
"walletPlaceholder": "tmw_…",
|
"walletPlaceholder": "tmw_…",
|
||||||
"tempLabel": "Partager temporairement",
|
"tempLabel": "Partager temporairement",
|
||||||
"tempHint": "Le dossier est automatiquement supprimé de cette clinique à la fin de la période de partage.",
|
"tempHint": "Le dossier est automatiquement supprimé de cette clinique à la fin de la période de partage.",
|
||||||
|
|||||||
@@ -298,6 +298,8 @@
|
|||||||
"qrCaption": "Ku sawir tan app-ka bukaanka",
|
"qrCaption": "Ku sawir tan app-ka bukaanka",
|
||||||
"generateQr": "Tus koodhka QR",
|
"generateQr": "Tus koodhka QR",
|
||||||
"walletLabel": "Lambarka wallet-ka bukaanka",
|
"walletLabel": "Lambarka wallet-ka bukaanka",
|
||||||
|
"scan": "Iskaan garee koodhka bukaanka",
|
||||||
|
"scanHint": "Iskaan garee koodhka QR ama barcode ee ka muuqda abka wallet-ka bukaanka.",
|
||||||
"walletPlaceholder": "tmw_…",
|
"walletPlaceholder": "tmw_…",
|
||||||
"tempLabel": "Wadaag si ku meel gaar ah",
|
"tempLabel": "Wadaag si ku meel gaar ah",
|
||||||
"tempHint": "Diiwaanka si toos ah ayaa looga tirtirayaa rugtan marka daaqadda wadaagista dhammaato.",
|
"tempHint": "Diiwaanka si toos ah ayaa looga tirtirayaa rugtan marka daaqadda wadaagista dhammaato.",
|
||||||
|
|||||||
Reference in New Issue
Block a user