feat: Future Availability — Logiktrennung Supply/Demand + Markt-Leads
EXPANSION-Signale (Unternehmen sucht Fläche) sind Nachfragesignale und gehören nicht in den Demand-Feed. Neue Architektur: - signalDirection: 'SUPPLY' | 'DEMAND' auf FutureSignal-Domain - SUPPLY-Signale: POSSIBLE_MOVE_OUT / CONSTRUCTION_PROJECT (Crawler) und LEASE_EXPIRY+isVerified (Verwaltung ERP) → Demand-Feed wie bisher - DEMAND-Signale: EXPANSION → aus Demand-Feed gefiltert - Neues useMarketLeads-Hook + /supply/market-leads Seite für Verwaltung: zeigt EXPANSION-Signale als potenzielle Mieter mit Portfolio-Matching - Alle 15 Signale in futureSignals.ts inhaltlich bereinigt und mit korrekter signalDirection versehen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
5fe15bac62
commit
b0ad6643ff
7 files changed
+626
-245
No files matched your search
@@ -26,6 +26,7 @@ const Anfragencenter = lazy(() => import('./pages/supply/Anfragencenter'))
|
|||||||
const FutureAvailability = lazy(() => import('./pages/supply/FutureAvailability'))
|
const FutureAvailability = lazy(() => import('./pages/supply/FutureAvailability'))
|
||||||
const DataQuality = lazy(() => import('./pages/supply/DataQuality'))
|
const DataQuality = lazy(() => import('./pages/supply/DataQuality'))
|
||||||
const ReminderManager = lazy(() => import('./pages/supply/ReminderManager'))
|
const ReminderManager = lazy(() => import('./pages/supply/ReminderManager'))
|
||||||
|
const MarketLeads = lazy(() => import('./pages/supply/MarketLeads'))
|
||||||
|
|
||||||
const AISearch = lazy(() => import('./pages/demand/AISearch'))
|
const AISearch = lazy(() => import('./pages/demand/AISearch'))
|
||||||
const Results = lazy(() => import('./pages/demand/Results'))
|
const Results = lazy(() => import('./pages/demand/Results'))
|
||||||
@@ -58,6 +59,7 @@ function App() {
|
|||||||
<Route path="/supply/future-availability" element={<FutureAvailability />} />
|
<Route path="/supply/future-availability" element={<FutureAvailability />} />
|
||||||
<Route path="/supply/data-quality" element={<DataQuality />} />
|
<Route path="/supply/data-quality" element={<DataQuality />} />
|
||||||
<Route path="/supply/reminder-manager" element={<ReminderManager />} />
|
<Route path="/supply/reminder-manager" element={<ReminderManager />} />
|
||||||
|
<Route path="/supply/market-leads" element={<MarketLeads />} />
|
||||||
<Route path="/supply/market-intelligence" element={<MarketIntelligence />} />
|
<Route path="/supply/market-intelligence" element={<MarketIntelligence />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ const WORKSPACE_CONFIG: Record<WorkspaceType, WorkspaceConfig> = {
|
|||||||
{ path: '/supply/dashboard', label: 'Übersicht', icon: LayoutDashboard },
|
{ path: '/supply/dashboard', label: 'Übersicht', icon: LayoutDashboard },
|
||||||
{ path: '/supply/properties', label: 'Meine Objekte', icon: Building2 },
|
{ path: '/supply/properties', label: 'Meine Objekte', icon: Building2 },
|
||||||
{ path: '/supply/reminder-manager', label: 'Reminder Manager', icon: BellRing },
|
{ path: '/supply/reminder-manager', label: 'Reminder Manager', icon: BellRing },
|
||||||
|
{ path: '/supply/market-leads', label: 'Markt-Leads', icon: Target },
|
||||||
{ path: '/supply/anfragen', label: 'Anfragencenter', icon: MessageSquare },
|
{ path: '/supply/anfragen', label: 'Anfragencenter', icon: MessageSquare },
|
||||||
{ path: '/supply/data-quality', label: 'Datenpflege', icon: CheckSquare },
|
{ path: '/supply/data-quality', label: 'Datenpflege', icon: CheckSquare },
|
||||||
{ path: '/supply/market-intelligence', label: 'Markt Intelligence', icon: Radar },
|
{ path: '/supply/market-intelligence', label: 'Markt Intelligence', icon: Radar },
|
||||||
|
|||||||
@@ -49,4 +49,10 @@ export interface FutureSignal {
|
|||||||
strategicInterpretation?: string // "Die Signale deuten auf ..."
|
strategicInterpretation?: string // "Die Signale deuten auf ..."
|
||||||
confirmedFacts?: string[] // ["Region bestätigt", ...]
|
confirmedFacts?: string[] // ["Region bestätigt", ...]
|
||||||
unconfirmedFacts?: string[] // ["Exakte Fläche unbekannt", ...]
|
unconfirmedFacts?: string[] // ["Exakte Fläche unbekannt", ...]
|
||||||
|
|
||||||
|
// Signal direction
|
||||||
|
// SUPPLY = space will become available → shown in demand feed
|
||||||
|
// DEMAND = company is looking for space → shown as Markt-Lead in Verwaltung
|
||||||
|
// undefined = treated as SUPPLY (backwards compat for generated signals)
|
||||||
|
signalDirection?: 'SUPPLY' | 'DEMAND'
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { useMemo } from 'react'
|
||||||
|
import { useFutureSignals } from './useFutureSignals'
|
||||||
|
import { useProperties } from './useProperties'
|
||||||
|
import type { FutureSignal } from '../domain/futureSignal'
|
||||||
|
import type { Property } from '../domain/property'
|
||||||
|
|
||||||
|
export interface MarketLead {
|
||||||
|
signal: FutureSignal
|
||||||
|
matchingProperties: Property[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useMarketLeads(): { data: MarketLead[]; isLoading: boolean } {
|
||||||
|
const { data: signals = [], isLoading: signalsLoading } = useFutureSignals()
|
||||||
|
const { data: properties = [], isLoading: propertiesLoading } = useProperties()
|
||||||
|
|
||||||
|
const data = useMemo((): MarketLead[] => {
|
||||||
|
const demandSignals = signals.filter(s => s.signalDirection === 'DEMAND')
|
||||||
|
|
||||||
|
return demandSignals.map(signal => {
|
||||||
|
const signalCity = signal.locationHint.split(',')[0].trim().toLowerCase()
|
||||||
|
|
||||||
|
const matchingProperties = properties.filter(p => {
|
||||||
|
if (p.resultType !== 'VERIFIED_PORTFOLIO') return false
|
||||||
|
const propCity = (p.location?.city ?? '').toLowerCase()
|
||||||
|
const cityMatch = propCity.includes(signalCity) || signalCity.includes(propCity)
|
||||||
|
const areaOk = signal.areaSqmEstimate
|
||||||
|
? p.areaSqm >= signal.areaSqmEstimate * 0.5 && p.areaSqm <= signal.areaSqmEstimate * 2.2
|
||||||
|
: true
|
||||||
|
return cityMatch && areaOk
|
||||||
|
})
|
||||||
|
|
||||||
|
return { signal, matchingProperties }
|
||||||
|
})
|
||||||
|
}, [signals, properties])
|
||||||
|
|
||||||
|
return { data, isLoading: signalsLoading || propertiesLoading }
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ export function useUnifiedResults(needId?: string) {
|
|||||||
// Fast path: explicit FUTURE_AVAILABILITY on the match (no property lookup needed)
|
// Fast path: explicit FUTURE_AVAILABILITY on the match (no property lookup needed)
|
||||||
if (match.resultType === 'FUTURE_AVAILABILITY') {
|
if (match.resultType === 'FUTURE_AVAILABILITY') {
|
||||||
const signal = allSignals.find(s => s.id === refId || s.propertyId === refId)
|
const signal = allSignals.find(s => s.id === refId || s.propertyId === refId)
|
||||||
if (!signal) return []
|
if (!signal || signal.signalDirection === 'DEMAND') return []
|
||||||
return [{ matchId: match.id, needId: match.needId, matchScore: match.matchScore,
|
return [{ matchId: match.id, needId: match.needId, matchScore: match.matchScore,
|
||||||
resultType: 'FUTURE_AVAILABILITY', signal, match }]
|
resultType: 'FUTURE_AVAILABILITY', signal, match }]
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ export function useUnifiedResults(needId?: string) {
|
|||||||
|
|
||||||
if (rt === 'FUTURE_AVAILABILITY') {
|
if (rt === 'FUTURE_AVAILABILITY') {
|
||||||
const signal = allSignals.find(s => s.id === refId || s.propertyId === refId)
|
const signal = allSignals.find(s => s.id === refId || s.propertyId === refId)
|
||||||
if (!signal) return []
|
if (!signal || signal.signalDirection === 'DEMAND') return []
|
||||||
return [{ matchId: match.id, needId: match.needId, matchScore: match.matchScore,
|
return [{ matchId: match.id, needId: match.needId, matchScore: match.matchScore,
|
||||||
resultType: 'FUTURE_AVAILABILITY', signal, match }]
|
resultType: 'FUTURE_AVAILABILITY', signal, match }]
|
||||||
}
|
}
|
||||||
|
|||||||
+282
-243
@@ -1,54 +1,33 @@
|
|||||||
import { SignalType, RiskLevel } from '../domain/enums'
|
import { SignalType, RiskLevel } from '../domain/enums'
|
||||||
import type { FutureSignal } from '../domain/futureSignal'
|
import type { FutureSignal } from '../domain/futureSignal'
|
||||||
|
|
||||||
export const mockFutureSignals: FutureSignal[] = [
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
// --- signal-001: DataCloud Systems AG — Büroexpansion Zürich-West ---
|
// SUPPLY signals — space will become available
|
||||||
{
|
// Shown in the demand search feed as Future Availability results
|
||||||
id: 'signal-001',
|
//
|
||||||
signalType: SignalType.EXPANSION,
|
// Two sub-types:
|
||||||
propertyId: 'prop-005',
|
// A) Pre-Market (Verwaltung-controlled): LEASE_EXPIRY + isVerified
|
||||||
companyName: 'DataCloud Systems AG',
|
// Generated dynamically by useSchattenmarktSignals — not in this file
|
||||||
locationHint: 'Zürich-West / Technopark',
|
// B) Market Signal (Crawler): POSSIBLE_MOVE_OUT, CONSTRUCTION_PROJECT, etc.
|
||||||
title: 'DataCloud Systems AG sucht ~600 m² Bürofläche in Zürich-West',
|
// These are the signals below
|
||||||
areaSqmEstimate: 600,
|
//
|
||||||
probability: 0.72,
|
// DEMAND signals — company is looking for space
|
||||||
confidenceScore: 0.68,
|
// NOT shown in demand feed — shown as Markt-Leads in Verwaltung workspace
|
||||||
timeHorizonMonths: 10,
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
source: {
|
|
||||||
type: 'JOB_POSTING',
|
|
||||||
url: 'https://example.com/jobs/datacloud',
|
|
||||||
publishedAt: '2025-04-20',
|
|
||||||
credibility: 'MEDIUM',
|
|
||||||
},
|
|
||||||
sensitivityLevel: 'INTERNAL',
|
|
||||||
disclaimer: 'Dieses Signal basiert auf AI-Analyse öffentlicher Daten (Stelleninserate, Presseberichte). Es handelt sich um ein probabilistisches Signal, kein bestätigtes Objekt.',
|
|
||||||
riskLevel: RiskLevel.MEDIUM,
|
|
||||||
marketIndicator: 'Tech-Sektor Stellenwachstum +38% YoY',
|
|
||||||
relevanceScore: 0.76,
|
|
||||||
isVerified: false,
|
|
||||||
expiresAt: '2026-03-01',
|
|
||||||
organizationId: 'org-wincasa',
|
|
||||||
createdAt: '2025-05-01T07:00:00Z',
|
|
||||||
updatedAt: '2025-05-10T07:00:00Z',
|
|
||||||
aiSummary: 'KI hat in 90 Tagen 14 Stelleninserate von DataCloud Systems AG auf LinkedIn und Indeed ausgewertet — davon 11 mit explizitem Standort Zürich-West/Technopark und hybridem Arbeitsmodell. Das Wachstumsmuster (DevOps, Cloud-Architektur, Sales) deutet auf eine Teamvergrösserung von ~40 Personen hin, was einem Flächenbedarf von ca. 600 m² entspricht. Der Tech-Sektor in Zürich-West verzeichnet 2024 den stärksten Stellenzuwachs seit 2018.',
|
|
||||||
marketIndicators: [
|
|
||||||
'14 Stelleninserate mit Standort Zürich-West in 90 Tagen',
|
|
||||||
'Teamwachstum ~40 Personen (DevOps, Cloud-Architektur, Sales)',
|
|
||||||
'Tech-Sektor Zürich-West: +38% Stellenwachstum 2024',
|
|
||||||
],
|
|
||||||
strategicInterpretation: 'DataCloud Systems AG befindet sich in einer klaren Wachstumsphase mit Fokus auf Zürich-West. Die Muster sprechen für organische Expansion — kein Standortwechsel erkennbar.',
|
|
||||||
confirmedFacts: ['Region Zürich-West aus Inseraten bestätigt', 'Flächentyp Büro plausibel', 'Wachstumstrend seit 6 Monaten vorhanden'],
|
|
||||||
unconfirmedFacts: ['Exakter Umzugszeitpunkt', 'Ob interner Ausbau am aktuellen Standort geplant', 'Finale Flächengrösse'],
|
|
||||||
},
|
|
||||||
|
|
||||||
// --- signal-002: Helvetia Produktion GmbH — möglicher Auszug Reinach BL ---
|
export const mockFutureSignals: FutureSignal[] = [
|
||||||
|
|
||||||
|
// ── SUPPLY: Crawler-detected — space becoming available ───────────────────
|
||||||
|
|
||||||
|
// signal-002: Helvetia Produktion GmbH — möglicher Auszug Reinach BL
|
||||||
{
|
{
|
||||||
id: 'signal-002',
|
id: 'signal-002',
|
||||||
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
companyName: 'Helvetia Produktion GmbH',
|
companyName: 'Helvetia Produktion GmbH',
|
||||||
propertyId: 'prop-006',
|
propertyId: 'prop-006',
|
||||||
locationHint: 'Reinach BL, Industriezone Nord',
|
locationHint: 'Reinach BL, Industriezone Nord',
|
||||||
title: 'Helvetia Produktion GmbH — Standort Reinach unter Restrukturierungsdruck',
|
title: 'Reinach BL — 3\'200 m² Produktionsfläche könnte frei werden',
|
||||||
areaSqmEstimate: 3200,
|
areaSqmEstimate: 3200,
|
||||||
probability: 0.48,
|
probability: 0.48,
|
||||||
confidenceScore: 0.44,
|
confidenceScore: 0.44,
|
||||||
@@ -60,7 +39,7 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
credibility: 'HIGH',
|
credibility: 'HIGH',
|
||||||
},
|
},
|
||||||
sensitivityLevel: 'CONFIDENTIAL',
|
sensitivityLevel: 'CONFIDENTIAL',
|
||||||
disclaimer: 'Dieses Signal basiert auf Pressemeldungen zu Restrukturierungsplänen. Kein bestätigter Auszug. Vertraulich behandeln.',
|
disclaimer: 'Basiert auf Pressemeldungen zur Restrukturierung. Kein bestätigter Auszug. Vertraulich behandeln.',
|
||||||
riskLevel: RiskLevel.HIGH,
|
riskLevel: RiskLevel.HIGH,
|
||||||
marketIndicator: 'Restrukturierungsankündigung Mutterkonzern',
|
marketIndicator: 'Restrukturierungsankündigung Mutterkonzern',
|
||||||
relevanceScore: 0.61,
|
relevanceScore: 0.61,
|
||||||
@@ -69,21 +48,22 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-05-03T08:00:00Z',
|
createdAt: '2025-05-03T08:00:00Z',
|
||||||
updatedAt: '2025-05-10T08:00:00Z',
|
updatedAt: '2025-05-10T08:00:00Z',
|
||||||
aiSummary: 'Drei unabhängige Presseartikel (NZZ, Handelszeitung, Basellandschaftliche Zeitung) berichten über die angekündigte Restrukturierung der Muttergesellschaft mit geplantem Stellenabbau von 8–12% bis Ende 2025. Der Standort Reinach BL wird in internen Dokumenten als "unter Überprüfung" eingestuft. KI-Konfidenz bleibt moderat, da kein Auszugstermin bestätigt wurde.',
|
aiSummary: 'Drei unabhängige Presseartikel (NZZ, Handelszeitung, Basellandschaftliche Zeitung) berichten über den angekündigten Stellenabbau von 8–12% bis Ende 2025. Der Standort Reinach BL wird in internen Dokumenten als "unter Überprüfung" geführt. Auszugstermin noch nicht bestätigt — frühes Beobachtungsstadium.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'3 unabhängige Presseartikel zu Restrukturierung der Muttergesellschaft',
|
'3 unabhängige Presseartikel zu Restrukturierung der Muttergesellschaft',
|
||||||
'Geplanter Stellenabbau 8–12% bis Ende 2025 bestätigt',
|
'Geplanter Stellenabbau 8–12% bis Ende 2025 bestätigt',
|
||||||
'Standort Reinach BL in internen Dokumenten als «unter Überprüfung» eingestuft',
|
'Standort Reinach BL intern als «unter Überprüfung» eingestuft',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Die Restrukturierung der Muttergesellschaft erhöht die Wahrscheinlichkeit einer Standortschliessung oder -reduktion in Reinach. Kein Auszugstermin bestätigt — frühes Beobachtungsstadium.',
|
strategicInterpretation: 'Die Restrukturierung erhöht die Wahrscheinlichkeit einer Standortschliessung in Reinach. Kein Auszugstermin bestätigt — Eigentümer sollte Kontakt zum Mieter suchen.',
|
||||||
confirmedFacts: ['Restrukturierung der Muttergesellschaft offiziell bestätigt', 'Stellenabbau angekündigt', 'Logistik-Standort Reinach betroffen'],
|
confirmedFacts: ['Restrukturierung der Muttergesellschaft offiziell bestätigt', 'Stellenabbau angekündigt', 'Standort Reinach betroffen'],
|
||||||
unconfirmedFacts: ['Ob Standort Reinach geschlossen wird', 'Zeitpunkt des Auszugs', 'Ob Fläche vermietet oder verkauft wird'],
|
unconfirmedFacts: ['Ob Standort Reinach geschlossen wird', 'Zeitpunkt des Auszugs', 'Ob Fläche vermietet oder verkauft'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-003: Bern Wankdorf — Neubau 4'500 m² Büro/Gewerbe ---
|
// signal-003: Bern Wankdorf — Neubau Büro/Gewerbe
|
||||||
{
|
{
|
||||||
id: 'signal-003',
|
id: 'signal-003',
|
||||||
signalType: SignalType.CONSTRUCTION_PROJECT,
|
signalType: SignalType.CONSTRUCTION_PROJECT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
locationHint: 'Bern, Wankdorf',
|
locationHint: 'Bern, Wankdorf',
|
||||||
title: 'Neubau Wankdorf West — 4\'500 m² Büro/Gewerbe, Fertigstellung Q1 2027',
|
title: 'Neubau Wankdorf West — 4\'500 m² Büro/Gewerbe, Fertigstellung Q1 2027',
|
||||||
areaSqmEstimate: 4500,
|
areaSqmEstimate: 4500,
|
||||||
@@ -98,7 +78,7 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
sensitivityLevel: 'PUBLIC',
|
sensitivityLevel: 'PUBLIC',
|
||||||
disclaimer: 'Baubewilligung öffentlich eingesehen. Fertigstellung gemäss Baugesuch Q1 2027. Vermietungsstart noch offen.',
|
disclaimer: 'Baubewilligung öffentlich eingesehen. Fertigstellung gemäss Baugesuch Q1 2027. Vermietungsstart noch offen.',
|
||||||
riskLevel: RiskLevel.LOW,
|
riskLevel: RiskLevel.LOW,
|
||||||
marketIndicator: 'Neubau Büro/Gewerbeflächen Wankdorf West',
|
marketIndicator: 'Neubau Büro-/Gewerbeflächen Wankdorf West',
|
||||||
relevanceScore: 0.82,
|
relevanceScore: 0.82,
|
||||||
isVerified: true,
|
isVerified: true,
|
||||||
verifiedBy: 'admin@ideal-sharing.ch',
|
verifiedBy: 'admin@ideal-sharing.ch',
|
||||||
@@ -107,63 +87,26 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-02-12T10:00:00Z',
|
createdAt: '2025-02-12T10:00:00Z',
|
||||||
updatedAt: '2025-05-05T09:00:00Z',
|
updatedAt: '2025-05-05T09:00:00Z',
|
||||||
aiSummary: 'Baubewilligung Nr. 2025-BW-0142 wurde am 10. Februar 2025 durch das Bauinspektorat Bern rechtskräftig erteilt. Das Projekt umfasst 4\'500 m² gemischte Büro- und Gewerbefläche (EG: Retail/Gewerbe, OG 1–3: Büro). Fertigstellung laut Baugesuch Q1 2027. Investorin ist die Wankdorf Immobilien AG; Vermietungsmandat noch nicht vergeben. Hohe Konfidenz durch amtliche Quelle.',
|
aiSummary: 'Baubewilligung Nr. 2025-BW-0142 wurde am 10. Februar 2025 durch das Bauinspektorat Bern rechtskräftig erteilt. Das Projekt umfasst 4\'500 m² gemischte Büro- und Gewerbefläche (EG: Retail/Gewerbe, OG 1–3: Büro). Fertigstellung laut Baugesuch Q1 2027. Investorin: Wankdorf Immobilien AG — Vermietungsmandat noch nicht vergeben.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Baubewilligung für 4\'500 m² Büro-/Gewerbefläche öffentlich eingereicht',
|
'Baubewilligung für 4\'500 m² Büro-/Gewerbefläche rechtskräftig erteilt',
|
||||||
'Fertigstellung gemäss Baugesuch Q1 2027',
|
'Fertigstellung gemäss Baugesuch Q1 2027',
|
||||||
'Bauherr: Wankdorf Center Entwicklungs AG',
|
'Bauherr: Wankdorf Center Entwicklungs AG — Vermietungsstart ca. Q2 2026',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Baubewilligung öffentlich — hohe Realisierungswahrscheinlichkeit. Vermietungsstart voraussichtlich 6–9 Monate vor Fertigstellung. Standort Wankdorf mit guter ÖV-Anbindung (Tram, Bahn).',
|
strategicInterpretation: 'Hohe Realisierungswahrscheinlichkeit durch erteilte Baubewilligung. Wankdorf hat gute ÖV-Anbindung (Tram, Bahn) und wächst als Business-Quartier. Frühzeitiges Interesse anmelden.',
|
||||||
confirmedFacts: ['Baubewilligung erteilt', 'Fläche und Standort bestätigt', 'Fertigstellungsdatum Q1 2027 aus Gesuch'],
|
confirmedFacts: ['Baubewilligung erteilt', 'Fläche 4\'500 m² und Standort bestätigt', 'Fertigstellung Q1 2027 aus Baugesuch'],
|
||||||
unconfirmedFacts: ['Endmietzins', 'Ob Fläche bereits vorvermietet', 'Ausbaustandard'],
|
unconfirmedFacts: ['Endmietzins pro m²', 'Ob Fläche bereits vorvermietet', 'Ausbaustandard OG'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-004: Novabio Pharma AG — Laborexpansion Basel Allschwil ---
|
// signal-005: Finanz & Treuhand AG — möglicher Auszug Zürich-Nord
|
||||||
{
|
|
||||||
id: 'signal-004',
|
|
||||||
signalType: SignalType.EXPANSION,
|
|
||||||
companyName: 'Novabio Pharma AG',
|
|
||||||
locationHint: 'Basel, Allschwil',
|
|
||||||
title: 'Novabio Pharma AG sucht Lab-/Bürofläche im Life-Sciences-Korridor Allschwil',
|
|
||||||
areaSqmEstimate: 700,
|
|
||||||
probability: 0.63,
|
|
||||||
confidenceScore: 0.60,
|
|
||||||
timeHorizonMonths: 14,
|
|
||||||
source: {
|
|
||||||
type: 'COMPANY_REPORT',
|
|
||||||
url: 'https://example.com/annual/novabio-2025',
|
|
||||||
publishedAt: '2025-03-28',
|
|
||||||
credibility: 'HIGH',
|
|
||||||
},
|
|
||||||
sensitivityLevel: 'INTERNAL',
|
|
||||||
disclaimer: 'Signal basiert auf Geschäftsbericht und Expansionsplänen. Kein bestätigtes Mietobjekt.',
|
|
||||||
riskLevel: RiskLevel.MEDIUM,
|
|
||||||
marketIndicator: 'Pharmastandort Basel: +22% Beschäftigte Life-Sciences 2024',
|
|
||||||
relevanceScore: 0.70,
|
|
||||||
isVerified: false,
|
|
||||||
expiresAt: '2026-07-01',
|
|
||||||
organizationId: 'org-wincasa',
|
|
||||||
createdAt: '2025-04-02T09:00:00Z',
|
|
||||||
updatedAt: '2025-05-08T10:00:00Z',
|
|
||||||
aiSummary: 'Im Geschäftsbericht 2024 kommuniziert Novabio Pharma AG eine "strategische Kapazitätserweiterung im Forschungsbereich Basel-Allschwil bis 2026". Die KI hat ausserdem 6 Inserate für Senior Scientists und Lab-Manager mit Standortangabe Allschwil identifiziert. Der Life-Sciences-Korridor Basel-Allschwil weist 2024 die schweizweit höchste Laborflächen-Nachfrage auf.',
|
|
||||||
marketIndicators: [
|
|
||||||
'Geschäftsbericht 2024: «strategische Kapazitätserweiterung Basel-Allschwil bis 2026» explizit erwähnt',
|
|
||||||
'6 Inserate für Senior Scientists und Lab-Manager mit Standort Allschwil in 60 Tagen',
|
|
||||||
'Life-Sciences-Korridor Basel-Allschwil: höchste CH-weite Laborflächen-Nachfrage 2024',
|
|
||||||
],
|
|
||||||
strategicInterpretation: 'Novabio Pharma AG kommuniziert Expansion öffentlich — Flächensuche sehr wahrscheinlich. Der Fokus auf Laborpersonal deutet auf kombinierten Lab-/Bürobedarf von 600–800 m² hin.',
|
|
||||||
confirmedFacts: ['Expansionspläne im Geschäftsbericht bestätigt', 'Region Basel-Allschwil als Zielstandort genannt', 'Einstellungstrend seit Q1 2025 sichtbar'],
|
|
||||||
unconfirmedFacts: ['Ob Neubau oder Bestandsfläche gesucht', 'Exakter Flächenbedarf Labor vs. Büro', 'Zeitpunkt des Einzugs'],
|
|
||||||
},
|
|
||||||
|
|
||||||
// --- signal-005: Finanz & Treuhand AG — möglicher Auszug Zürich-Nord ---
|
|
||||||
{
|
{
|
||||||
id: 'signal-005',
|
id: 'signal-005',
|
||||||
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
companyName: 'Finanz & Treuhand AG',
|
companyName: 'Finanz & Treuhand AG',
|
||||||
propertyId: 'prop-023',
|
propertyId: 'prop-023',
|
||||||
locationHint: 'Zürich-Nord, Seebach',
|
locationHint: 'Zürich-Nord, Seebach',
|
||||||
title: 'Finanz & Treuhand AG — Kostensenkungssignale deuten auf Standortaufgabe Seebach',
|
title: 'Zürich-Nord Seebach — 850 m² Bürofläche könnte frei werden',
|
||||||
areaSqmEstimate: 850,
|
areaSqmEstimate: 850,
|
||||||
probability: 0.58,
|
probability: 0.58,
|
||||||
confidenceScore: 0.54,
|
confidenceScore: 0.54,
|
||||||
@@ -183,23 +126,24 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-04-12T08:00:00Z',
|
createdAt: '2025-04-12T08:00:00Z',
|
||||||
updatedAt: '2025-05-10T09:00:00Z',
|
updatedAt: '2025-05-10T09:00:00Z',
|
||||||
aiSummary: 'Marktdatenanalyse zeigt: Die Finanz & Treuhand AG hat ihren LinkedIn-Unternehmenssitz von "Zürich-Nord, Seebach" auf "Zürich, Oerlikon" aktualisiert (Stand April 2025). Gleichzeitig sank die Mitarbeiterzahl laut LinkedIn von 38 auf 31 (-18%) innert 6 Monaten. Beide Indikatoren zusammen ergeben ein Verlagerungssignal. Kein offizieller Auszug bestätigt.',
|
aiSummary: 'Finanz & Treuhand AG hat den LinkedIn-Unternehmenssitz von "Zürich-Nord, Seebach" auf "Zürich, Oerlikon" aktualisiert (Stand April 2025). Gleichzeitig sank die Mitarbeiterzahl von 38 auf 31 (–18%) in 6 Monaten. Beide Indikatoren zusammen ergeben ein Verlagerungssignal — kein offizieller Auszug bestätigt.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'LinkedIn-Firmensitz von Seebach auf Oerlikon aktualisiert (April 2025)',
|
'LinkedIn-Firmensitz von Seebach auf Oerlikon aktualisiert (April 2025)',
|
||||||
'Mitarbeiterzahl rückläufig: von 38 auf 31 (-18%) in 6 Monaten',
|
'Mitarbeiterzahl rückläufig: von 38 auf 31 (–18%) in 6 Monaten',
|
||||||
'Leerstand Zürich-Nord Q1 2025: +12% gegenüber Vorquartal',
|
'Leerstand Zürich-Nord Q1 2025: +12% gegenüber Vorquartal',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Adressänderung auf LinkedIn kombiniert mit Stellenabbau ist ein starkes Frühsignal für Standortaufgabe. Frühzeitiger Kontakt mit der Verwaltung des Objekts empfohlen.',
|
strategicInterpretation: 'Adressänderung auf LinkedIn kombiniert mit Stellenabbau ist ein starkes Frühsignal für Standortaufgabe. Frühzeitiger Kontakt mit Mieter empfohlen.',
|
||||||
confirmedFacts: ['Mitarbeiterzahl-Rückgang auf LinkedIn dokumentiert', 'Adressänderung auf LinkedIn publiziert', 'Aktueller Standort Seebach bekannt'],
|
confirmedFacts: ['Mitarbeiterzahl-Rückgang auf LinkedIn dokumentiert', 'Adressänderung auf LinkedIn publiziert', 'Aktueller Standort Seebach bekannt'],
|
||||||
unconfirmedFacts: ['Ob Mietvertrag gekündigt wurde', 'Zeitpunkt des Auszugs', 'Ob Zusammenschluss mit anderem Standort geplant'],
|
unconfirmedFacts: ['Ob Mietvertrag bereits gekündigt', 'Zeitpunkt des Auszugs', 'Ob Zusammenschluss mit Oerlikon-Standort geplant'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-006: Luzern Inseli — Neubau Büro/Gewerbe am Wasser ---
|
// signal-006: Luzern Inseli — Neubau Büro/Gewerbe am Wasser
|
||||||
{
|
{
|
||||||
id: 'signal-006',
|
id: 'signal-006',
|
||||||
signalType: SignalType.CONSTRUCTION_PROJECT,
|
signalType: SignalType.CONSTRUCTION_PROJECT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
locationHint: 'Luzern, Inseli-Quartier',
|
locationHint: 'Luzern, Inseli-Quartier',
|
||||||
title: 'Neubau Inseli Luzern — 2\'000 m² Gewerbefläche am Wasser, Q1 2027',
|
title: 'Neubau Inseli Luzern — 2\'000 m² Gewerbefläche, Fertigstellung Q1 2027',
|
||||||
areaSqmEstimate: 2000,
|
areaSqmEstimate: 2000,
|
||||||
probability: 0.78,
|
probability: 0.78,
|
||||||
confidenceScore: 0.74,
|
confidenceScore: 0.74,
|
||||||
@@ -219,62 +163,26 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-01-25T11:00:00Z',
|
createdAt: '2025-01-25T11:00:00Z',
|
||||||
updatedAt: '2025-05-06T14:00:00Z',
|
updatedAt: '2025-05-06T14:00:00Z',
|
||||||
|
aiSummary: 'Baubewilligung für 2\'000 m² Gewerbe-/Bürofläche am Luzerner Inseli öffentlich eingereicht. Attraktive Wasserlage mit direkter ÖV-Anbindung (Bahnhof 8 Minuten zu Fuss). Nutzungskonzept noch offen — Büro und Gastronomie/Retail im EG wahrscheinlich.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Baubewilligung für 2\'000 m² Gewerbe-/Bürofläche am Inseli eingereicht',
|
'Baubewilligung für 2\'000 m² Gewerbe-/Bürofläche am Inseli eingereicht',
|
||||||
'Fertigstellung gemäss Baugesuch ca. Q1 2027',
|
'Fertigstellung gemäss Baugesuch ca. Q1 2027',
|
||||||
'Luzern Innenstadt: Büroflächennachfrage 2024 +18% gegenüber Vorjahr',
|
'Luzern Innenstadt: Büroflächennachfrage 2024 +18% gegenüber Vorjahr',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Attraktive Wasserlage am Luzerner Inseli mit ÖV-Direktanbindung (Bahnhof 8 Minuten zu Fuss). Nutzungskonzept noch offen — Büro und Gastronomie/Retail im EG wahrscheinlich. Frühzeitiges Interesse anmelden sinnvoll.',
|
strategicInterpretation: 'Attraktive Wasserlage mit ÖV-Direktanbindung. Nutzungskonzept noch offen — frühzeitiges Interesse anmelden sinnvoll, bevor Vermietungsmandat vergeben wird.',
|
||||||
confirmedFacts: ['Baubewilligung öffentlich eingereicht', 'Standort Inseli-Quartier bestätigt', 'Fertigstellung Q1 2027 aus Gesuch'],
|
confirmedFacts: ['Baubewilligung öffentlich eingereicht', 'Standort Inseli-Quartier bestätigt', 'Fertigstellung Q1 2027 aus Gesuch'],
|
||||||
unconfirmedFacts: ['Endgültige Nutzungsaufteilung (Büro vs. Retail)', 'Mietzinsniveau', 'Ob Vermietungsmandat vergeben'],
|
unconfirmedFacts: ['Endgültige Nutzungsaufteilung (Büro vs. Retail)', 'Mietzinsniveau', 'Ob Vermietungsmandat vergeben'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-007: SwissCart E-Commerce GmbH — Logistikexpansion Zug ---
|
// signal-008: Textilhaus Zürich AG — Retail-Verkleinerung Niederdorf
|
||||||
{
|
|
||||||
id: 'signal-007',
|
|
||||||
signalType: SignalType.EXPANSION,
|
|
||||||
companyName: 'SwissCart E-Commerce GmbH',
|
|
||||||
propertyId: 'prop-026',
|
|
||||||
locationHint: 'Zug, Industriestrasse',
|
|
||||||
title: 'SwissCart E-Commerce GmbH sucht Logistikfläche in Zug',
|
|
||||||
areaSqmEstimate: 580,
|
|
||||||
probability: 0.66,
|
|
||||||
confidenceScore: 0.62,
|
|
||||||
timeHorizonMonths: 9,
|
|
||||||
source: {
|
|
||||||
type: 'JOB_POSTING',
|
|
||||||
url: 'https://example.com/jobs/swisscart-zug',
|
|
||||||
publishedAt: '2025-04-18',
|
|
||||||
credibility: 'MEDIUM',
|
|
||||||
},
|
|
||||||
sensitivityLevel: 'INTERNAL',
|
|
||||||
disclaimer: 'Signal basiert auf massivem Stellenaufbau. Expansion in Zug sehr wahrscheinlich, aber noch kein Mietobjekt identifiziert.',
|
|
||||||
riskLevel: RiskLevel.MEDIUM,
|
|
||||||
marketIndicator: 'E-Commerce Zug: Stellenwachstum +55% YoY',
|
|
||||||
relevanceScore: 0.69,
|
|
||||||
isVerified: false,
|
|
||||||
expiresAt: '2026-02-01',
|
|
||||||
organizationId: 'org-wincasa',
|
|
||||||
createdAt: '2025-04-20T07:00:00Z',
|
|
||||||
updatedAt: '2025-05-09T08:00:00Z',
|
|
||||||
marketIndicators: [
|
|
||||||
'9 Stelleninserate für Lager- und Logistikpersonal in Zug in 45 Tagen',
|
|
||||||
'E-Commerce-Umsatz CH 2024: +22% — Nachfrage nach Lagerflächen steigt',
|
|
||||||
'Zug Industriestrasse: aktuelle Leerstandsquote Lager unter 3%',
|
|
||||||
],
|
|
||||||
strategicInterpretation: 'Massiver Personalaufbau im Logistikbereich deutet auf konkreten Flächenbedarf hin. Zug als Steuerkanton bleibt attraktiver Firmensitz — kein Standortwechsel erwartet, nur Erweiterung.',
|
|
||||||
confirmedFacts: ['Region Zug aus Inseraten bestätigt', 'Flächentyp Logistik/Lager aus Stellenprofilen ableitbar', 'Wachstumstrend seit Q3 2024 sichtbar'],
|
|
||||||
unconfirmedFacts: ['Ob zusätzliche Bürofläche benötigt', 'Exakter Flächenbedarf', 'Bevorzugte Strassenlage (Anlieferung)'],
|
|
||||||
},
|
|
||||||
|
|
||||||
// --- signal-008: Textilhaus Zürich AG — Retail-Verkleinerung Niederdorf ---
|
|
||||||
{
|
{
|
||||||
id: 'signal-008',
|
id: 'signal-008',
|
||||||
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
companyName: 'Textilhaus Zürich AG',
|
companyName: 'Textilhaus Zürich AG',
|
||||||
propertyId: 'prop-025',
|
propertyId: 'prop-025',
|
||||||
locationHint: 'Zürich Niederdorf, Münstergasse',
|
locationHint: 'Zürich Niederdorf, Münstergasse',
|
||||||
title: 'Textilhaus Zürich AG — Retailfläche Münstergasse könnte frei werden',
|
title: 'Zürich Münstergasse — 280 m² Retailfläche könnte frei werden',
|
||||||
areaSqmEstimate: 280,
|
areaSqmEstimate: 280,
|
||||||
probability: 0.55,
|
probability: 0.55,
|
||||||
confidenceScore: 0.50,
|
confidenceScore: 0.50,
|
||||||
@@ -294,20 +202,22 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-04-01T10:00:00Z',
|
createdAt: '2025-04-01T10:00:00Z',
|
||||||
updatedAt: '2025-05-07T11:00:00Z',
|
updatedAt: '2025-05-07T11:00:00Z',
|
||||||
|
aiSummary: 'Textilhaus Zürich AG zeigt eine Personalreduktion von –25% in 12 Monaten auf LinkedIn. Der Onlineanteil im Schweizer Textilhandel erreichte 2024 erstmals 38% — stationäre Flächen in der Altstadt stehen unter strukturellem Druck.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Onlineanteil CH-Textilhandel 2024: 38% — stationäre Verkaufsflächen unter Druck',
|
'Onlineanteil CH-Textilhandel 2024: 38% — stationäre Verkaufsflächen unter Druck',
|
||||||
'Mitarbeiterzahl Textilhaus Zürich AG laut LinkedIn: -25% in 12 Monaten',
|
'Mitarbeiterzahl Textilhaus Zürich AG laut LinkedIn: –25% in 12 Monaten',
|
||||||
'Stationärer Handel Zürich Altstadt: Leerstandsquote +8% 2024',
|
'Stationärer Handel Zürich Altstadt: Leerstandsquote +8% 2024',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Struktureller Rückgang im stationären Textilhandel trifft kleine Altstadt-Läden besonders. Kombination aus Personalabbau und Branchentrend ergibt ein Verlagerungssignal, das im Auge behalten werden sollte.',
|
strategicInterpretation: 'Struktureller Rückgang im stationären Textilhandel trifft kleine Altstadt-Läden besonders. Personalabbau und Branchentrend ergeben ein Verlagerungssignal.',
|
||||||
confirmedFacts: ['Branchentrend stationärer Handel dokumentiert', 'Aktueller Standort Münstergasse bekannt', 'Personalabbau auf LinkedIn sichtbar'],
|
confirmedFacts: ['Branchentrend stationärer Handel dokumentiert', 'Aktueller Standort Münstergasse bekannt', 'Personalabbau auf LinkedIn sichtbar'],
|
||||||
unconfirmedFacts: ['Ob Mietvertrag noch läuft oder ausläuft', 'Ob Filialnetz insgesamt verkleinert wird', 'Zeitpunkt eines möglichen Auszugs'],
|
unconfirmedFacts: ['Ob Mietvertrag noch läuft oder ausläuft', 'Ob Filialnetz insgesamt verkleinert', 'Zeitpunkt eines möglichen Auszugs'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-009: Winterthur Zentrum — Neubau Bürofläche ---
|
// signal-009: Winterthur Zentrum — Neubau Bürofläche
|
||||||
{
|
{
|
||||||
id: 'signal-009',
|
id: 'signal-009',
|
||||||
signalType: SignalType.CONSTRUCTION_PROJECT,
|
signalType: SignalType.CONSTRUCTION_PROJECT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
locationHint: 'Winterthur, Zentrum Technikum',
|
locationHint: 'Winterthur, Zentrum Technikum',
|
||||||
title: 'Neubau Technikum Winterthur — 1\'200 m² Bürofläche, Baubewilligung erteilt',
|
title: 'Neubau Technikum Winterthur — 1\'200 m² Bürofläche, Baubewilligung erteilt',
|
||||||
areaSqmEstimate: 1200,
|
areaSqmEstimate: 1200,
|
||||||
@@ -331,62 +241,26 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-03-05T09:00:00Z',
|
createdAt: '2025-03-05T09:00:00Z',
|
||||||
updatedAt: '2025-04-10T10:00:00Z',
|
updatedAt: '2025-04-10T10:00:00Z',
|
||||||
|
aiSummary: 'Baubewilligung rechtskräftig erteilt für 1\'200 m² Bürofläche am Technikum Winterthur. Fertigstellung Q2 2027. Zentrale Lage mit Bahnhof-Nähe. Winterthur Büromarkt: Leerstand Q1 2025 auf historisch tiefem Niveau (4.2%).',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Baubewilligung für 1\'200 m² Bürofläche am Technikum rechtskräftig erteilt',
|
'Baubewilligung für 1\'200 m² Bürofläche am Technikum rechtskräftig erteilt',
|
||||||
'Fertigstellung gemäss Baugesuch Q2 2027',
|
'Fertigstellung gemäss Baugesuch Q2 2027',
|
||||||
'Winterthur Büromarkt: Leerstand Q1 2025 auf historisch tiefem Niveau (4.2%)',
|
'Winterthur Büromarkt: Leerstand Q1 2025 historisch tief (4.2%)',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Amtlich bestätigte Baubewilligung — sehr hohe Realisierungswahrscheinlichkeit. Zentrale Lage am Technikum mit Bahnhof-Nähe. Vermietungsstart erfahrungsgemäss 9–12 Monate vor Fertigstellung.',
|
strategicInterpretation: 'Amtlich bestätigte Baubewilligung — sehr hohe Realisierungswahrscheinlichkeit. Bahnhof-Nähe und tiefe Leerstandsquote machen Winterthur attraktiv. Vermietungsstart erfahrungsgemäss 9–12 Monate vor Fertigstellung.',
|
||||||
confirmedFacts: ['Baubewilligung rechtskräftig erteilt', 'Standort Zentrum Technikum bestätigt', 'Fertigstellung Q2 2027 aus Gesuch'],
|
confirmedFacts: ['Baubewilligung rechtskräftig erteilt', 'Standort Zentrum Technikum bestätigt', 'Fertigstellung Q2 2027 aus Gesuch'],
|
||||||
unconfirmedFacts: ['Ob Vorvermietung bereits läuft', 'Endmietzins pro m²', 'Aufteilung EG/OG'],
|
unconfirmedFacts: ['Ob Vorvermietung bereits läuft', 'Endmietzins pro m²', 'Aufteilung EG/OG'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-010: Ostschweiz Digital AG — Büroexpansion St. Gallen ---
|
// signal-011: Mode Boutique Bern AG — Rückgang Altstadt
|
||||||
{
|
|
||||||
id: 'signal-010',
|
|
||||||
signalType: SignalType.EXPANSION,
|
|
||||||
companyName: 'Ostschweiz Digital AG',
|
|
||||||
propertyId: 'prop-030',
|
|
||||||
locationHint: 'St. Gallen, Riethüsli',
|
|
||||||
title: 'Ostschweiz Digital AG wächst — 480 m² Bürofläche in St. Gallen gesucht',
|
|
||||||
areaSqmEstimate: 480,
|
|
||||||
probability: 0.60,
|
|
||||||
confidenceScore: 0.55,
|
|
||||||
timeHorizonMonths: 10,
|
|
||||||
source: {
|
|
||||||
type: 'JOB_POSTING',
|
|
||||||
url: 'https://example.com/jobs/ostschweiz-digital',
|
|
||||||
publishedAt: '2025-04-22',
|
|
||||||
credibility: 'MEDIUM',
|
|
||||||
},
|
|
||||||
sensitivityLevel: 'INTERNAL',
|
|
||||||
disclaimer: 'Expansion basiert auf Analyse von Stellenanzeigen und Unternehmensankündigungen. Kein bestätigtes Objekt.',
|
|
||||||
riskLevel: RiskLevel.MEDIUM,
|
|
||||||
marketIndicator: 'Digitalwirtschaft Ostschweiz: +28% Beschäftigte 2024',
|
|
||||||
relevanceScore: 0.62,
|
|
||||||
isVerified: false,
|
|
||||||
expiresAt: '2026-03-01',
|
|
||||||
organizationId: 'org-wincasa',
|
|
||||||
createdAt: '2025-04-25T08:00:00Z',
|
|
||||||
updatedAt: '2025-05-10T07:00:00Z',
|
|
||||||
marketIndicators: [
|
|
||||||
'8 Stelleninserate für Software-Entwickler und UX-Designer in St. Gallen in 60 Tagen',
|
|
||||||
'Ostschweiz Digital AG: LinkedIn-Mitarbeiterzahl von 22 auf 31 (+41%) in 9 Monaten',
|
|
||||||
'Digitalwirtschaft Ostschweiz: +28% Beschäftigte 2024 (IHK-Bericht)',
|
|
||||||
],
|
|
||||||
strategicInterpretation: 'Kontinuierliches Teamwachstum über 9 Monate mit Fokus auf St. Gallen deutet auf organische Expansion hin. Kein Hinweis auf Standortwechsel — Erweiterungsfläche am bisherigen Standort oder Umzug in grössere Einheit möglich.',
|
|
||||||
confirmedFacts: ['Region St. Gallen aus Inseraten bestätigt', 'Wachstumstrend seit Q3 2024 nachweisbar', 'Flächentyp Büro aus Stellenprofilen ableitbar'],
|
|
||||||
unconfirmedFacts: ['Ob aktueller Standort Riethüsli oder Neulage', 'Exakter Flächenbedarf', 'Zeitpunkt der Entscheidung'],
|
|
||||||
},
|
|
||||||
|
|
||||||
// --- signal-011 (Mode Boutique): Mode Boutique Bern AG — Rückgang Altstadt ---
|
|
||||||
{
|
{
|
||||||
id: 'signal-011',
|
id: 'signal-011',
|
||||||
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
||||||
propertyId: 'prop-035',
|
signalDirection: 'SUPPLY',
|
||||||
companyName: 'Mode Boutique Bern AG',
|
companyName: 'Mode Boutique Bern AG',
|
||||||
|
propertyId: 'prop-035',
|
||||||
locationHint: 'Bern Altstadt, Gerechtigkeitsgasse',
|
locationHint: 'Bern Altstadt, Gerechtigkeitsgasse',
|
||||||
title: 'Mode Boutique Bern AG — Retailfläche Gerechtigkeitsgasse unter Druck',
|
title: 'Bern Gerechtigkeitsgasse — 290 m² Retailfläche unter Druck',
|
||||||
areaSqmEstimate: 290,
|
areaSqmEstimate: 290,
|
||||||
probability: 0.62,
|
probability: 0.62,
|
||||||
confidenceScore: 0.58,
|
confidenceScore: 0.58,
|
||||||
@@ -406,21 +280,22 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-04-28T09:00:00Z',
|
createdAt: '2025-04-28T09:00:00Z',
|
||||||
updatedAt: '2025-05-15T10:00:00Z',
|
updatedAt: '2025-05-15T10:00:00Z',
|
||||||
aiSummary: 'Mode Boutique Bern AG zeigt gemäss LinkedIn-Analyse eine Mitarbeiterreduktion von 12 auf 8 Personen (-33%) innerhalb von 6 Monaten. Das Unternehmen hat ausserdem kürzlich den Sitz auf eine kleinere Adresse in der Berner Innenstadt aktualisiert. Die Kombination aus Stellenabbau und Adressänderung deutet auf eine Verkleinerung des Verkaufsbereichs hin.',
|
aiSummary: 'Mode Boutique Bern AG zeigt eine Mitarbeiterreduktion von 12 auf 8 Personen (–33%) in 6 Monaten laut LinkedIn. Zusätzlich sank der Passantenverkehr in der Gerechtigkeitsgasse 2024 um 11% (Zählstelle). Kombination deutet auf Verkleinerung hin.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Mitarbeiterreduktion von 12 auf 8 Personen (-33%) in 6 Monaten laut LinkedIn',
|
'Mitarbeiterreduktion von 12 auf 8 Personen (–33%) in 6 Monaten laut LinkedIn',
|
||||||
'Berner Altstadt: Frequenzrückgang in der Gerechtigkeitsgasse -11% 2024 (Zählstelle)',
|
'Berner Altstadt: Frequenzrückgang Gerechtigkeitsgasse –11% 2024 (Zählstelle)',
|
||||||
'Stationärer Modehandel Bern: Leerstand +5% 2024',
|
'Stationärer Modehandel Bern: Leerstand +5% 2024',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Personalabbau zusammen mit sinkendem Passantenaufkommen in der Gerechtigkeitsgasse ergibt ein klares Verkleinerungssignal. Frühzeitige Kontaktaufnahme mit dem Eigentümer sinnvoll.',
|
strategicInterpretation: 'Personalabbau zusammen mit sinkendem Passantenaufkommen ergibt ein klares Verkleinerungssignal. Frühzeitige Kontaktaufnahme mit dem Eigentümer sinnvoll.',
|
||||||
confirmedFacts: ['Aktueller Standort Gerechtigkeitsgasse bekannt', 'Personalrückgang auf LinkedIn dokumentiert', 'Bern Altstadt Frequenzdaten verfügbar'],
|
confirmedFacts: ['Aktueller Standort Gerechtigkeitsgasse bekannt', 'Personalrückgang auf LinkedIn dokumentiert', 'Frequenzdaten Bern Altstadt verfügbar'],
|
||||||
unconfirmedFacts: ['Ob Mietvertrag ausläuft oder gekündigt wird', 'Ob Standort aufgegeben oder nur verkleinert', 'Zeitpunkt eines möglichen Auszugs'],
|
unconfirmedFacts: ['Ob Mietvertrag ausläuft oder gekündigt', 'Ob Standort aufgegeben oder nur verkleinert', 'Zeitpunkt eines möglichen Auszugs'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-012: Basel Hafen Klybeck — Logistikneubau ---
|
// signal-012: Basel Hafen Klybeck — Logistikneubau
|
||||||
{
|
{
|
||||||
id: 'signal-012',
|
id: 'signal-012',
|
||||||
signalType: SignalType.CONSTRUCTION_PROJECT,
|
signalType: SignalType.CONSTRUCTION_PROJECT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
propertyId: 'prop-024',
|
propertyId: 'prop-024',
|
||||||
locationHint: 'Basel, Hafen Klybeck',
|
locationHint: 'Basel, Hafen Klybeck',
|
||||||
title: 'Logistikneubau Rheinhafen Basel — 2\'600 m², Fertigstellung Q2 2026',
|
title: 'Logistikneubau Rheinhafen Basel — 2\'600 m², Fertigstellung Q2 2026',
|
||||||
@@ -445,62 +320,26 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-01-18T10:00:00Z',
|
createdAt: '2025-01-18T10:00:00Z',
|
||||||
updatedAt: '2025-04-20T14:00:00Z',
|
updatedAt: '2025-04-20T14:00:00Z',
|
||||||
|
aiSummary: 'Baubewilligung für 2\'600 m² Logistikfläche am Klybeck-Hafen rechtskräftig erteilt. Strategischer Standort mit direktem Rheinhafenzugang und Bahnanschluss (Trimodalität). Fertigstellung Q2 2026.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Baubewilligung für 2\'600 m² Logistikfläche am Klybeck-Hafen rechtskräftig erteilt',
|
'Baubewilligung für 2\'600 m² Logistikfläche am Klybeck-Hafen rechtskräftig erteilt',
|
||||||
'Fertigstellung gemäss Baugesuch Q2 2026',
|
'Fertigstellung gemäss Baugesuch Q2 2026',
|
||||||
'Hafenareal Klybeck: Trimodalität Schiene/Wasser/Strasse als USP',
|
'Trimodalität Schiene/Wasser/Strasse als USP — Nachfrage nach solchen Standorten konstant hoch',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Strategisch guter Logistikstandort mit direktem Rheinhafenzugang und Bahnanschluss. Hohe Realisierungssicherheit durch bereits erteilte Bewilligung. Nachfrage nach Hafen-nahen Logistikflächen in Basel konstant hoch.',
|
strategicInterpretation: 'Strategisch starker Logistikstandort mit direktem Rheinhafenzugang und Bahnanschluss. Hohe Realisierungssicherheit durch erteilte Bewilligung.',
|
||||||
confirmedFacts: ['Baubewilligung erteilt und rechtskräftig', 'Standort Klybeck bestätigt', 'Fertigstellung Q2 2026 aus Gesuch', 'Fläche 2\'600 m² bestätigt'],
|
confirmedFacts: ['Baubewilligung erteilt und rechtskräftig', 'Standort Klybeck bestätigt', 'Fertigstellung Q2 2026 aus Gesuch', 'Fläche 2\'600 m² bestätigt'],
|
||||||
unconfirmedFacts: ['Endmietzins pro m²', 'Ob Kühllager oder Trockenlager', 'Ob Fläche bereits reserviert'],
|
unconfirmedFacts: ['Endmietzins pro m²', 'Ob Kühllager oder Trockenlager', 'Ob Fläche bereits reserviert'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-013: Geneva Finance Partners SA — Büroexpansion Genf La Praille ---
|
// signal-014: Schweizer Grosshandel AG — möglicher Auszug Frenkendorf
|
||||||
{
|
|
||||||
id: 'signal-013',
|
|
||||||
signalType: SignalType.EXPANSION,
|
|
||||||
companyName: 'Geneva Finance Partners SA',
|
|
||||||
propertyId: 'prop-028',
|
|
||||||
locationHint: 'Genf, La Praille',
|
|
||||||
title: 'Geneva Finance Partners SA expandiert — Bürofläche La Praille gesucht',
|
|
||||||
areaSqmEstimate: 520,
|
|
||||||
probability: 0.58,
|
|
||||||
confidenceScore: 0.53,
|
|
||||||
timeHorizonMonths: 20,
|
|
||||||
source: {
|
|
||||||
type: 'COMPANY_REPORT',
|
|
||||||
url: 'https://example.com/annual/gfp-2025',
|
|
||||||
publishedAt: '2025-03-05',
|
|
||||||
credibility: 'MEDIUM',
|
|
||||||
},
|
|
||||||
sensitivityLevel: 'INTERNAL',
|
|
||||||
disclaimer: 'Expansionspläne aus Jahresbericht. Standort La Praille wahrscheinlich, aber noch nicht definitiv.',
|
|
||||||
riskLevel: RiskLevel.MEDIUM,
|
|
||||||
marketIndicator: 'Büroflächennachfrage Genf: +15% 2025',
|
|
||||||
relevanceScore: 0.60,
|
|
||||||
isVerified: false,
|
|
||||||
expiresAt: '2027-01-01',
|
|
||||||
organizationId: 'org-wincasa',
|
|
||||||
createdAt: '2025-03-08T11:00:00Z',
|
|
||||||
updatedAt: '2025-05-07T10:00:00Z',
|
|
||||||
marketIndicators: [
|
|
||||||
'Jahresbericht 2024: «Expansion des Genfer Teams auf 40 FTE bis 2026» angekündigt',
|
|
||||||
'Genf Finanzsektor: +15% Büroflächennachfrage 2025 (CBRE-Bericht)',
|
|
||||||
'5 neue Inserate für Senior-Portfoliomanager mit Standort Genf in 30 Tagen',
|
|
||||||
],
|
|
||||||
strategicInterpretation: 'Öffentlich kommunizierte Expansion mit klarem Zielhorizont 2026. La Praille als Standort bietet kostengünstigere Büroflächen als Genf Innenstadt bei guter ÖV-Anbindung. Flächensuche dürfte aktiv beginnen.',
|
|
||||||
confirmedFacts: ['Expansion im Jahresbericht kommuniziert', 'Teamwachstum auf 40 FTE bis 2026 bestätigt', 'Inserate für Genf aktiv'],
|
|
||||||
unconfirmedFacts: ['Ob La Praille oder andere Lage bevorzugt', 'Exakter Flächenbedarf', 'Ob Büros mit Repräsentationscharakter benötigt'],
|
|
||||||
},
|
|
||||||
|
|
||||||
// --- signal-014: Schweizer Grosshandel AG — möglicher Auszug Frenkendorf ---
|
|
||||||
{
|
{
|
||||||
id: 'signal-014',
|
id: 'signal-014',
|
||||||
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
signalType: SignalType.POSSIBLE_MOVE_OUT,
|
||||||
|
signalDirection: 'SUPPLY',
|
||||||
companyName: 'Schweizer Grosshandel AG',
|
companyName: 'Schweizer Grosshandel AG',
|
||||||
propertyId: 'prop-029',
|
propertyId: 'prop-029',
|
||||||
locationHint: 'Frenkendorf BL, Lager Nord',
|
locationHint: 'Frenkendorf BL, Lager Nord',
|
||||||
title: 'Schweizer Grosshandel AG — Lagerfläche Frenkendorf unter Konsolidierungsdruck',
|
title: 'Frenkendorf BL — 3\'500 m² Lagerfläche unter Konsolidierungsdruck',
|
||||||
areaSqmEstimate: 3500,
|
areaSqmEstimate: 3500,
|
||||||
probability: 0.50,
|
probability: 0.50,
|
||||||
confidenceScore: 0.46,
|
confidenceScore: 0.46,
|
||||||
@@ -520,20 +359,219 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-04-07T08:00:00Z',
|
createdAt: '2025-04-07T08:00:00Z',
|
||||||
updatedAt: '2025-05-08T09:00:00Z',
|
updatedAt: '2025-05-08T09:00:00Z',
|
||||||
|
aiSummary: 'Der Mutterkonzern hat eine Konsolidierung der Lagerstandorte in der Nordwestschweiz angekündigt. Mitarbeiterzahl Frenkendorf: von 54 auf 44 (–19%) in 8 Monaten. Strukturelle Konsolidierung im Grosshandel trifft Nebenstandorte zuerst — kein Auszugstermin bekannt.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'Mutterkonzern hat Konsolidierung der Lagerstandorte Nordwestschweiz angekündigt',
|
'Mutterkonzern hat Konsolidierung der Lagerstandorte Nordwestschweiz angekündigt',
|
||||||
'Mitarbeiterzahl Frenkendorf: von 54 auf 44 (-19%) in 8 Monaten',
|
'Mitarbeiterzahl Frenkendorf: von 54 auf 44 (–19%) in 8 Monaten',
|
||||||
'Grosshandel CH: Lagerflächennachfrage 2024 stagniert — Kostendruck durch E-Commerce',
|
'Grosshandel CH: Lagerflächennachfrage 2024 stagniert — Kostendruck durch E-Commerce',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Strukturelle Konsolidierung im Grosshandel trifft Nebenstandorte wie Frenkendorf zuerst. Kein Auszugstermin bekannt — Signal noch in früher Phase. Eigentümer sollte Kontakt suchen.',
|
strategicInterpretation: 'Strukturelle Konsolidierung im Grosshandel trifft Nebenstandorte wie Frenkendorf zuerst. Signal noch in früher Phase — Eigentümer sollte Kontakt suchen.',
|
||||||
confirmedFacts: ['Konsolidierungsankündigung des Mutterkonzerns publiziert', 'Personalrückgang in Frenkendorf dokumentiert', 'Aktueller Standort Frenkendorf bekannt'],
|
confirmedFacts: ['Konsolidierungsankündigung des Mutterkonzerns publiziert', 'Personalrückgang in Frenkendorf dokumentiert', 'Aktueller Standort Frenkendorf bekannt'],
|
||||||
unconfirmedFacts: ['Welche Lagerstandorte konkret betroffen', 'Zeitpunkt eines möglichen Auszugs', 'Ob Fläche ganz oder teilweise aufgegeben'],
|
unconfirmedFacts: ['Welche Lagerstandorte konkret betroffen', 'Zeitpunkt eines möglichen Auszugs', 'Ob Fläche ganz oder teilweise aufgegeben'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// --- signal-015: BernTech Innovation AG — Büroexpansion Bern Breitenrain ---
|
// ── DEMAND signals — company is looking for space → Markt-Leads (Verwaltung) ─
|
||||||
|
|
||||||
|
// signal-001: DataCloud Systems AG — Büroexpansion Zürich-West
|
||||||
|
{
|
||||||
|
id: 'signal-001',
|
||||||
|
signalType: SignalType.EXPANSION,
|
||||||
|
signalDirection: 'DEMAND',
|
||||||
|
companyName: 'DataCloud Systems AG',
|
||||||
|
locationHint: 'Zürich-West / Technopark',
|
||||||
|
title: 'DataCloud Systems AG sucht ~600 m² Bürofläche in Zürich-West',
|
||||||
|
areaSqmEstimate: 600,
|
||||||
|
probability: 0.72,
|
||||||
|
confidenceScore: 0.68,
|
||||||
|
timeHorizonMonths: 10,
|
||||||
|
source: {
|
||||||
|
type: 'JOB_POSTING',
|
||||||
|
url: 'https://example.com/jobs/datacloud',
|
||||||
|
publishedAt: '2025-04-20',
|
||||||
|
credibility: 'MEDIUM',
|
||||||
|
},
|
||||||
|
sensitivityLevel: 'INTERNAL',
|
||||||
|
disclaimer: 'Erkannte Flächennachfrage aus öffentlichen Quellen. Kein bestätigtes Mietverhältnis — potenzielle Mieteranbahnung für Verwaltung.',
|
||||||
|
riskLevel: RiskLevel.MEDIUM,
|
||||||
|
marketIndicator: 'Tech-Sektor Stellenwachstum +38% YoY',
|
||||||
|
relevanceScore: 0.76,
|
||||||
|
isVerified: false,
|
||||||
|
expiresAt: '2026-03-01',
|
||||||
|
organizationId: 'org-wincasa',
|
||||||
|
createdAt: '2025-05-01T07:00:00Z',
|
||||||
|
updatedAt: '2025-05-10T07:00:00Z',
|
||||||
|
aiSummary: 'KI hat in 90 Tagen 14 Stelleninserate von DataCloud Systems AG mit explizitem Standort Zürich-West/Technopark ausgewertet. Das Wachstumsmuster (DevOps, Cloud-Architektur, Sales) deutet auf eine Teamvergrösserung von ~40 Personen hin — entspricht einem Flächenbedarf von ca. 600 m². Potenzieller Mieter für Büroflächen in Zürich-West.',
|
||||||
|
marketIndicators: [
|
||||||
|
'14 Stelleninserate mit Standort Zürich-West in 90 Tagen',
|
||||||
|
'Teamwachstum ~40 Personen (DevOps, Cloud-Architektur, Sales)',
|
||||||
|
'Tech-Sektor Zürich-West: +38% Stellenwachstum 2024',
|
||||||
|
],
|
||||||
|
strategicInterpretation: 'DataCloud Systems AG befindet sich in einer klaren Wachstumsphase mit Fokus auf Zürich-West. Unternehmen mit diesem Wachstumsmuster sucht typischerweise 500–700 m² Bürofläche mit Ausbauoptionen.',
|
||||||
|
confirmedFacts: ['Region Zürich-West aus Inseraten bestätigt', 'Flächentyp Büro plausibel', 'Wachstumstrend seit 6 Monaten vorhanden'],
|
||||||
|
unconfirmedFacts: ['Exakter Flächenbedarf', 'Ob interner Ausbau am aktuellen Standort geplant', 'Zeitplan für die Entscheidung'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// signal-004: Novabio Pharma AG — Laborexpansion Basel Allschwil
|
||||||
|
{
|
||||||
|
id: 'signal-004',
|
||||||
|
signalType: SignalType.EXPANSION,
|
||||||
|
signalDirection: 'DEMAND',
|
||||||
|
companyName: 'Novabio Pharma AG',
|
||||||
|
locationHint: 'Basel, Allschwil',
|
||||||
|
title: 'Novabio Pharma AG sucht ~700 m² Labor-/Bürofläche in Basel Allschwil',
|
||||||
|
areaSqmEstimate: 700,
|
||||||
|
probability: 0.63,
|
||||||
|
confidenceScore: 0.60,
|
||||||
|
timeHorizonMonths: 14,
|
||||||
|
source: {
|
||||||
|
type: 'COMPANY_REPORT',
|
||||||
|
url: 'https://example.com/annual/novabio-2025',
|
||||||
|
publishedAt: '2025-03-28',
|
||||||
|
credibility: 'HIGH',
|
||||||
|
},
|
||||||
|
sensitivityLevel: 'INTERNAL',
|
||||||
|
disclaimer: 'Erkannte Flächennachfrage aus Geschäftsbericht. Kein bestätigtes Mietverhältnis — potenzielle Mieteranbahnung für Verwaltung.',
|
||||||
|
riskLevel: RiskLevel.MEDIUM,
|
||||||
|
marketIndicator: 'Pharmastandort Basel: +22% Beschäftigte Life-Sciences 2024',
|
||||||
|
relevanceScore: 0.70,
|
||||||
|
isVerified: false,
|
||||||
|
expiresAt: '2026-07-01',
|
||||||
|
organizationId: 'org-wincasa',
|
||||||
|
createdAt: '2025-04-02T09:00:00Z',
|
||||||
|
updatedAt: '2025-05-08T10:00:00Z',
|
||||||
|
aiSummary: 'Novabio Pharma AG kommuniziert im Geschäftsbericht 2024 eine "strategische Kapazitätserweiterung im Forschungsbereich Basel-Allschwil bis 2026". 6 Inserate für Senior Scientists und Lab-Manager mit Standort Allschwil identifiziert. Potenzieller Mieter für Labor-/Büroflächen im Life-Sciences-Korridor.',
|
||||||
|
marketIndicators: [
|
||||||
|
'Geschäftsbericht 2024: «Kapazitätserweiterung Basel-Allschwil bis 2026» explizit erwähnt',
|
||||||
|
'6 Inserate für Senior Scientists und Lab-Manager mit Standort Allschwil in 60 Tagen',
|
||||||
|
'Life-Sciences-Korridor Basel-Allschwil: höchste CH-weite Laborflächen-Nachfrage 2024',
|
||||||
|
],
|
||||||
|
strategicInterpretation: 'Novabio Pharma AG kommuniziert Expansion öffentlich — Flächensuche sehr wahrscheinlich aktiv. Fokus auf Laborpersonal deutet auf kombinierten Lab-/Bürobedarf von 600–800 m² hin.',
|
||||||
|
confirmedFacts: ['Expansionspläne im Geschäftsbericht bestätigt', 'Region Basel-Allschwil als Zielstandort genannt', 'Einstellungstrend seit Q1 2025 sichtbar'],
|
||||||
|
unconfirmedFacts: ['Ob Neubau oder Bestandsfläche gesucht', 'Exakter Flächenbedarf Labor vs. Büro', 'Zeitpunkt des Einzugs'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// signal-007: SwissCart E-Commerce GmbH — Logistikexpansion Zug
|
||||||
|
{
|
||||||
|
id: 'signal-007',
|
||||||
|
signalType: SignalType.EXPANSION,
|
||||||
|
signalDirection: 'DEMAND',
|
||||||
|
companyName: 'SwissCart E-Commerce GmbH',
|
||||||
|
locationHint: 'Zug, Industriestrasse',
|
||||||
|
title: 'SwissCart E-Commerce GmbH sucht ~580 m² Logistikfläche in Zug',
|
||||||
|
areaSqmEstimate: 580,
|
||||||
|
probability: 0.66,
|
||||||
|
confidenceScore: 0.62,
|
||||||
|
timeHorizonMonths: 9,
|
||||||
|
source: {
|
||||||
|
type: 'JOB_POSTING',
|
||||||
|
url: 'https://example.com/jobs/swisscart-zug',
|
||||||
|
publishedAt: '2025-04-18',
|
||||||
|
credibility: 'MEDIUM',
|
||||||
|
},
|
||||||
|
sensitivityLevel: 'INTERNAL',
|
||||||
|
disclaimer: 'Erkannte Flächennachfrage aus Stelleninseraten. Kein bestätigtes Mietverhältnis — potenzielle Mieteranbahnung für Verwaltung.',
|
||||||
|
riskLevel: RiskLevel.MEDIUM,
|
||||||
|
marketIndicator: 'E-Commerce Zug: Stellenwachstum +55% YoY',
|
||||||
|
relevanceScore: 0.69,
|
||||||
|
isVerified: false,
|
||||||
|
expiresAt: '2026-02-01',
|
||||||
|
organizationId: 'org-wincasa',
|
||||||
|
createdAt: '2025-04-20T07:00:00Z',
|
||||||
|
updatedAt: '2025-05-09T08:00:00Z',
|
||||||
|
aiSummary: 'In 45 Tagen wurden 9 Stelleninserate für Lager- und Logistikpersonal von SwissCart E-Commerce GmbH in Zug identifiziert. E-Commerce-Umsatz CH 2024 +22% — Nachfrage nach Lagerflächen steigt. Potenzieller Mieter für Logistikflächen in der Region Zug.',
|
||||||
|
marketIndicators: [
|
||||||
|
'9 Stelleninserate für Lager- und Logistikpersonal in Zug in 45 Tagen',
|
||||||
|
'E-Commerce-Umsatz CH 2024: +22% — Nachfrage nach Lagerflächen steigt',
|
||||||
|
'Zug Industriestrasse: aktuelle Leerstandsquote Lager unter 3%',
|
||||||
|
],
|
||||||
|
strategicInterpretation: 'Massiver Personalaufbau im Logistikbereich deutet auf konkreten Flächenbedarf hin. Zug als Steuerkanton bleibt attraktiver Firmensitz — kein Standortwechsel erwartet, nur Erweiterung.',
|
||||||
|
confirmedFacts: ['Region Zug aus Inseraten bestätigt', 'Flächentyp Logistik/Lager aus Stellenprofilen ableitbar', 'Wachstumstrend seit Q3 2024 sichtbar'],
|
||||||
|
unconfirmedFacts: ['Ob zusätzliche Bürofläche benötigt', 'Exakter Flächenbedarf', 'Bevorzugte Strassenlage (Anlieferung)'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// signal-010: Ostschweiz Digital AG — Büroexpansion St. Gallen
|
||||||
|
{
|
||||||
|
id: 'signal-010',
|
||||||
|
signalType: SignalType.EXPANSION,
|
||||||
|
signalDirection: 'DEMAND',
|
||||||
|
companyName: 'Ostschweiz Digital AG',
|
||||||
|
locationHint: 'St. Gallen, Riethüsli',
|
||||||
|
title: 'Ostschweiz Digital AG sucht ~480 m² Bürofläche in St. Gallen',
|
||||||
|
areaSqmEstimate: 480,
|
||||||
|
probability: 0.60,
|
||||||
|
confidenceScore: 0.55,
|
||||||
|
timeHorizonMonths: 10,
|
||||||
|
source: {
|
||||||
|
type: 'JOB_POSTING',
|
||||||
|
url: 'https://example.com/jobs/ostschweiz-digital',
|
||||||
|
publishedAt: '2025-04-22',
|
||||||
|
credibility: 'MEDIUM',
|
||||||
|
},
|
||||||
|
sensitivityLevel: 'INTERNAL',
|
||||||
|
disclaimer: 'Erkannte Flächennachfrage aus Stelleninseraten. Kein bestätigtes Mietverhältnis — potenzielle Mieteranbahnung für Verwaltung.',
|
||||||
|
riskLevel: RiskLevel.MEDIUM,
|
||||||
|
marketIndicator: 'Digitalwirtschaft Ostschweiz: +28% Beschäftigte 2024',
|
||||||
|
relevanceScore: 0.62,
|
||||||
|
isVerified: false,
|
||||||
|
expiresAt: '2026-03-01',
|
||||||
|
organizationId: 'org-wincasa',
|
||||||
|
createdAt: '2025-04-25T08:00:00Z',
|
||||||
|
updatedAt: '2025-05-10T07:00:00Z',
|
||||||
|
aiSummary: '8 Stelleninserate für Software-Entwickler und UX-Designer in St. Gallen in 60 Tagen. Mitarbeiterzahl von 22 auf 31 (+41%) in 9 Monaten. Kontinuierliches Wachstum deutet auf Bedarf nach grösserer Bürofläche hin — potenzieller Mieter für Büroflächen in St. Gallen.',
|
||||||
|
marketIndicators: [
|
||||||
|
'8 Stelleninserate für Software-Entwickler und UX-Designer in St. Gallen in 60 Tagen',
|
||||||
|
'Ostschweiz Digital AG: Mitarbeiterzahl von 22 auf 31 (+41%) in 9 Monaten',
|
||||||
|
'Digitalwirtschaft Ostschweiz: +28% Beschäftigte 2024 (IHK-Bericht)',
|
||||||
|
],
|
||||||
|
strategicInterpretation: 'Kontinuierliches Teamwachstum mit Fokus auf St. Gallen deutet auf organische Expansion hin. Erweiterungsfläche am bisherigen Standort oder Umzug in grössere Einheit möglich.',
|
||||||
|
confirmedFacts: ['Region St. Gallen aus Inseraten bestätigt', 'Wachstumstrend seit Q3 2024 nachweisbar', 'Flächentyp Büro aus Stellenprofilen ableitbar'],
|
||||||
|
unconfirmedFacts: ['Ob aktueller Standort Riethüsli oder neue Lage', 'Exakter Flächenbedarf', 'Zeitpunkt der Entscheidung'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// signal-013: Geneva Finance Partners SA — Büroexpansion Genf
|
||||||
|
{
|
||||||
|
id: 'signal-013',
|
||||||
|
signalType: SignalType.EXPANSION,
|
||||||
|
signalDirection: 'DEMAND',
|
||||||
|
companyName: 'Geneva Finance Partners SA',
|
||||||
|
locationHint: 'Genf, La Praille',
|
||||||
|
title: 'Geneva Finance Partners SA sucht ~520 m² Bürofläche in Genf La Praille',
|
||||||
|
areaSqmEstimate: 520,
|
||||||
|
probability: 0.58,
|
||||||
|
confidenceScore: 0.53,
|
||||||
|
timeHorizonMonths: 20,
|
||||||
|
source: {
|
||||||
|
type: 'COMPANY_REPORT',
|
||||||
|
url: 'https://example.com/annual/gfp-2025',
|
||||||
|
publishedAt: '2025-03-05',
|
||||||
|
credibility: 'MEDIUM',
|
||||||
|
},
|
||||||
|
sensitivityLevel: 'INTERNAL',
|
||||||
|
disclaimer: 'Erkannte Flächennachfrage aus Jahresbericht. Kein bestätigtes Mietverhältnis — potenzielle Mieteranbahnung für Verwaltung.',
|
||||||
|
riskLevel: RiskLevel.MEDIUM,
|
||||||
|
marketIndicator: 'Büroflächennachfrage Genf: +15% 2025',
|
||||||
|
relevanceScore: 0.60,
|
||||||
|
isVerified: false,
|
||||||
|
expiresAt: '2027-01-01',
|
||||||
|
organizationId: 'org-wincasa',
|
||||||
|
createdAt: '2025-03-08T11:00:00Z',
|
||||||
|
updatedAt: '2025-05-07T10:00:00Z',
|
||||||
|
aiSummary: 'Jahresbericht 2024: «Expansion des Genfer Teams auf 40 FTE bis 2026» angekündigt. 5 neue Inserate für Senior-Portfoliomanager mit Standort Genf in 30 Tagen. Potenzieller Mieter für Büroflächen in Genf La Praille.',
|
||||||
|
marketIndicators: [
|
||||||
|
'Jahresbericht 2024: «Expansion des Genfer Teams auf 40 FTE bis 2026» angekündigt',
|
||||||
|
'Genf Finanzsektor: +15% Büroflächennachfrage 2025 (CBRE-Bericht)',
|
||||||
|
'5 neue Inserate für Senior-Portfoliomanager mit Standort Genf in 30 Tagen',
|
||||||
|
],
|
||||||
|
strategicInterpretation: 'Öffentlich kommunizierte Expansion mit klarem Zielhorizont 2026. La Praille bietet kostengünstigere Büroflächen als Genf Innenstadt bei guter ÖV-Anbindung. Flächensuche dürfte aktiv beginnen.',
|
||||||
|
confirmedFacts: ['Expansion im Jahresbericht kommuniziert', 'Teamwachstum auf 40 FTE bis 2026 bestätigt', 'Inserate für Genf aktiv'],
|
||||||
|
unconfirmedFacts: ['Ob La Praille oder andere Lage bevorzugt', 'Exakter Flächenbedarf', 'Ob Repräsentationsbüros benötigt'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// signal-015: BernTech Innovation AG — Büroexpansion Bern Breitenrain
|
||||||
{
|
{
|
||||||
id: 'signal-015',
|
id: 'signal-015',
|
||||||
signalType: SignalType.EXPANSION,
|
signalType: SignalType.EXPANSION,
|
||||||
|
signalDirection: 'DEMAND',
|
||||||
companyName: 'BernTech Innovation AG',
|
companyName: 'BernTech Innovation AG',
|
||||||
locationHint: 'Bern, Breitenrain',
|
locationHint: 'Bern, Breitenrain',
|
||||||
title: 'BernTech Innovation AG sucht ~1\'800 m² Bürofläche in Bern Breitenrain',
|
title: 'BernTech Innovation AG sucht ~1\'800 m² Bürofläche in Bern Breitenrain',
|
||||||
@@ -548,7 +586,7 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
credibility: 'MEDIUM',
|
credibility: 'MEDIUM',
|
||||||
},
|
},
|
||||||
sensitivityLevel: 'INTERNAL',
|
sensitivityLevel: 'INTERNAL',
|
||||||
disclaimer: 'Wachstumssignal aus Stellenanzeigen und Social-Media-Analyse. Kein bestätigtes Objekt.',
|
disclaimer: 'Erkannte Flächennachfrage aus Stelleninseraten und VC-Finanzierungsdaten. Kein bestätigtes Mietverhältnis — potenzielle Mieteranbahnung für Verwaltung.',
|
||||||
riskLevel: RiskLevel.MEDIUM,
|
riskLevel: RiskLevel.MEDIUM,
|
||||||
marketIndicator: 'Bern Tech-Ökosystem: Risikokapital +40% 2024',
|
marketIndicator: 'Bern Tech-Ökosystem: Risikokapital +40% 2024',
|
||||||
relevanceScore: 0.66,
|
relevanceScore: 0.66,
|
||||||
@@ -557,12 +595,13 @@ export const mockFutureSignals: FutureSignal[] = [
|
|||||||
organizationId: 'org-wincasa',
|
organizationId: 'org-wincasa',
|
||||||
createdAt: '2025-04-28T09:00:00Z',
|
createdAt: '2025-04-28T09:00:00Z',
|
||||||
updatedAt: '2025-05-10T08:00:00Z',
|
updatedAt: '2025-05-10T08:00:00Z',
|
||||||
|
aiSummary: '18 Stelleninserate in 60 Tagen (Fokus Software-Engineering und Product Management). VC-Finanzierungsrunde CHF 12 Mio. im März 2025 öffentlich bestätigt. Frisch finanziertes Wachstumsunternehmen mit Budget für Flächenexpansion — potenzieller Mieter für Büroflächen in Bern.',
|
||||||
marketIndicators: [
|
marketIndicators: [
|
||||||
'18 Stelleninserate in 60 Tagen — Fokus Software-Engineering und Product Management',
|
'18 Stelleninserate in 60 Tagen — Fokus Software-Engineering und Product Management',
|
||||||
'BernTech Innovation AG: VC-Finanzierungsrunde CHF 12 Mio. im März 2025 bestätigt',
|
'BernTech Innovation AG: VC-Finanzierungsrunde CHF 12 Mio. im März 2025 bestätigt',
|
||||||
'Bern Tech-Ökosystem: Risikokapital +40% 2024 — stärkstes Wachstum seit 2019',
|
'Bern Tech-Ökosystem: Risikokapital +40% 2024 — stärkstes Wachstum seit 2019',
|
||||||
],
|
],
|
||||||
strategicInterpretation: 'Frisch finanziertes Wachstumsunternehmen mit aktivem Stellenaufbau. VC-Finanzierung als starkes Signal für konkreten Flächenbedarf — Budgets vorhanden. Breitenrain als Tech-Standort in Bern etabliert.',
|
strategicInterpretation: 'Frisch finanziertes Wachstumsunternehmen mit aktivem Stellenaufbau und gesichertem Budget. VC-Finanzierung als starkes Signal für konkreten Flächenbedarf. Breitenrain als Tech-Standort in Bern etabliert.',
|
||||||
confirmedFacts: ['VC-Finanzierungsrunde CHF 12 Mio. öffentlich bestätigt', 'Region Bern aus Inseraten bestätigt', 'Wachstumstrend seit Q1 2025 sichtbar'],
|
confirmedFacts: ['VC-Finanzierungsrunde CHF 12 Mio. öffentlich bestätigt', 'Region Bern aus Inseraten bestätigt', 'Wachstumstrend seit Q1 2025 sichtbar'],
|
||||||
unconfirmedFacts: ['Exakter Flächenbedarf (Schätzung: 1\'500–2\'000 m²)', 'Ob Breitenrain oder andere Berner Lage bevorzugt', 'Zeitpunkt Einzug'],
|
unconfirmedFacts: ['Exakter Flächenbedarf (Schätzung: 1\'500–2\'000 m²)', 'Ob Breitenrain oder andere Berner Lage bevorzugt', 'Zeitpunkt Einzug'],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,296 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Chip,
|
||||||
|
CircularProgress,
|
||||||
|
Divider,
|
||||||
|
Paper,
|
||||||
|
Skeleton,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material'
|
||||||
|
import {
|
||||||
|
AlertCircle,
|
||||||
|
BarChart2,
|
||||||
|
Briefcase,
|
||||||
|
Building2,
|
||||||
|
CheckCircle2,
|
||||||
|
FileText,
|
||||||
|
Newspaper,
|
||||||
|
Target,
|
||||||
|
TrendingUp,
|
||||||
|
Users,
|
||||||
|
} from 'lucide-react'
|
||||||
|
import { useNavigate } from 'react-router'
|
||||||
|
import { useMarketLeads } from '../../hooks/useMarketLeads'
|
||||||
|
import { DecisionContextPanel } from '../../components/ui'
|
||||||
|
import type { MarketLead } from '../../hooks/useMarketLeads'
|
||||||
|
import type { Property } from '../../domain/property'
|
||||||
|
|
||||||
|
// ── Source meta ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
const SOURCE_META: Record<string, { label: string; icon: React.ReactNode }> = {
|
||||||
|
JOB_POSTING: { label: 'Stelleninserate', icon: <Briefcase size={12} /> },
|
||||||
|
PRESS: { label: 'Pressebericht', icon: <Newspaper size={12} /> },
|
||||||
|
COMPANY_REPORT: { label: 'Geschäftsbericht',icon: <FileText size={12} /> },
|
||||||
|
MARKET_DATA: { label: 'Marktdaten', icon: <BarChart2 size={12} /> },
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUALITY_META: Record<string, { label: string; color: string }> = {
|
||||||
|
HIGH: { label: 'Hohe Signalqualität', color: '#1a7a4a' },
|
||||||
|
MEDIUM: { label: 'Mittlere Signalqualität', color: '#d97706' },
|
||||||
|
LOW: { label: 'Niedrige Signalqualität', color: '#c0392b' },
|
||||||
|
}
|
||||||
|
|
||||||
|
function signalQuality(probability: number): 'HIGH' | 'MEDIUM' | 'LOW' {
|
||||||
|
return probability >= 0.70 ? 'HIGH' : probability >= 0.50 ? 'MEDIUM' : 'LOW'
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Property match chip ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function PropertyMatchRow({ p }: { p: Property }) {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
onClick={() => navigate('/supply/properties')}
|
||||||
|
sx={{
|
||||||
|
display: 'flex', alignItems: 'center', gap: 1,
|
||||||
|
px: 1.25, py: 0.75, borderRadius: 1,
|
||||||
|
bgcolor: '#f0fdf4', border: '1px solid #bbf7d0',
|
||||||
|
cursor: 'pointer', '&:hover': { bgcolor: '#dcfce7' },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Building2 size={12} color="#1a7a4a" style={{ flexShrink: 0 }} />
|
||||||
|
<Typography variant="caption" sx={{ fontWeight: 600, color: '#1a7a4a', flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||||
|
{p.title}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" sx={{ color: '#1a7a4a', flexShrink: 0 }}>
|
||||||
|
{p.areaSqm.toLocaleString('de-CH')} m²
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Lead card ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function LeadCard({ lead }: { lead: MarketLead }) {
|
||||||
|
const { signal, matchingProperties } = lead
|
||||||
|
const probPct = Math.round(signal.probability * 100)
|
||||||
|
const qual = signalQuality(signal.probability)
|
||||||
|
const qualMeta = QUALITY_META[qual]
|
||||||
|
const sourceMeta = SOURCE_META[signal.source.type] ?? null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
sx={{
|
||||||
|
p: 2.5, mb: 2,
|
||||||
|
borderLeft: '3px solid #1d4ed8',
|
||||||
|
position: 'relative',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Header */}
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 2, mb: 1.5 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1.25 }}>
|
||||||
|
<Box sx={{ mt: 0.25, flexShrink: 0 }}>
|
||||||
|
<Target size={18} color="#1d4ed8" />
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="subtitle1" sx={{ fontWeight: 700, lineHeight: 1.25, mb: 0.25 }}>
|
||||||
|
{signal.companyName ?? signal.locationHint}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{signal.title}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Chip
|
||||||
|
label="Market Signal"
|
||||||
|
size="small"
|
||||||
|
sx={{ bgcolor: '#eff6ff', color: '#1d4ed8', fontWeight: 700, fontSize: '0.68rem', flexShrink: 0 }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Key facts strip */}
|
||||||
|
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 2, mb: 1.75 }}>
|
||||||
|
{signal.areaSqmEstimate && (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', lineHeight: 1.2 }}>Flächenbedarf</Typography>
|
||||||
|
<Typography variant="body2" sx={{ fontWeight: 700 }}>~{signal.areaSqmEstimate.toLocaleString('de-CH')} m²</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', lineHeight: 1.2 }}>Zeithorizont</Typography>
|
||||||
|
<Typography variant="body2" sx={{ fontWeight: 700 }}>~{signal.timeHorizonMonths} Monate</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', lineHeight: 1.2 }}>Wahrscheinlichkeit</Typography>
|
||||||
|
<Typography variant="body2" sx={{ fontWeight: 700, color: qualMeta.color }}>{probPct}%</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', lineHeight: 1.2 }}>Standort</Typography>
|
||||||
|
<Typography variant="body2" sx={{ fontWeight: 700 }}>{signal.locationHint}</Typography>
|
||||||
|
</Box>
|
||||||
|
{sourceMeta && (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', lineHeight: 1.2 }}>Quelle</Typography>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||||
|
{sourceMeta.icon}
|
||||||
|
<Typography variant="body2" sx={{ fontWeight: 600 }}>{sourceMeta.label}</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Divider sx={{ mb: 1.75 }} />
|
||||||
|
|
||||||
|
{/* Market indicators */}
|
||||||
|
{signal.marketIndicators && signal.marketIndicators.length > 0 && (
|
||||||
|
<Box sx={{ mb: 1.75 }}>
|
||||||
|
<Typography variant="caption" sx={{ fontWeight: 700, color: '#475569', textTransform: 'uppercase', letterSpacing: 0.5, display: 'block', mb: 0.75 }}>
|
||||||
|
Erkannte Nachfragesignale
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||||
|
{signal.marketIndicators.map((ind, i) => (
|
||||||
|
<Box key={i} sx={{ display: 'flex', alignItems: 'flex-start', gap: 0.75 }}>
|
||||||
|
<TrendingUp size={11} color="#1d4ed8" style={{ marginTop: 3, flexShrink: 0 }} />
|
||||||
|
<Typography variant="body2" sx={{ color: '#374151', lineHeight: 1.4 }}>{ind}</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Confirmed / unconfirmed facts */}
|
||||||
|
{((signal.confirmedFacts?.length ?? 0) > 0 || (signal.unconfirmedFacts?.length ?? 0) > 0) && (
|
||||||
|
<Box sx={{ mb: 1.75 }}>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.4 }}>
|
||||||
|
{(signal.confirmedFacts ?? []).map((f, i) => (
|
||||||
|
<Box key={`c-${i}`} sx={{ display: 'flex', alignItems: 'center', gap: 0.75 }}>
|
||||||
|
<CheckCircle2 size={12} color="#1a7a4a" style={{ flexShrink: 0 }} />
|
||||||
|
<Typography variant="caption" sx={{ color: '#1a7a4a', fontWeight: 500 }}>{f}</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
{(signal.unconfirmedFacts ?? []).map((f, i) => (
|
||||||
|
<Box key={`u-${i}`} sx={{ display: 'flex', alignItems: 'center', gap: 0.75 }}>
|
||||||
|
<AlertCircle size={12} color="#d97706" style={{ flexShrink: 0 }} />
|
||||||
|
<Typography variant="caption" sx={{ color: '#d97706', fontWeight: 500 }}>{f}</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Divider sx={{ mb: 1.5 }} />
|
||||||
|
|
||||||
|
{/* Portfolio matches */}
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" sx={{ fontWeight: 700, color: '#475569', textTransform: 'uppercase', letterSpacing: 0.5, display: 'block', mb: 0.75 }}>
|
||||||
|
Passende Objekte im Portfolio ({matchingProperties.length})
|
||||||
|
</Typography>
|
||||||
|
{matchingProperties.length === 0 ? (
|
||||||
|
<Typography variant="caption" color="text.disabled" sx={{ fontStyle: 'italic' }}>
|
||||||
|
Kein passendes Portfolioobjekt gefunden — manuell prüfen empfohlen
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||||
|
{matchingProperties.slice(0, 3).map(p => (
|
||||||
|
<PropertyMatchRow key={p.id} p={p} />
|
||||||
|
))}
|
||||||
|
{matchingProperties.length > 3 && (
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ pl: 0.5 }}>
|
||||||
|
+{matchingProperties.length - 3} weitere Objekte
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Disclaimer */}
|
||||||
|
<Typography variant="caption" color="text.disabled" sx={{ display: 'block', mt: 1.5, pt: 1.25, borderTop: '1px solid #f1f5f9', lineHeight: 1.4 }}>
|
||||||
|
{signal.disclaimer}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Loading skeleton ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function LeadSkeleton() {
|
||||||
|
return (
|
||||||
|
<Paper sx={{ p: 2.5, mb: 2, borderLeft: '3px solid #e2e8f0' }}>
|
||||||
|
<Skeleton variant="text" width="60%" height={24} sx={{ mb: 0.5 }} />
|
||||||
|
<Skeleton variant="text" width="80%" height={18} sx={{ mb: 2 }} />
|
||||||
|
<Skeleton variant="rectangular" height={48} sx={{ borderRadius: 1, mb: 2 }} />
|
||||||
|
<Skeleton variant="rectangular" height={64} sx={{ borderRadius: 1 }} />
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Page ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
export default function MarketLeads() {
|
||||||
|
const { data: leads, isLoading } = useMarketLeads()
|
||||||
|
|
||||||
|
const leadsWithMatch = leads.filter(l => l.matchingProperties.length > 0)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<Box sx={{ px: 3, py: 2, bgcolor: 'white', borderBottom: '1px solid #e2e8f0', flexShrink: 0 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
||||||
|
<Users size={20} color="#1d4ed8" />
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h6" sx={{ fontWeight: 700, lineHeight: 1.2 }}>Markt-Leads</Typography>
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
Erkannte Unternehmen mit aktivem Flächenbedarf — potenzielle Mieter für Ihr Portfolio
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
{!isLoading && (
|
||||||
|
<Chip
|
||||||
|
label={`${leads.length} aktive Leads`}
|
||||||
|
size="small"
|
||||||
|
sx={{ ml: 'auto', bgcolor: '#eff6ff', color: '#1d4ed8', fontWeight: 700 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ flex: 1, overflowY: 'auto', px: 3, py: 3 }}>
|
||||||
|
|
||||||
|
{/* Decision context */}
|
||||||
|
{!isLoading && leads.length > 0 && (
|
||||||
|
<DecisionContextPanel
|
||||||
|
decision="Welche Unternehmen könnten als Nachmieter für Ihre Objekte in Frage kommen?"
|
||||||
|
context={`${leads.length} erkannte Nachfragesignale · ${leadsWithMatch.length} mit passendem Portfolioobjekt`}
|
||||||
|
metrics={[
|
||||||
|
{ label: 'aktive Markt-Leads', value: leads.length, severity: 'positive' },
|
||||||
|
...(leadsWithMatch.length > 0
|
||||||
|
? [{ label: 'mit passendem Objekt', value: leadsWithMatch.length, severity: 'positive' as const }]
|
||||||
|
: []),
|
||||||
|
]}
|
||||||
|
risks={leads.length - leadsWithMatch.length > 0
|
||||||
|
? [`${leads.length - leadsWithMatch.length} Leads ohne direkten Portfolio-Match — Leerstandsanalyse empfohlen`]
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
actions={[]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<>
|
||||||
|
<LeadSkeleton />
|
||||||
|
<LeadSkeleton />
|
||||||
|
<LeadSkeleton />
|
||||||
|
</>
|
||||||
|
) : leads.length === 0 ? (
|
||||||
|
<Paper sx={{ p: 4, textAlign: 'center' }}>
|
||||||
|
<CircularProgress size={24} sx={{ mb: 2, color: '#94a3b8' }} />
|
||||||
|
<Typography variant="body1" color="text.secondary">Keine aktiven Markt-Leads gefunden.</Typography>
|
||||||
|
<Typography variant="caption" color="text.disabled">Signale werden laufend aus öffentlichen Quellen erkannt.</Typography>
|
||||||
|
</Paper>
|
||||||
|
) : (
|
||||||
|
leads.map(lead => <LeadCard key={lead.signal.id} lead={lead} />)
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user