const { useState, useEffect, useRef } = React; const API_BASE = '/api/v1/medical-store/'; // Detect store slug from URL (e.g. /MedicalStore/storeA or /app/medical-store/storeB) function getInitialStoreSlug() { if (window.INITIAL_STORE_SLUG) { return window.INITIAL_STORE_SLUG; } const path = window.location.pathname; const match = path.match(/(?:MedicalStore|app\/medical-store)\/([a-zA-Z0-9_\-]+)/i); return match ? match[1] : null; } // ========================================================================= // ROOT ERROR BOUNDARY // ========================================================================= class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error) { return { hasError: true, error }; } componentDidCatch(error, errorInfo) { console.error("Medical Store UI Error:", error, errorInfo); } render() { if (this.state.hasError) { return (

Counter Desk Interruption

{this.state.error?.message || 'An unexpected error occurred while rendering the counter desk.'}

); } return this.props.children; } } function App() { const [stores, setStores] = useState([]); const [activeStoreId, setActiveStoreId] = useState(null); const [activeTab, setActiveTab] = useState('pos'); // pos, inventory, purchase, transfer, ledgers, settings const [notification, setNotification] = useState(null); const [isLoadingStores, setIsLoadingStores] = useState(true); // Machine Authorization State const [isDeviceAuthorized, setIsDeviceAuthorized] = useState(false); const [deviceToken, setDeviceToken] = useState(''); const [machineName, setMachineName] = useState('Counter PC ' + (navigator.platform || 'Desktop')); const [secKeyInput, setSecKeyInput] = useState(''); const [verifyMethod, setVerifyMethod] = useState('key'); // 'key' or 'otp' const [isVerifying, setIsVerifying] = useState(false); const storeSlugFromUrl = getInitialStoreSlug(); // Active Store Object const activeStore = stores.find(s => s.store_id == activeStoreId) || stores[0] || null; useEffect(() => { fetchStores(); }, []); useEffect(() => { if (activeStore) { checkMachineAuthorization(activeStore.store_id); } }, [activeStoreId, stores]); const fetchStores = async () => { setIsLoadingStores(true); try { const url = storeSlugFromUrl ? `${API_BASE}stores?slug=${encodeURIComponent(storeSlugFromUrl)}` : `${API_BASE}stores`; const res = await fetch(url); const data = await res.json(); if (data.status && data.stores && data.stores.length > 0) { setStores(data.stores); // If slug matched specific store, select it (case-insensitive) if (storeSlugFromUrl) { const matched = data.stores.find(s => (s.store_slug && s.store_slug.toLowerCase() === storeSlugFromUrl.toLowerCase()) || (s.store_code && s.store_code.toLowerCase() === storeSlugFromUrl.toLowerCase()) ); if (matched) { setActiveStoreId(matched.store_id); return; } } if (!activeStoreId) { setActiveStoreId(data.stores[0].store_id); } } } catch (e) { console.error('Failed to load stores:', e); } finally { setIsLoadingStores(false); } }; const checkMachineAuthorization = async (storeId) => { const savedToken = localStorage.getItem('mst_device_token_' + storeId); if (!savedToken) { setIsDeviceAuthorized(false); return; } try { const res = await fetch(API_BASE + 'device/check', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ store_id: storeId, device_token: savedToken }) }); const data = await res.json(); if (data.status && data.authorized) { setIsDeviceAuthorized(true); setDeviceToken(savedToken); if (data.machine_name) setMachineName(data.machine_name); } else { localStorage.removeItem('mst_device_token_' + storeId); setIsDeviceAuthorized(false); } } catch (e) { console.error('Device authorization check error:', e); } }; const submitDeviceVerification = async (e) => { e.preventDefault(); if (!activeStore || !secKeyInput) return; setIsVerifying(true); try { const payload = { store_id: activeStore.store_id, store_slug: activeStore.store_slug, machine_name: machineName, security_key: verifyMethod === 'key' ? secKeyInput : '', otp: verifyMethod === 'otp' ? secKeyInput : '' }; const res = await fetch(API_BASE + 'device/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const data = await res.json(); if (data.status && data.device_token) { localStorage.setItem('mst_device_token_' + activeStore.store_id, data.device_token); setDeviceToken(data.device_token); setIsDeviceAuthorized(true); notify(data.message, 'success'); } else { alert(data.message || 'Verification failed. Please check with HMS Admin.'); } } catch (e) { alert('Verification request failed: ' + e.message); } finally { setIsVerifying(false); } }; const notify = (msg, type = 'success') => { setNotification({ msg, type }); setTimeout(() => setNotification(null), 4000); }; if (isLoadingStores && !activeStore) { return (
Loading Store Counter...
HMS Multi-Building Medical Store

Synchronizing pharmacy counters, terminal licenses & ABDM...

); } if (!activeStore) { return (

Medical Store Not Found

Could not locate any active pharmacy store counter for /{storeSlugFromUrl || 'default'}. Please verify store configuration in HMS Admin.

Try Main Store (storeA) Open HMS Store Settings
); } return (
{/* Machine Lock Screen Modal if PC is not verified */} {!isDeviceAuthorized && activeStore && (
Terminal Machine Verification
Counter Authorization Required
{activeStore.store_name}
{activeStore.building_name || 'Main Hospital'} • {activeStore.floor_no || 'Ground Floor'} Link: MedicalStore/{activeStore.store_slug}

This computer terminal is accessing the counter for the first time. Please enter the Security Key or 6-digit OTP provided by HMS Admin.

setMachineName(e.target.value)} required />
setSecKeyInput(e.target.value)} required />
)} {/* Top Store Header */}
{activeStore ? activeStore.store_name : 'Medical Store Counter'}
{activeStore && ( /{activeStore.store_slug || activeStore.store_code} )}
{activeStore ? `${activeStore.building_name || 'Main Building'} • ${activeStore.floor_no || 'Ground Floor'}` : 'Counter'}
{/* Active Store Statutory License Badges */} {activeStore && (
{activeStore.abdm_hfr_id && ( HFR: {activeStore.abdm_hfr_id} )} DL 20B: {activeStore.drug_license_no_20b || 'N/A'} DL 21B: {activeStore.drug_license_no_21b || 'N/A'} GSTIN: {activeStore.gstin || 'N/A'} {isDeviceAuthorized && ( Terminal Verified )}
)} {/* Store Selector & Exit */}
{/* Notification Alert Banner */} {notification && (
{notification.msg}
)} {/* Main Navigation Tabs */} {/* Main View Container */}
{activeTab === 'pos' && } {activeTab === 'inventory' && } {activeTab === 'purchase' && } {activeTab === 'transfer' && } {activeTab === 'ledgers' && } {activeTab === 'settings' && }
); } // ========================================================================= // 1. POS BILLING & DISPENSING COUNTER (MULTI-PRINT: A4, A5, 80mm THERMAL) // ========================================================================= function PosCounter({ store, notify }) { if (!store) { return (
Loading counter desk...
); } const [patientQuery, setPatientQuery] = useState(''); const [patientResults, setPatientResults] = useState([]); const [selectedPatient, setSelectedPatient] = useState(null); const [patientType, setPatientType] = useState('Walk-in'); // Walk-in, OPD, IPD const [walkinAbhaId, setWalkinAbhaId] = useState(''); const [walkinAbhaAddress, setWalkinAbhaAddress] = useState(''); const [showFhirModal, setShowFhirModal] = useState(false); const [fhirBundleData, setFhirBundleData] = useState(null); const [isLoadingFhir, setIsLoadingFhir] = useState(false); const [copiedFhir, setCopiedFhir] = useState(false); const [doctorName, setDoctorName] = useState(''); const [doctorRegNo, setDoctorRegNo] = useState(''); const [itemQuery, setItemQuery] = useState(''); const [itemResults, setItemResults] = useState([]); const [isSearchingItems, setIsSearchingItems] = useState(false); const [cart, setCart] = useState([]); const [wholeDiscountType, setWholeDiscountType] = useState('pct'); // 'pct' or 'val' const [wholeDiscountVal, setWholeDiscountVal] = useState(0); const [paymentMode, setPaymentMode] = useState('Cash'); // Cash, UPI, Card, Mixed, IPD_Credit const [paymentRef, setPaymentRef] = useState(''); const [lastInvoice, setLastInvoice] = useState(null); const [printFormat, setPrintFormat] = useState('thermal'); // 'thermal', 'a5', 'a4' const [isProcessing, setIsProcessing] = useState(false); // Search patient const searchPatients = async (val) => { setPatientQuery(val); if (val.length < 2) { setPatientResults([]); return; } try { const res = await fetch(API_BASE + `patient/search?q=${encodeURIComponent(val)}`); const data = await res.json(); if (data.status) { setPatientResults(data.patients || []); } } catch (e) { console.error(e); } }; const selectPatient = (pt) => { setSelectedPatient(pt); setPatientResults([]); setPatientQuery(pt.full_name + ' (' + pt.uhid + ')'); setWalkinAbhaId(pt.abha_id || ''); setWalkinAbhaAddress(pt.abha_address || ''); if (pt.has_active_ipd && pt.active_ipd) { setPatientType('IPD'); setDoctorName(pt.active_ipd.doctor_name || ''); setPrintFormat('a4'); // Default IPD bills to A4 } else if (pt.has_active_opd && pt.active_opd) { setPatientType('OPD'); setDoctorName(pt.active_opd.doctor_name || ''); setPrintFormat('a5'); // Default OPD bills to A5 } else { setPatientType('Walk-in'); setPrintFormat('thermal'); // Default walkin to Thermal } }; const resetPatient = () => { setSelectedPatient(null); setPatientQuery(''); setPatientType('Walk-in'); setDoctorName(''); setDoctorRegNo(''); setWalkinAbhaId(''); setWalkinAbhaAddress(''); setPrintFormat('thermal'); }; const viewAbdmBundle = async (saleId) => { setIsLoadingFhir(true); setShowFhirModal(true); setCopiedFhir(false); try { const res = await fetch(API_BASE + `abdm/bundle/${saleId}`); const data = await res.json(); if (data.status) { setFhirBundleData(data); } else { notify(data.message || 'Unable to retrieve ABDM FHIR bundle', 'error'); setShowFhirModal(false); } } catch (e) { notify('FHIR Fetch error: ' + e.message, 'error'); setShowFhirModal(false); } finally { setIsLoadingFhir(false); } }; const copyFhirToClipboard = () => { if (!fhirBundleData?.bundle) return; navigator.clipboard.writeText(JSON.stringify(fhirBundleData.bundle, null, 2)); setCopiedFhir(true); setTimeout(() => setCopiedFhir(false), 2500); }; // 1-Click Load Doctor Rx const loadDoctorPrescription = async () => { if (!selectedPatient) return; const encType = selectedPatient.has_active_ipd ? 'ipd' : (selectedPatient.has_active_opd ? 'opd' : null); const encId = selectedPatient.has_active_ipd ? selectedPatient.active_ipd.ipd_id : (selectedPatient.has_active_opd ? selectedPatient.active_opd.opd_id : null); if (!encType || !encId) { notify('No active OPD or IPD prescription found for this patient.', 'error'); return; } try { const res = await fetch(API_BASE + `patient/prescription/${encType}/${encId}`); const data = await res.json(); if (data.status && data.medicines && data.medicines.length > 0) { let addedCount = 0; for (const med of data.medicines) { const sRes = await fetch(API_BASE + `items/search?store_id=${store.store_id}&q=${encodeURIComponent(med.medicine_name)}`); const sData = await sRes.json(); if (sData.status && sData.items && sData.items.length > 0) { const matchedItem = sData.items[0]; if (matchedItem.fefo_batch) { addItemToCart(matchedItem, matchedItem.fefo_batch, med.prescribed_qty || 10); addedCount++; } } } notify(`Imported ${addedCount} prescribed medicines into cart!`, 'success'); } else { notify('No electronic medicines found for this visit.', 'error'); } } catch (e) { notify('Failed to load prescription: ' + e.message, 'error'); } }; // Search Items in Store const searchItems = async (val) => { setItemQuery(val); if (val.length < 2) { setItemResults([]); return; } setIsSearchingItems(true); try { const res = await fetch(API_BASE + `items/search?store_id=${store.store_id}&q=${encodeURIComponent(val)}`); const data = await res.json(); if (data.status) { setItemResults(data.items || []); } } catch (e) { console.error(e); } finally { setIsSearchingItems(false); } }; const addItemToCart = (item, batch, qty = 1) => { if (!batch) { notify('No active batch available for ' + item.item_name, 'error'); return; } if (batch.is_expired) { notify(`STATUTORY BLOCK: Batch ${batch.batch_no} is expired! Cannot be sold.`, 'error'); return; } const existingIdx = cart.findIndex(c => c.item_id === item.item_id && c.batch_id === batch.batch_id); if (existingIdx >= 0) { const updated = [...cart]; updated[existingIdx].qty += qty; setCart(updated); } else { setCart([...cart, { item_id: item.item_id, item_name: item.item_name, generic_name: item.generic_name, unit_pack: item.unit_pack, drug_schedule: item.drug_schedule, hsn_code: item.hsn_code || '3004', gst_rate: batch.gst_rate || 12.0, batch_id: batch.batch_id, batch_no: batch.batch_no, expiry_display: batch.expiry_display, expiry_date: batch.expiry_date, current_qty: batch.current_qty, unit_mrp: batch.mrp, discount_type: 'pct', discount_val: 0, qty: qty }]); } setItemResults([]); setItemQuery(''); // Auto-suggest format based on item count if (cart.length + 1 > 5 && printFormat === 'thermal') { setPrintFormat('a5'); } }; const getItemDiscount = (it) => { const lineGross = (Number(it.qty) || 0) * (Number(it.unit_mrp) || 0); const val = Number(it.discount_val) || 0; if (val <= 0) return 0; if (it.discount_type === 'val') { return Math.min(lineGross, val); } else { const pct = Math.min(100, Math.max(0, val)); return (lineGross * pct) / 100; } }; const toggleItemDiscType = (idx) => { const updated = [...cart]; const it = updated[idx]; const lineGross = (Number(it.qty) || 0) * (Number(it.unit_mrp) || 0); const currentDisc = getItemDiscount(it); if (it.discount_type === 'val') { it.discount_type = 'pct'; it.discount_val = lineGross > 0 ? Number(((currentDisc / lineGross) * 100).toFixed(1)) : 0; } else { it.discount_type = 'val'; it.discount_val = Math.round(currentDisc); } setCart(updated); }; const updateCartItem = (idx, field, val) => { const updated = [...cart]; if (field === 'discount_type') { updated[idx][field] = val; } else { updated[idx][field] = Number(val); } setCart(updated); }; const removeCartItem = (idx) => { setCart(cart.filter((_, i) => i !== idx)); }; // Calculate totals with whole bill discount const grossTotal = cart.reduce((acc, it) => acc + ((Number(it.qty) || 0) * (Number(it.unit_mrp) || 0)), 0); const itemDiscountTotal = cart.reduce((acc, it) => acc + getItemDiscount(it), 0); const balanceAfterItemDisc = Math.max(0, grossTotal - itemDiscountTotal); let wholeDiscountAmt = 0; const numWholeDisc = Number(wholeDiscountVal) || 0; if (numWholeDisc > 0) { if (wholeDiscountType === 'val') { wholeDiscountAmt = Math.min(balanceAfterItemDisc, numWholeDisc); } else { const pct = Math.min(100, Math.max(0, numWholeDisc)); wholeDiscountAmt = (balanceAfterItemDisc * pct) / 100; } } const discountTotal = itemDiscountTotal + wholeDiscountAmt; const netBeforeRound = Math.max(0, grossTotal - discountTotal); const netPayable = Math.round(netBeforeRound); const roundOff = (netPayable - netBeforeRound).toFixed(2); // Save and print sale const processSale = async () => { if (cart.length === 0) { notify('Cart is empty!', 'error'); return; } if (paymentMode === 'IPD_Credit' && (!selectedPatient || !selectedPatient.has_active_ipd)) { notify('IPD Credit mode is only allowed for admitted IPD patients.', 'error'); return; } setIsProcessing(true); const payload = { store_id: store.store_id, patient_type: patientType, uhid: selectedPatient ? selectedPatient.uhid : null, patient_id: selectedPatient ? selectedPatient.patient_id : null, opd_id: selectedPatient && selectedPatient.active_opd ? selectedPatient.active_opd.opd_id : null, ipd_id: selectedPatient && selectedPatient.active_ipd ? selectedPatient.active_ipd.ipd_id : null, patient_name: selectedPatient ? selectedPatient.full_name : (patientQuery || 'Walk-in Customer'), patient_mobile: selectedPatient ? selectedPatient.mobile : '', patient_address: selectedPatient ? selectedPatient.address : '', abha_id: selectedPatient?.abha_id || walkinAbhaId || null, abha_address: selectedPatient?.abha_address || walkinAbhaAddress || null, age: selectedPatient ? selectedPatient.age : '', gender: selectedPatient ? selectedPatient.gender : '', doctor_name: doctorName || (selectedPatient?.active_opd?.doctor_name || selectedPatient?.active_ipd?.doctor_name || 'Dr. Consultant'), doctor_reg_no: doctorRegNo, payment_mode: paymentMode, payment_reference: paymentRef, whole_discount_type: wholeDiscountType, whole_discount_val: Number(wholeDiscountVal) || 0, items: cart.map(it => { const lineGross = (Number(it.qty) || 0) * (Number(it.unit_mrp) || 0); const lineDisc = getItemDiscount(it); const discPct = lineGross > 0 ? Number(((lineDisc / lineGross) * 100).toFixed(2)) : 0; return { item_id: it.item_id, batch_id: it.batch_id, qty: Number(it.qty) || 1, discount_type: it.discount_type || 'pct', discount_val: Number(it.discount_val) || 0, discount_pct: discPct, discount_amount: lineDisc }; }) }; try { const res = await fetch(API_BASE + 'sales/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const data = await res.json(); if (data.status) { notify(`Invoice ${data.invoice_no} generated successfully! Amount: ₹${data.net_amount}`, 'success'); fetchInvoiceDetails(data.sale_id); setCart([]); setWholeDiscountVal(0); resetPatient(); } else { notify(data.message || 'Failed to complete sale.', 'error'); } } catch (e) { notify('Sale error: ' + e.message, 'error'); } finally { setIsProcessing(false); } }; const fetchInvoiceDetails = async (saleId) => { try { const res = await fetch(API_BASE + `sales/invoice/${saleId}`); const data = await res.json(); if (data.status) { setLastInvoice(data); } } catch (e) { console.error(e); } }; return (
{/* Left Column: Patient Selector & Cart Grid */}
{/* Patient Information Panel */}
Patient & Prescription {patientType}
{selectedPatient && (
{(selectedPatient.has_active_opd || selectedPatient.has_active_ipd) && ( )}
)}
searchPatients(e.target.value)} />
{/* Patient Search Results Dropdown */} {patientResults.length > 0 && (
{patientResults.map(p => (
selectPatient(p)}>
{p.full_name} ({p.uhid}) {(p.abha_id || p.abha_address) && ( ABHA: {p.abha_id || p.abha_address} )}
{p.mobile || 'No Mobile'} • {p.gender} • {p.age}
{p.has_active_ipd && IPD Admitted: {p.active_ipd.bed_info?.bed_no || 'Bed'}} {p.has_active_opd && OPD Visit Today}
))}
)}
setDoctorName(e.target.value)} />
{/* ABDM ABHA ID & Address Quick-Link Row */}
ABHA No setWalkinAbhaId(e.target.value)} />
ABHA Address setWalkinAbhaAddress(e.target.value)} />
{/* Patient Context Tags */} {selectedPatient && (
Name: {selectedPatient.full_name} UHID: {selectedPatient.uhid} Gender/Age: {selectedPatient.gender}, {selectedPatient.age} {(selectedPatient.abha_id || selectedPatient.abha_address) && ( ABDM Linked: {selectedPatient.abha_id || ''} {selectedPatient.abha_address ? `(${selectedPatient.abha_address})` : ''} )} {selectedPatient.has_active_ipd && ( {selectedPatient.active_ipd.bed_info?.ward_name || 'Ward'} / {selectedPatient.active_ipd.bed_info?.bed_no || 'Bed'} (Dr. {selectedPatient.active_ipd.doctor_name}) )} {selectedPatient.has_active_opd && !selectedPatient.has_active_ipd && ( OPD Dr. {selectedPatient.active_opd.doctor_name} )}
)}
{/* Medicine Search & Barcode Scanner Line */}
Medicine Lookup & Barcode Dispenser
searchItems(e.target.value)} /> {isSearchingItems && }
{/* Item & FEFO Batch Dropdown */} {itemResults.length > 0 && (
{itemResults.map(it => (
{it.item_name} {it.unit_pack} {it.drug_schedule && it.drug_schedule !== 'OTC' && ( {it.drug_schedule} )}
Total Stock: {it.total_stock}
{it.generic_name} • HSN: {it.hsn_code} {/* Batches Table */} {it.batches && it.batches.length > 0 ? (
{it.batches.map(b => ( ))}
) : ( Out of Stock in this Counter )}
))}
)}
{/* Billing Cart Table */}
Dispensing Cart ({cart.length} items)
{cart.length > 0 && ( )}
{cart.length === 0 ? ( ) : ( cart.map((it, idx) => { const lineGross = (Number(it.qty) || 0) * (Number(it.unit_mrp) || 0); const lineDisc = getItemDiscount(it); const lineNet = Math.max(0, lineGross - lineDisc).toFixed(2); return ( ); }) )}
# Medicine Name Batch / Exp Qty MRP (₹) Disc (% / ₹) GST% Total (₹)
Scan barcode or search medicine to add items to bill.
{idx + 1}
{it.item_name}
{it.generic_name} • HSN: {it.hsn_code}
{it.batch_no}
Exp: {it.expiry_display}
updateCartItem(idx, 'qty', e.target.value)} /> ₹{it.unit_mrp}
updateCartItem(idx, 'discount_val', e.target.value)} />
{lineDisc > 0 && (
{it.discount_type === 'pct' ? `-₹${lineDisc.toFixed(2)}` : `${(lineGross > 0 ? ((lineDisc / lineGross) * 100).toFixed(1) : 0)}% off`}
)}
{it.gst_rate}% ₹{lineNet}
{/* Right Column: Checkout, Totals & Multi-Format Printing */}
Checkout Desk {store?.store_code || ''}
{/* Whole Bill Discount Controller */}
{wholeDiscountType === 'pct' ? '%' : '₹'} setWholeDiscountVal(e.target.value)} /> {Number(wholeDiscountVal) > 0 && ( )}
{/* Quick Preset Buttons */}
Presets: {wholeDiscountType === 'pct' ? ( [5, 10, 15, 20].map(p => ( )) ) : ( [20, 50, 100, 200].map(v => ( )) )} {Number(wholeDiscountVal) > 0 && ( )}
{/* Breakdown */}
Gross Items Total: ₹{grossTotal.toFixed(2)}
{itemDiscountTotal > 0 && (
Item-Level Discounts: -₹{itemDiscountTotal.toFixed(2)}
)} {wholeDiscountAmt > 0 && (
Whole Bill Discount ({wholeDiscountType === 'pct' ? `${wholeDiscountVal}%` : `₹${wholeDiscountVal}`}): -₹{wholeDiscountAmt.toFixed(2)}
)}
Total Discounts: -₹{discountTotal.toFixed(2)}
Round Off: ₹{roundOff}

