mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-25 00:16:41 +02:00
Problem: <a href="/api/v1/auth/integrations/microsoft-365"> sendet keinen
JWT-Authorization-Header (JWT liegt im Memory, nicht als Cookie).
Lösung:
- Backend: initM365Integration gibt JSON {url} zurück statt server-redirect
- Frontend: integrationsApi.connectM365() ruft Endpoint via Axios ab, dann
window.location.href zur OAuth-URL
- ProfilePage + EmailsTab + CalendarTab + TasksTab: <a href> → <button onClick>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
122 lines
4 KiB
TypeScript
122 lines
4 KiB
TypeScript
import { useContactEmails, useIntegrations } from '../hooks';
|
|
import { integrationsApi } from '../api';
|
|
import type { M365Email } from '../types';
|
|
|
|
interface Props {
|
|
contactId: string;
|
|
}
|
|
|
|
function formatEmailDate(iso: string): string {
|
|
return new Date(iso).toLocaleString('de-DE', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
});
|
|
}
|
|
|
|
export function EmailsTab({ contactId }: Props) {
|
|
const { data: integrationsData } = useIntegrations();
|
|
const isConnected = integrationsData?.data?.some(
|
|
(i) => i.provider === 'MICROSOFT_365' && i.connected,
|
|
) ?? false;
|
|
|
|
const { data, isLoading, error } = useContactEmails(contactId);
|
|
const emails: M365Email[] = data?.data ?? [];
|
|
|
|
if (!isConnected) {
|
|
return (
|
|
<div style={{ padding: '1.5rem 0', textAlign: 'center' }}>
|
|
<p style={{ color: 'var(--color-text-muted)', fontSize: '0.9375rem', marginBottom: '1rem' }}>
|
|
Verbinden Sie Microsoft 365, um E-Mails zu diesem Kontakt zu sehen.
|
|
</p>
|
|
<button
|
|
type="button"
|
|
onClick={() => integrationsApi.connectM365()}
|
|
style={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
gap: '0.5rem',
|
|
padding: '0.4375rem 1rem',
|
|
background: 'var(--color-primary)',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: 'var(--radius-sm)',
|
|
fontSize: '0.875rem',
|
|
fontWeight: 600,
|
|
cursor: 'pointer',
|
|
}}
|
|
>
|
|
Microsoft 365 verbinden
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (isLoading) {
|
|
return <p style={{ color: 'var(--color-text-muted)', fontSize: '0.875rem', padding: '1rem 0' }}>Laden…</p>;
|
|
}
|
|
|
|
if (error) {
|
|
return <p style={{ color: 'var(--color-error)', fontSize: '0.875rem', padding: '1rem 0' }}>E-Mails konnten nicht geladen werden.</p>;
|
|
}
|
|
|
|
if (emails.length === 0) {
|
|
return <p style={{ color: 'var(--color-text-muted)', fontSize: '0.875rem', padding: '1rem 0' }}>Keine E-Mails gefunden.</p>;
|
|
}
|
|
|
|
return (
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
|
|
{emails.map((email) => (
|
|
<a
|
|
key={email.id}
|
|
href={email.webLink}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
style={{
|
|
display: 'block',
|
|
padding: '0.75rem 1rem',
|
|
background: email.isRead ? 'var(--color-bg-card)' : 'var(--color-bg-subtle, var(--color-bg-card))',
|
|
border: '1px solid var(--color-border)',
|
|
borderRadius: 'var(--radius-sm)',
|
|
textDecoration: 'none',
|
|
borderLeft: email.isRead ? undefined : '3px solid var(--color-primary)',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: '0.5rem' }}>
|
|
<span style={{
|
|
fontSize: '0.875rem',
|
|
fontWeight: email.isRead ? 400 : 600,
|
|
color: 'var(--color-text)',
|
|
flex: 1,
|
|
overflow: 'hidden',
|
|
textOverflow: 'ellipsis',
|
|
whiteSpace: 'nowrap',
|
|
}}>
|
|
{email.subject || '(kein Betreff)'}
|
|
</span>
|
|
<span style={{ fontSize: '0.75rem', color: 'var(--color-text-muted)', flexShrink: 0 }}>
|
|
{formatEmailDate(email.receivedDateTime)}
|
|
</span>
|
|
</div>
|
|
<div style={{ fontSize: '0.8125rem', color: 'var(--color-text-muted)', marginTop: '0.25rem' }}>
|
|
Von: {email.from?.emailAddress?.name ?? email.from?.emailAddress?.address ?? '—'}
|
|
</div>
|
|
{email.bodyPreview && (
|
|
<div style={{
|
|
fontSize: '0.8125rem',
|
|
color: 'var(--color-text-secondary)',
|
|
marginTop: '0.25rem',
|
|
overflow: 'hidden',
|
|
textOverflow: 'ellipsis',
|
|
whiteSpace: 'nowrap',
|
|
}}>
|
|
{email.bodyPreview}
|
|
</div>
|
|
)}
|
|
</a>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|