refactor(clients): rebuild detail tabs + columns for new data model

- ClientData in client-detail.tsx now reflects the stripped shape from
  Task 8.2 (drop companyName/isProxy/proxy*/yacht*/berthSizeDesired) and
  gains yachts / companies / activeReservations arrays.
- client-tabs.tsx: Overview trimmed (personal, contacts, source, tags);
  three new count-badged tabs (Yachts, Companies, Reservations).
- New client-yachts-tab.tsx renders owned yachts + Add yacht CTA (TODO:
  YachtForm preset-owner wiring for v2).
- New client-companies-tab.tsx renders memberships with Primary badge and
  since-date; management still lives on the company detail page.
- New client-reservations-tab.tsx maps activeReservations into ReservationRow
  shape and delegates to <ReservationList showBerth />.
- client-columns.tsx drops companyName column (TODO: add Yachts count +
  Primary company once list endpoint joins those).
- client-filters.tsx drops isProxy filter.
- Wire realtime invalidations for yacht:ownership_transferred,
  company_membership:added/ended, and berth_reservation:*.
This commit is contained in:
Matt Ciaccio
2026-04-24 14:36:34 +02:00
parent 4c171848fc
commit b75834ab7e
7 changed files with 374 additions and 113 deletions

View File

@@ -0,0 +1,51 @@
'use client';
import { ReservationList, type ReservationRow } from '@/components/reservations/reservation-list';
interface ClientReservationsTabProps {
clientId: string;
activeReservations: Array<{
id: string;
berthId: string;
yachtId: string;
startDate: string | Date;
tenureType: string;
status: string;
}>;
}
export function ClientReservationsTab({
clientId,
activeReservations,
}: ClientReservationsTabProps) {
const rows: ReservationRow[] = activeReservations.map((r) => ({
id: r.id,
berthId: r.berthId,
portId: '', // not rendered by ReservationList
clientId,
yachtId: r.yachtId,
status: r.status as ReservationRow['status'],
startDate: typeof r.startDate === 'string' ? r.startDate : r.startDate.toISOString(),
endDate: null,
tenureType: r.tenureType,
contractFileId: null,
notes: null,
createdAt: '',
}));
return (
<div className="space-y-4">
<div>
<h3 className="text-sm font-medium">Active reservations</h3>
<p className="text-xs text-muted-foreground mt-0.5">
Showing currently active reservations. History is coming soon.
</p>
</div>
<ReservationList
reservations={rows}
showBerth
emptyMessage="This client has no active reservations."
/>
</div>
);
}