import '../style.scss'; import '@/app/styles/data-table.scss'; import { Metadata } from 'next'; import Link from 'next/link'; import MarketNav from '../_components/MarketNav'; import MarketFilterTabs from '../_components/MarketFilterTabs'; import FuturesTable from '../_components/FuturesTable'; import OptionsTable from '../_components/OptionsTable'; import Pager from '../_components/Pager'; import { fetchMarketFutures, fetchMarketOptions } from '@/lib/api/market'; import { FuturesKindName, OptionsKindName, MarketSession, MarketSessionName } from '@/types/market'; import { formatNumber } from '@/lib/utils/stock'; import { tradeDateLabel } from '@/lib/utils/market'; export const metadata: Metadata = { title: '파생 (선물·옵션) — 개미투자', description: '국내 파생상품 시세 — 선물·옵션 현재가·정산가·미결제약정·거래량 (정규/야간 세션, 전일 종가 기준)' }; const SECTION_TABS: { value: 'futures'|'options'; label: string }[] = [ { value: 'futures', label: '선물' }, { value: 'options', label: '옵션' } ]; const KIND_TABS: { value: FuturesKindName&OptionsKindName; label: string }[] = [ { value: 'General', label: '일반' }, { value: 'StockKospi', label: '주식(코스피)' }, { value: 'StockKosdaq', label: '주식(코스닥)' } ]; // 세션 토글 (정규/야간) — API 로는 숫자 1/2 전송 (MarketSession) const SESSION_TABS: { value: MarketSessionName; label: string }[] = [ { value: 'Regular', label: '정규' }, { value: 'Night', label: '야간' } ]; const PER_PAGE = 20; type Props = { searchParams: Promise<{ section?: string; kind?: string; session?: string; page?: string; }>; }; export default async function MarketDerivativesPage({ searchParams }: Props) { const query = await searchParams; const section: 'futures'|'options' = SECTION_TABS.some(c => c.value === query.section) ? (query.section as 'futures'|'options') : 'futures'; const kind = KIND_TABS.some(c => c.value === query.kind) ? (query.kind as FuturesKindName&OptionsKindName) : 'General'; const session: MarketSessionName = query.session === 'Night' ? 'Night' : 'Regular'; const isNight = session === 'Night'; const page = Math.max(Number(query.page) || 1, 1); const futuresRes = section === 'futures' ? await fetchMarketFutures({ kind, page, session: MarketSession[session] }) : null; const optionsRes = section === 'options' ? await fetchMarketOptions({ kind, page, session: MarketSession[session] }) : null; const res = section === 'futures' ? futuresRes! : optionsRes!; const data = res.success ? res.data : null; const tradeDate = section === 'futures' ? futuresRes?.data?.tradeDate : optionsRes?.data?.tradeDate; const sectionLabel = section === 'futures' ? '선물' : '옵션'; return (

파생

{tradeDateLabel(tradeDate)} · 선물/옵션{isNight ? ' · 야간 세션' : ''}
{/* 선물/옵션 섹션 탭 (kind 는 섹션 변경 시 초기화, 세션은 유지) */} {!res.success ? (
{sectionLabel} 목록을 불러오지 못했습니다. 잠시 후 다시 시도해 주세요.
) : !data || data.list.length === 0 ? (
{isNight ? `야간 세션 ${sectionLabel} 데이터가 없습니다. 야간(글로벌) 시세 수집 전이거나 휴장일 수 있습니다.` : `표시할 ${sectionLabel}이 없습니다.`}
) : ( <>

전체 {formatNumber(data.total)}종목

{section === 'futures' ? ( ) : ( )}
)}
); }