From 01b2fbd8a19b837a87c4d3e2f2a9c10f4ef26737 Mon Sep 17 00:00:00 2001 From: TheCreatorNode Date: Mon, 27 Apr 2026 22:21:44 +0100 Subject: [PATCH] feat: add issuer authorization status indicator - Add isAuthorized state to track on-chain authorization - Check authorization status on wallet connect - Show green badge when authorized, red badge when not - Display warning message for unauthorized issuers - Disable form when issuer is not authorized Closes #12 --- frontend/src/pages/IssuerDashboard.jsx | 41 ++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/IssuerDashboard.jsx b/frontend/src/pages/IssuerDashboard.jsx index 9d34a99..71b2e0f 100644 --- a/frontend/src/pages/IssuerDashboard.jsx +++ b/frontend/src/pages/IssuerDashboard.jsx @@ -13,6 +13,10 @@ const styles = { btnDisabled: { padding: '0.7rem', background: '#334155', color: '#64748b', border: 'none', borderRadius: 8, fontSize: '1rem', cursor: 'not-allowed', width: '100%' }, label: { color: '#94a3b8', fontSize: '0.85rem', marginBottom: '0.25rem' }, fieldError: { color: '#f87171', fontSize: '0.78rem', marginTop: '0.25rem' }, + statusBadge: { display: 'inline-flex', alignItems: 'center', gap: '0.5rem', padding: '0.5rem 0.75rem', borderRadius: 6, fontSize: '0.85rem', marginBottom: '1rem' }, + authorized: { background: '#065f46', color: '#10b981', border: '1px solid #10b981' }, + unauthorized: { background: '#7f1d1d', color: '#f87171', border: '1px solid #f87171' }, + warning: { background: '#78350f', color: '#f59e0b', padding: '0.75rem', borderRadius: 8, marginBottom: '1rem', fontSize: '0.9rem' }, }; const STELLAR_ADDRESS_RE = /^G[A-Z2-7]{55}$/; @@ -23,7 +27,7 @@ const EMPTY_FORM = { patient_address: '', vaccine_name: '', date_administered: ' export default function IssuerDashboard() { const { t } = useTranslation(); const { publicKey, role, connect } = useAuth(); - const { issueVaccination, loading } = useVaccination(); + const { issueVaccination, checkIssuerStatus, loading } = useVaccination(); const [form, setForm] = useState(() => { try { @@ -36,6 +40,7 @@ export default function IssuerDashboard() { const [touched, setTouched] = useState({}); const [mintResult, setMintResult] = useState(null); const [confirming, setConfirming] = useState(false); + const [isAuthorized, setIsAuthorized] = useState(null); const validate = (f) => { const errors = {}; @@ -57,6 +62,12 @@ export default function IssuerDashboard() { sessionStorage.setItem(FORM_KEY, JSON.stringify(form)); }, [form]); + useEffect(() => { + if (publicKey && role === 'issuer') { + checkIssuerStatus().then(setIsAuthorized); + } + }, [publicKey, role, checkIssuerStatus]); + if (!publicKey) { return (
@@ -70,6 +81,14 @@ export default function IssuerDashboard() { return

{t('issuer.accessDenied')}

; } + if (isAuthorized === null) { + return ( +
+

Checking authorization status...

+
+ ); + } + const handleSubmit = async (e) => { e.preventDefault(); const result = await issueVaccination(form); @@ -89,6 +108,24 @@ export default function IssuerDashboard() { return (

Issue Vaccination NFT

+ + {isAuthorized ? ( +
+ + Authorized Issuer +
+ ) : ( + <> +
+ + Not Authorized +
+
+ Your wallet is not authorized to issue vaccination records. Contact an administrator to grant issuer permissions. +
+ + )} +
{[ { key: 'patient_address', label: 'Patient Stellar Address', placeholder: 'G...' }, @@ -107,7 +144,7 @@ export default function IssuerDashboard() { />
))} -