Add SKU edit actions
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m18s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m18s
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Loader2, Package, RefreshCw, Ruler, Save, Tags, Trash2 } from 'lucide-react';
|
||||
import {
|
||||
deleteCatalogCategory,
|
||||
@@ -35,6 +36,21 @@ const defaultSizeAreas: Record<string, string> = {
|
||||
G5: '1.40'
|
||||
};
|
||||
|
||||
const defaultProductForm = {
|
||||
type: 'finished_product' as CatalogProductType,
|
||||
sku: '',
|
||||
name: '',
|
||||
categoryId: '',
|
||||
composition: '',
|
||||
notes: '',
|
||||
gramature: '',
|
||||
materialYield: '',
|
||||
widthCm: '',
|
||||
color: '',
|
||||
subcategory: 'malha',
|
||||
sizes: ['P', 'M', 'G', 'GG'] as string[]
|
||||
};
|
||||
|
||||
const rawMaterialSubcategories = [
|
||||
{ value: 'fio', label: 'Fio' },
|
||||
{ value: 'malha', label: 'Malha' },
|
||||
@@ -77,28 +93,17 @@ const getAverageYield = (reference: ConsumptionReference) => {
|
||||
};
|
||||
|
||||
const Registrations = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const [catalog, setCatalog] = useState<CatalogSummary>(emptyCatalog);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [activeTab, setActiveTab] = useState<RegistrationTab>('products');
|
||||
const [productFilter, setProductFilter] = useState<'all' | CatalogProductType>('all');
|
||||
const [status, setStatus] = useState<SaveStatus>('idle');
|
||||
const [feedback, setFeedback] = useState('');
|
||||
const appliedSkuPrefillRef = useRef('');
|
||||
|
||||
const [categoryForm, setCategoryForm] = useState({ name: '', description: '' });
|
||||
const [productForm, setProductForm] = useState({
|
||||
type: 'finished_product' as CatalogProductType,
|
||||
sku: '',
|
||||
name: '',
|
||||
categoryId: '',
|
||||
composition: '',
|
||||
notes: '',
|
||||
gramature: '',
|
||||
materialYield: '',
|
||||
widthCm: '',
|
||||
color: '',
|
||||
subcategory: 'malha',
|
||||
sizes: ['P', 'M', 'G', 'GG'] as string[]
|
||||
});
|
||||
const [productForm, setProductForm] = useState(defaultProductForm);
|
||||
const [referenceForm, setReferenceForm] = useState({
|
||||
productId: '',
|
||||
materialProductId: '',
|
||||
@@ -136,6 +141,58 @@ const Registrations = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const requestedTab = searchParams.get('tab');
|
||||
const sku = (searchParams.get('sku') || '').trim();
|
||||
if (!sku && !(requestedTab === 'products' || requestedTab === 'categories' || requestedTab === 'references')) return;
|
||||
|
||||
const prefillKey = `${sku}|${searchParams.get('name') || ''}|${catalog.products.length}`;
|
||||
if (appliedSkuPrefillRef.current === prefillKey) return;
|
||||
appliedSkuPrefillRef.current = prefillKey;
|
||||
|
||||
queueMicrotask(() => {
|
||||
if (requestedTab === 'products' || requestedTab === 'categories' || requestedTab === 'references') {
|
||||
setActiveTab(requestedTab);
|
||||
}
|
||||
|
||||
if (!sku) return;
|
||||
|
||||
const existingProduct = catalog.products.find(product => product.sku.toLowerCase() === sku.toLowerCase());
|
||||
setActiveTab('products');
|
||||
setProductFilter('all');
|
||||
setStatus('idle');
|
||||
|
||||
if (existingProduct) {
|
||||
setProductForm({
|
||||
type: existingProduct.type,
|
||||
sku: existingProduct.sku,
|
||||
name: existingProduct.name,
|
||||
categoryId: existingProduct.categoryId ? String(existingProduct.categoryId) : '',
|
||||
composition: existingProduct.composition || '',
|
||||
notes: existingProduct.notes || '',
|
||||
gramature: existingProduct.gramature ? String(existingProduct.gramature) : '',
|
||||
materialYield: existingProduct.materialYield ? String(existingProduct.materialYield) : '',
|
||||
widthCm: existingProduct.widthCm ? String(existingProduct.widthCm) : '',
|
||||
color: existingProduct.color || searchParams.get('color') || '',
|
||||
subcategory: existingProduct.subcategory || 'malha',
|
||||
sizes: existingProduct.sizes?.length ? existingProduct.sizes : defaultProductForm.sizes
|
||||
});
|
||||
setFeedback(`Editando SKU ${existingProduct.sku}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const requestedSize = (searchParams.get('size') || '').trim().toUpperCase();
|
||||
setProductForm({
|
||||
...defaultProductForm,
|
||||
sku,
|
||||
name: searchParams.get('name') || '',
|
||||
color: searchParams.get('color') || '',
|
||||
sizes: requestedSize ? [requestedSize] : defaultProductForm.sizes
|
||||
});
|
||||
setFeedback(`Novo cadastro para SKU ${sku}.`);
|
||||
});
|
||||
}, [catalog.products, searchParams]);
|
||||
|
||||
const finishedProducts = useMemo(
|
||||
() => catalog.products.filter(product => product.type === 'finished_product'),
|
||||
[catalog.products]
|
||||
@@ -464,21 +521,32 @@ const Registrations = () => {
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div>
|
||||
<p className="mb-2 text-xs font-bold text-dark-muted">Tamanhos disponiveis</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{sizeOptions.map(size => (
|
||||
<button
|
||||
key={size}
|
||||
type="button"
|
||||
onClick={() => toggleProductSize(size)}
|
||||
className={`rounded-full border px-3 py-1.5 text-xs font-bold transition-colors cursor-pointer ${productForm.sizes.includes(size) ? 'border-brand-primary bg-brand-primary/15 text-brand-primary' : 'border-dark-border bg-dark-input text-dark-muted hover:text-dark-text'}`}
|
||||
>
|
||||
{size}
|
||||
</button>
|
||||
))}
|
||||
<>
|
||||
<label className={`block ${labelClassName}`}>
|
||||
Cor
|
||||
<input
|
||||
value={productForm.color}
|
||||
onChange={(event) => setProductForm(current => ({ ...current, color: event.target.value }))}
|
||||
placeholder="ex: Preto"
|
||||
className={inputClassName}
|
||||
/>
|
||||
</label>
|
||||
<div>
|
||||
<p className="mb-2 text-xs font-bold text-dark-muted">Tamanhos disponiveis</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{sizeOptions.map(size => (
|
||||
<button
|
||||
key={size}
|
||||
type="button"
|
||||
onClick={() => toggleProductSize(size)}
|
||||
className={`rounded-full border px-3 py-1.5 text-xs font-bold transition-colors cursor-pointer ${productForm.sizes.includes(size) ? 'border-brand-primary bg-brand-primary/15 text-brand-primary' : 'border-dark-border bg-dark-input text-dark-muted hover:text-dark-text'}`}
|
||||
>
|
||||
{size}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<label className={`block ${labelClassName}`}>
|
||||
|
||||
Reference in New Issue
Block a user