Add bulkCsvFile/bulkZipFile fields and handleBulkUploadSubmit to support ZIP archive uploads in frontend
This commit is contained in:
parent
b924a30af7
commit
6e5e175689
1 changed files with 82 additions and 41 deletions
125
src/App.tsx
125
src/App.tsx
|
|
@ -276,9 +276,11 @@ export default function App() {
|
|||
.catch(err => console.error(err))
|
||||
}
|
||||
|
||||
// Bulk Upload simulations
|
||||
// Bulk Upload
|
||||
const [bulkLog, setBulkLog] = useState<string[]>([])
|
||||
const [isParsingBulk, setIsParsingBulk] = useState(false)
|
||||
const [bulkCsvFile, setBulkCsvFile] = useState<File | null>(null)
|
||||
const [bulkZipFile, setBulkZipFile] = useState<File | null>(null)
|
||||
|
||||
// GSTIN verification simulator
|
||||
const handleVerifyGstin = () => {
|
||||
|
|
@ -625,45 +627,56 @@ export default function App() {
|
|||
}
|
||||
}
|
||||
|
||||
// Bulk parser simulation
|
||||
const handleBulkUploadSimulate = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (!e.target.files?.length) return
|
||||
setIsParsingBulk(true)
|
||||
setBulkLog(['Parsing CSV file template...', 'Validating rows against inventory Schema...'])
|
||||
|
||||
const mockBulkProducts = [
|
||||
{ title: 'Hand-Carved Walnut Bowl', category: 'Kitchenware', price: '65.00', stock: 15, sku: 'BOWL-WAL-12' },
|
||||
{ title: 'Organic Cotton Tablecloth', category: 'Linens', price: '48.00', stock: 30, sku: 'LINE-COT-15' }
|
||||
]
|
||||
|
||||
setTimeout(() => {
|
||||
apiFetch(`${CONFIG.apiBaseUrl}/api/products/bulk-upload/`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ products: mockBulkProducts })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(() => {
|
||||
setBulkLog(prev => [
|
||||
...prev,
|
||||
'Row 1: Verified SKU BOWL-WAL-12 - Added',
|
||||
'Row 2: Verified SKU LINE-COT-15 - Added',
|
||||
'Successfully added 2 new listings bulk!'
|
||||
])
|
||||
// Refresh products
|
||||
apiFetch(`${CONFIG.apiBaseUrl}/api/products/`)
|
||||
.then(r => r.json())
|
||||
.then(prods => {
|
||||
setProducts(prods)
|
||||
setIsParsingBulk(false)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
setBulkLog(prev => [...prev, 'Error during upload to server.'])
|
||||
setIsParsingBulk(false)
|
||||
})
|
||||
}, 1500)
|
||||
const handleBulkUploadSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!bulkCsvFile) {
|
||||
alert("Please select a CSV file to upload.");
|
||||
return;
|
||||
}
|
||||
setIsParsingBulk(true);
|
||||
setBulkLog(['Uploading files to server...', 'Parsing CSV data and extracting ZIP images...']);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('csv_file', bulkCsvFile);
|
||||
if (bulkZipFile) {
|
||||
formData.append('zip_file', bulkZipFile);
|
||||
}
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('access_token');
|
||||
const response = await fetch(`${CONFIG.apiBaseUrl}/api/products/bulk-upload/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(token ? { 'Authorization': `Bearer ${token}` } : {})
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Failed to complete bulk upload.');
|
||||
}
|
||||
|
||||
setBulkLog([
|
||||
'CSV file parsed successfully.',
|
||||
`Extracted and matched images for SKUs from ZIP file.`,
|
||||
`Successfully added ${data.products?.length || 0} product listings!`,
|
||||
]);
|
||||
|
||||
// Refresh product list
|
||||
const prodRes = await apiFetch(`${CONFIG.apiBaseUrl}/api/products/`);
|
||||
const prods = await prodRes.json();
|
||||
if (Array.isArray(prods)) {
|
||||
setProducts(prods);
|
||||
}
|
||||
setBulkCsvFile(null);
|
||||
setBulkZipFile(null);
|
||||
} catch (err: any) {
|
||||
setBulkLog(prev => [...prev, `Error: ${err.message}`]);
|
||||
} finally {
|
||||
setIsParsingBulk(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Wallet outstanding requests
|
||||
const handleWithdrawRequest = (e: React.FormEvent) => {
|
||||
|
|
@ -1983,11 +1996,39 @@ export default function App() {
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<div className="bulk-drop-zone" onClick={() => document.getElementById('bulk-file-pick')?.click()}>
|
||||
<span>{isParsingBulk ? 'Processing bulk data...' : '📂 Click or drop your populated template file here to import'}</span>
|
||||
<input id="bulk-file-pick" type="file" accept=".csv" onChange={handleBulkUploadSimulate} style={{ display: 'none' }} />
|
||||
<form onSubmit={handleBulkUploadSubmit} style={{ marginTop: '1.5rem' }}>
|
||||
<div className="form-group" style={{ marginBottom: '1rem' }}>
|
||||
<label style={{ fontWeight: 'bold', fontSize: '0.85rem' }}>1. Upload Populated Template (.csv) *</label>
|
||||
<input
|
||||
type="file"
|
||||
accept=".csv"
|
||||
onChange={(e) => setBulkCsvFile(e.target.files?.[0] || null)}
|
||||
style={{ display: 'block', marginTop: '0.5rem', width: '100%', padding: '0.5rem', border: '1px solid var(--border)', borderRadius: '6px' }}
|
||||
/>
|
||||
{bulkCsvFile && <span style={{ fontSize: '0.8rem', color: 'green', display: 'block', marginTop: '0.25rem' }}>✓ Selected: {bulkCsvFile.name}</span>}
|
||||
</div>
|
||||
|
||||
<div className="form-group" style={{ marginBottom: '1.5rem' }}>
|
||||
<label style={{ fontWeight: 'bold', fontSize: '0.85rem' }}>2. Upload Image Archive (.zip) - Optional</label>
|
||||
<input
|
||||
type="file"
|
||||
accept=".zip"
|
||||
onChange={(e) => setBulkZipFile(e.target.files?.[0] || null)}
|
||||
style={{ display: 'block', marginTop: '0.5rem', width: '100%', padding: '0.5rem', border: '1px solid var(--border)', borderRadius: '6px' }}
|
||||
/>
|
||||
{bulkZipFile && <span style={{ fontSize: '0.8rem', color: 'green', display: 'block', marginTop: '0.25rem' }}>✓ Selected: {bulkZipFile.name}</span>}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
style={{ width: '100%', padding: '0.75rem', backgroundColor: 'var(--primary)', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}
|
||||
disabled={isParsingBulk || !bulkCsvFile}
|
||||
>
|
||||
{isParsingBulk ? 'Uploading & Processing...' : '🚀 Start Bulk Import'}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{bulkLog.length > 0 && (
|
||||
<div style={{ backgroundColor: '#f1f5f9', padding: '1rem', borderRadius: '8px', fontFamily: 'monospace', fontSize: '0.85rem', marginTop: '1rem' }}>
|
||||
<h4 style={{ marginBottom: '0.5rem' }}>Import log:</h4>
|
||||
|
|
|
|||
Loading…
Reference in a new issue