feat(grouping): add area grouping, refine UI and cleanup

- update dev server port to 4001 in package.json
- remove unused formatCurrency import from SupplierGroup component
- refactor cluster label generation for better multi-supplier display
- overhaul AreaGroup UI to use chip-style supplier tags with updated typography
- expand collapseAll handler to support both supplier and area group modes
This commit is contained in:
SJCoetz 2026-07-10 02:01:57 +02:00
parent 85662380a2
commit 2a7720cd1f
6 changed files with 43 additions and 20 deletions

View file

@ -311,7 +311,13 @@ const loadItems = useCallback(async (showLoading = true) => {
}
};
const collapseAll = () => setExpandedSuppliers(new Set());
const collapseAll = () => {
if (groupMode === 'supplier') {
setExpandedSuppliers(new Set());
} else {
setExpandedAreas(new Set());
}
};
// Group by supplier - items without supplier are grouped under "Unknown"
const groupedArray = useMemo(() => {

View file

@ -93,19 +93,27 @@ export default function AreaGroup({
</div>
<div className="flex-1 min-w-0">
<h2 className={cn('font-semibold text-[15px] truncate leading-snug', color.text)}>
<h2 className={cn('font-bold text-[17px] leading-snug', color.text)}>
{label}
</h2>
{uniqueSuppliers.length > 1 ? (
<p className="text-[12px] text-[rgba(38,37,30,0.55)] truncate mt-0.5">
{uniqueSuppliers.join(' · ')}
</p>
) : uniqueSuppliers.length === 1 ? (
<p className="text-[12px] text-[rgba(38,37,30,0.55)] truncate mt-0.5 flex items-center gap-1">
<MapPin size={10} aria-hidden="true" />
{uniqueSuppliers[0]}
</p>
) : null}
{uniqueSuppliers.length > 0 && (
<div className="flex flex-wrap gap-1.5 mt-1.5">
{uniqueSuppliers.map((name) => (
<span
key={name}
className={cn(
'inline-flex items-center gap-1 px-2.5 py-1 rounded-lg text-[12px] font-semibold',
color.light,
color.text,
`ring-1 ${color.ring}`
)}
>
<MapPin size={10} aria-hidden="true" />
{name}
</span>
))}
</div>
)}
</div>
<div className="flex items-center gap-2 flex-shrink-0">

View file

@ -1,7 +1,7 @@
'use client';
import { OrderItem, Supplier } from '@/lib/types';
import { cn, formatCurrency, parseCoordinates } from '@/lib/utils';
import { cn, parseCoordinates } from '@/lib/utils';
import CollectionItemCard from '@/components/CollectionItemCard';
import {
ChevronDown,

View file

@ -163,15 +163,24 @@ export function clusterByProximity<T extends { id: string; expand?: { supplier?:
)
);
let label: string;
if (supplierNames.length === 0) {
label = `Stop ${clusters.length + 1}`;
} else if (supplierNames.length === 1) {
label = supplierNames[0];
} else if (supplierNames.length === 2) {
label = `${supplierNames[0]} · ${supplierNames[1]}`;
} else if (supplierNames.length === 3) {
label = `${supplierNames[0]} · ${supplierNames[1]} · ${supplierNames[2]}`;
} else {
label = `${supplierNames[0]} · ${supplierNames[1]} +${supplierNames.length - 2} more`;
}
clusters.push({
id: `cluster-${clusters.length}`,
items: clusterItems.map(c => c.item),
center: { latitude: centerLat, longitude: centerLng },
label: supplierNames.length === 1
? supplierNames[0]
: supplierNames.length > 1
? `${supplierNames[0]} +${supplierNames.length - 1}`
: `Stop ${clusters.length + 1}`,
label,
});
}

View file

@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev -p 4001",
"build": "next build",
"export": "NEXT_EXPORT=true next build",
"start": "next start",

File diff suppressed because one or more lines are too long