diff --git a/src/app/api/v1/yachts/autocomplete/handlers.ts b/src/app/api/v1/yachts/autocomplete/handlers.ts
index 48d6166b..7f00e251 100644
--- a/src/app/api/v1/yachts/autocomplete/handlers.ts
+++ b/src/app/api/v1/yachts/autocomplete/handlers.ts
@@ -6,10 +6,7 @@ import { autocomplete } from '@/lib/services/yachts.service';
export const autocompleteHandler: RouteHandler = async (req, ctx) => {
try {
- const q = req.nextUrl.searchParams.get('q');
- if (!q) {
- return NextResponse.json({ data: [] });
- }
+ const q = req.nextUrl.searchParams.get('q') ?? '';
const yachts = await autocomplete(ctx.portId, q);
return NextResponse.json({ data: yachts });
} catch (error) {
diff --git a/src/components/admin/bulk-add-berths-wizard.tsx b/src/components/admin/bulk-add-berths-wizard.tsx
index 1b937115..a785006e 100644
--- a/src/components/admin/bulk-add-berths-wizard.tsx
+++ b/src/components/admin/bulk-add-berths-wizard.tsx
@@ -36,6 +36,7 @@ import {
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { useVocabulary } from '@/hooks/use-vocabulary';
+import { CurrencySelect } from '@/components/shared/currency-select';
const DOCK_LETTERS = ['A', 'B', 'C', 'D', 'E'] as const;
type DockLetter = (typeof DOCK_LETTERS)[number];
@@ -283,12 +284,10 @@ export function BulkAddBerthsWizard() {
/>
- applyToAll('priceCurrency', v)}
className="h-7 text-xs"
- onBlur={(e) => {
- if (e.target.value) applyToAll('priceCurrency', e.target.value.toUpperCase());
- }}
- placeholder="all"
/>
|
|
@@ -351,12 +350,10 @@ export function BulkAddBerthsWizard() {
/>
-
- setRowField(idx, 'priceCurrency', e.target.value.toUpperCase())
- }
+ setRowField(idx, 'priceCurrency', v)}
+ className="h-7 w-24 text-xs"
/>
|
diff --git a/src/components/documents/documents-hub.tsx b/src/components/documents/documents-hub.tsx
index 9cc35baf..25e1cb61 100644
--- a/src/components/documents/documents-hub.tsx
+++ b/src/components/documents/documents-hub.tsx
@@ -193,9 +193,9 @@ export function DocumentsHub({ portSlug }: DocumentsHubProps) {
const contentPane = (
-
-
- {selectedFolderId !== undefined && (
+ {selectedFolderId !== undefined && (
+
+
- )}
-
+
+ )}
{selectedFolderId === undefined ? (
<>
diff --git a/src/components/yachts/yacht-picker.tsx b/src/components/yachts/yacht-picker.tsx
index 2bddc9e0..c3c02333 100644
--- a/src/components/yachts/yacht-picker.tsx
+++ b/src/components/yachts/yacht-picker.tsx
@@ -72,10 +72,23 @@ export function YachtPicker({
)
: rawOptions;
+ // When `value` is set but the selected yacht isn't in the current
+ // autocomplete window (e.g. parent pre-selected it from a URL param
+ // or the rep typed something that filtered it out), fetch its name
+ // by id so the trigger doesn't fall back to "Yacht ".
+ const fallbackQuery = useQuery<{ data: { name: string } }>({
+ queryKey: ['yacht-detail-label', value],
+ queryFn: () => apiFetch(`/api/v1/yachts/${value}`),
+ enabled: !!value && !rawOptions.some((o) => o.id === value),
+ staleTime: 60_000,
+ });
+
const selectedLabel = (() => {
if (!value) return placeholder;
const match = rawOptions.find((o) => o.id === value);
- return match?.name ?? `Yacht ${value.slice(0, 8)}`;
+ if (match) return match.name;
+ if (fallbackQuery.data?.data.name) return fallbackQuery.data.data.name;
+ return `Yacht ${value.slice(0, 8)}`;
})();
return (
diff --git a/src/lib/services/yachts.service.ts b/src/lib/services/yachts.service.ts
index 39435c94..5f277524 100644
--- a/src/lib/services/yachts.service.ts
+++ b/src/lib/services/yachts.service.ts
@@ -1,4 +1,4 @@
-import { and, eq, ilike, inArray, isNull, or, sql } from 'drizzle-orm';
+import { and, desc, eq, ilike, inArray, isNull, or, sql } from 'drizzle-orm';
import { db } from '@/lib/db';
import { yachts, yachtOwnershipHistory, yachtTags, clients } from '@/lib/db/schema';
import type { Yacht } from '@/lib/db/schema/yachts';
@@ -393,6 +393,17 @@ export async function listOwnershipHistory(yachtId: string, portId: string) {
// ─── Autocomplete ─────────────────────────────────────────────────────────────
export async function autocomplete(portId: string, q: string) {
+ // Empty query returns the top 20 most-recently-updated yachts so the
+ // picker has something useful to show the moment it opens, instead of
+ // a dead-end empty state until the rep types something.
+ if (!q) {
+ return await db
+ .select()
+ .from(yachts)
+ .where(eq(yachts.portId, portId))
+ .orderBy(desc(yachts.updatedAt))
+ .limit(20);
+ }
const pattern = `%${q}%`;
return await db
.select()
|