Net Payable: ₹{netPayable.toLocaleString('en-IN')}
{/* Payment Mode Selection */}
{paymentMode === 'IPD_Credit' && (
Medicines will be charged directly to the patient's IPD Hospital Account and settled at discharge.
)} {paymentMode === 'UPI' && store?.upi_id && (
Store UPI VPA: {store?.upi_id}
)} {/* Print Format Selector */}
{/* Print Preview Component for Thermal 80mm, A5, and A4 */} {lastInvoice && (
Bill: {lastInvoice.sale.invoice_no} {lastInvoice.sale.abdm_care_context_ref && ( {lastInvoice.sale.abdm_care_context_ref} )}
{/* Format 1: 80mm Thermal Slip (Single or 1-5 Items) */} {printFormat === 'thermal' && (
{lastInvoice.sale.store_name}
{lastInvoice.sale.building_name}, {lastInvoice.sale.floor_no}
{lastInvoice.sale.abdm_hfr_id && (
HFR ID: {lastInvoice.sale.abdm_hfr_id}
)}
DL 20B: {lastInvoice.sale.drug_license_no_20b}
DL 21B: {lastInvoice.sale.drug_license_no_21b}
GSTIN: {lastInvoice.sale.gstin}

Bill No: {lastInvoice.sale.invoice_no}
Date: {lastInvoice.sale.sale_date}
Patient: {lastInvoice.sale.patient_name} {lastInvoice.sale.uhid ? `(${lastInvoice.sale.uhid})` : ''}
{(lastInvoice.sale.abha_id || lastInvoice.sale.abha_address) && (
ABHA: {lastInvoice.sale.abha_id || ''} {lastInvoice.sale.abha_address ? `(${lastInvoice.sale.abha_address})` : ''}
)} {lastInvoice.sale.abdm_care_context_ref && (
Care Context: {lastInvoice.sale.abdm_care_context_ref}
)}
Doctor: {lastInvoice.sale.doctor_name}

{lastInvoice.items.map((it, i) => ( ))}
Item Batch Qty Total
{it.item_name} {it.batch_no} {it.qty} ₹{it.total_amount}

Gross Total: ₹{lastInvoice.sale.gross_amount}
{Number(lastInvoice.sale.discount_amount) > 0 && (
Total Discount: -₹{lastInvoice.sale.discount_amount}
)}
NET AMOUNT: ₹{lastInvoice.sale.net_amount}
Mode: {lastInvoice.sale.payment_mode}
R.Ph: {lastInvoice.sale.registered_pharmacist_name || 'Pharmacist'} {lastInvoice.sale.pharmacist_hpr_id ? `(HPR: ${lastInvoice.sale.pharmacist_hpr_id})` : ''}
{lastInvoice.sale.terms_conditions || 'Thank you! Get well soon.'}
)} {/* Format 2: A5 Half-Page Invoice (Normal OPD/Walk-in) */} {printFormat === 'a5' && (
{lastInvoice.sale.store_name}
{lastInvoice.sale.building_name}, {lastInvoice.sale.floor_no}, {lastInvoice.sale.store_address}
DL 20B: {lastInvoice.sale.drug_license_no_20b} | DL 21B: {lastInvoice.sale.drug_license_no_21b} {lastInvoice.sale.abdm_hfr_id && | HFR ID: {lastInvoice.sale.abdm_hfr_id}}
GSTIN: {lastInvoice.sale.gstin} | Phone: {lastInvoice.sale.contact_phone}
RETAIL TAX INVOICE
{lastInvoice.sale.invoice_no}
{lastInvoice.sale.sale_date}
Patient: {lastInvoice.sale.patient_name} {lastInvoice.sale.uhid ? `(${lastInvoice.sale.uhid})` : ''}
Prescribed By: {lastInvoice.sale.doctor_name}
Age/Gender: {lastInvoice.sale.age || 'N/A'} / {lastInvoice.sale.gender || 'N/A'}
Payment Mode: {lastInvoice.sale.payment_mode}
{(lastInvoice.sale.abha_id || lastInvoice.sale.abha_address) && (
ABHA: {lastInvoice.sale.abha_id || 'N/A'} ({lastInvoice.sale.abha_address || 'N/A'}) {lastInvoice.sale.abdm_care_context_ref && | Care Context: {lastInvoice.sale.abdm_care_context_ref}}
)}
{lastInvoice.items.map((it, i) => ( ))}
# Medicine Name HSN Batch Exp Qty MRP (₹) Amount (₹)
{i + 1} {it.item_name} {it.snomed_ct_code &&
SNOMED: {it.snomed_ct_code}
}
{it.hsn_code} {it.batch_no} {it.expiry_date.substring(0,7)} {it.qty} ₹{it.unit_mrp} ₹{it.total_amount}
R.Ph: {lastInvoice.sale.registered_pharmacist_name || 'Pharmacist'} ({lastInvoice.sale.pharmacist_reg_no}) {lastInvoice.sale.pharmacist_hpr_id && | HPR ID: {lastInvoice.sale.pharmacist_hpr_id}}
Gross: ₹{lastInvoice.sale.gross_amount} {Number(lastInvoice.sale.discount_amount) > 0 && ( Disc: -₹{lastInvoice.sale.discount_amount} )}
TOTAL: ₹{lastInvoice.sale.net_amount}
)} {/* Format 3: A4 Comprehensive Hospital Tax Invoice (IPD & Large Bills) */} {printFormat === 'a4' && (

{lastInvoice.sale.store_name}

{lastInvoice.sale.building_name}, {lastInvoice.sale.floor_no}, {lastInvoice.sale.store_address}
Drug License 20-B: {lastInvoice.sale.drug_license_no_20b} | 21-B: {lastInvoice.sale.drug_license_no_21b} | FSSAI: {lastInvoice.sale.fssai_no || 'N/A'}
GSTIN: {lastInvoice.sale.gstin} | State: {lastInvoice.sale.state_name} (Code: {lastInvoice.sale.state_code}) {lastInvoice.sale.abdm_hfr_id && | ABDM HFR Facility ID: {lastInvoice.sale.abdm_hfr_id}}
HOSPITAL GST TAX INVOICE
{lastInvoice.sale.invoice_no}
Date & Time: {lastInvoice.sale.sale_date}
{/* Patient & Hospital Admission Info */}
Patient Name: {lastInvoice.sale.patient_name}
UHID No: {lastInvoice.sale.uhid || 'Walk-in'}
Phone: {lastInvoice.sale.patient_mobile || 'N/A'}
Age / Gender: {lastInvoice.sale.age || 'N/A'} / {lastInvoice.sale.gender || 'N/A'}
Consultant Doctor: {lastInvoice.sale.doctor_name}
Doctor Reg No: {lastInvoice.sale.doctor_reg_no || 'N/A'}
{(lastInvoice.sale.abha_id || lastInvoice.sale.abha_address) && (
ABDM Linked: ABHA Number: {lastInvoice.sale.abha_id || 'N/A'} | ABHA Address: {lastInvoice.sale.abha_address || 'N/A'} | Care Context: {lastInvoice.sale.abdm_care_context_ref || 'N/A'}
)} {lastInvoice.sale.ipd_id && (
IPD Admission #{lastInvoice.sale.ipd_id} • Ward: {lastInvoice.sale.ward_name || 'General'} • Bed: {lastInvoice.sale.bed_no || 'Bed'} (Charged to IPD Running Bill)
)}
{/* Items Table */} {lastInvoice.items.map((it, i) => ( ))}
# Medicine & Formulation HSN Batch No Exp Date Qty MRP (₹) Taxable (₹) CGST (₹) SGST (₹) Total (₹)
{i + 1} {it.item_name} {it.snomed_ct_code && (
SNOMED-CT: {it.snomed_ct_code} ({it.snomed_display || ''})
)}
{it.hsn_code} {it.batch_no} {it.expiry_date} {it.qty} ₹{it.unit_mrp} ₹{it.taxable_value} ₹{it.cgst_amount} ₹{it.sgst_amount} ₹{it.total_amount}
{/* HSN Summary Table */} {lastInvoice.hsn_summary && lastInvoice.hsn_summary.length > 0 && (
{lastInvoice.hsn_summary.map((h, idx) => ( ))}
HSN Code GST Rate Taxable Value (₹) CGST (₹) SGST (₹) Total Tax (₹)
{h.hsn_code} {h.gst_rate}% ₹{h.taxable_value.toFixed(2)} ₹{h.cgst_amount.toFixed(2)} ₹{h.sgst_amount.toFixed(2)} ₹{h.total_tax.toFixed(2)}
)} {/* Summary Totals & Signatures */}
Registered Pharmacist: {lastInvoice.sale.registered_pharmacist_name || 'Pharmacist'} (Reg No: {lastInvoice.sale.pharmacist_reg_no || 'N/A'}) {lastInvoice.sale.pharmacist_hpr_id && | HPR ID: {lastInvoice.sale.pharmacist_hpr_id}} {lastInvoice.sale.terms_conditions || '1. Goods once sold are returnable only as per Drug Rules.\n2. Store medicines below 25°C.'}
Gross Items Total: ₹{lastInvoice.sale.gross_amount}
{Number(lastInvoice.sale.discount_amount) > 0 && (
Total Discounts Allowed: -₹{lastInvoice.sale.discount_amount}
)}
Taxable Amount: ₹{lastInvoice.sale.taxable_amount}
CGST Amount: ₹{lastInvoice.sale.cgst_amount}
SGST Amount: ₹{lastInvoice.sale.sgst_amount}
Round Off: ₹{lastInvoice.sale.round_off}
GRAND TOTAL: ₹{lastInvoice.sale.net_amount}
)}
)} {/* ABDM FHIR R4 Bundle Modal */} {showFhirModal && (
ABDM NRCES FHIR R4 MedicationDispense Document
Profile: MedicationDispenseDocument | LOINC: 60590-7
{isLoadingFhir ? (
Retrieving & Validating ABDM FHIR R4 Bundle...
) : fhirBundleData ? (
Care Context Reference {fhirBundleData.care_context_ref}
ABHA Number / Address {fhirBundleData.abha_id || fhirBundleData.abha_address || 'Not ABHA Linked'}
Gateway Sync Status {fhirBundleData.sync_status || 'QUEUED_FOR_BRIDGE'}
NRCES FHIR R4 Document Bundle (JSON):
                                                {JSON.stringify(fhirBundleData.bundle, null, 2)}
                                            
) : (
No FHIR bundle data found.
)}
Includes SNOMED-CT clinical codes, HFR Facility ID, and Practitioner HPR ID.
)}
); } // ========================================================================= // 2. LIVE INVENTORY & BATCH MATRIX VIEW // ========================================================================= function InventoryView({ store, notify }) { if (!store) return null; const [stock, setStock] = useState([]); const [summary, setSummary] = useState({}); const [filter, setFilter] = useState('all'); const [searchTerm, setSearchTerm] = useState(''); const [loading, setLoading] = useState(false); useEffect(() => { if (store?.store_id) { loadStock(); } }, [store?.store_id, filter]); const loadStock = async () => { setLoading(true); try { const res = await fetch(API_BASE + `stock/list?store_id=${store.store_id}&filter=${filter}`); const data = await res.json(); if (data.status) { setStock(data.stock || []); setSummary(data.summary || {}); } } catch (e) { console.error(e); } finally { setLoading(false); } }; const filteredStock = stock.filter(s => s.item_name.toLowerCase().includes(searchTerm.toLowerCase()) || (s.generic_name && s.generic_name.toLowerCase().includes(searchTerm.toLowerCase())) || s.batch_no.toLowerCase().includes(searchTerm.toLowerCase()) ); return (
{/* KPI Summary Cards */}
Total Batches in Store

