feat(berths): active-interests popover + row-density toggle on berth list
Two complementary UX upgrades on the berth list: 1. Active-interests popover — replaces the plain "Active interests" count cell with a click-to-expand popover. Each row shows the linked deal's client name, pipeline stage (with stage-badge tint), and a primary-star icon. Lazy-loads on first open (30s stale), capped at 20 entries server-side, sorted most-recently-updated first. Backed by `GET /api/v1/berths/[id]/active-interests`. 2. Row-density toggle — DataTable gains a `density: 'comfortable' | 'compact'` prop. Compact drops cell vertical padding from py-3 to py-1.5 so reps can scan many more berths per viewport on the high-density admin lists. Persisted alongside hidden-columns in `user_profiles.preferences. tablePreferences[entityType].density`. Hook returns `density + setDensity`; defaults to 'comfortable' for users who haven't chosen. The setter shares the same debounced PATCH with setHidden so toggling both doesn't multiply the network round-trips. Toolbar adds a Rows3/Rows4 icon button between the saved-views dropdown and the ColumnPicker. tooltip + aria-label flip to communicate the next state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import { formatCurrency } from '@/lib/utils/currency';
|
||||
import { mooringLetterDot } from './mooring-letter-tone';
|
||||
import { stageBadgeClass, stageLabel } from '@/lib/constants';
|
||||
import { CatchUpWizard } from '@/components/berths/catch-up-wizard';
|
||||
import { ActiveInterestsPopover } from '@/components/berths/active-interests-popover';
|
||||
|
||||
export type BerthRow = {
|
||||
id: string;
|
||||
@@ -226,6 +227,12 @@ function ActionsCell({ row }: { row: { original: BerthRow } }) {
|
||||
);
|
||||
}
|
||||
|
||||
function ActiveInterestsCell({ berthId, count }: { berthId: string; count: number }) {
|
||||
const params = useParams<{ portSlug: string }>();
|
||||
const portSlug = params?.portSlug ?? '';
|
||||
return <ActiveInterestsPopover berthId={berthId} portSlug={portSlug} count={count} />;
|
||||
}
|
||||
|
||||
function joinNonNull(parts: Array<string | null | undefined>, sep = ' · '): string {
|
||||
return parts.filter((p): p is string => Boolean(p)).join(sep);
|
||||
}
|
||||
@@ -290,11 +297,12 @@ export const berthColumns: ColumnDef<BerthRow, unknown>[] = [
|
||||
id: 'activeInterestCount',
|
||||
accessorKey: 'activeInterestCount',
|
||||
header: 'Active interests',
|
||||
cell: ({ row }) => {
|
||||
const n = row.original.activeInterestCount ?? 0;
|
||||
if (n === 0) return <span className="text-muted-foreground">—</span>;
|
||||
return <span className="font-medium tabular-nums">{n}</span>;
|
||||
},
|
||||
cell: ({ row }) => (
|
||||
<ActiveInterestsCell
|
||||
berthId={row.original.id}
|
||||
count={row.original.activeInterestCount ?? 0}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'sidePontoon',
|
||||
|
||||
Reference in New Issue
Block a user