Files
auto-trade/features/trade/components/search/TradeSearchSection.tsx

102 lines
3.7 KiB
TypeScript
Raw Normal View History

2026-02-12 10:24:03 +09:00
import type { FormEvent, KeyboardEvent, FocusEvent, MutableRefObject } from "react";
import { StockSearchForm } from "@/features/trade/components/search/StockSearchForm";
import { StockSearchHistory } from "@/features/trade/components/search/StockSearchHistory";
import { StockSearchResults } from "@/features/trade/components/search/StockSearchResults";
import type {
DashboardStockSearchHistoryItem,
DashboardStockSearchItem,
} from "@/features/trade/types/trade.types";
interface TradeSearchSectionProps {
canSearch: boolean;
isSearchPanelOpen: boolean;
isSearching: boolean;
keyword: string;
selectedSymbol?: string;
searchResults: DashboardStockSearchItem[];
searchHistory: DashboardStockSearchHistoryItem[];
searchShellRef: MutableRefObject<HTMLDivElement | null>;
onKeywordChange: (value: string) => void;
onSearchSubmit: (event: FormEvent) => void;
onSearchFocus: () => void;
onSearchShellBlur: (event: FocusEvent<HTMLDivElement>) => void;
onSearchShellKeyDown: (event: KeyboardEvent<HTMLDivElement>) => void;
onSelectStock: (item: DashboardStockSearchItem) => void;
onRemoveHistory: (symbol: string) => void;
onClearHistory: () => void;
}
/**
* @description // .
* @see features/trade/components/TradeContainer.tsx TradeContainer에서 .
* @see features/trade/hooks/useTradeSearchPanel.ts / .
*/
export function TradeSearchSection({
canSearch,
isSearchPanelOpen,
isSearching,
keyword,
selectedSymbol,
searchResults,
searchHistory,
searchShellRef,
onKeywordChange,
onSearchSubmit,
onSearchFocus,
onSearchShellBlur,
onSearchShellKeyDown,
onSelectStock,
onRemoveHistory,
onClearHistory,
}: TradeSearchSectionProps) {
return (
<div className="z-30 flex-none border-b bg-background/95 p-4 backdrop-blur-sm dark:border-brand-800/45 dark:bg-brand-900/22">
{/* ========== SEARCH SHELL ========== */}
<div
ref={searchShellRef}
onBlurCapture={onSearchShellBlur}
onKeyDownCapture={onSearchShellKeyDown}
className="relative mx-auto max-w-2xl"
>
<StockSearchForm
keyword={keyword}
onKeywordChange={onKeywordChange}
onSubmit={onSearchSubmit}
onInputFocus={onSearchFocus}
disabled={!canSearch}
isLoading={isSearching}
/>
{/* ========== SEARCH DROPDOWN ========== */}
{isSearchPanelOpen && canSearch && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-80 overflow-x-hidden overflow-y-auto rounded-md border bg-background shadow-lg dark:border-brand-800/45 dark:bg-brand-950/95">
{searchResults.length > 0 ? (
<StockSearchResults
items={searchResults}
onSelect={onSelectStock}
selectedSymbol={selectedSymbol}
/>
) : keyword.trim() ? (
<div className="px-3 py-2 text-sm text-muted-foreground">
{isSearching ? "검색 중..." : "검색 결과가 없습니다."}
</div>
) : searchHistory.length > 0 ? (
<StockSearchHistory
items={searchHistory}
onSelect={onSelectStock}
onRemove={onRemoveHistory}
onClear={onClearHistory}
selectedSymbol={selectedSymbol}
/>
) : (
<div className="px-3 py-2 text-sm text-muted-foreground">
.
</div>
)}
</div>
)}
</div>
</div>
);
}