-
-
-
setEntryMode('single')}
- className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg text-xs font-bold transition cursor-pointer ${
- entryMode === 'single'
- ? 'bg-blue-600 text-white shadow-xs'
- : 'text-slate-600 hover:text-ink-950'
- }`}
- >
- Single Entry Form
-
-
-
setEntryMode('batch')}
- className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-lg text-xs font-bold transition cursor-pointer ${
- entryMode === 'batch'
- ? 'bg-blue-600 text-white shadow-xs'
- : 'text-slate-600 hover:text-ink-950'
- }`}
- >
- Batch CSV / Excel Upload
-
-
-
-
- Auto-Enrich & Dual Persistence
-
-
-
- {/* SINGLE PRODUCT FORM */}
- {entryMode === 'single' && (
-
- {singleError && (
-
- {singleError}
-
- )}
-
-
-
- )}
-
- {/* BATCH CSV/EXCEL UPLOAD */}
- {entryMode === 'batch' && (
-
- {batchError && (
-
- {batchError}
-
- )}
-
-
-
-
-
Upload Product Spreadsheet (.csv, .xlsx, .xls)
-
- Supports multiple rows containing Brand Name, Product Name, Category, Price, Barcode, HSN Code.
-
-
-
setBatchFile(e.target.files?.[0] || null)}
- className="hidden"
- id="batch-file-input"
- />
-
- Select CSV or Excel File
-
-
- {batchFile && (
-
-
- {batchFile.name} ({(batchFile.size / 1024).toFixed(1)} KB)
-
- )}
-
-
-
- {uploadingBatch ? : }
- {uploadingBatch ? 'Processing & Enriching Batch Products...' : 'Upload & Sync Batch Records'}
-
-
-
- )}
-
-
- {/* Right Panel: Results & Quick Brand Inspection */}
-
- {singleResult && (
-
-
-
-
Product Record Created & Synced
-
-
{singleResult.message}
-
-
{singleResult.product.product_name}
-
Brand: {singleResult.product.brand}
- {singleResult.product.barcode && (
-
Barcode: {singleResult.product.barcode}
- )}
-
-
- )}
-
- {batchResult && (
-
-
- {batchHadErrors ?
:
}
-
- {batchHadErrors ? 'Batch Partially Imported' : 'Batch Products Saved to Database'}
-
-
-
-
{batchResult.message}
-
- {/* Counts, so "success" is never a claim without a number
- behind it. added_count is the number of rows verified
- present in the database, not the number attempted. */}
-
-
-
{batchResult.added_count ?? 0}
-
Saved
-
-
-
{batchResult.error_count ?? 0}
-
Failed
-
-
-
{batchResult.skipped_blank_rows ?? 0}
-
Blank Rows
-
-
-
- {Array.isArray(batchResult.warnings) && batchResult.warnings.length > 0 && (
-
- {batchResult.warnings.map((w, idx) => (
-
-
- {w}
-
- ))}
-
- )}
-
- {Array.isArray(batchResult.errors) && batchResult.errors.length > 0 && (
-
-
Rows that were not saved
- {batchResult.errors.map((e, idx) => (
-
- {e.row ? `Row ${e.row}: ` : ''}
- {e.product_name ? `${e.product_name} - ` : ''}
- {e.error}
-
- ))}
- {batchResult.errors_truncated > 0 && (
-
- +{batchResult.errors_truncated} more not shown
-
- )}
-
- )}
-
- )}
-
- {!singleResult && !batchResult && (
-
-
-
Dual Storage Persistence
-
- Every product submitted (single or batch CSV/Excel) is automatically parsed, assigned high-resolution images, and synced into PostgreSQL brand tables and JSON catalog seed files.
-
-
- )}
-
- {/* Quick Brand Catalog Search */}
-
-
-
- Inspect Brand Products
-
- {brandProducts.length} items
-
-
-
- setBrandSearch(e.target.value)}
- placeholder="Enter brand to inspect (e.g. Lion Dates)"
- className="flex-1 rounded-xl border border-ink-900/15 bg-white p-2 text-xs font-medium text-ink-950 focus:outline-none"
- />
- fetchBrandCatalog(brandSearch)}
- className="px-3 py-1.5 bg-ink-900 text-white text-xs font-semibold rounded-xl hover:bg-ink-950 cursor-pointer"
- >
- Fetch
-
-
-
- {loadingBrand ? (
-
Loading catalog items...
- ) : (
-
- {brandProducts.map((p, idx) => (
-
setSelectedProduct(p)}
- className="cursor-pointer flex items-center justify-between gap-2 p-2.5 rounded-xl border border-slate-200 bg-white hover:border-amber-500/60 transition shadow-xs"
- >
-
- {p.image_url ? (
-
- ) : (
-
No img
- )}
-
-
{p.product_name}
-
- {p.barcode ? `Barcode: ${p.barcode}` : p.product_sku ? `SKU: ${p.product_sku}` : 'Standard Record'}
-
-
-
- {p.final_selling_price && (
-
₹{p.final_selling_price}
- )}
-
- ))}
-
- )}
-
-