126 lines
7.3 KiB
JavaScript
126 lines
7.3 KiB
JavaScript
const fs = require('fs');
|
|
|
|
const path = 'C:/Users/CSH12/Desktop/AI_Pharamcy_Frontend/AI_Pharmacy_Application/src/pages/Inventory.tsx';
|
|
let content = fs.readFileSync(path, 'utf8');
|
|
|
|
if (!content.includes('isProductDropdownOpen')) {
|
|
// 1. Add state & memo
|
|
const stateSearch = `const [supplierOptions, setSupplierOptions] = useState<any[]>([]);`;
|
|
const stateReplace = `const [supplierOptions, setSupplierOptions] = useState<any[]>([]);
|
|
const [isProductDropdownOpen, setIsProductDropdownOpen] = useState(false);
|
|
const [productSearchQuery, setProductSearchQuery] = useState('');
|
|
|
|
const filteredProductOptions = useMemo(() => {
|
|
if (!productSearchQuery || productSearchQuery.trim() === '') {
|
|
return drugOptions;
|
|
}
|
|
const q = productSearchQuery.toLowerCase().trim();
|
|
return drugOptions.filter(d =>
|
|
(d.product_id && String(d.product_id).toLowerCase().includes(q)) ||
|
|
(d.brand_name && String(d.brand_name).toLowerCase().includes(q)) ||
|
|
(d.generic_name && String(d.generic_name).toLowerCase().includes(q)) ||
|
|
(d.manufacturer && String(d.manufacturer).toLowerCase().includes(q))
|
|
);
|
|
}, [drugOptions, productSearchQuery]);`;
|
|
|
|
content = content.replace(stateSearch, stateReplace);
|
|
|
|
// 2. Replace datalist input block with modern searchable dropdown
|
|
const oldBlock = `<div className="col-span-2">
|
|
<label className="block text-xs font-bold uppercase tracking-wider text-slate-500" style={{ marginBottom: '8px' }}>Product ID</label>
|
|
<div className="relative group">
|
|
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-slate-400 group-focus-within:text-blue-500 transition-colors z-10">
|
|
<Package size={18} strokeWidth={2} />
|
|
</div>
|
|
<input
|
|
type="text"
|
|
list="product-options"
|
|
value={formData.product_id}
|
|
onChange={(e) => setFormData({ ...formData, product_id: e.target.value })}
|
|
placeholder="Select or enter Product ID..."
|
|
className="w-full bg-slate-50 border border-slate-200 rounded-xl focus:bg-white focus:outline-none focus:ring-4 focus:ring-blue-500/10 focus:border-blue-500 text-[15px] font-medium text-slate-800 transition-all hover:bg-slate-100 hover:border-slate-300 placeholder:text-slate-400"
|
|
style={{ padding: '12px 16px', paddingLeft: '44px' }}
|
|
/>
|
|
<datalist id="product-options">
|
|
{drugOptions.map(d => (
|
|
<option key={d.product_id} value={d.product_id}>
|
|
{d.brand_name}
|
|
</option>
|
|
))}
|
|
</datalist>
|
|
</div>
|
|
</div>`;
|
|
|
|
const newBlock = `<div className="col-span-2 relative">
|
|
<label className="block text-xs font-bold uppercase tracking-wider text-slate-500" style={{ marginBottom: '8px' }}>Product / Medicine (Search by Brand, Generic or Product ID)</label>
|
|
<div className="relative group">
|
|
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-slate-400 group-focus-within:text-blue-500 transition-colors z-10">
|
|
<Search size={18} strokeWidth={2} />
|
|
</div>
|
|
<input
|
|
type="text"
|
|
value={productSearchQuery || formData.product_id}
|
|
onFocus={() => setIsProductDropdownOpen(true)}
|
|
onChange={(e) => {
|
|
setProductSearchQuery(e.target.value);
|
|
setFormData({ ...formData, product_id: e.target.value });
|
|
setIsProductDropdownOpen(true);
|
|
}}
|
|
placeholder="Type medicine name, generic name or Product ID..."
|
|
className="w-full bg-slate-50 border border-slate-200 rounded-xl focus:bg-white focus:outline-none focus:ring-4 focus:ring-blue-500/10 focus:border-blue-500 text-[15px] font-medium text-slate-800 transition-all hover:bg-slate-100 hover:border-slate-300 placeholder:text-slate-400"
|
|
style={{ padding: '12px 16px', paddingLeft: '44px', paddingRight: '40px' }}
|
|
/>
|
|
<div
|
|
className="absolute inset-y-0 right-0 pr-4 flex items-center cursor-pointer text-slate-400 hover:text-slate-600 z-10"
|
|
onClick={() => setIsProductDropdownOpen(!isProductDropdownOpen)}
|
|
>
|
|
<ChevronDown size={18} strokeWidth={2} className={\`transition-transform \${isProductDropdownOpen ? 'rotate-180' : ''}\`} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Searchable Custom Dropdown Menu */}
|
|
{isProductDropdownOpen && (
|
|
<div
|
|
className="absolute left-0 right-0 top-full mt-2 bg-white border border-slate-200 rounded-xl shadow-2xl z-50 max-h-64 overflow-y-auto divide-y divide-slate-100"
|
|
style={{ boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)' }}
|
|
>
|
|
{filteredProductOptions.length > 0 ? (
|
|
filteredProductOptions.map((d: any) => (
|
|
<div
|
|
key={d.product_id}
|
|
onClick={() => {
|
|
setFormData({ ...formData, product_id: d.product_id });
|
|
setProductSearchQuery(\`\${d.brand_name} (\${d.product_id})\`);
|
|
setIsProductDropdownOpen(false);
|
|
}}
|
|
className="p-3 hover:bg-blue-50/80 cursor-pointer flex items-center justify-between transition-colors group"
|
|
>
|
|
<div className="flex flex-col">
|
|
<span className="font-bold text-slate-800 text-[14px] group-hover:text-blue-600">
|
|
{d.brand_name}
|
|
</span>
|
|
<span className="text-xs text-slate-500">
|
|
{d.generic_name || 'Generic Medicine'} {d.manufacturer ? \`• \${d.manufacturer}\` : ''}
|
|
</span>
|
|
</div>
|
|
<span className="text-[11px] font-mono font-bold bg-slate-100 text-slate-700 group-hover:bg-blue-100 group-hover:text-blue-700 px-2.5 py-1 rounded-md transition-colors shrink-0">
|
|
{d.product_id}
|
|
</span>
|
|
</div>
|
|
))
|
|
) : (
|
|
<div className="p-4 text-center text-slate-400 text-sm">
|
|
No matching medicines found
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>`;
|
|
|
|
content = content.replace(oldBlock, newBlock);
|
|
fs.writeFileSync(path, content);
|
|
console.log("Patched Inventory.tsx successfully!");
|
|
} else {
|
|
console.log("Already patched Inventory.tsx");
|
|
}
|