feat: globale Suche und Anbindung an das ICON CRM
Beides lag bisher nur als nicht eingecheckte Arbeit im Arbeitsverzeichnis, waehrend auf Gitea nur die Doku dazu stand (docs/12-suche.md). Damit ist der Code jetzt versioniert. Globale Suche: - server/src/routes/search.js: Volltext ueber Kontakte, Opportunities und Akquise, dazu die erweiterte Suche mit dem Modell des Scanners - src/components/GlobalSearch.tsx im Kopf der Anwendung; ein Treffer springt in die Ansicht und oeffnet den Datensatz (navigation.tsx) ICON CRM: - server/src/routes/integrations.js liefert die Kontakte mit gesetztem Haekchen hinaus, server/src/routes/iconCrm.js holt die Kontakte von drueben herein - beide nur lesend, mit festem Token statt JWT - server/src/contactBridge.js und src/lib/contactMatch.ts erkennen Dubletten, src/components/leads/IconMergeDialog.tsx laesst sie zusammenfuehren - server/src/ai.js buendelt die OpenAI-Aufrufe Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ad7f806258
commit
49c03f5e1b
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { OpportunityGrid } from './OpportunityGrid';
|
||||
import {
|
||||
OpportunityList,
|
||||
@@ -33,6 +33,9 @@ interface OpportunitiesProps {
|
||||
users: AppUser[];
|
||||
isLoading: boolean;
|
||||
reload: () => void;
|
||||
/** Von aussen gewuenschte Opportunity (globale Suche) - wird geoeffnet. */
|
||||
focusOpportunityId?: number | null;
|
||||
onFocusHandled?: () => void;
|
||||
}
|
||||
|
||||
const VIEW_BUTTONS: { mode: OpportunityViewMode; label: string; icon: string }[] = [
|
||||
@@ -99,6 +102,8 @@ export const Opportunities: React.FC<OpportunitiesProps> = ({
|
||||
users,
|
||||
isLoading,
|
||||
reload,
|
||||
focusOpportunityId,
|
||||
onFocusHandled,
|
||||
}) => {
|
||||
const { addToast } = useToast();
|
||||
// Kanban zuerst: die Pipeline ist die Arbeitsansicht, Kachel und Liste sind
|
||||
@@ -117,6 +122,21 @@ export const Opportunities: React.FC<OpportunitiesProps> = ({
|
||||
// Fuer welche Opportunity gerade Kopien fuer andere Berater angelegt werden.
|
||||
const [toCopy, setToCopy] = useState<Opportunity | null>(null);
|
||||
|
||||
/*
|
||||
* Ein Treffer der globalen Suche soll die Karte zeigen, nicht nur die Liste.
|
||||
* Der Wunsch wird genau einmal erfuellt und danach zurueckgemeldet - sonst
|
||||
* spraenge der Dialog beim naechsten Schliessen wieder auf.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!focusOpportunityId) return;
|
||||
const wanted = opportunities.find((item) => item.id === focusOpportunityId);
|
||||
if (wanted) {
|
||||
setEditing(wanted);
|
||||
setIsModalOpen(true);
|
||||
}
|
||||
onFocusHandled?.();
|
||||
}, [focusOpportunityId, opportunities, onFocusHandled]);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
const terms = searchTerm
|
||||
.toLowerCase()
|
||||
|
||||
Reference in New Issue
Block a user