feat: Nur neue speichern als Button in den Suchergebnissen
Button erscheint in der Ergebnis-Headerzeile sobald vorhandene Leads dabei sind. Löscht diese aus dem Leadspeicher und zeigt Bilanz-Toast. Verschwindet nach Ausführung. Checkbox vor der Suche entfernt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,33 +53,16 @@ export default function SuchePage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDone = useCallback(async (result: LeadResult[], warning?: string) => {
|
const handleDone = useCallback((result: LeadResult[], warning?: string) => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setLeads(result);
|
setLeads(result);
|
||||||
setSearchDone(true);
|
setSearchDone(true);
|
||||||
|
|
||||||
// Auto-delete existing (non-new) leads from vault if "Nur neue speichern" is active
|
|
||||||
const existingIds = result.filter(l => !l.isNew).map(l => l.id);
|
|
||||||
if (saveOnlyNew && existingIds.length > 0) {
|
|
||||||
try {
|
|
||||||
await fetch("/api/leads/delete-from-results", {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({ resultIds: existingIds }),
|
|
||||||
});
|
|
||||||
// Mark them as deleted in local state (isNew stays false, they remain visible but are gone from vault)
|
|
||||||
} catch { /* silent — vault cleanup best-effort */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
const newCount = result.filter(l => l.isNew).length;
|
|
||||||
if (warning) {
|
if (warning) {
|
||||||
toast.warning(`${result.length} Unternehmen gefunden — E-Mail-Anreicherung fehlgeschlagen: ${warning}`, { duration: 6000 });
|
toast.warning(`${result.length} Unternehmen gefunden — E-Mail-Anreicherung fehlgeschlagen: ${warning}`, { duration: 6000 });
|
||||||
} else if (saveOnlyNew && existingIds.length > 0) {
|
|
||||||
toast.success(`✓ ${newCount} neue Leads gespeichert, ${existingIds.length} bereits vorhandene verworfen`, { duration: 5000 });
|
|
||||||
} else {
|
} else {
|
||||||
toast.success(`✓ ${result.length} Leads gefunden und im Leadspeicher gespeichert`, { duration: 4000 });
|
toast.success(`✓ ${result.length} Leads gefunden und im Leadspeicher gespeichert`, { duration: 4000 });
|
||||||
}
|
}
|
||||||
}, [saveOnlyNew]);
|
}, []);
|
||||||
|
|
||||||
async function handleDelete(ids: string[]) {
|
async function handleDelete(ids: string[]) {
|
||||||
if (!ids.length || deleting) return;
|
if (!ids.length || deleting) return;
|
||||||
@@ -104,6 +87,26 @@ export default function SuchePage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleSaveOnlyNew() {
|
||||||
|
const existingIds = leads.filter(l => !l.isNew).map(l => l.id);
|
||||||
|
if (!existingIds.length || deleting) return;
|
||||||
|
setDeleting(true);
|
||||||
|
try {
|
||||||
|
await fetch("/api/leads/delete-from-results", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ resultIds: existingIds }),
|
||||||
|
});
|
||||||
|
setSaveOnlyNew(true);
|
||||||
|
const newCount = leads.filter(l => l.isNew).length;
|
||||||
|
toast.success(`✓ ${newCount} neue Leads behalten, ${existingIds.length} vorhandene aus Leadspeicher entfernt`, { duration: 5000 });
|
||||||
|
} catch {
|
||||||
|
toast.error("Fehler beim Bereinigen");
|
||||||
|
} finally {
|
||||||
|
setDeleting(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleError = useCallback((message: string) => {
|
const handleError = useCallback((message: string) => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setJobId(null);
|
setJobId(null);
|
||||||
@@ -146,28 +149,6 @@ export default function SuchePage() {
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Save option */}
|
|
||||||
{!loading && !searchDone && (
|
|
||||||
<label
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 8,
|
|
||||||
marginTop: 10,
|
|
||||||
padding: "0 4px",
|
|
||||||
cursor: "pointer",
|
|
||||||
width: "fit-content",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={saveOnlyNew}
|
|
||||||
onChange={e => setSaveOnlyNew(e.target.checked)}
|
|
||||||
style={{ accentColor: "#3b82f6", width: 13, height: 13, cursor: "pointer" }}
|
|
||||||
/>
|
|
||||||
<span style={{ fontSize: 12, color: "#6b7280" }}>Nur neue Leads speichern</span>
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Loading Card */}
|
{/* Loading Card */}
|
||||||
{loading && jobId && (
|
{loading && jobId && (
|
||||||
@@ -282,7 +263,7 @@ export default function SuchePage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: 10 }}>
|
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||||
{selectedVisible.length > 0 && (
|
{selectedVisible.length > 0 && (
|
||||||
<button
|
<button
|
||||||
className="del-btn"
|
className="del-btn"
|
||||||
@@ -308,6 +289,34 @@ export default function SuchePage() {
|
|||||||
{selectedVisible.length} löschen
|
{selectedVisible.length} löschen
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Nur neue speichern — only shown when there are existing leads */}
|
||||||
|
{!saveOnlyNew && leads.some(l => !l.isNew) && (
|
||||||
|
<button
|
||||||
|
onClick={handleSaveOnlyNew}
|
||||||
|
disabled={deleting}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 6,
|
||||||
|
background: "linear-gradient(135deg, rgba(59,130,246,0.12), rgba(139,92,246,0.12))",
|
||||||
|
border: "1px solid rgba(99,102,241,0.35)",
|
||||||
|
borderRadius: 7,
|
||||||
|
padding: "5px 12px",
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#a5b4fc",
|
||||||
|
cursor: deleting ? "not-allowed" : "pointer",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||||
|
<path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20z"/>
|
||||||
|
<path d="M9 12h6M12 9v6"/>
|
||||||
|
</svg>
|
||||||
|
Nur neue speichern
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<Link href="/leadspeicher" style={{ fontSize: 12, color: "#3b82f6", textDecoration: "none" }}>
|
<Link href="/leadspeicher" style={{ fontSize: 12, color: "#3b82f6", textDecoration: "none" }}>
|
||||||
Im Leadspeicher →
|
Im Leadspeicher →
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
Reference in New Issue
Block a user