mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 15:55:23 +02:00
Optimize Grid header UI: reduce font sizes, padding, and improve alignment of metric columns
This commit is contained in:
+29
-24
@@ -703,8 +703,8 @@ const DataGrid: React.FC<DataGridProps> = ({ data, filters, hasCustomerFilter, a
|
||||
};
|
||||
|
||||
const getSortIcon = (key: string) => {
|
||||
if (sortConfig.key !== key) return <span className="text-slate-600 ml-1">⇅</span>;
|
||||
return <span className="text-primary ml-1">{sortConfig.direction === 'asc' ? '↑' : '↓'}</span>;
|
||||
if (sortConfig.key !== key) return <span className="text-slate-600 opacity-20 group-hover:opacity-100 transition-opacity ml-0.5">↕</span>;
|
||||
return <span className="text-primary ml-0.5">{sortConfig.direction === 'asc' ? '↑' : '↓'}</span>;
|
||||
};
|
||||
|
||||
const handleExport = () => {
|
||||
@@ -1256,11 +1256,11 @@ const DataGrid: React.FC<DataGridProps> = ({ data, filters, hasCustomerFilter, a
|
||||
return (
|
||||
<th
|
||||
key={dim}
|
||||
className={`px-4 py-3 border-b border-border group bg-slate-950 ${dim === 'title' ? 'min-w-[450px]' : 'min-w-[150px]'}`}
|
||||
className={`px-2.5 py-3 border-b border-border group bg-slate-950 ${dim === 'title' ? 'min-w-[400px]' : 'min-w-[140px]'}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center justify-between gap-1">
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:text-white"
|
||||
className="flex items-center cursor-pointer hover:text-white text-[11px] font-bold uppercase tracking-wide truncate"
|
||||
onClick={() => requestSort(dim)}
|
||||
>
|
||||
{label} {getSortIcon(dim)}
|
||||
@@ -1268,6 +1268,7 @@ const DataGrid: React.FC<DataGridProps> = ({ data, filters, hasCustomerFilter, a
|
||||
<ExcelFilter
|
||||
columnKey={dim}
|
||||
title={label}
|
||||
buttonClassName={`p-1 rounded hover:bg-white/10 transition-all ${columnFilters[dim] ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-500'}`}
|
||||
uniqueValues={uniqueValues}
|
||||
currentFilter={columnFilters[dim]}
|
||||
onFilterChange={handleColumnFilterChange}
|
||||
@@ -1283,38 +1284,42 @@ const DataGrid: React.FC<DataGridProps> = ({ data, filters, hasCustomerFilter, a
|
||||
return (
|
||||
<React.Fragment key={year}>
|
||||
{/* Sell Out & Units */}
|
||||
<th className="px-4 py-3 border-b border-border text-right bg-slate-950 min-w-[120px]">
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:text-white"
|
||||
onClick={() => requestSort(`total_sellOut_${year}`)}
|
||||
>
|
||||
Sell Out {year} {getSortIcon(`total_sellOut_${year}`)}
|
||||
</div>
|
||||
<th className="px-2 py-2.5 border-b border-border bg-slate-950 min-w-[105px]">
|
||||
<div className="flex items-center justify-end gap-1 leading-none">
|
||||
<ExcelFilter
|
||||
columnKey={`total_sellOut_${year}`}
|
||||
title={`Sell Out ${year}`}
|
||||
buttonClassName={`w-4 h-4 flex items-center justify-center rounded hover:bg-white/10 transition-all ${columnFilters[`total_sellOut_${year}`] ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-600'}`}
|
||||
uniqueValues={Array.from(new Set(pivotRows.map(r => String(r.totalsByYear[year]?.sellOut || 0)))).sort((a, b) => parseFloat(a as string) - parseFloat(b as string))}
|
||||
currentFilter={columnFilters[`total_sellOut_${year}`]}
|
||||
onFilterChange={handleColumnFilterChange}
|
||||
icon={<FunnelIcon className="w-2.5 h-2.5" />}
|
||||
/>
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:text-white text-[10px] font-black uppercase tracking-tight"
|
||||
onClick={() => requestSort(`total_sellOut_${year}`)}
|
||||
>
|
||||
{year} SO {getSortIcon(`total_sellOut_${year}`)}
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th className="px-4 py-3 border-b border-border text-right bg-slate-950 min-w-[100px]">
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:text-white"
|
||||
onClick={() => requestSort(`total_units_${year}`)}
|
||||
>
|
||||
Units {year} {getSortIcon(`total_units_${year}`)}
|
||||
</div>
|
||||
<th className="px-2 py-2.5 border-b border-border bg-slate-950 min-w-[85px]">
|
||||
<div className="flex items-center justify-end gap-1 leading-none">
|
||||
<ExcelFilter
|
||||
columnKey={`total_units_${year}`}
|
||||
title={`Units ${year}`}
|
||||
buttonClassName={`w-4 h-4 flex items-center justify-center rounded hover:bg-white/10 transition-all ${columnFilters[`total_units_${year}`] ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-600'}`}
|
||||
uniqueValues={Array.from(new Set(pivotRows.map(r => String(r.totalsByYear[year]?.units || 0)))).sort((a, b) => parseFloat(a as string) - parseFloat(b as string))}
|
||||
currentFilter={columnFilters[`total_units_${year}`]}
|
||||
onFilterChange={handleColumnFilterChange}
|
||||
icon={<FunnelIcon className="w-2.5 h-2.5" />}
|
||||
/>
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:text-white text-[10px] font-black uppercase tracking-tight"
|
||||
onClick={() => requestSort(`total_units_${year}`)}
|
||||
>
|
||||
{year} U {getSortIcon(`total_units_${year}`)}
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
|
||||
@@ -1370,7 +1375,7 @@ const DataGrid: React.FC<DataGridProps> = ({ data, filters, hasCustomerFilter, a
|
||||
{paginatedRows.map((row) => (
|
||||
<tr key={row.id} className="hover:bg-slate-800/50 transition-colors group relative hover:z-50">
|
||||
{effectiveDimensions.map(dim => (
|
||||
<td key={dim} className="px-4 py-3 font-medium text-slate-200 break-words max-w-xs">
|
||||
<td key={dim} className="px-2.5 py-3 font-medium text-slate-200 break-words max-w-xs">
|
||||
{dim === 'title'
|
||||
? <div className="flex items-start gap-2 max-w-sm relative group/title">
|
||||
<span className="line-clamp-2 cursor-help decoration-dotted underline underline-offset-2 decoration-slate-600">
|
||||
@@ -1435,10 +1440,10 @@ const DataGrid: React.FC<DataGridProps> = ({ data, filters, hasCustomerFilter, a
|
||||
|
||||
return (
|
||||
<React.Fragment key={year}>
|
||||
<td className="px-4 py-3 text-right font-medium text-white group-hover:text-emerald-400 transition-colors">
|
||||
<td className="px-2 py-3 text-right font-medium text-white group-hover:text-emerald-400 transition-colors">
|
||||
{data ? `€${data.sellOut.toLocaleString('de-DE', { maximumFractionDigits: 0 })}` : '-'}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-right text-slate-400">
|
||||
<td className="px-2 py-3 text-right text-slate-400">
|
||||
{data ? data.units.toLocaleString('de-DE') : '-'}
|
||||
</td>
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ export const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
||||
uniqueValues,
|
||||
currentFilter,
|
||||
onFilterChange,
|
||||
icon
|
||||
icon,
|
||||
buttonClassName
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [operator, setOperator] = useState<typeof OPERATORS[number]['value']>(currentFilter?.textFilter?.operator || '');
|
||||
@@ -113,16 +114,16 @@ export const ExcelFilter: React.FC<ExcelFilterProps> = ({
|
||||
const hasActiveFilter = !!(currentFilter?.textFilter || currentFilter?.selectedValues);
|
||||
|
||||
return (
|
||||
<div className="relative inline-block ml-1" ref={containerRef}>
|
||||
<div className="relative inline-block" ref={containerRef}>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
className={`flex flex-col items-center gap-0.5 p-1 rounded hover:bg-white/10 transition-all ${hasActiveFilter ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-500'}`}
|
||||
className={buttonClassName || `flex items-center justify-center p-1 rounded hover:bg-white/10 transition-all ${hasActiveFilter ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-500'}`}
|
||||
title={`Filter by ${title}`}
|
||||
>
|
||||
{icon || <FunnelIcon className="w-3 h-3" />}
|
||||
{icon || <FunnelIcon className={buttonClassName?.includes('w-') ? '' : "w-3 h-3"} />}
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
|
||||
Reference in New Issue
Block a user