page.tsx 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import '../style.scss';
  2. import '@/app/styles/data-table.scss';
  3. import { Metadata } from 'next';
  4. import MarketNav from '../_components/MarketNav';
  5. import MarketFilterTabs from '../_components/MarketFilterTabs';
  6. import CommoditiesTable from '../_components/CommoditiesTable';
  7. import Pager from '../_components/Pager';
  8. import { fetchMarketCommodities } from '@/lib/api/market';
  9. import { CommodityMarketName } from '@/types/market';
  10. import { formatNumber } from '@/lib/utils/stock';
  11. import { tradeDateLabel } from '@/lib/utils/market';
  12. export const metadata: Metadata = {
  13. title: '상품 (석유·금·배출권) — 개미투자',
  14. description: '국내 파생상품시장 상품 시세 — 석유·금·배출권 현재가·등락률·거래량 (전일 종가 기준)'
  15. };
  16. const MARKET_TABS: { value: CommodityMarketName; label: string }[] = [
  17. { value: 'Oil', label: '석유' },
  18. { value: 'Gold', label: '금' },
  19. { value: 'Emission', label: '배출권' }
  20. ];
  21. const PER_PAGE = 20;
  22. type Props = {
  23. searchParams: Promise<{
  24. market?: string;
  25. page?: string;
  26. }>;
  27. };
  28. export default async function MarketCommoditiesPage({ searchParams }: Props)
  29. {
  30. const query = await searchParams;
  31. const market: CommodityMarketName = MARKET_TABS.some(c => c.value === query.market) ? (query.market as CommodityMarketName) : 'Oil';
  32. const page = Math.max(Number(query.page) || 1, 1);
  33. const res = await fetchMarketCommodities({ market, page });
  34. const data = res.success ? res.data : null;
  35. return (
  36. <div className='market'>
  37. <div className='market__head'>
  38. <h1 className='market__title'>상품</h1>
  39. <span className='market__basis'>{tradeDateLabel(data?.tradeDate)} · 석유/금/배출권</span>
  40. </div>
  41. <MarketNav />
  42. <div className='market__filters'>
  43. <MarketFilterTabs
  44. label='시장'
  45. paramKey='market'
  46. tabs={MARKET_TABS}
  47. active={market}
  48. basePath='/market/commodities'
  49. />
  50. </div>
  51. {!res.success ? (
  52. <div className='market__error' role='alert'>
  53. <strong>상품 목록을 불러오지 못했습니다.</strong>
  54. 잠시 후 다시 시도해 주세요.
  55. </div>
  56. ) : !data || data.list.length === 0 ? (
  57. <div className='market__empty'>표시할 상품이 없습니다.</div>
  58. ) : (
  59. <>
  60. <p className='market__total'>전체 {formatNumber(data.total)}종목</p>
  61. <div className='market__table-wrap'>
  62. <CommoditiesTable rows={data.list} />
  63. </div>
  64. <Pager
  65. total={data.total}
  66. page={page}
  67. perPage={PER_PAGE}
  68. basePath='/market/commodities'
  69. query={{ market }}
  70. />
  71. </>
  72. )}
  73. </div>
  74. );
  75. }