Remove AI analysis and rank cities by recent DEB performance
This commit is contained in:
@@ -21,6 +21,10 @@ function toRiskGroup(level?: string): RiskGroupKey {
|
||||
return "other";
|
||||
}
|
||||
|
||||
function toPerformanceGroup(city: CityListItem): RiskGroupKey {
|
||||
return toRiskGroup(city.deb_recent_tier);
|
||||
}
|
||||
|
||||
function normalizeExpandedGroups(
|
||||
value: unknown,
|
||||
): Record<RiskGroupKey, boolean> {
|
||||
@@ -60,11 +64,17 @@ export function CitySidebar() {
|
||||
const sortedCities = useMemo(
|
||||
() =>
|
||||
[...store.cities].sort((a, b) => {
|
||||
const aGroup = toRiskGroup(a.risk_level);
|
||||
const bGroup = toRiskGroup(b.risk_level);
|
||||
const aGroup = toPerformanceGroup(a);
|
||||
const bGroup = toPerformanceGroup(b);
|
||||
const aHitRate = Number(a.deb_recent_hit_rate ?? -1);
|
||||
const bHitRate = Number(b.deb_recent_hit_rate ?? -1);
|
||||
const aSamples = Number(a.deb_recent_sample_count ?? 0);
|
||||
const bSamples = Number(b.deb_recent_sample_count ?? 0);
|
||||
return (
|
||||
(riskOrder[aGroup] ?? 3) -
|
||||
(riskOrder[bGroup] ?? 3) ||
|
||||
bHitRate - aHitRate ||
|
||||
bSamples - aSamples ||
|
||||
a.display_name.localeCompare(b.display_name)
|
||||
);
|
||||
}),
|
||||
@@ -79,7 +89,7 @@ export function CitySidebar() {
|
||||
other: [],
|
||||
};
|
||||
sortedCities.forEach((city) => {
|
||||
groups[toRiskGroup(city.risk_level)].push(city);
|
||||
groups[toPerformanceGroup(city)].push(city);
|
||||
});
|
||||
return groups;
|
||||
}, [sortedCities]);
|
||||
@@ -88,7 +98,7 @@ export function CitySidebar() {
|
||||
if (!selectedCity) return;
|
||||
const selected = store.cities.find((city) => city.name === selectedCity);
|
||||
if (!selected) return;
|
||||
const groupKey = toRiskGroup(selected.risk_level);
|
||||
const groupKey = toPerformanceGroup(selected);
|
||||
setExpandedGroups((current) =>
|
||||
current[groupKey] ? current : { ...current, [groupKey]: true },
|
||||
);
|
||||
@@ -200,6 +210,7 @@ export function CitySidebar() {
|
||||
const deviationSeverity =
|
||||
snapshot?.deviation_monitor?.severity || "normal";
|
||||
const secondaryText = deviationText || peakTempText;
|
||||
const performanceTier = toPerformanceGroup(city);
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -213,7 +224,7 @@ export function CitySidebar() {
|
||||
}
|
||||
>
|
||||
<div className="city-item-main">
|
||||
<span className={clsx("risk-dot", city.risk_level)} />
|
||||
<span className={clsx("risk-dot", performanceTier)} />
|
||||
<span className="city-name-text">{city.display_name}</span>
|
||||
<span
|
||||
className={clsx(
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
getRiskBadgeLabel,
|
||||
getTemperatureChartData,
|
||||
getWeatherSummary,
|
||||
parseAiAnalysis,
|
||||
} from "@/lib/dashboard-utils";
|
||||
|
||||
function EmptyState({ text }: { text: string }) {
|
||||
@@ -760,35 +759,6 @@ export function ForecastTable() {
|
||||
);
|
||||
}
|
||||
|
||||
export function AiAnalysis() {
|
||||
const { data } = useCityData();
|
||||
const { t } = useI18n();
|
||||
if (!data) return null;
|
||||
const ai = parseAiAnalysis(data.ai_analysis);
|
||||
|
||||
return (
|
||||
<section className="ai-section">
|
||||
<h3>{t("section.ai")}</h3>
|
||||
<div className="ai-box">
|
||||
{!ai.summary && ai.bullets.length === 0 ? (
|
||||
<span className="ai-placeholder">{t("section.aiEmpty")}</span>
|
||||
) : (
|
||||
<>
|
||||
{ai.summary && <div className="ai-summary">{ai.summary}</div>}
|
||||
{ai.bullets.length > 0 && (
|
||||
<ul className="ai-list">
|
||||
{ai.bullets.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export function RiskInfo() {
|
||||
const { data } = useCityData();
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -4,7 +4,6 @@ import React from "react";
|
||||
import {
|
||||
BarChart2,
|
||||
Target,
|
||||
ShieldAlert,
|
||||
Zap,
|
||||
Info,
|
||||
Activity,
|
||||
@@ -23,7 +22,7 @@ export function AnalyticsPanel({
|
||||
data,
|
||||
t = {}, // Default empty for now, can be expanded via context or props
|
||||
}: AnalyticsPanelProps) {
|
||||
const { overview, market_scan, models, ai_analysis } = data;
|
||||
const { overview, market_scan, models } = data;
|
||||
|
||||
const modelEntries = Object.entries(models)
|
||||
.filter(([_, v]) => v !== undefined && v !== null)
|
||||
@@ -222,25 +221,6 @@ export function AnalyticsPanel({
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{ai_analysis && (
|
||||
<section className="pt-2">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Activity className="h-3 w-3 text-amber-500" />
|
||||
<span className="text-[10px] font-black uppercase tracking-[0.15em] text-zinc-400">
|
||||
AI COGNITIVE ANALYSIS
|
||||
</span>
|
||||
</div>
|
||||
<div className="rounded-lg border border-zinc-800 bg-zinc-900/30 p-4 relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 p-2 opacity-20">
|
||||
<ShieldAlert className="w-8 h-8 text-amber-500" />
|
||||
</div>
|
||||
<p className="text-[11px] leading-relaxed text-zinc-400 relative z-10 font-medium">
|
||||
{ai_analysis}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Execute Scan Footer */}
|
||||
|
||||
Reference in New Issue
Block a user