feat: remove Administration workspace — keep only Verwaltung + Suche
- Delete all ops page components (ReviewQueue, AIMonitoring, Governance, SourceMonitoring, ActivityTimeline, SignalPipeline) - Remove OPERATIONS workspace from AppShell config, nav order, path detection - Remove all /ops/* routes from App.tsx - Remove WorkspaceType.OPERATIONS from allowedWorkspaces in authService, sessionStore, permissions - Keep MarketIntelligence page (already moved to /supply/market-intelligence) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import {
|
||||
DQ_HIGH, DQ_MEDIUM,
|
||||
CONF_HIGH, CONF_MEDIUM,
|
||||
SCORE_STRONG, SCORE_MODERATE,
|
||||
PROB_HIGH, PROB_MEDIUM,
|
||||
} from './constants'
|
||||
|
||||
// ── Formatting ────────────────────────────────────────────────────────────────
|
||||
|
||||
export function formatCHF(amount: number, decimals = 0): string {
|
||||
return new Intl.NumberFormat('de-CH', {
|
||||
style: 'currency',
|
||||
currency: 'CHF',
|
||||
minimumFractionDigits: decimals,
|
||||
maximumFractionDigits: decimals,
|
||||
}).format(amount)
|
||||
}
|
||||
|
||||
export function formatArea(sqm: number): string {
|
||||
return `${new Intl.NumberFormat('de-CH').format(sqm)} m²`
|
||||
}
|
||||
|
||||
export function formatPercent(value: number, decimals = 0): string {
|
||||
return `${(value * 100).toFixed(decimals)} %`
|
||||
}
|
||||
|
||||
export function formatDate(iso: string): string {
|
||||
return new Intl.DateTimeFormat('de-CH', { day: '2-digit', month: '2-digit', year: 'numeric' }).format(new Date(iso))
|
||||
}
|
||||
|
||||
export function formatRelativeDate(iso: string): string {
|
||||
const diff = Date.now() - new Date(iso).getTime()
|
||||
const hours = Math.floor(diff / 3_600_000)
|
||||
if (hours < 1) return 'Gerade eben'
|
||||
if (hours < 24) return `vor ${hours} Stunde${hours === 1 ? '' : 'n'}`
|
||||
const days = Math.floor(hours / 24)
|
||||
if (days < 7) return `vor ${days} Tag${days === 1 ? '' : 'en'}`
|
||||
return formatDate(iso)
|
||||
}
|
||||
|
||||
// ── Color helpers (return MUI color token strings) ────────────────────────────
|
||||
|
||||
export function dataQualityColor(score: number): 'success' | 'warning' | 'error' {
|
||||
if (score >= DQ_HIGH) return 'success'
|
||||
if (score >= DQ_MEDIUM) return 'warning'
|
||||
return 'error'
|
||||
}
|
||||
|
||||
export function confidenceColor(score: number): 'success' | 'primary' | 'warning' {
|
||||
if (score >= CONF_HIGH) return 'success'
|
||||
if (score >= CONF_MEDIUM) return 'primary'
|
||||
return 'warning'
|
||||
}
|
||||
|
||||
export function matchScoreColor(score: number): 'success' | 'warning' | 'error' {
|
||||
if (score >= SCORE_STRONG) return 'success'
|
||||
if (score >= SCORE_MODERATE) return 'warning'
|
||||
return 'error'
|
||||
}
|
||||
|
||||
export function probabilityColor(prob: number): 'success' | 'warning' | 'error' {
|
||||
if (prob >= PROB_HIGH) return 'success'
|
||||
if (prob >= PROB_MEDIUM) return 'warning'
|
||||
return 'error'
|
||||
}
|
||||
|
||||
// Hex color variants for use in sx (when MUI color tokens aren't enough)
|
||||
export function dataQualityHex(score: number): string {
|
||||
if (score >= DQ_HIGH) return '#1a7a4a'
|
||||
if (score >= DQ_MEDIUM) return '#d97706'
|
||||
return '#c0392b'
|
||||
}
|
||||
|
||||
export function confidenceHex(score: number): string {
|
||||
if (score >= CONF_HIGH) return '#1a7a4a'
|
||||
if (score >= CONF_MEDIUM) return '#1e3a5f'
|
||||
return '#d97706'
|
||||
}
|
||||
|
||||
export function probabilityHex(prob: number): string {
|
||||
if (prob >= PROB_HIGH) return '#1a7a4a'
|
||||
if (prob >= PROB_MEDIUM) return '#d97706'
|
||||
return '#c0392b'
|
||||
}
|
||||
|
||||
// ── Misc ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
export function clamp(value: number, min: number, max: number): number {
|
||||
return Math.min(Math.max(value, min), max)
|
||||
}
|
||||
|
||||
export function average(values: number[]): number {
|
||||
if (values.length === 0) return 0
|
||||
return values.reduce((a, b) => a + b, 0) / values.length
|
||||
}
|
||||
|
||||
export function truncate(str: string, maxLen: number): string {
|
||||
return str.length <= maxLen ? str : str.slice(0, maxLen - 1) + '…'
|
||||
}
|
||||
Reference in New Issue
Block a user