Files
pn-new-crm/src/components/companies/company-owned-yachts-tab.tsx
Matt Ciaccio 8699f81879
Some checks failed
Build & Push Docker Images / lint (push) Failing after 1m18s
Build & Push Docker Images / build-and-push (push) Has been skipped
chore(style): codebase em-dash sweep + minor layout polish
Replaces every em-dash and en-dash with regular ASCII hyphens
across comments, JSX strings, and dev-facing logs. Mostly cosmetic
but stops the inconsistent mix that crept in over the last few
months (some files used em-dashes in comments, others didn't,
some used both).

Bundles two small dashboard-layout tweaks that touch a couple of
already-modified files:
- (dashboard)/layout.tsx main padding goes from p-6 to pt-3 px-6
  pb-6 so page content sits closer to the topbar.
- Sidebar now receives the ports list it needs for the footer
  port switcher.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 22:57:01 +02:00

157 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import Link from 'next/link';
import { useQuery } from '@tanstack/react-query';
import { Loader2 } from 'lucide-react';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { EmptyState } from '@/components/shared/empty-state';
import { apiFetch } from '@/lib/api/client';
interface OwnedYachtRow {
id: string;
name: string;
hullNumber: string | null;
lengthFt: string | null;
widthFt: string | null;
lengthM: string | null;
widthM: string | null;
status: string;
}
interface YachtListResponse {
data: OwnedYachtRow[];
}
interface CompanyOwnedYachtsTabProps {
companyId: string;
portSlug: string;
}
const STATUS_COLORS: Record<string, string> = {
active: 'bg-green-100 text-green-800 border-green-300',
retired: 'bg-gray-100 text-gray-800 border-gray-300',
sold_away: 'bg-amber-100 text-amber-800 border-amber-300',
};
const STATUS_LABELS: Record<string, string> = {
active: 'Active',
retired: 'Retired',
sold_away: 'Sold Away',
};
function formatDimensions(y: OwnedYachtRow): string | null {
if (y.lengthFt || y.widthFt) {
const length = y.lengthFt ?? '-';
const width = y.widthFt ?? '-';
return `${length} × ${width} ft`;
}
if (y.lengthM || y.widthM) {
const length = y.lengthM ?? '-';
const width = y.widthM ?? '-';
return `${length} × ${width} m`;
}
return null;
}
export function CompanyOwnedYachtsTab({ companyId, portSlug }: CompanyOwnedYachtsTabProps) {
const { data, isLoading } = useQuery<OwnedYachtRow[]>({
queryKey: ['companies', companyId, 'owned-yachts'],
queryFn: async () => {
const params = new URLSearchParams({
ownerType: 'company',
ownerId: companyId,
page: '1',
limit: '50',
includeArchived: 'false',
order: 'desc',
});
const res = await apiFetch<YachtListResponse>(`/api/v1/yachts?${params.toString()}`);
return res.data;
},
});
if (isLoading) {
return (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
</div>
);
}
const yachts = data ?? [];
if (yachts.length === 0) {
return (
<EmptyState
title="No yachts owned"
description="Yachts owned by this company will appear here."
/>
);
}
return (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Dimensions</TableHead>
<TableHead>Hull Number</TableHead>
<TableHead>Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{yachts.map((y) => {
const dims = formatDimensions(y);
const statusLabel = STATUS_LABELS[y.status] ?? y.status;
const statusColor =
STATUS_COLORS[y.status] ?? 'bg-muted text-muted-foreground border-muted';
return (
<TableRow key={y.id}>
<TableCell>
<Link
// eslint-disable-next-line @typescript-eslint/no-explicit-any
href={`/${portSlug}/yachts/${y.id}` as any}
className="font-medium text-primary hover:underline"
>
{y.name}
</Link>
</TableCell>
<TableCell>
{dims ? (
<span className="text-sm">{dims}</span>
) : (
<span className="text-muted-foreground">-</span>
)}
</TableCell>
<TableCell>
{y.hullNumber ? (
<span className="text-sm">{y.hullNumber}</span>
) : (
<span className="text-muted-foreground">-</span>
)}
</TableCell>
<TableCell>
<span
className={`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium ${statusColor}`}
>
{statusLabel}
</span>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
);
}