{summary.total_rows || 0}

Stock Cost Valuation (PTR)

₹{(summary.total_cost_valuation || 0).toLocaleString('en-IN')}

Stock Retail Valuation (MRP)

₹{(summary.total_mrp_valuation || 0).toLocaleString('en-IN')}

Counter / URL
MedicalStore/{store.store_slug}
{/* Filter Tabs & Search Bar */}
setSearchTerm(e.target.value)} />
{/* Stock Table */}
{loading ? ( ) : filteredStock.length === 0 ? ( ) : ( filteredStock.map((s, idx) => ( )) )}
# Item & Generic Molecule Category Batch No Expiry Current Qty PTR (₹) MRP (₹) Cost Value (₹) Status
Loading inventory...
No stock records found.
{idx + 1}
{s.item_name}
{s.generic_name} • HSN: {s.hsn_code}
{s.category} {s.batch_no} {s.expiry_display} {s.current_qty} ₹{s.ptr} ₹{s.mrp} ₹{s.cost_valuation} {s.is_expired ? ( EXPIRED ) : s.is_near_expiry ? ( Near Expiry ) : ( Good Stock )}
); } // ========================================================================= // 3. INWARD PURCHASES, SUPPLIERS & MARG ERP IMPORT // ========================================================================= function PurchaseView({ store, notify }) { if (!store) return null; const [subTab, setSubTab] = useState('inward'); // inward, marg, suppliers const [suppliers, setSuppliers] = useState([]); const [selectedSupplierId, setSelectedSupplierId] = useState(''); const [invoiceNo, setInvoiceNo] = useState(''); const [invoiceDate, setInvoiceDate] = useState(new Date().toISOString().split('T')[0]); const [rows, setRows] = useState([ { item_name: '', generic_name: '', batch_no: '', expiry_date: '', qty_packs: 1, free_qty_packs: 0, units_per_pack: 10, mrp: 0, ptr: 0, discount_pct: 0, gst_rate: 12 } ]); useEffect(() => { fetchSuppliers(); }, []); const fetchSuppliers = async () => { try { const res = await fetch(API_BASE + 'suppliers'); const data = await res.json(); if (data.status) setSuppliers(data.suppliers || []); } catch (e) { console.error(e); } }; const addRow = () => { setRows([...rows, { item_name: '', generic_name: '', batch_no: '', expiry_date: '', qty_packs: 1, free_qty_packs: 0, units_per_pack: 10, mrp: 0, ptr: 0, discount_pct: 0, gst_rate: 12 }]); }; const updateRow = (idx, field, val) => { const updated = [...rows]; updated[idx][field] = val; setRows(updated); }; const removeRow = (idx) => { setRows(rows.filter((_, i) => i !== idx)); }; const savePurchaseBill = async () => { if (!selectedSupplierId || !invoiceNo) { notify('Please select supplier and enter invoice number.', 'error'); return; } const validItems = rows.filter(r => r.item_name && r.batch_no && r.expiry_date && Number(r.qty_packs) > 0); if (validItems.length === 0) { notify('Please fill at least one valid item line.', 'error'); return; } try { const itemsPayload = []; for (const r of validItems) { const searchRes = await fetch(API_BASE + `items/search?store_id=${store.store_id}&q=${encodeURIComponent(r.item_name)}`); const sData = await searchRes.json(); let itemId = 1; if (sData.status && sData.items && sData.items.length > 0) { itemId = sData.items[0].item_id; } itemsPayload.push({ item_id: itemId, batch_no: r.batch_no, expiry_date: r.expiry_date, qty_packs: Number(r.qty_packs), free_qty_packs: Number(r.free_qty_packs || 0), units_per_pack: Number(r.units_per_pack || 10), mrp: Number(r.mrp), ptr: Number(r.ptr), discount_pct: Number(r.discount_pct || 0), gst_rate: Number(r.gst_rate || 12) }); } const res = await fetch(API_BASE + 'purchase/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ store_id: store.store_id, supplier_id: Number(selectedSupplierId), supplier_invoice_no: invoiceNo, invoice_date: invoiceDate, items: itemsPayload }) }); const data = await res.json(); if (data.status) { notify('Purchase inward recorded! Supplier Ledger & Stock updated.', 'success'); setInvoiceNo(''); setRows([{ item_name: '', generic_name: '', batch_no: '', expiry_date: '', qty_packs: 1, free_qty_packs: 0, units_per_pack: 10, mrp: 0, ptr: 0, discount_pct: 0, gst_rate: 12 }]); } else { notify(data.message || 'Failed to save purchase bill.', 'error'); } } catch (e) { notify('Purchase bill error: ' + e.message, 'error'); } }; return (
{subTab === 'inward' && (
Distributor Purchase Inward (Stock Entry)
setInvoiceNo(e.target.value)} />
setInvoiceDate(e.target.value)} />
{rows.map((r, i) => ( ))}
Medicine Name Batch No Expiry Packs Free Units/Pack PTR (₹) MRP (₹) GST%
updateRow(i, 'item_name', e.target.value)} /> updateRow(i, 'batch_no', e.target.value)} /> updateRow(i, 'expiry_date', e.target.value)} /> updateRow(i, 'qty_packs', e.target.value)} /> updateRow(i, 'free_qty_packs', e.target.value)} /> updateRow(i, 'units_per_pack', e.target.value)} /> updateRow(i, 'ptr', e.target.value)} /> updateRow(i, 'mrp', e.target.value)} />
)} {subTab === 'marg' && (
Marg ERP / Excel Inventory Importer

Upload your stock export from Marg Pharmacy Software or Microsoft Excel to seamlessly import medicines, batch numbers, MRP, PTR, HSN codes, and opening stock into {store.store_name}.

Upload Marg CSV / Excel File

Ensure file is exported in CSV format from Marg ERP.

)} {subTab === 'suppliers' && (
Approved Drug Distributors & Suppliers
{suppliers.map((s, i) => ( ))}
# Supplier Name DL Form 20B / 21B GSTIN Phone / Contact Credit Terms
{i + 1} {s.supplier_name} {s.dl_no_20b || 'N/A'} / {s.dl_no_21b || 'N/A'} {s.gstin} {s.phone} ({s.contact_person}) {s.credit_days} Days
)}
); } // ========================================================================= // 4. INTER-STORE INDENTS & TRANSFERS // ========================================================================= function TransferView({ store, stores, notify }) { if (!store) return null; const [toStoreId, setToStoreId] = useState(''); const [remarks, setRemarks] = useState(''); const [transferItems, setTransferItems] = useState([ { item_name: '', qty: 10 } ]); const addTransferRow = () => { setTransferItems([...transferItems, { item_name: '', qty: 10 }]); }; const submitIndent = async () => { if (!toStoreId) { notify('Please select destination store counter.', 'error'); return; } try { const res = await fetch(API_BASE + 'transfer/request', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ from_store_id: store.store_id, to_store_id: Number(toStoreId), remarks: remarks, items: transferItems.map(it => ({ item_id: 1, qty: Number(it.qty) })) }) }); const data = await res.json(); if (data.status) { notify(`Store Indent ${data.transfer_no} submitted to Central Pharmacy!`, 'success'); setRemarks(''); } else { notify(data.message || 'Failed to submit indent.', 'error'); } } catch (e) { notify('Indent error: ' + e.message, 'error'); } }; return (
Multi-Building Store Requisition (Indent)

