e.stopPropagation()}
- >
-
Leads aus CSV importieren
-
- Spalten: Quelle, Vorname, Nachname, Position, Firma, Straße, PLZ, Ort, Telefon, Mobil,
- Fax, E-Mail, Website, Branche, Notizen. Je Zeile entsteht ein Lead mit primärem Kontakt;
- Notizen werden als erster Austausch-Log-Eintrag gespeichert. Duplikate (gleicher
- Firmenname) werden übersprungen.
-
+
+
+ Spalten: Quelle, Vorname, Nachname, Position, Firma, Straße, PLZ, Ort, Telefon, Mobil, Fax,
+ E-Mail, Website, Branche, Notizen. Je Zeile entsteht ein Lead mit primärem Kontakt; Notizen
+ werden als erster Austausch-Log-Eintrag gespeichert. Duplikate (gleicher Firmenname) werden
+ übersprungen.
+
-
-
- Projekt zuordnen (optional)
- setProjectId(e.target.value)}
- disabled={!!result}
- className="mt-1 w-full rounded-[var(--radius-md)] border border-[var(--color-border)] bg-white px-3 py-2 text-sm"
- >
- — kein Projekt —
- {projects.map((p) => (
-
- {p.name}
-
- ))}
-
-
-
- CSV-Datei
-
-
- {fileName && !result && (
-
- Bereit: {fileName} ({Math.max(0, csv.split('\n').filter((l) => l.trim()).length - 1)}{' '}
- Datenzeilen)
+
+
+ Projekt zuordnen (optional)
+ setProjectId(e.target.value)}
+ disabled={!!result}
+ className="mt-1 w-full rounded-[var(--radius-md)] border border-[var(--color-border)] bg-white px-3 py-2 text-sm"
+ >
+ — kein Projekt —
+ {projects.map((p) => (
+
+ {p.name}
+
+ ))}
+
+
+
+ CSV-Datei
+
+
+ {fileName && !result && (
+
+ Bereit: {fileName} ({Math.max(0, csv.split('\n').filter((l) => l.trim()).length - 1)}{' '}
+ Datenzeilen)
+
+ )}
+
+ {result && (
+
+
+ {result.created} Leads importiert
- )}
-
- {result && (
-
-
- {result.created} Leads importiert
-
-
- {result.contacts} Kontakte angelegt
- {result.touchpoints} Notizen als Log-Eintrag
- {result.skippedDuplicate > 0 && (
- {result.skippedDuplicate} Duplikate übersprungen
- )}
- {result.skippedEmpty > 0 && (
- {result.skippedEmpty} leere Zeilen übersprungen
- )}
-
-
- )}
-
-
-
- {result ? 'Schließen' : 'Abbrechen'}
-
- {!result && (
-
importMut.mutate({ csv, projectId: projectId || undefined })}
- disabled={!csv || importMut.isPending}
- >
- {importMut.isPending ? 'Importiere…' : 'Importieren'}
-
- )}
+
+ {result.contacts} Kontakte angelegt
+ {result.touchpoints} Notizen als Log-Eintrag
+ {result.skippedDuplicate > 0 && (
+ {result.skippedDuplicate} Duplikate übersprungen
+ )}
+ {result.skippedEmpty > 0 && {result.skippedEmpty} leere Zeilen übersprungen }
+
+ )}
+
+
+
+ {result ? 'Schließen' : 'Abbrechen'}
+
+ {!result && (
+ importMut.mutate({ csv, projectId: projectId || undefined })}
+ disabled={!csv || importMut.isPending}
+ >
+ {importMut.isPending ? 'Importiere…' : 'Importieren'}
+
+ )}
-
+
);
}
@@ -282,121 +272,108 @@ function LeadCreateDialog({ onClose }: { onClose: () => void }) {
}
return (
-
-
e.stopPropagation()}
- >
-
Neuer Lead
-
- Nur die Firma ist Pflicht — alles Weitere füllst du im Dossier.
-
-
+
+
+ setScore(Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+ Abbrechen
+
+
+ Anlegen
+
+
+
+
);
}
diff --git a/apps/web/src/routes/projekt.tsx b/apps/web/src/routes/projekt.tsx
index 12d18dd..33e641e 100644
--- a/apps/web/src/routes/projekt.tsx
+++ b/apps/web/src/routes/projekt.tsx
@@ -8,6 +8,7 @@ import { Card } from '../components/ui/Card';
import { Button } from '../components/ui/Button';
import { SkeletonCard } from '../components/ui/SkeletonCard';
import { ErrorState } from '../components/ui/ErrorState';
+import { Modal } from '../components/ui/Modal';
import { useConfirm } from '../components/ui/ConfirmProvider';
import { useCurrentUser } from '../hooks/useCurrentUser';
import { voice } from '../lib/voice';
@@ -704,65 +705,52 @@ function GateDialog({
},
});
return (
-
-
e.stopPropagation()}
+
+
+ Ziel: {PHASE_META[phase].gateZiel}
+
+ {
+ e.preventDefault();
+ add.mutate({
+ projectId,
+ phase,
+ ergebnisErreicht: erreicht,
+ notiz: notiz.trim() || undefined,
+ advance,
+ });
+ }}
>
- Gate-Review: {PHASE_META[phase].label}
-
- Ziel: {PHASE_META[phase].gateZiel}
-
- {
- e.preventDefault();
- add.mutate({
- projectId,
- phase,
- ergebnisErreicht: erreicht,
- notiz: notiz.trim() || undefined,
- advance,
- });
- }}
- >
-
- setErreicht(e.target.checked)}
- />
- Ergebnis erreicht
-
- setNotiz(e.target.value)}
- rows={3}
- placeholder="Rückblick / Maßnahmen (bei Gelb/Rot)"
- className={inputCls}
+
+ setErreicht(e.target.checked)}
/>
-
- setAdvance(e.target.checked)}
- />
- Folgephase jetzt freigeben
-
-
-
- Abbrechen
-
-
- Speichern
-
-
-
-
-
+ Ergebnis erreicht
+
+
setNotiz(e.target.value)}
+ rows={3}
+ placeholder="Rückblick / Maßnahmen (bei Gelb/Rot)"
+ className={inputCls}
+ />
+
+ setAdvance(e.target.checked)} />
+ Folgephase jetzt freigeben
+
+
+
+ Abbrechen
+
+
+ Speichern
+
+
+
+
);
}
@@ -2320,65 +2308,56 @@ function AbschlussDialog({
{ key: 'retro', label: 'Retrospektive / Lessons Learned durchgeführt' },
];
return (
-
-
e.stopPropagation()}
- >
-
Projekt abschließen
-
- Ein Projekt endet bewusst (Leitfaden Phase 4).
-
-
-
- {checkItems.map((it) => (
-
- setChecks((c) => ({ ...c, [it.key]: e.target.checked }))}
- className="mt-0.5"
- />
- {it.label}
-
- ))}
-
-
- Abschlussvermerk
- setVermerk(e.target.value)}
- rows={3}
- maxLength={2000}
- placeholder="Ziel erreicht? Aufwand gegen Plan? Wichtigste Erkenntnisse — eine halbe Seite, kein Roman."
- className={clsx(inputCls, 'mt-1')}
- />
-
-
- Lessons-Learned-URL (Outline)
- setUrl(e.target.value)}
- placeholder="https://outline.tool-ctrl.de/lessons-learned/..."
- className={clsx(inputCls, 'mt-1')}
- />
-
-
-
- Abbrechen
-
-
- Abschließen
-
-
-
-
-
+
+
+ Ein Projekt endet bewusst (Leitfaden Phase 4).
+
+
+
+ {checkItems.map((it) => (
+
+ setChecks((c) => ({ ...c, [it.key]: e.target.checked }))}
+ className="mt-0.5"
+ />
+ {it.label}
+
+ ))}
+
+
+ Abschlussvermerk
+ setVermerk(e.target.value)}
+ rows={3}
+ maxLength={2000}
+ placeholder="Ziel erreicht? Aufwand gegen Plan? Wichtigste Erkenntnisse — eine halbe Seite, kein Roman."
+ className={clsx(inputCls, 'mt-1')}
+ />
+
+
+ Lessons-Learned-URL (Outline)
+ setUrl(e.target.value)}
+ placeholder="https://outline.tool-ctrl.de/lessons-learned/..."
+ className={clsx(inputCls, 'mt-1')}
+ />
+
+
+
+ Abbrechen
+
+
+ Abschließen
+
+
+
+
);
}