From 81c9a5d692d4a8cfc7c9054bdf0e24e7565caac9 Mon Sep 17 00:00:00 2001 From: gahusb Date: Fri, 10 Jul 2026 10:10:42 +0900 Subject: [PATCH] =?UTF-8?q?refactor(portfolio):=20formatPriceTime=20util?= =?UTF-8?q?=20+=20PriceSessionBadge=20=EC=B6=94=EC=B6=9C=20+=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01UHXzpsZQxKG9hQmNRfZjRS --- src/pages/stock/components/PortfolioTab.jsx | 21 +------------------ .../portfolio/PriceSessionBadge.jsx | 17 +++++++++++++++ .../portfolio/PriceSessionBadge.test.jsx | 17 +++++++++++++++ .../components/portfolio/portfolioUtils.js | 6 ++++++ .../portfolio/portfolioUtils.test.js | 14 +++++++++++++ 5 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 src/pages/stock/components/portfolio/PriceSessionBadge.jsx create mode 100644 src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx create mode 100644 src/pages/stock/components/portfolio/portfolioUtils.js create mode 100644 src/pages/stock/components/portfolio/portfolioUtils.test.js diff --git a/src/pages/stock/components/PortfolioTab.jsx b/src/pages/stock/components/PortfolioTab.jsx index 2104fad..9582799 100644 --- a/src/pages/stock/components/PortfolioTab.jsx +++ b/src/pages/stock/components/PortfolioTab.jsx @@ -5,26 +5,7 @@ import { Tooltip as ChartTooltip, } from 'recharts'; import { formatNumber, formatPercent, toNumeric, profitColorClass, numFitClass } from '../stockUtils'; - -const formatPriceTime = (iso) => { - if (!iso) return ''; - const d = new Date(iso); - if (Number.isNaN(d.getTime())) return ''; - return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`; -}; - -const PriceSessionBadge = ({ session, asOf }) => { - if (session !== 'NXT_AFTER' && session !== 'NXT_PRE') return null; - const isPre = session === 'NXT_PRE'; - const label = isPre ? 'NXT 프리' : 'NXT'; - const desc = isPre ? 'NXT 프리마켓 거래가' : 'NXT 야간거래 (15:30~20:00)'; - const time = formatPriceTime(asOf); - return ( - - {label} - - ); -}; +import PriceSessionBadge from './portfolio/PriceSessionBadge'; const PortfolioTab = ({ pf, asset, handleSell, handleSaveSnapshot }) => ( <> diff --git a/src/pages/stock/components/portfolio/PriceSessionBadge.jsx b/src/pages/stock/components/portfolio/PriceSessionBadge.jsx new file mode 100644 index 0000000..390fbd3 --- /dev/null +++ b/src/pages/stock/components/portfolio/PriceSessionBadge.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { formatPriceTime } from './portfolioUtils'; + +const PriceSessionBadge = ({ session, asOf }) => { + if (session !== 'NXT_AFTER' && session !== 'NXT_PRE') return null; + const isPre = session === 'NXT_PRE'; + const label = isPre ? 'NXT 프리' : 'NXT'; + const desc = isPre ? 'NXT 프리마켓 거래가' : 'NXT 야간거래 (15:30~20:00)'; + const time = formatPriceTime(asOf); + return ( + + {label} + + ); +}; + +export default PriceSessionBadge; diff --git a/src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx b/src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx new file mode 100644 index 0000000..b31ca89 --- /dev/null +++ b/src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx @@ -0,0 +1,17 @@ +import { describe, it, expect } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import PriceSessionBadge from './PriceSessionBadge.jsx'; + +describe('PriceSessionBadge', () => { + it('NXT_AFTER → "NXT", NXT_PRE → "NXT 프리"', () => { + const { unmount } = render(); + expect(screen.getByText('NXT')).toBeInTheDocument(); + unmount(); + render(); + expect(screen.getByText('NXT 프리')).toBeInTheDocument(); + }); + it('그 외 세션 → 렌더 없음', () => { + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/src/pages/stock/components/portfolio/portfolioUtils.js b/src/pages/stock/components/portfolio/portfolioUtils.js new file mode 100644 index 0000000..414d01a --- /dev/null +++ b/src/pages/stock/components/portfolio/portfolioUtils.js @@ -0,0 +1,6 @@ +export const formatPriceTime = (iso) => { + if (!iso) return ''; + const d = new Date(iso); + if (Number.isNaN(d.getTime())) return ''; + return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`; +}; diff --git a/src/pages/stock/components/portfolio/portfolioUtils.test.js b/src/pages/stock/components/portfolio/portfolioUtils.test.js new file mode 100644 index 0000000..f9ae276 --- /dev/null +++ b/src/pages/stock/components/portfolio/portfolioUtils.test.js @@ -0,0 +1,14 @@ +import { describe, it, expect } from 'vitest'; +import { formatPriceTime } from './portfolioUtils.js'; + +describe('formatPriceTime', () => { + it('유효 ISO → HH:MM (제로패드)', () => { + expect(formatPriceTime('2026-07-10T09:05:00')).toBe('09:05'); + expect(formatPriceTime('2026-07-10T18:30:00')).toBe('18:30'); + }); + it('falsy/invalid → 빈 문자열', () => { + expect(formatPriceTime('')).toBe(''); + expect(formatPriceTime(null)).toBe(''); + expect(formatPriceTime('not-a-date')).toBe(''); + }); +});