5d53f35dea
- layoutStore: remove 4 dead field groups (pinnedPanels, selectedResultId, compareTrayVisible, notificationsOpen) — none were read outside the store - CompareTray: drop dead useLayoutStore side-effect (state was write-only) - 8 components: replace bare useStore() with explicit selectors / useShallow to prevent unnecessary re-renders on unrelated state mutations - lib/constants: add STALE_MARKET_SIGNALS + STALE_REVIEW_QUEUE (30s each) - useMarketSignals, useReviewQueue: use global constants instead of hook-local magic numbers - Add STATE_MANAGEMENT.md: decision tree + rules for RQ/Zustand/local/derived Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
// 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 (0–100)
|
||
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
|
||
export const STALE_MARKET_SIGNALS = 30 * 1000 // aggressive — market leads refresh often
|
||
export const STALE_REVIEW_QUEUE = 30 * 1000 // aggressive — ops team works in real-time
|
||
|
||
// 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: 'Plattform',
|
||
EXTERNAL_MARKET: 'Plattform',
|
||
MAISON_WORK: 'Maison Work',
|
||
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',
|
||
}
|
||
|
||
// Confidence level display labels
|
||
export const CONFIDENCE_LABELS: Record<string, string> = {
|
||
VERY_HIGH: 'Sehr hoch',
|
||
HIGH: 'Hoch',
|
||
MEDIUM: 'Mittel',
|
||
LOW: 'Niedrig',
|
||
VERY_LOW: 'Sehr niedrig',
|
||
}
|
||
|
||
// Data quality level display labels
|
||
export const DATA_QUALITY_LABELS: Record<string, string> = {
|
||
HIGH: 'Hoch',
|
||
MEDIUM: 'Mittel',
|
||
LOW: 'Niedrig',
|
||
INCOMPLETE: 'Unvollständig',
|
||
}
|