Building counters can requisition medicines from the Main Hospital Central Store. Once dispatched and physically verified, stock transfers automatically.

{transferItems.map((ti, i) => (
{ const updated = [...transferItems]; updated[i].item_name = e.target.value; setTransferItems(updated); }} />
{ const updated = [...transferItems]; updated[i].qty = e.target.value; setTransferItems(updated); }} />
))}
); } // ========================================================================= // 5. ACCOUNTING, LEDGERS, DAYBOOK & GST REPORTS // ========================================================================= function LedgersView({ store, notify }) { if (!store) return null; const [accTab, setAccTab] = useState('daybook'); const [daybookData, setDaybookData] = useState(null); const [gstData, setGstData] = useState(null); const [h1Records, setH1Records] = useState([]); useEffect(() => { if (!store?.store_id) return; if (accTab === 'daybook') loadDaybook(); if (accTab === 'gst') loadGst(); if (accTab === 'schedule_h1') loadScheduleH1(); }, [accTab, store?.store_id]); const loadDaybook = async () => { try { const res = await fetch(API_BASE + `accounting/daybook?store_id=${store.store_id}`); const data = await res.json(); if (data.status) setDaybookData(data); } catch (e) { console.error(e); } }; const loadGst = async () => { try { const res = await fetch(API_BASE + `accounting/gst-report?store_id=${store.store_id}`); const data = await res.json(); if (data.status) setGstData(data); } catch (e) { console.error(e); } }; const loadScheduleH1 = async () => { try { const res = await fetch(API_BASE + `compliance/schedule-h1-register?store_id=${store.store_id}`); const data = await res.json(); if (data.status) setH1Records(data.records || []); } catch (e) { console.error(e); } }; return (
{accTab === 'daybook' && daybookData && (
TOTAL TODAY SALES

₹{daybookData.summary.total_sales.toLocaleString('en-IN')}

{daybookData.summary.total_invoices} Bills
CASH IN DRAWER

₹{daybookData.summary.cash_in_drawer.toLocaleString('en-IN')}

UPI / QR COLLECTIONS

₹{daybookData.summary.upi_collection.toLocaleString('en-IN')}

IPD CREDIT BILLED

₹{daybookData.summary.ipd_credit.toLocaleString('en-IN')}

Today's Transactions Journal
{daybookData.transactions.map((t) => ( ))}
Invoice No Time Patient (UHID) Doctor Mode CGST (₹) SGST (₹) Net Amount
{t.invoice_no} {t.sale_date.split(' ')[1]} {t.patient_name} {t.uhid ? `(${t.uhid})` : ''} {t.doctor_name} {t.payment_mode} ₹{t.cgst_amount} ₹{t.sgst_amount} ₹{t.net_amount}
)} {accTab === 'gst' && gstData && (
GSTR-1 Outward Sales Summary (HSN-wise)
{gstData.gstr1_sales.map((g, i) => ( ))}
HSN Code GST Slab Taxable Value (₹) CGST (₹) SGST (₹) IGST (₹) Total Invoice Value (₹)
{g.hsn_code} {g.gst_rate}% ₹{Number(g.taxable_val).toFixed(2)} ₹{Number(g.cgst_val).toFixed(2)} ₹{Number(g.sgst_val).toFixed(2)} ₹{Number(g.igst_val).toFixed(2)} ₹{Number(g.total_val).toFixed(2)}
)} {accTab === 'schedule_h1' && (
Statutory Schedule H1 Drug Register
Mandatory under Indian Drugs & Cosmetics Rules (4th Amendment 2013). Retain records for 3 years.
{h1Records.length === 0 ? ( ) : ( h1Records.map((h, i) => ( )) )}
Date Bill No Patient Name & Address Prescribing Doctor & Reg No Medicine Name Batch No Qty Supplied
No Schedule H1 medicines dispensed in this period.
{h.sale_date.split(' ')[0]} {h.invoice_no} {h.patient_name} {h.patient_address ? `(${h.patient_address})` : ''} {h.doctor_name} {h.doctor_reg_no ? `(Reg: ${h.doctor_reg_no})` : ''} {h.item_name} {h.batch_no} {h.qty}
)}
); } // ========================================================================= // 6. STORE & STATUTORY LICENSING SETUP // ========================================================================= function SettingsView({ store, onStoreSaved, notify }) { const [formData, setFormData] = useState({ store_id: store ? store.store_id : 0, store_code: store ? store.store_code : '', store_slug: store ? store.store_slug : '', store_name: store ? store.store_name : '', building_name: store ? store.building_name : '', floor_no: store ? store.floor_no : '', room_no: store ? store.room_no : '', drug_license_no_20b: store ? store.drug_license_no_20b : '', drug_license_no_21b: store ? store.drug_license_no_21b : '', drug_license_no_20f_x: store ? store.drug_license_no_20f_x : '', gstin: store ? store.gstin : '', pan_no: store ? store.pan_no : '', fssai_no: store ? store.fssai_no : '', state_code: store ? store.state_code : '07', state_name: store ? store.state_name : 'Delhi', registered_pharmacist_name: store ? store.registered_pharmacist_name : '', pharmacist_reg_no: store ? store.pharmacist_reg_no : '', pharmacist_hpr_id: store ? (store.pharmacist_hpr_id || '') : '', abdm_hfr_id: store ? (store.abdm_hfr_id || '') : '', abdm_hip_id: store ? (store.abdm_hip_id || '') : '', invoice_prefix: store ? store.invoice_prefix : 'INV/', next_invoice_no: store ? store.next_invoice_no : 1001, upi_id: store ? store.upi_id : '', terms_conditions: store ? store.terms_conditions : '' }); const handleChange = (field, val) => { setFormData({ ...formData, [field]: val }); }; const handleSave = async (e) => { e.preventDefault(); try { const res = await fetch(API_BASE + 'stores/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData) }); const data = await res.json(); if (data.status) { notify('Store & statutory licensing updated successfully!', 'success'); onStoreSaved(); } else { notify(data.message || 'Failed to update store.', 'error'); } } catch (e) { notify('Save error: ' + e.message, 'error'); } }; return (
Hospital Pharmacy Store & Indian Licensing Configuration
handleChange('store_code', e.target.value)} />
handleChange('store_slug', e.target.value)} />
handleChange('store_name', e.target.value)} />
handleChange('building_name', e.target.value)} />
handleChange('floor_no', e.target.value)} />
handleChange('room_no', e.target.value)} />
Indian Drug & Tax Statutory Licenses
handleChange('drug_license_no_20b', e.target.value)} />
handleChange('drug_license_no_21b', e.target.value)} />
handleChange('drug_license_no_20f_x', e.target.value)} />
handleChange('gstin', e.target.value)} />
handleChange('pan_no', e.target.value)} />
handleChange('fssai_no', e.target.value)} />
Pharmacist & POS Bill Configuration
handleChange('registered_pharmacist_name', e.target.value)} />
handleChange('pharmacist_reg_no', e.target.value)} />
handleChange('invoice_prefix', e.target.value)} />
handleChange('next_invoice_no', e.target.value)} />
handleChange('upi_id', e.target.value)} />
Ayushman Bharat Digital Mission (ABDM) Registry Configuration
handleChange('abdm_hfr_id', e.target.value)} /> Facility ID registered in National Health Authority HFR
handleChange('abdm_hip_id', e.target.value)} /> Identifier configured in ABDM Gateway Bridge
handleChange('pharmacist_hpr_id', e.target.value)} /> National Pharmacist ID from HPR Portal
); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render( );