Files
property-match/src/App.tsx
T
Benjamin Sutter cc5582b7fd refactor: dritte Bereinigungsrunde Property On
Kopfzeile: Der zusaetzliche Titelbalken mit dem Chip Verwaltung und dem
wiederholten Seitennamen entfaellt auf allen Hauptseiten, ebenso der
Einstieg AI Assistent. Ohne Trennlinie geht die Zeile bruchlos in den
Seiteninhalt ueber; Glocke und Profil bleiben rechts stehen. Der
Pilotkunde heisst sichtbar Beispiel Immobilien AG, die technische Kennung
org-wincasa bleibt unangetastet.

Flaechensuche und Anfragencenter sind aus Navigation, Routing und Branch
entfernt. Verweise, die dadurch ins Leere zeigten, haengen neu am Match
Center; der Quicklink ins Anfragencenter im Vorgangsdetail ist entfallen.

Meine Objekte: feste vier Karten je Zeile auf Desktop, zwei auf Tablet,
eine auf Mobil. Die Dichteauswahl 3/5/10 und der Datenpflege-Hinweis sind
weg; die Datenpflege bleibt als eigener Hauptreiter erreichbar.

Objektbilder liegen erstmals lokal. Zuvor zeigten 98 Objekte auf Unsplash
und teilten sich 29 Fotos, verschiedene Adressen trugen also dasselbe
Bild. Neu traegt jede Objekt-ID genau eine eigene Datei; die Zuordnung
laeuft ueber die stabile ID, nicht ueber den Titel. Die Dateien sind
erzeugte Vektorgrafiken, keine Fotografien - echte Aufnahmen ersetzen sie
spaeter unter demselben Dateinamen ohne Codeaenderung. Vite bettet sie
nicht mehr als Base64 ein, damit alle Objekte gleich behandelt sind.

Teamuebersicht zeigt nur noch das Kernteam; die Stufenfilter sind
entfallen und die aeusseren Ringe werden nicht mehr gezeichnet statt nur
durchsichtig zu sein - unsichtbare, aber anspringbare Schaltflaechen sind
eine Falle. Die Nabe nennt daher die Zahl der gezeigten Mitarbeitenden
statt der Gesamtzahl. Die Personalverwaltung hat nur noch die
Dossieransicht, der Umschalter und das drehbare Organigramm sind weg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 10:37:36 +02:00

86 lines
4.3 KiB
TypeScript

import { lazy, Suspense } from 'react'
import { Routes, Route, Navigate } from 'react-router'
import { LoadingPage, AppErrorBoundary } from './components/ui'
import { AppShell } from './components/layout'
import { ProtectedRoute } from './components/auth'
import { WorkspaceType } from './domain/enums'
import { useSessionStore } from './stores/sessionStore'
// Die Flächensuche ist entfernt — es bleibt ein einziger erreichbarer Einstieg.
const WORKSPACE_HOME: Record<string, string> = {
[WorkspaceType.SUPPLY]: '/supply/dashboard',
}
function RoleRedirect() {
const currentUser = useSessionStore(s => s.currentUser)
const first = currentUser?.allowedWorkspaces[0] ?? WorkspaceType.SUPPLY
return <Navigate to={WORKSPACE_HOME[first] ?? '/supply/dashboard'} replace />
}
const LoginScreen = lazy(() => import('./pages/auth/LoginScreen'))
const SupplyDashboard = lazy(() => import('./pages/supply/SupplyDashboard'))
const Properties = lazy(() => import('./pages/supply/Properties'))
const MatchCenter = lazy(() => import('./pages/supply/MatchCenter'))
const FutureAvailability = lazy(() => import('./pages/supply/FutureAvailability'))
const DataQuality = lazy(() => import('./pages/supply/DataQuality'))
const ReminderManager = lazy(() => import('./pages/supply/ReminderManager'))
const MarketIntelligence = lazy(() => import('./pages/supply/MarketIntelligence'))
const NewListing = lazy(() => import('./pages/supply/NewListing'))
const MyListings = lazy(() => import('./pages/supply/MyListings'))
// Property On — «Teamübersicht»
const Teamuebersicht = lazy(() => import('./pages/supply/Teamuebersicht'))
const Personalverwaltung = lazy(() => import('./pages/supply/Personalverwaltung'))
const Bearbeitungsverlauf = lazy(() => import('./pages/supply/Bearbeitungsverlauf'))
const KanaeleSysteme = lazy(() => import('./pages/supply/KanaeleSysteme'))
function App() {
return (
<AppErrorBoundary>
<Suspense fallback={<LoadingPage />}>
<Routes>
{/* Public */}
<Route path="/auth/login" element={<LoginScreen />} />
{/* Protected: auth check only */}
<Route element={<ProtectedRoute />}>
<Route element={<AppShell />}>
<Route path="/" element={<RoleRedirect />} />
{/* Supply Workspace */}
<Route element={<ProtectedRoute workspace={WorkspaceType.SUPPLY} />}>
<Route path="/supply/dashboard" element={<SupplyDashboard />} />
<Route path="/supply/properties" element={<Properties />} />
<Route path="/supply/match-center" element={<MatchCenter />} />
<Route path="/supply/future-availability" element={<FutureAvailability />} />
<Route path="/supply/data-quality" element={<DataQuality />} />
<Route path="/supply/reminder-manager" element={<ReminderManager />} />
<Route path="/supply/market-intelligence" element={<MarketIntelligence />} />
<Route path="/supply/new-listing" element={<NewListing />} />
<Route path="/supply/my-listings" element={<MyListings />} />
{/* Property On — Hierarchie und Deep-Links bleiben erhalten (§3.4).
Bewusst flache Geschwisterrouten statt <Outlet/>: die App kennt
keine einzige Feature-Route mit eigenem Outlet, ein Novum hier
würde Sidebar, Seitentitel und Guards gleichzeitig betreffen. */}
<Route path="/supply/team" element={<Teamuebersicht />} />
<Route path="/supply/team/personalverwaltung" element={<Personalverwaltung />} />
<Route path="/supply/team/personalverwaltung/:agentId" element={<Personalverwaltung />} />
<Route path="/supply/team/personalverwaltung/:agentId/:tab" element={<Personalverwaltung />} />
<Route path="/supply/team/bearbeitungsverlauf" element={<Bearbeitungsverlauf />} />
<Route path="/supply/team/bearbeitungsverlauf/:tab" element={<Bearbeitungsverlauf />} />
<Route path="/supply/team/kanaele-systeme" element={<KanaeleSysteme />} />
</Route>
</Route>
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</Suspense>
</AppErrorBoundary>
)
}
export default App