feat(quick-260909-ab3): verstaendlicher Sync-Bericht, Konten ohne Adresse in der UI

- admin/ldap/page.tsx: SyncResult um emailConflicts/skippedNoLogin/
  entryFailures erweitert; drei neue Berichtsabschnitte (Bernstein fuer
  Kollisionen, neutral fuer fehlenden Anmeldenamen, destruktiv fuer
  unerwartete Fehler) — kein englischer Techniktext, kein roher
  Datenbank-Wortlaut mehr im Bericht
- GroupMembersModal.tsx: TenantUser.email optional, Suchvergleich gegen
  leere Adresse abgesichert (WINDOWS #15) — die Mitgliedersuche stuerzt
  nicht mehr ab, sobald ein Konto ohne Adresse existiert
- users/page.tsx: User.email optional, Formular faellt auf leere
  Zeichenkette zurueck, Tabellenzelle zeigt einen Gedankenstrich;
  UserFormData.email bleibt bei Handanlage Pflicht
- Neue Sprachschluessel unter admin.ldap.sync in de.json/en.json,
  Umlaut- und Sprachschluessel-Gate bestaetigt gruen (kein neues
  Allowlist-Wort noetig)
- Neuer Testfall in groups-page.test.tsx vorab gegen den unveraenderten
  Bestand rot gelaufen; Abweichung von der Plan-Fixture dokumentiert
  (Kurzfassung: ein einzelnes Konto mit passendem Benutzernamen loest die
  Kollision wegen OR-Kurzschlussauswertung nie aus, ein zweites,
  nicht-treffendes Konto ohne Adresse schon — Vollfassung im SUMMARY)
- 651/651 API- und 233/233 Web-Tests gruen, beide Typpruefungen sauber

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYZcd3SSmo14QTqWx2KKzU
This commit is contained in:
2026-09-09 07:54:32 +02:00
parent 1222951af6
commit 21670462dd
6 changed files with 99 additions and 6 deletions
@@ -10,7 +10,10 @@ const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
interface User {
id: string;
username: string;
email: string;
// WINDOWS #15: ein Konto ohne Adresse (kollidierte AD-Adresse) ist
// moeglich, seit User.email optional ist. Die Handanlage (UserFormData)
// verlangt weiterhin eine Adresse.
email: string | null;
displayName: string | null;
role: 'SUPER_ADMIN' | 'ADMIN' | 'USER';
isActive: boolean;
@@ -93,7 +96,7 @@ export default function AdminUsersPage() {
setEditingUser(user);
setFormData({
username: user.username,
email: user.email,
email: user.email ?? '',
password: '',
displayName: user.displayName ?? '',
role: user.role,
@@ -222,7 +225,7 @@ export default function AdminUsersPage() {
{user.username}
</td>
<td className="px-4 py-3 text-muted-foreground">
{user.email}
{user.email ?? '–'}
</td>
<td className="px-4 py-3 text-muted-foreground">
{user.displayName ?? '-'}