feat: add search functionality to Matrix View

This commit is contained in:
Christian Vidal Wolf
2026-04-07 13:40:50 +02:00
parent ec1b506341
commit 935cd5b510
+27 -5
View File
@@ -1,4 +1,5 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo } from 'react';
import { Search } from 'lucide-react';
import { ExcelRow } from '../types'; import { ExcelRow } from '../types';
interface MatrixViewProps { interface MatrixViewProps {
@@ -9,11 +10,20 @@ interface MatrixViewProps {
export function MatrixView({ data, headers }: MatrixViewProps) { export function MatrixView({ data, headers }: MatrixViewProps) {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(25); const [pageSize, setPageSize] = useState(25);
const [search, setSearch] = useState('');
const filteredData = useMemo(() => {
if (!search) return data;
const s = search.toLowerCase();
return data.filter(row =>
row.some(cell => String(cell || '').toLowerCase().includes(s))
);
}, [data, search]);
const paginatedData = useMemo(() => { const paginatedData = useMemo(() => {
const start = (page - 1) * pageSize; const start = (page - 1) * pageSize;
return data.slice(start, start + pageSize); return filteredData.slice(start, start + pageSize);
}, [data, page, pageSize]); }, [filteredData, page, pageSize]);
const formatCellValue = (val: any, header: string = '') => { const formatCellValue = (val: any, header: string = '') => {
if (val === undefined || val === null || val === '') return ''; if (val === undefined || val === null || val === '') return '';
@@ -72,14 +82,26 @@ export function MatrixView({ data, headers }: MatrixViewProps) {
return val; return val;
}; };
const totalPages = Math.ceil(data.length / pageSize); const totalPages = Math.ceil(filteredData.length / pageSize);
return ( return (
<div className="flex flex-col h-full bg-slate-800 rounded-xl border border-slate-700 shadow-xl overflow-hidden"> <div className="flex flex-col h-full bg-slate-800 rounded-xl border border-slate-700 shadow-xl overflow-hidden">
<div className="p-4 border-b border-slate-700 bg-slate-800/50"> <div className="p-4 border-b border-slate-700 bg-slate-800/50 flex items-center justify-between">
<div>
<h2 className="text-lg font-semibold text-white">Matrix View</h2> <h2 className="text-lg font-semibold text-white">Matrix View</h2>
<p className="text-sm text-slate-400">All data fields formatted to 2 decimal places for numbers/prices.</p> <p className="text-sm text-slate-400">All data fields formatted to 2 decimal places for numbers/prices.</p>
</div> </div>
<div className="relative min-w-[300px]">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
<input
type="text"
placeholder="Search article, name, weight..."
value={search}
onChange={e => { setSearch(e.target.value); setPage(1); }}
className="w-full pl-9 pr-4 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all font-medium"
/>
</div>
</div>
<div className="overflow-auto flex-1"> <div className="overflow-auto flex-1">
<table className="w-full text-left text-sm whitespace-nowrap"> <table className="w-full text-left text-sm whitespace-nowrap">
@@ -122,7 +144,7 @@ export function MatrixView({ data, headers }: MatrixViewProps) {
<div className="bg-slate-900 border-t border-slate-700 p-4 flex items-center justify-between text-sm text-slate-400"> <div className="bg-slate-900 border-t border-slate-700 p-4 flex items-center justify-between text-sm text-slate-400">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<span>Showing {Math.min((page - 1) * pageSize + 1, data.length)} to {Math.min(page * pageSize, data.length)} of {data.length} entries</span> <span>Showing {Math.min((page - 1) * pageSize + 1, filteredData.length)} to {Math.min(page * pageSize, filteredData.length)} of {filteredData.length} entries</span>
<select <select
value={pageSize} value={pageSize}
onChange={e => { setPageSize(Number(e.target.value)); setPage(1); }} onChange={e => { setPageSize(Number(e.target.value)); setPage(1); }}