feat(frontend): Kalender-Modal – Teilnehmer-Chips + Auto-Vorauswahl

- Suche startet mit Organisator-Name vorbelegt → CRM zeigt sofort
  passende Kontakte
- Klickbare Teilnehmer-Chips ermöglichen schnellen Wechsel zwischen
  den Event-Attendees als Suchbegriff
- Aktiver Chip wird farblich hervorgehoben

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas Reitz 2026-03-13 14:34:56 +01:00
parent 2d56ab6b3d
commit 17a81c97ef
2 changed files with 66 additions and 1 deletions

View file

@ -778,6 +778,40 @@
margin-bottom: 0.5rem;
}
.attendeeSuggestions {
display: flex;
flex-wrap: wrap;
gap: 0.375rem;
margin-bottom: 0.625rem;
}
.attendeeChip {
padding: 0.2rem 0.625rem;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: 999px;
font-size: 0.75rem;
color: var(--color-text-secondary);
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
max-width: 180px;
overflow: hidden;
text-overflow: ellipsis;
}
.attendeeChip:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
.attendeeChipActive {
background: rgba(59, 130, 246, 0.1);
border-color: var(--color-primary);
color: var(--color-primary);
font-weight: 500;
}
.contactSearchWrap {
margin-bottom: 0.375rem;
}

View file

@ -92,7 +92,13 @@ function CalendarEventModal({
onClose: () => void;
}) {
const createActivity = useCreateActivity();
const [contactSearch, setContactSearch] = useState('');
// Organisator oder erster Teilnehmer als Startsuchbegriff
const initialSearch =
event.organizer?.emailAddress.name ||
event.attendees?.[0]?.emailAddress.name ||
'';
const [contactSearch, setContactSearch] = useState(initialSearch);
const [selectedContact, setSelectedContact] = useState<Contact | null>(null);
const [actStatus, setActStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
@ -214,6 +220,31 @@ function CalendarEventModal({
{actStatus !== 'success' ? (
<div className={styles.contactSection}>
<div className={styles.contactSectionTitle}>Als Aktivität bei Kontakt speichern</div>
{/* Teilnehmer-Chips für schnelle Auswahl */}
{event.attendees && event.attendees.length > 0 && (
<div className={styles.attendeeSuggestions}>
{event.attendees.slice(0, 7).map((a, i) => {
const label = a.emailAddress.name || a.emailAddress.address;
const isActive = contactSearch === label;
return (
<button
key={i}
type="button"
className={`${styles.attendeeChip} ${isActive ? styles.attendeeChipActive : ''}`}
onClick={() => {
setContactSearch(label);
setSelectedContact(null);
setActStatus('idle');
}}
>
{label}
</button>
);
})}
</div>
)}
<div className={styles.contactSearchWrap}>
<input
type="text"