Files
property-match/src/lib/ds.ts
T
Benjamin Sutter 11de05025c fix: merge EXTERNAL_MARKET into Verifiziertes Objekt
Only 3 result types shown to users: Verifiziertes Objekt, Maison Work,
Zukunftssignal. EXTERNAL_MARKET label and color now identical to
VERIFIED_PORTFOLIO — no visible distinction for end users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 17:18:33 +02:00

206 lines
9.0 KiB
TypeScript

import type { ConfidenceLevel, DataQualityLevel } from '../domain/enums'
import { CONF_HIGH, CONF_MEDIUM, DQ_HIGH, DQ_MEDIUM } from './constants'
// ── Semantic color tokens ─────────────────────────────────────────────────────
// Single source of truth for badge/score colors. All badge components read from here.
export const DS_COLORS = {
resultType: {
VERIFIED_PORTFOLIO: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
EXTERNAL_MARKET: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
MAISON_WORK: { bg: 'rgba(3,105,161,0.10)', fg: '#0369a1' },
FUTURE_AVAILABILITY: { bg: 'rgba(109,40,217,0.10)', fg: '#6d28d9' },
},
confidence: {
VERY_HIGH: { bg: 'rgba(26,122,74,0.12)', fg: '#1a7a4a' },
HIGH: { bg: 'rgba(26,122,74,0.09)', fg: '#1a7a4a' },
MEDIUM: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
LOW: { bg: 'rgba(217,119,6,0.12)', fg: '#d97706' },
VERY_LOW: { bg: 'rgba(192,57,43,0.12)', fg: '#c0392b' },
},
risk: {
LOW: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
MEDIUM: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
HIGH: { bg: 'rgba(192,57,43,0.10)', fg: '#c0392b' },
CRITICAL: { bg: 'rgba(127,0,0,0.12)', fg: '#7f1d1d' },
},
availability: {
AVAILABLE_NOW: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
AVAILABLE_SOON: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
FUTURE_SIGNAL: { bg: 'rgba(109,40,217,0.10)', fg: '#6d28d9' },
OCCUPIED: { bg: 'rgba(100,116,139,0.10)', fg: '#475569' },
UNKNOWN: { bg: '#f1f5f9', fg: '#94a3b8' },
},
freshness: {
FRESH: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
STALE: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
OUTDATED: { bg: 'rgba(192,57,43,0.10)', fg: '#c0392b' },
},
dataQuality: {
HIGH: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
MEDIUM: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
LOW: { bg: 'rgba(192,57,43,0.10)', fg: '#c0392b' },
INCOMPLETE: { bg: 'rgba(127,0,0,0.12)', fg: '#7f1d1d' },
},
heat: {
VERY_HOT: { bg: '#fef3c7', border: '#fcd34d', icon: '#d97706', text: '#92400e' },
HOT: { bg: '#fff7ed', border: '#fed7aa', icon: '#ea580c', text: '#c2410c' },
},
futureCard: {
controlled: {
accent: '#7c3aed',
accentHover: '#6d28d9',
headerBg: '#faf5ff',
border: '#e9d5ff',
badgeBg: '#ede9fe',
badgeText: '#5b21b6',
},
signal: {
accent: '#1d4ed8',
accentHover: '#1e40af',
headerBg: '#eff6ff',
border: '#bfdbfe',
badgeBg: '#dbeafe',
badgeText: '#1e40af',
indicator: '#1d4ed8',
},
},
} as const
// ── Text color tokens ─────────────────────────────────────────────────────────
// For sx={{ color: DS_TEXT.secondary }} instead of hardcoded '#475569'
export const DS_TEXT = {
primary: '#1e293b',
secondary: '#475569',
muted: '#64748b',
disabled: '#94a3b8',
inverted: '#ffffff',
success: '#1a7a4a',
warning: '#d97706',
error: '#c0392b',
danger: '#dc2626',
info: '#0369a1',
brand: '#1e3a5f',
signal: '#6d28d9',
// Dark variants — use for text on light-tinted surface boxes
successDark: '#166534',
warningDark: '#92400e',
signalDark: '#4c1d95',
infoDark: '#0c4a6e',
brandDark: '#162d4a',
} as const
// ── Background tokens ─────────────────────────────────────────────────────────
export const DS_BG = {
page: '#f8fafc',
surface: '#ffffff',
subtle: '#f1f5f9',
muted: '#e2e8f0',
} as const
// ── Border tokens ─────────────────────────────────────────────────────────────
export const DS_BORDER = {
default: '#e2e8f0',
muted: '#f1f5f9',
strong: '#cbd5e1',
} as const
// ── Surface tokens — bg + border pairs for highlighted/tinted boxes ───────────
// Use as: sx={{ bgcolor: DS_SURFACE.success.bg, border: `1px solid ${DS_SURFACE.success.border}` }}
export const DS_SURFACE = {
success: { bg: '#f0fdf4', border: '#bbf7d0' }, // green tint
warning: { bg: '#fffbeb', border: '#fde68a' }, // amber tint
error: { bg: '#fef2f2', border: '#fecaca' }, // red tint
info: { bg: '#f0f9ff', border: '#bae6fd' }, // sky tint
indigo: { bg: '#eef2ff', border: '#e0e7ff' }, // indigo tint (hard-criteria rows)
purple: { bg: '#faf5ff', border: '#e9d5ff' }, // purple tint (pre-market / future)
orange: { bg: '#fff7ed', border: '#fed7aa' }, // orange tint (HOT heat badge bg)
blue: { bg: '#eff6ff', border: '#bfdbfe' }, // blue tint (market signal)
neutral: { bg: '#f8fafc', border: '#e2e8f0' }, // neutral/slate tint (formula rows)
slate: { bg: '#f1f5f9', border: '#e2e8f0' }, // slightly darker neutral
} as const
// ── Match tier surface — bg tint keyed by score tier ─────────────────────────
// Use with SCORE_STRONG / SCORE_MODERATE thresholds from constants.ts
export const DS_MATCH_TIER = {
strong: DS_SURFACE.success,
moderate: DS_SURFACE.warning,
weak: DS_SURFACE.error,
} as const
// ── Pre-market & market signal shorthand aliases ──────────────────────────────
// DS_COLORS.futureCard.controlled / signal are the full token sets.
// These aliases make imports more readable in supply-side components.
export const DS_PRE_MARKET = DS_COLORS.futureCard.controlled
export const DS_MARKET_SIGNAL = DS_COLORS.futureCard.signal
// ── Badge color presets ───────────────────────────────────────────────────────
// Pass to GenericBadge.color instead of raw hex strings.
// BADGE_COLORS.confidenceHigh replaces '#1a7a4a' at call sites.
export const BADGE_COLORS = {
confidenceHigh: '#1a7a4a',
confidenceMedium: '#d97706',
confidenceLow: '#c0392b',
riskHigh: '#c0392b',
riskMedium: '#d97706',
riskLow: '#1a7a4a',
preMarket: '#7c3aed',
marketSignal: '#1d4ed8',
verified: '#1e3a5f',
info: '#0369a1',
muted: '#64748b',
gold: '#d97706',
silver: '#64748b',
bronze: '#b45309',
} as const
// ── Shadow tokens ─────────────────────────────────────────────────────────────
export const DS_SHADOW = {
card: '0 1px 3px 0 rgba(0,0,0,0.08), 0 1px 2px -1px rgba(0,0,0,0.04)',
panel: '0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04)',
dialog: '0 20px 25px -5px rgba(0,0,0,0.10), 0 8px 10px -6px rgba(0,0,0,0.06)',
} as const
// ── Inquiry status metadata ───────────────────────────────────────────────────
export const INQUIRY_STATUS_META: Record<string, { label: string; fg: string; bg: string }> = {
new: { label: 'Neu', fg: '#dc2626', bg: '#fef2f2' },
in_progress: { label: 'Aktiv', fg: '#d97706', bg: '#fffbeb' },
answered: { label: 'Beantwortet', fg: '#1a7a4a', bg: '#f0fdf4' },
archived: { label: 'Archiviert', fg: '#64748b', bg: '#f8fafc' },
}
// ── Score → qualitative level helpers ────────────────────────────────────────
export function scoreToConfidenceLevel(score: number): ConfidenceLevel {
if (score >= CONF_HIGH) return 'VERY_HIGH'
if (score >= 0.75) return 'HIGH'
if (score >= CONF_MEDIUM) return 'MEDIUM'
if (score >= 0.35) return 'LOW'
return 'VERY_LOW'
}
export function scoreToDataQualityLevel(score: number): DataQualityLevel {
if (score >= DQ_HIGH) return 'HIGH'
if (score >= DQ_MEDIUM) return 'MEDIUM'
if (score > 0) return 'LOW'
return 'INCOMPLETE'
}
// ── Result type meta — single source for labels + colors ─────────────────────
export const RESULT_TYPE_META: Record<string, { label: string; color: string; bg: string }> = {
VERIFIED_PORTFOLIO: { label: 'Verifiziertes Objekt', color: '#1e3a5f', bg: 'rgba(30,58,95,0.10)' },
EXTERNAL_MARKET: { label: 'Verifiziertes Objekt', color: '#1e3a5f', bg: 'rgba(30,58,95,0.10)' },
MAISON_WORK: { label: 'Maison Work', color: '#0369a1', bg: 'rgba(3,105,161,0.10)' },
FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#7c3aed', bg: 'rgba(109,40,217,0.10)' },
}