Clarify current market opportunities
This commit is contained in:
@@ -2278,6 +2278,26 @@
|
|||||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root :global(.opportunity-empty-state) {
|
||||||
|
display: flex;
|
||||||
|
min-height: 132px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px dashed rgba(34, 211, 238, 0.2);
|
||||||
|
border-radius: 16px;
|
||||||
|
background:
|
||||||
|
radial-gradient(
|
||||||
|
circle at 50% 0%,
|
||||||
|
rgba(34, 211, 238, 0.08),
|
||||||
|
transparent 44%
|
||||||
|
),
|
||||||
|
rgba(7, 12, 22, 0.72);
|
||||||
|
color: rgba(148, 163, 184, 0.9);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
.root :global(.opportunity-card) {
|
.root :global(.opportunity-card) {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@@ -2421,22 +2441,6 @@
|
|||||||
filter: drop-shadow(0 0 8px rgba(34, 211, 238, 0.22));
|
filter: drop-shadow(0 0 8px rgba(34, 211, 238, 0.22));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Market-closed opportunity card — dimmed state */
|
|
||||||
.root :global(.opportunity-card.market-closed) {
|
|
||||||
opacity: 0.6;
|
|
||||||
border-style: dashed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.root :global(.opportunity-card.market-closed:hover) {
|
|
||||||
opacity: 0.82;
|
|
||||||
}
|
|
||||||
|
|
||||||
.root :global(.opportunity-market-status) {
|
|
||||||
color: rgba(251, 191, 36, 0.8);
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes home-panel-enter {
|
@keyframes home-panel-enter {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ function buildDashboardSummaryCards(
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: "opportunities",
|
key: "opportunities",
|
||||||
title: locale === "en-US" ? "Today's Opportunities" : "今日机会分布",
|
title: locale === "en-US" ? "Current Opportunities" : "当前机会分布",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: locale === "en-US" ? "High risk" : "高风险",
|
label: locale === "en-US" ? "High risk" : "高风险",
|
||||||
@@ -1147,8 +1147,13 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) {
|
|||||||
[locale, snapshots],
|
[locale, snapshots],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Always show top 5 cities by score, regardless of market tradability
|
const items = useMemo(
|
||||||
const items = useMemo(() => snapshots.slice(0, 5), [snapshots]);
|
() =>
|
||||||
|
snapshots
|
||||||
|
.filter((snapshot) => snapshot.tradableOpportunity)
|
||||||
|
.slice(0, 5),
|
||||||
|
[snapshots],
|
||||||
|
);
|
||||||
|
|
||||||
// Always render: summary cards should be visible even without tradable opportunities
|
// Always render: summary cards should be visible even without tradable opportunities
|
||||||
if (!snapshots.length) return null;
|
if (!snapshots.length) return null;
|
||||||
@@ -1186,28 +1191,26 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{items.length > 0 && (
|
<div className="opportunity-strip-heading">
|
||||||
<>
|
<div>
|
||||||
<div className="opportunity-strip-heading">
|
<span>
|
||||||
<div>
|
{locale === "en-US"
|
||||||
<span>
|
? "Current Best Markets"
|
||||||
{locale === "en-US"
|
: "当前最佳机会市场"}
|
||||||
? "Today's Top Opportunities"
|
</span>
|
||||||
: "今日最佳机会"}
|
<strong>
|
||||||
</span>
|
{locale === "en-US"
|
||||||
<strong>
|
? "Live market question · YES/NO · Edge · Trend"
|
||||||
{locale === "en-US"
|
: "当前市场问题 · YES/NO 价格 · Edge · 小趋势线"}
|
||||||
? "Market question · YES/NO · Edge · Trend"
|
</strong>
|
||||||
: "市场问题 · YES/NO 价格 · Edge · 小趋势线"}
|
</div>
|
||||||
</strong>
|
<Link href="/docs/intraday-signal" className="opportunity-view-all">
|
||||||
</div>
|
{locale === "en-US" ? "View all" : "查看全部"}
|
||||||
<Link href="/docs/intraday-signal" className="opportunity-view-all">
|
</Link>
|
||||||
{locale === "en-US" ? "View all" : "查看全部"}
|
</div>
|
||||||
</Link>
|
{items.length > 0 ? (
|
||||||
</div>
|
<div className="opportunity-card-grid top-opportunities">
|
||||||
<div className="opportunity-card-grid top-opportunities">
|
{items.map(({ city, detail, summary }, index) => {
|
||||||
{items.map(
|
|
||||||
({ city, detail, summary, tradableOpportunity }, index) => {
|
|
||||||
const symbol = getTempSymbol(city, summary, detail);
|
const symbol = getTempSymbol(city, summary, detail);
|
||||||
const debPrediction =
|
const debPrediction =
|
||||||
summary?.deb?.prediction ?? detail?.deb?.prediction;
|
summary?.deb?.prediction ?? detail?.deb?.prediction;
|
||||||
@@ -1222,7 +1225,6 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) {
|
|||||||
city.risk_level ||
|
city.risk_level ||
|
||||||
summary?.risk?.level ||
|
summary?.risk?.level ||
|
||||||
detail?.risk?.level;
|
detail?.risk?.level;
|
||||||
const marketClosed = !tradableOpportunity;
|
|
||||||
const marketBucket = detail?.market_scan?.temperature_bucket;
|
const marketBucket = detail?.market_scan?.temperature_bucket;
|
||||||
const marketQuestion =
|
const marketQuestion =
|
||||||
detail?.market_scan?.primary_market?.question ||
|
detail?.market_scan?.primary_market?.question ||
|
||||||
@@ -1235,19 +1237,20 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) {
|
|||||||
detail?.market_scan?.sparkline?.length
|
detail?.market_scan?.sparkline?.length
|
||||||
? detail.market_scan.sparkline
|
? detail.market_scan.sparkline
|
||||||
: [
|
: [
|
||||||
Number(summary?.current?.temp ?? detail?.current?.temp ?? 0),
|
Number(
|
||||||
|
summary?.current?.temp ?? detail?.current?.temp ?? 0,
|
||||||
|
),
|
||||||
Number(debPrediction ?? 0),
|
Number(debPrediction ?? 0),
|
||||||
Number(detail?.forecast?.today_high ?? debPrediction ?? 0),
|
Number(
|
||||||
|
detail?.forecast?.today_high ?? debPrediction ?? 0,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={city.name}
|
key={city.name}
|
||||||
type="button"
|
type="button"
|
||||||
className={clsx(
|
className="opportunity-card"
|
||||||
"opportunity-card",
|
|
||||||
marketClosed && "market-closed",
|
|
||||||
)}
|
|
||||||
onClick={() => void store.focusCity(city.name)}
|
onClick={() => void store.focusCity(city.name)}
|
||||||
>
|
>
|
||||||
<div className="opportunity-card-header">
|
<div className="opportunity-card-header">
|
||||||
@@ -1266,12 +1269,6 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) {
|
|||||||
</div>
|
</div>
|
||||||
<span className="opportunity-meta">
|
<span className="opportunity-meta">
|
||||||
{marketQuestion}
|
{marketQuestion}
|
||||||
{marketClosed && (
|
|
||||||
<span className="opportunity-market-status">
|
|
||||||
{" · "}
|
|
||||||
{locale === "en-US" ? "Market closed" : "市场已关闭"}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
<div className="opportunity-card-footer">
|
<div className="opportunity-card-footer">
|
||||||
<div className="opportunity-price-pair">
|
<div className="opportunity-price-pair">
|
||||||
@@ -1293,10 +1290,14 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
},
|
})}
|
||||||
)}
|
</div>
|
||||||
</div>
|
) : (
|
||||||
</>
|
<div className="opportunity-empty-state">
|
||||||
|
{locale === "en-US"
|
||||||
|
? "No active opportunity market right now."
|
||||||
|
: "当前暂无可交易机会市场"}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user