page.tsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import '../style.scss';
  2. import '@/app/styles/data-table.scss';
  3. import { Metadata } from 'next';
  4. import MarketNav from '../_components/MarketNav';
  5. import LockupCalendarTable from '../_components/LockupCalendarTable';
  6. import Pager from '../_components/Pager';
  7. import { fetchLockupCalendar } from '@/lib/api/seibro';
  8. import { formatNumber } from '@/lib/utils/stock';
  9. export const metadata: Metadata = {
  10. title: '락업(보호예수) 캘린더 — 개미투자',
  11. description: '보호예수 예수·해제 일정 — 종목·해제일·수량·사유 (오버행 리스크 점검, SEIBro 수집)'
  12. };
  13. const PER_PAGE = 30;
  14. type Props = {
  15. searchParams: Promise<{
  16. page?: string;
  17. }>;
  18. };
  19. export default async function MarketLockupPage({ searchParams }: Props)
  20. {
  21. const query = await searchParams;
  22. const page = Math.max(Number(query.page) || 1, 1);
  23. const res = await fetchLockupCalendar({ page, perPage: PER_PAGE });
  24. const data = res.success ? res.data : null;
  25. return (
  26. <div className='market'>
  27. <div className='market__head'>
  28. <h1 className='market__title'>락업 (보호예수)</h1>
  29. <span className='market__basis'>예수/반환 최신순 · 해제일·수량·사유 (SEIBro)</span>
  30. </div>
  31. <MarketNav />
  32. {!res.success ? (
  33. <div className='market__error' role='alert'>
  34. <strong>락업 일정을 불러오지 못했습니다.</strong>
  35. 잠시 후 다시 시도해 주세요.
  36. </div>
  37. ) : !data || data.list.length === 0 ? (
  38. <div className='market__empty'>표시할 락업 일정이 없습니다.</div>
  39. ) : (
  40. <>
  41. <p className='market__total'>전체 {formatNumber(data.total)}건</p>
  42. <div className='market__table-wrap'>
  43. <LockupCalendarTable rows={data.list} />
  44. </div>
  45. <Pager
  46. total={data.total}
  47. page={page}
  48. perPage={PER_PAGE}
  49. basePath='/market/lockup'
  50. query={{}}
  51. />
  52. </>
  53. )}
  54. </div>
  55. );
  56. }