추세검색 화면 적용

This commit is contained in:
Macbook
2026-05-26 00:51:07 +09:00
parent 1e950c7db4
commit 1e11884fef
29 changed files with 3753 additions and 71 deletions
@@ -0,0 +1,70 @@
import React, { useMemo } from 'react';
import type { TrendSearchConditionDto } from '../../utils/trendSearchApi';
import { computeMatchRate, getTrafficLightState } from '../../utils/virtualSignalMetrics';
import { buildTrendSearchMetrics } from '../../utils/trendSearchMetrics';
import VirtualSignalEqualizer from '../virtual/VirtualSignalEqualizer';
import VirtualConditionList from '../virtual/VirtualConditionList';
import VirtualSignalTrafficLight from '../virtual/VirtualSignalTrafficLight';
import VirtualIndicatorCompareTable from '../virtual/VirtualIndicatorCompareTable';
interface Props {
conditions: TrendSearchConditionDto[];
matchRate: number;
matchedCount: number;
totalConditions: number;
updatedAt?: number;
}
const TrendSearchCardSignalPanel: React.FC<Props> = ({
conditions,
matchRate,
matchedCount,
totalConditions,
updatedAt,
}) => {
const metrics = useMemo(() => buildTrendSearchMetrics(conditions), [conditions]);
const resolvedMatch = useMemo(
() => computeMatchRate(metrics, matchRate),
[metrics, matchRate],
);
const trafficState = useMemo(
() => getTrafficLightState(resolvedMatch, metrics),
[resolvedMatch, metrics],
);
if (conditions.length === 0) {
return <p className="vtd-muted vtd-card-empty"> </p>;
}
const updatedLabel = updatedAt
? new Date(updatedAt).toLocaleTimeString('ko-KR', {
hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false,
})
: '—';
return (
<div className="vtd-sig-panel-wrap vtd-sig-panel-wrap--detail">
<div className="vtd-sig-panel vtd-sig-panel--detail-top">
<div className="vtd-sig-panel-title">SIGNAL INTELLIGENCE &amp; MATCH RATES</div>
<div className="vtd-sig-visual">
<div className="vtd-sig-visual-eq">
<VirtualSignalEqualizer matchRate={resolvedMatch} />
</div>
<VirtualConditionList metrics={metrics} />
<VirtualSignalTrafficLight state={trafficState} matchRate={resolvedMatch} />
</div>
</div>
<div className="vtd-sig-detail-table" aria-label="지표별 상태 목록">
<VirtualIndicatorCompareTable metrics={metrics} />
</div>
<div className="vtd-card-foot">
<span className="vtd-card-updated"> {updatedLabel}</span>
<span className="vtd-card-match-summary">
{matchedCount}/{totalConditions} · {resolvedMatch}%
</span>
</div>
</div>
);
};
export default TrendSearchCardSignalPanel;