Files
breakpilot-lehrer/website/app/mail/page.tsx
Benjamin Admin b4613e26f3 [split-required] Split 500-850 LOC files (batch 2)
backend-lehrer (10 files):
- game/database.py (785 → 5), correction_api.py (683 → 4)
- classroom_engine/antizipation.py (676 → 5)
- llm_gateway schools/edu_search already done in prior batch

klausur-service (12 files):
- orientation_crop_api.py (694 → 5), pdf_export.py (677 → 4)
- zeugnis_crawler.py (676 → 5), grid_editor_api.py (671 → 5)
- eh_templates.py (658 → 5), mail/api.py (651 → 5)
- qdrant_service.py (638 → 5), training_api.py (625 → 4)

website (6 pages):
- middleware (696 → 8), mail (733 → 6), consent (628 → 8)
- compliance/risks (622 → 5), export (502 → 5), brandbook (629 → 7)

studio-v2 (3 components):
- B2BMigrationWizard (848 → 3), CleanupPanel (765 → 2)
- dashboard-experimental (739 → 2)

admin-lehrer (4 files):
- uebersetzungen (769 → 4), manager (670 → 2)
- ChunkBrowserQA (675 → 6), dsfa/page (674 → 5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 08:24:01 +02:00

159 lines
6.5 KiB
TypeScript

'use client'
/**
* Unified Inbox - User Frontend
*
* Main email interface for users with:
* - Unified inbox view (all accounts)
* - Email detail view with AI analysis
* - Quick actions and response suggestions
*
* See: docs/klausur-modul/UNIFIED-INBOX-SPECIFICATION.md
*/
import type { Folder } from './_components/types'
import { useMail } from './_components/useMail'
import MailSidebar from './_components/MailSidebar'
import EmailListItem from './_components/EmailListItem'
import EmailDetail from './_components/EmailDetail'
export default function MailPage() {
const mail = useMail()
const folders: Folder[] = [
{
name: 'inbox',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" />
</svg>
),
},
{
name: 'unread',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
),
},
{
name: 'tasks',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4" />
</svg>
),
},
{
name: 'sent',
icon: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
),
},
]
return (
<div className="h-screen flex flex-col bg-slate-100">
{/* Header */}
<header className="bg-white border-b border-slate-200 px-6 py-4 flex items-center justify-between">
<div className="flex items-center gap-4">
<h1 className="text-xl font-semibold text-slate-900">Unified Inbox</h1>
{mail.totalUnread > 0 && (
<span className="px-2 py-1 bg-primary-100 text-primary-700 text-sm font-medium rounded-full">
{mail.totalUnread} ungelesen
</span>
)}
</div>
<div className="flex items-center gap-4">
{/* Search */}
<div className="relative">
<input
type="text"
placeholder="E-Mails durchsuchen..."
value={mail.searchQuery}
onChange={(e) => mail.setSearchQuery(e.target.value)}
className="w-64 pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
/>
<svg className="absolute left-3 top-2.5 w-5 h-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
{/* Compose Button */}
<a
href="/mail/compose"
className="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 flex items-center gap-2"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Verfassen
</a>
</div>
</header>
{/* Main Content */}
<div className="flex-1 flex overflow-hidden">
<MailSidebar
folders={folders}
accounts={mail.accounts}
selectedFolder={mail.selectedFolder}
setSelectedFolder={mail.setSelectedFolder}
selectedAccount={mail.selectedAccount}
setSelectedAccount={mail.setSelectedAccount}
totalUnread={mail.totalUnread}
/>
{/* Email List */}
<div className="w-96 bg-white border-r border-slate-200 overflow-y-auto">
{mail.loading ? (
<div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"></div>
</div>
) : mail.emails.length === 0 ? (
<div className="flex flex-col items-center justify-center py-12 text-center px-4">
<svg className="w-12 h-12 text-slate-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<p className="text-slate-500">Keine E-Mails gefunden</p>
</div>
) : (
<div className="divide-y divide-slate-100">
{mail.emails.map((email) => (
<EmailListItem
key={email.id}
email={email}
isSelected={mail.selectedEmail?.id === email.id}
onClick={() => mail.handleEmailClick(email)}
/>
))}
</div>
)}
</div>
{/* Email Detail / AI Panel */}
<div className="flex-1 bg-white overflow-y-auto">
{mail.selectedEmail ? (
<EmailDetail
email={mail.selectedEmail}
onAnalyze={() => mail.analyzeEmail(mail.selectedEmail!.id)}
/>
) : (
<div className="flex flex-col items-center justify-center h-full text-center px-4">
<svg className="w-16 h-16 text-slate-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<p className="text-slate-500 text-lg">Wählen Sie eine E-Mail aus</p>
<p className="text-slate-400 text-sm mt-1">
Klicken Sie auf eine E-Mail, um sie zu lesen
</p>
</div>
)}
</div>
</div>
</div>
)
}