Allow searching sellers in client filters
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m5s

This commit is contained in:
Cauê Faleiros
2026-06-24 11:18:27 -03:00
parent b7a2059070
commit aeb801c0ba
3 changed files with 41 additions and 12 deletions

View File

@@ -215,11 +215,13 @@ const appendOrderMetadataFilters = (params, filters, range = {}) => {
params.push(seller.value); params.push(seller.value);
filters.push(`NULLIF(TRIM(id_vendedor), '') = $${params.length}`); filters.push(`NULLIF(TRIM(id_vendedor), '') = $${params.length}`);
} else if (seller?.type === 'name') { } else if (seller?.type === 'name') {
params.push(seller.value); params.push(`%${seller.value}%`);
filters.push(`NULLIF(TRIM(nome_vendedor), '') = $${params.length}`); filters.push(`NULLIF(TRIM(nome_vendedor), '') ILIKE $${params.length}`);
} else if (seller?.type === 'any') { } else if (seller?.type === 'any') {
params.push(seller.value); params.push(seller.value);
filters.push(`(NULLIF(TRIM(id_vendedor), '') = $${params.length} OR NULLIF(TRIM(nome_vendedor), '') = $${params.length})`); const idParamIndex = params.length;
params.push(`%${seller.value}%`);
filters.push(`(NULLIF(TRIM(id_vendedor), '') = $${idParamIndex} OR NULLIF(TRIM(nome_vendedor), '') ILIKE $${params.length})`);
} }
}; };

View File

@@ -112,10 +112,20 @@ test('buildDateFilter composes client metadata predicates after date predicates'
test('buildDateFilter can filter seller by display name when no seller id is selected', () => { test('buildDateFilter can filter seller by display name when no seller id is selected', () => {
const filter = buildDateFilter({ seller: 'name:Maria' }); const filter = buildDateFilter({ seller: 'name:Maria' });
assert.deepEqual(filter.params, ['Maria']); assert.deepEqual(filter.params, ['%Maria%']);
assert.equal( assert.equal(
filter.whereClause, filter.whereClause,
"WHERE data_pedido_date IS NOT NULL AND NULLIF(TRIM(nome_vendedor), '') = $1" "WHERE data_pedido_date IS NOT NULL AND NULLIF(TRIM(nome_vendedor), '') ILIKE $1"
);
});
test('buildDateFilter can search seller names from typed text', () => {
const filter = buildDateFilter({ seller: 'MARCUS' });
assert.deepEqual(filter.params, ['MARCUS', '%MARCUS%']);
assert.equal(
filter.whereClause,
"WHERE data_pedido_date IS NOT NULL AND (NULLIF(TRIM(id_vendedor), '') = $1 OR NULLIF(TRIM(nome_vendedor), '') ILIKE $2)"
); );
}); });

View File

@@ -104,6 +104,7 @@ const dateFilterPresets = [
]; ];
const filterSelectClassName = "w-full h-9 bg-dark-input border border-dark-border text-dark-text text-sm rounded-lg px-3 focus:outline-none focus:border-brand-primary transition-colors cursor-pointer"; const filterSelectClassName = "w-full h-9 bg-dark-input border border-dark-border text-dark-text text-sm rounded-lg px-3 focus:outline-none focus:border-brand-primary transition-colors cursor-pointer";
const filterInputClassName = "w-full h-9 bg-dark-input border border-dark-border text-dark-text text-sm rounded-lg px-3 focus:outline-none focus:border-brand-primary transition-colors";
const Clients = () => { const Clients = () => {
const { dateRange, setDateRange } = useOutletContext<{ const { dateRange, setDateRange } = useOutletContext<{
@@ -350,6 +351,19 @@ const Clients = () => {
return [fallbackSeller, ...filterOptions.sellers]; return [fallbackSeller, ...filterOptions.sellers];
}, [filterOptions.sellers, metadataFilters.seller]); }, [filterOptions.sellers, metadataFilters.seller]);
const sellerSuggestions = useMemo(() => {
const suggestions = new Set<string>();
sellerOptions.forEach(seller => {
const label = getSellerOptionLabel(seller);
if (seller.name) suggestions.add(seller.name);
if (seller.id) suggestions.add(seller.id);
if (label) suggestions.add(label);
});
return [...suggestions].filter(Boolean);
}, [sellerOptions]);
const activeMetadataFilters = useMemo(() => { const activeMetadataFilters = useMemo(() => {
const filters = []; const filters = [];
const selectedSeller = sellerOptions.find(seller => seller.value === metadataFilters.seller); const selectedSeller = sellerOptions.find(seller => seller.value === metadataFilters.seller);
@@ -515,16 +529,19 @@ const Clients = () => {
<label className="block text-xs font-bold uppercase tracking-wider text-dark-muted"> <label className="block text-xs font-bold uppercase tracking-wider text-dark-muted">
Vendedor Vendedor
<select <input
type="text"
list="client-seller-filter-options"
value={metadataFilters.seller} value={metadataFilters.seller}
onChange={(event) => updateMetadataFilter('seller', event.target.value)} onChange={(event) => updateMetadataFilter('seller', event.target.value)}
className={`${filterSelectClassName} mt-1`} placeholder="Todos"
> className={`${filterInputClassName} mt-1`}
<option value="">Todos</option> />
{sellerOptions.map(seller => ( <datalist id="client-seller-filter-options">
<option key={seller.value} value={seller.value}>{getSellerOptionLabel(seller)}</option> {sellerSuggestions.map(seller => (
<option key={seller} value={seller} />
))} ))}
</select> </datalist>
</label> </label>
<label className="block text-xs font-bold uppercase tracking-wider text-dark-muted"> <label className="block text-xs font-bold uppercase tracking-wider text-dark-muted">