feat(opportunities): Phasen des Vermittlungsprozesses, Kanban zuerst, Zahlen im Menue
Drei Dinge: - Die Phasen sind jetzt die des Vermittlungsprozesses: Neu, Beworben, Erstgespraech Berater, Kundenvorstellung, Interview Kunde, Zusage, Beauftragt, Absage. Offen ist alles bis einschliesslich Zusage - dort ist der Einsatz bestaetigt, die Beauftragung steht aber noch aus. migrateOpportunityStages() stellt bestehende Datenbanken um und setzt alle vorhandenen Opportunities auf "Neu": in welcher der neuen Phasen ein Projekt steckt, sagt der alte Trichter nicht (so mit dem Nutzer entschieden). Der Datenbankwert heisst 'Erstgespraech Berater' ohne Umlaut - Projektkonvention fuer Datenbankwerte. Angezeigt wird er ueber STAGE_LABELS; dazu gibt es STAGE_HINTS mit der Erlaeuterung je Phase als Titelhinweis an Auswahl, Badge und Spaltenkopf. - Kanban ist die erste Ansicht der Opportunities. Die Pipeline ist die Arbeitsansicht, Kachel und Liste sind zum Nachschauen. - Hinter "Archiv", beiden "Papierkorb"-Punkten und "Unpassend" steht die Anzahl, wie schon bei "Aus Mails". Die Zahlen kommen aus einem eigenen Endpunkt (/api/badges), weil sie alle ins Menue gehoeren und zusammen kommen sollen; Inhalte laedt weiter jede Ansicht selbst. Der Scanner liegt in einer eigenen Datenbank und kann fehlen - sein Zaehler ist dann null und die Leiste zeigt dort einfach keine Zahl. Der Aufruf haengt bewusst hinter den Daten und nicht im Promise.all: faellt er aus, bleibt das Menue ohne Zahlen statt die Ansicht mit einem Fehler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1ac0e2d2c7
commit
42639c65fa
@@ -15,8 +15,12 @@ interface SidebarProps {
|
||||
onViewChange: (view: ViewState) => void;
|
||||
isOpen: boolean;
|
||||
onToggle: () => void;
|
||||
/** Anzahl der Eintraege in "Aus Mails" - als Zaehler am Unterpunkt. */
|
||||
mailPoolCount?: number;
|
||||
/**
|
||||
* Zahlen an den Unterpunkten. Was auf eine Entscheidung wartet oder sich
|
||||
* ansammelt, soll man sehen, ohne die Ansicht zu oeffnen. 0 zeigt nichts an -
|
||||
* eine Null waere nur Rauschen.
|
||||
*/
|
||||
counts?: Partial<Record<ViewState, number | null>>;
|
||||
}
|
||||
|
||||
interface MenuItem {
|
||||
@@ -185,7 +189,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
||||
onViewChange,
|
||||
isOpen,
|
||||
onToggle,
|
||||
mailPoolCount = 0,
|
||||
counts = {},
|
||||
}) => {
|
||||
const { user, logout } = useAuth();
|
||||
const isMobile = useIsMobile();
|
||||
@@ -208,7 +212,10 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
||||
setOpenGroups((open) => (open.includes(active.item.name) ? open : [...open, active.item.name]));
|
||||
}, [currentView]);
|
||||
|
||||
const renderItem = (item: MenuItem, options: { indented?: boolean; badge?: number } = {}) => {
|
||||
const renderItem = (
|
||||
item: MenuItem,
|
||||
options: { indented?: boolean; badge?: number | null } = {}
|
||||
) => {
|
||||
const isActive = currentView === item.name;
|
||||
return (
|
||||
<button
|
||||
@@ -324,10 +331,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
||||
{showLabels && isGroupOpen && (
|
||||
<div className="mt-1 space-y-1">
|
||||
{children.map((child) =>
|
||||
renderItem(child, {
|
||||
indented: true,
|
||||
badge: child.name === 'Aus Mails' ? mailPoolCount : undefined,
|
||||
})
|
||||
renderItem(child, { indented: true, badge: counts[child.name] ?? undefined })
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user