feat(F020): frontend infrastructure foundation

- src/lib/constants.ts: centralized route paths, labels, thresholds
- src/lib/utils.ts: formatting, color helpers, math utils
- src/hooks/: useProperties, useMatches, useFutureSignals, useNeeds
- src/components/scores/MatchScoreRing
- src/components/data-quality/DataQualityBar
- src/components/future-signals/SignalTypeBadge
- src/components/cards/SourceTypeBadge
- src/provider/AuthProvider (placeholder, swappable)
- main.tsx: AuthProvider + centralized stale time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-15 10:50:26 +02:00
parent e20e0e9a2e
commit 3b45b0c121
17 changed files with 600 additions and 2 deletions
+113
View File
@@ -0,0 +1,113 @@
// Centralized app-wide constants — no magic strings anywhere else
export const APP_NAME = 'Property-Match'
export const APP_VERSION = '0.1.0'
// Organisation
export const DEFAULT_ORG_ID = 'org-wincasa'
// Pagination
export const DEFAULT_PAGE_SIZE = 25
export const MAX_COMPARE_ITEMS = 3
// Data quality thresholds
export const DQ_HIGH = 0.8
export const DQ_MEDIUM = 0.6
// Confidence thresholds
export const CONF_HIGH = 0.85
export const CONF_MEDIUM = 0.65
// Match score thresholds (0100)
export const SCORE_STRONG = 80
export const SCORE_MODERATE = 60
// Probability thresholds (future signals)
export const PROB_HIGH = 0.7
export const PROB_MEDIUM = 0.5
// Query stale times (ms)
export const STALE_PROPERTIES = 5 * 60 * 1000
export const STALE_MATCHES = 2 * 60 * 1000
export const STALE_SIGNALS = 5 * 60 * 1000
// Route paths — single source of truth
export const ROUTES = {
HOME: '/',
SUPPLY: {
DASHBOARD: '/supply/dashboard',
PROPERTIES: '/supply/properties',
MATCH_CENTER: '/supply/match-center',
FUTURE_AVAILABILITY: '/supply/future-availability',
DATA_QUALITY: '/supply/data-quality',
},
DEMAND: {
AI_SEARCH: '/demand/ai-search',
RESULTS: '/demand/results',
COMPARE: '/demand/compare',
SHORTLISTS: '/demand/shortlists',
},
OPS: {
REVIEW_QUEUE: '/ops/review-queue',
AI_MONITORING: '/ops/ai-monitoring',
GOVERNANCE: '/ops/governance',
},
} as const
// Asset type display labels
export const ASSET_TYPE_LABELS: Record<string, string> = {
OFFICE: 'Büro',
RETAIL: 'Retail',
GASTRO: 'Gastronomie',
LOGISTICS: 'Logistik',
PRODUCTION: 'Produktion',
MIXED: 'Gemischt',
}
// Result type display labels
export const RESULT_TYPE_LABELS: Record<string, string> = {
VERIFIED_PORTFOLIO: 'Verified Portfolio',
EXTERNAL_MARKET: 'Marktinserat',
FUTURE_AVAILABILITY: 'Zukunftssignal',
}
// Match strength display labels
export const MATCH_STRENGTH_LABELS: Record<string, string> = {
STRONG: 'Stark',
MODERATE: 'Mittel',
WEAK: 'Schwach',
}
// Availability status display labels
export const AVAILABILITY_LABELS: Record<string, string> = {
AVAILABLE_NOW: 'Verfügbar',
AVAILABLE_SOON: 'Bald verfügbar',
FUTURE_SIGNAL: 'Zukunftssignal',
OCCUPIED: 'Belegt',
UNKNOWN: 'Unbekannt',
}
// Risk level display labels
export const RISK_LABELS: Record<string, string> = {
LOW: 'Niedrig',
MEDIUM: 'Mittel',
HIGH: 'Hoch',
CRITICAL: 'Kritisch',
}
// Signal type display labels
export const SIGNAL_TYPE_LABELS: Record<string, string> = {
EXPANSION: 'Expansion',
POSSIBLE_MOVE_OUT: 'Möglicher Auszug',
CONSTRUCTION_PROJECT: 'Bauprojekt',
RESTRUCTURING: 'Umstrukturierung',
PROJECT_DEVELOPMENT: 'Projektentwicklung',
SPACE_CONSOLIDATION: 'Flächenkonsolidierung',
}
// Data freshness display labels
export const FRESHNESS_LABELS: Record<string, string> = {
FRESH: 'Aktuell',
STALE: 'Veraltet',
OUTDATED: 'Abgelaufen',
}