diff --git a/apps/client/src/features/search/components/search-spotlight.tsx b/apps/client/src/features/search/components/search-spotlight.tsx index 725f8d51..1a5d89a6 100644 --- a/apps/client/src/features/search/components/search-spotlight.tsx +++ b/apps/client/src/features/search/components/search-spotlight.tsx @@ -1,6 +1,6 @@ import { Spotlight } from "@mantine/spotlight"; import { IconSearch } from "@tabler/icons-react"; -import { Group, VisuallyHidden } from "@mantine/core"; +import { Group, Text, VisuallyHidden } from "@mantine/core"; import { useState, useMemo } from "react"; import { useDebouncedValue } from "@mantine/hooks"; import { useTranslation } from "react-i18next"; @@ -84,6 +84,11 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) { onFiltersChange={handleFiltersChange} spaceId={spaceId} /> + {/* #529: operator hint — matches ANY word by default; "…" for an exact + phrase, +term to require, -term to exclude. */} + + {t('Tip: "exact phrase", +required, -excluded')} + diff --git a/apps/client/src/features/search/types/search.types.ts b/apps/client/src/features/search/types/search.types.ts index 5aa3195b..453e1535 100644 --- a/apps/client/src/features/search/types/search.types.ts +++ b/apps/client/src/features/search/types/search.types.ts @@ -5,6 +5,9 @@ import { IPage } from "@/features/page/types/page.types.ts"; export interface IPageSearch { id: string; + // #529 A7 superset: `pageId` aliases `id`; `rank`/`highlight` are null for + // substring-only hits (the UI already falls back to the title/snippet). + pageId?: string; title: string; icon: string; parentPageId: string; @@ -12,9 +15,36 @@ export interface IPageSearch { creatorId: string; createdAt: Date; updatedAt: Date; - rank: string; - highlight: string; + rank: string | number | null; + highlight: string | null; space: Partial; + // New #529 fields (present from the native Postgres search driver). + snippet?: string; + score?: number; + path?: string[]; + matchedFields?: string[]; + matchedTerms?: string[]; +} + +// #529 A5 pagination envelope returned by POST /search (native driver). The web +// list helpers read `items`; these travel alongside for pagination + diagnostics. +export interface IPageSearchResponse { + items: IPageSearch[]; + total: number; + hasMore: boolean; + truncatedAtCap: boolean; + offset: number; + query?: { + raw: string; + parsed: { + positive: string[]; + required: string[]; + excluded: string[]; + reason?: string; + }; + mode: "or" | "and"; + match: string; + }; } export interface SearchSuggestionParams { @@ -37,6 +67,10 @@ export interface IPageSearchParams { query: string; spaceId?: string; shareId?: string; + // #529 A9: match mode (auto default) + pagination. + match?: "auto" | "word" | "prefix" | "substring"; + limit?: number; + offset?: number; } export interface IAttachmentSearch {