9ed21e33a7
Hauptnavigation und Startseite (§2) - Hauptseite «Übersicht» samt Route, Menüeintrag, Hook, Service und den nur dort verwendeten Widgets entfernt; /supply/dashboard leitet auf die Startseite um, damit Lesezeichen nicht ins Leere laufen. - «Meine Objekte» heisst im Menü «Startseite»; die frühere Überschrift «Objektverwaltung» heisst jetzt «Meine Objekte». - Die Startseite scrollt als Ganzes. Die Höhe des Meetingraums rechnet gegen die Viewport-Höhe, damit Titel und Balken «Filter & Übersicht» beim Einstieg auf jeder Monitorgrösse sichtbar bleiben (geprüft 1280–1920 px). Agenten-Meetingraum (§3) - Zentralperspektive aus clip-path-Flächen, ohne 3D-Engine und ohne Animationsbibliothek: rechts geschlossene Wand, links und gegenüber boden- bis deckenhohe Glasfronten mit Blick auf Rhein, Basler Münster, Altstadt und Wettsteinbrücke. - Sitzordnung, Zielrouten, Grössen und Plakettenversatz liegen in einer zentralen Konfiguration (meetingRoomSeats.ts). - Neuer Agent Giorgio, Personalverwalter, sitzt vis-à-vis und führt in «Meine Agenten». Er steht bewusst nicht in AGENT_WORKSPACES: er hat keine Arbeitsseite, sondern ist die Adminfläche selbst. - Auf schmalen Schirmen tritt eine vereinfachte Kachelanordnung an die Stelle der Perspektive; ausgeblendet wird kein Agent. Sticky Chat bei allen Agenten (§5, §9–§11) - Scrollt der Chatkopf unter den globalen Balken, übernimmt dort eine kompakte Fassung mit Porträt, Name, Frage und Eingabefeld. - Ein gemeinsamer Zustand (agentChatStore) statt zweier Chat-Instanzen: Eingabetext und Fokus überstehen den Wechsel in beide Richtungen. - Noras Seite scrollte bisher gar nicht — Chatkopf ausserhalb des Scrollbereichs, zwei getrennt scrollende Spalten darunter. Behoben über den Seitenaufbau, nicht über eine Nora-Sonderlösung. Nora: CRM-Kanal und gemeinsame Lead-Liste (§12, §13) - Dritter Kanal «CRM» mit eigenem Domänentyp, Mockdaten, Provider, Service und Hook nach dem bestehenden Schichtenmuster. - Die Reiter «KI-Signale»/«Netzwerk» sind einer gemeinsamen Liste gewichen. Jede Zeile trägt ihre Kanalherkunft als Badge; die Herkunft steht im Datenmodell (LeadChannel) und wird nicht aus der Darstellung geraten. - Der frühere Reiterbalken ist der Filter «Kanaltyp» mit Alle/KI Signal/ Netzwerk/CRM, Standard «Alle», mit Empty State und Rücksetzung. Produkttour und Profilmenü (§8) - Tour auf die neue Struktur umgeschrieben: Startseite, Meetingraum, Agenten, sticky Chat, Leadkanäle. «Übersicht» kommt nicht mehr vor, «Meine Objekte» bezeichnet nur noch den Objektbereich. - Bereich «Demo-Modus» mit «Verwaltung» und «Bürosuche» entfernt. Geprüft: 413 Tests, Typecheck, Build, ESLint, Token-Schwelle (889/925). Im Browser: Navigation, Agentenklicks aller sechs Plätze, Kanalfilter und Detailschubladen, Sticky Chat bei vier Agenten, 1280–1920 px sowie Tablet- und Mobilbreite, keine 404 für Bilder oder Routen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
80 lines
3.1 KiB
TypeScript
80 lines
3.1 KiB
TypeScript
import { Box, Chip, Typography } from '@mui/material'
|
|
import type { AssistantContext } from '../../domain/assistant'
|
|
import { DS_ACCENT, DS_SLATE } from '../../lib/ds'
|
|
|
|
const PAGE_LABELS: Record<string, string> = {
|
|
'/supply/properties': 'Startseite',
|
|
'/supply/match-center': 'Eingehende Bedarfe',
|
|
'/supply/data-quality': 'Datenpflege',
|
|
'/supply/future-availability':'Marktchancen',
|
|
'/demand/ai-search': 'Flächensuche',
|
|
'/demand/results': 'Ergebnisse',
|
|
'/demand/compare': 'Vergleich',
|
|
'/demand/shortlists': 'Shortlists',
|
|
'/ops/review-queue': 'Review Queue',
|
|
'/ops/ai-monitoring': 'AI Monitoring',
|
|
'/ops/governance': 'Governance',
|
|
}
|
|
|
|
function resolvePageLabel(route: string): string {
|
|
for (const [path, label] of Object.entries(PAGE_LABELS)) {
|
|
if (route.startsWith(path)) return label
|
|
}
|
|
return route.split('/').filter(Boolean).pop()?.replace(/-/g, ' ') ?? 'Seite'
|
|
}
|
|
|
|
const ENTITY_LABELS: Record<string, string> = {
|
|
PROPERTY: 'Objekt', NEED: 'Gesuch', MATCH: 'Match',
|
|
SIGNAL: 'Signal', AI_OUTPUT: 'AI-Output',
|
|
}
|
|
|
|
interface Props {
|
|
context: AssistantContext
|
|
}
|
|
|
|
export function AssistantContextSummary({ context }: Props) {
|
|
const pageLabel = resolvePageLabel(context.currentRoute)
|
|
|
|
return (
|
|
<Box sx={{ px: 2, py: 1, bgcolor: DS_SLATE[50], borderBottom: '1px solid #e2e8f0' }}>
|
|
<Box sx={{ display: 'flex', gap: 0.75, flexWrap: 'wrap', alignItems: 'center' }}>
|
|
<Chip
|
|
label={pageLabel}
|
|
size="small"
|
|
sx={{ bgcolor: DS_ACCENT.cyan.bg, color: DS_ACCENT.cyan.dark, fontWeight: 600, fontSize: '0.7rem', height: 20 }}
|
|
/>
|
|
{context.selectedEntityType && context.selectedEntityId && (
|
|
<Chip
|
|
label={`${ENTITY_LABELS[context.selectedEntityType] ?? context.selectedEntityType}: ${context.selectedEntityId}`}
|
|
size="small"
|
|
sx={{ bgcolor: DS_SLATE[100], color: DS_SLATE[600], fontWeight: 500, fontSize: '0.65rem', height: 20, fontFamily: 'monospace' }}
|
|
/>
|
|
)}
|
|
{context.visibleScores?.quality !== undefined && (
|
|
<Chip
|
|
label={`Qualität: ${context.visibleScores.quality}%`}
|
|
size="small"
|
|
sx={{
|
|
bgcolor: context.visibleScores.quality >= 70 ? '#dcfce7' : '#fef3c7',
|
|
color: context.visibleScores.quality >= 70 ? '#166534' : '#92400e',
|
|
fontWeight: 600, fontSize: '0.65rem', height: 20,
|
|
}}
|
|
/>
|
|
)}
|
|
{context.visibleScores?.matchScore !== undefined && (
|
|
<Chip
|
|
label={`Match: ${context.visibleScores.matchScore}%`}
|
|
size="small"
|
|
sx={{ bgcolor: DS_ACCENT.violet.tint, color: DS_ACCENT.violet.dark, fontWeight: 600, fontSize: '0.65rem', height: 20 }}
|
|
/>
|
|
)}
|
|
</Box>
|
|
{context.visibleMissingData && context.visibleMissingData.length > 0 && (
|
|
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 0.5, fontSize: '0.65rem' }}>
|
|
Fehlende Daten: {context.visibleMissingData.slice(0, 3).join(', ')}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
)
|
|
}
|