게시판 등록시간 수정
This commit is contained in:
@@ -28,7 +28,10 @@ export interface ChartLegendBarProps {
|
||||
useUpbit: boolean;
|
||||
wsStatus: WsStatus;
|
||||
mode: ChartMode;
|
||||
/** 크로스헤어·OHLC 범례용 (없으면 quoteBar) */
|
||||
currentBar: LegendData | null;
|
||||
/** 종목명 옆 시세·등락 — 실시간 현재가만 (크로스헤어 미반영) */
|
||||
quoteBar?: LegendData | null;
|
||||
isUp: boolean;
|
||||
dailyChange: number;
|
||||
dailyChangePct: number;
|
||||
@@ -44,13 +47,16 @@ export const ChartLegendBar: React.FC<ChartLegendBarProps> = ({
|
||||
wsStatus,
|
||||
mode,
|
||||
currentBar,
|
||||
quoteBar: quoteBarProp,
|
||||
isUp,
|
||||
dailyChange,
|
||||
dailyChangePct,
|
||||
indicators,
|
||||
legend,
|
||||
}) => {
|
||||
const showOhlc = currentBar && (v.open || v.high || v.low || v.close || v.change);
|
||||
const ohlcBar = currentBar;
|
||||
const quoteBar = quoteBarProp ?? currentBar;
|
||||
const showOhlc = ohlcBar && (v.open || v.high || v.low || v.close || v.change);
|
||||
const showAny =
|
||||
v.symbol || v.timeframe || (useUpbit && v.liveStatus) || (mode === 'trading' && v.tradingBadge)
|
||||
|| showOhlc || (v.indicators && indicators.length > 0);
|
||||
@@ -70,17 +76,17 @@ export const ChartLegendBar: React.FC<ChartLegendBarProps> = ({
|
||||
{mode === 'trading' && v.tradingBadge && <span className="tv-legend-badge trading">✏</span>}
|
||||
{showOhlc && (
|
||||
<span className="tv-legend-ohlcv">
|
||||
{v.open && (
|
||||
<span>O <b className={isUp ? 'up' : 'down'}>{formatPrice(currentBar!.open)}</b></span>
|
||||
{v.open && ohlcBar && (
|
||||
<span>O <b className={isUp ? 'up' : 'down'}>{formatPrice(ohlcBar.open)}</b></span>
|
||||
)}
|
||||
{v.high && (
|
||||
<span>H <b className="up">{formatPrice(currentBar!.high)}</b></span>
|
||||
{v.high && ohlcBar && (
|
||||
<span>H <b className="up">{formatPrice(ohlcBar.high)}</b></span>
|
||||
)}
|
||||
{v.low && (
|
||||
<span>L <b className="down">{formatPrice(currentBar!.low)}</b></span>
|
||||
{v.low && ohlcBar && (
|
||||
<span>L <b className="down">{formatPrice(ohlcBar.low)}</b></span>
|
||||
)}
|
||||
{v.close && (
|
||||
<span>C <b className={isUp ? 'up' : 'down'}>{formatPrice(currentBar!.close)}</b></span>
|
||||
{v.close && quoteBar && (
|
||||
<span>C <b className={isUp ? 'up' : 'down'}>{formatPrice(quoteBar.close)}</b></span>
|
||||
)}
|
||||
{v.change && (
|
||||
<span className={`tv-legend-chg ${isUp ? 'up' : 'down'}`}>
|
||||
|
||||
@@ -556,10 +556,10 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
||||
const lastKnownBar = useUpbit
|
||||
? (latestBar ?? (bars.length > 0 ? bars[bars.length - 1] : null))
|
||||
: (bars.length > 0 ? bars[bars.length - 1] : null);
|
||||
const currentBar = legend ?? lastKnownBar;
|
||||
const isUp = currentBar ? currentBar.close >= currentBar.open : true;
|
||||
const prevClose = bars.length > 1 ? bars[bars.length - 2].close : currentBar?.open ?? 0;
|
||||
const dailyChange = currentBar ? currentBar.close - prevClose : 0;
|
||||
const quoteBar = lastKnownBar;
|
||||
const isUp = quoteBar ? quoteBar.close >= quoteBar.open : true;
|
||||
const prevClose = bars.length > 1 ? bars[bars.length - 2].close : quoteBar?.open ?? 0;
|
||||
const dailyChange = quoteBar ? quoteBar.close - prevClose : 0;
|
||||
const dailyChangePct = prevClose > 0 ? dailyChange / prevClose * 100 : 0;
|
||||
|
||||
const receiveSignal = useMemo(() => {
|
||||
@@ -671,8 +671,8 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
||||
}, [compactMode, onActivate, showMarket]);
|
||||
|
||||
const displayKoName = compactKoName(symbol);
|
||||
const trendUp = compactMode && currentBar != null && dailyChangePct >= 0;
|
||||
const trendDown = compactMode && currentBar != null && dailyChangePct < 0;
|
||||
const trendUp = compactMode && quoteBar != null && dailyChangePct >= 0;
|
||||
const trendDown = compactMode && quoteBar != null && dailyChangePct < 0;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -708,13 +708,13 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
||||
<span className="slot-compact-name-text">{displayKoName}</span>
|
||||
</button>
|
||||
|
||||
{currentBar && (
|
||||
{quoteBar && (
|
||||
<div className="slot-compact-quote" aria-label="현재가">
|
||||
<span
|
||||
className="slot-compact-price"
|
||||
style={{ color: isUp ? 'var(--up)' : 'var(--down)' }}
|
||||
>
|
||||
{formatPrice(currentBar.close)}
|
||||
{formatPrice(quoteBar.close)}
|
||||
</span>
|
||||
<span
|
||||
className="slot-compact-change"
|
||||
@@ -772,9 +772,9 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{currentBar && (
|
||||
{quoteBar && (
|
||||
<span className="slot-price" style={{ color: isUp ? 'var(--up)' : 'var(--down)' }}>
|
||||
{formatPrice(currentBar.close)}
|
||||
{formatPrice(quoteBar.close)}
|
||||
<span className="slot-change" style={{ color: isUp ? 'var(--up)' : 'var(--down)' }}>
|
||||
{isUp ? '▲' : '▼'} {Math.abs(dailyChangePct).toFixed(2)}%
|
||||
</span>
|
||||
|
||||
@@ -586,7 +586,7 @@ const GeneralPanel: React.FC<{
|
||||
</select>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
label="날짜·시간 형식"
|
||||
label="차트 날짜, 시간형식"
|
||||
desc="캔들·보조지표 차트 하단 시간축·크로스헤어에 적용됩니다. 프리셋 선택 또는 직접 입력(토큰: yyyy, yy, MM, dd, HH, mm, ss)이 가능합니다."
|
||||
>
|
||||
<ChartTimeFormatPicker
|
||||
|
||||
@@ -10,20 +10,12 @@ import {
|
||||
updateVerificationIssueComment,
|
||||
type VerificationIssueCommentDto,
|
||||
} from '../../utils/verificationBoardApi';
|
||||
import { formatIsoDateTime } from '../../utils/timezone';
|
||||
|
||||
interface Props {
|
||||
issueId: number;
|
||||
}
|
||||
|
||||
function formatDateTime(iso?: string): string {
|
||||
if (!iso) return '';
|
||||
try {
|
||||
return new Date(iso).toLocaleString('ko-KR', {
|
||||
month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit',
|
||||
});
|
||||
} catch { return ''; }
|
||||
}
|
||||
|
||||
function defaultAuthorName(): string {
|
||||
const session = getAuthSession();
|
||||
if (session?.displayName) return session.displayName;
|
||||
@@ -142,7 +134,7 @@ const VerificationIssueCommentsSection: React.FC<Props> = ({ issueId }) => {
|
||||
<div className="vbd-comment-head">
|
||||
<span className="vbd-comment-author">{c.authorName ?? '익명'}</span>
|
||||
<span className="vbd-comment-date">
|
||||
{formatDateTime(c.updatedAt ?? c.createdAt)}
|
||||
{formatIsoDateTime(c.updatedAt ?? c.createdAt, undefined, 'short')}
|
||||
{c.updatedAt && c.createdAt && c.updatedAt !== c.createdAt && ' (수정됨)'}
|
||||
</span>
|
||||
<div className="vbd-comment-actions">
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import ReproductionPathInput from './ReproductionPathInput';
|
||||
import VerificationIssueCommentsSection from './VerificationIssueCommentsSection';
|
||||
import VerificationIssueAttachmentsSection from './VerificationIssueAttachmentsSection';
|
||||
import { formatIsoDateTime } from '../../utils/timezone';
|
||||
|
||||
interface Props {
|
||||
issue: VerificationIssueDto | null;
|
||||
@@ -23,13 +24,6 @@ interface Props {
|
||||
) => void | Promise<void>;
|
||||
}
|
||||
|
||||
function formatDateTime(iso?: string): string {
|
||||
if (!iso) return '—';
|
||||
try {
|
||||
return new Date(iso).toLocaleString('ko-KR');
|
||||
} catch { return iso; }
|
||||
}
|
||||
|
||||
const VerificationIssueDetailPanel: React.FC<Props> = ({
|
||||
issue,
|
||||
attachmentsRefreshKey = 0,
|
||||
@@ -137,8 +131,8 @@ const VerificationIssueDetailPanel: React.FC<Props> = ({
|
||||
</div>
|
||||
|
||||
<div className="vbd-detail-meta">
|
||||
<span>등록 {formatDateTime(issue.createdAt)}</span>
|
||||
<span>수정 {formatDateTime(issue.updatedAt)}</span>
|
||||
<span>등록 {formatIsoDateTime(issue.createdAt)}</span>
|
||||
<span>수정 {formatIsoDateTime(issue.updatedAt)}</span>
|
||||
</div>
|
||||
|
||||
<label className="vbd-field">
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
type VerificationIssueStage,
|
||||
} from '../../utils/verificationBoardStages';
|
||||
import VerificationStageIcon from './VerificationStageIcon';
|
||||
import { formatIsoDateTime } from '../../utils/timezone';
|
||||
|
||||
interface Props {
|
||||
issues: VerificationIssueDto[];
|
||||
@@ -21,16 +22,6 @@ interface Props {
|
||||
onSelect: (issue: VerificationIssueDto) => void;
|
||||
}
|
||||
|
||||
function formatDate(iso?: string): string {
|
||||
if (!iso) return '';
|
||||
try {
|
||||
const d = new Date(iso);
|
||||
return d.toLocaleString('ko-KR', {
|
||||
month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit',
|
||||
});
|
||||
} catch { return ''; }
|
||||
}
|
||||
|
||||
const VerificationIssueListPanel: React.FC<Props> = ({
|
||||
issues,
|
||||
selectedId,
|
||||
@@ -102,7 +93,7 @@ const VerificationIssueListPanel: React.FC<Props> = ({
|
||||
>
|
||||
{stageLabel(issue.stage)}
|
||||
</span>
|
||||
<span className="vbd-list-meta">{formatDate(issue.updatedAt ?? issue.createdAt)}</span>
|
||||
<span className="vbd-list-meta">{formatIsoDateTime(issue.updatedAt ?? issue.createdAt, undefined, 'short')}</span>
|
||||
</span>
|
||||
<span className="vbd-list-title">{issue.title}</span>
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user