[split-required] Split 500-1000 LOC files across all services
backend-lehrer (5 files): - alerts_agent/db/repository.py (992 → 5), abitur_docs_api.py (956 → 3) - teacher_dashboard_api.py (951 → 3), services/pdf_service.py (916 → 3) - mail/mail_db.py (987 → 6) klausur-service (5 files): - legal_templates_ingestion.py (942 → 3), ocr_pipeline_postprocess.py (929 → 4) - ocr_pipeline_words.py (876 → 3), ocr_pipeline_ocr_merge.py (616 → 2) - KorrekturPage.tsx (956 → 6) website (5 pages): - mail (985 → 9), edu-search (958 → 8), mac-mini (950 → 7) - ocr-labeling (946 → 7), audit-workspace (871 → 4) studio-v2 (5 files + 1 deleted): - page.tsx (946 → 5), MessagesContext.tsx (925 → 4) - korrektur (914 → 6), worksheet-cleanup (899 → 6) - useVocabWorksheet.ts (888 → 3) - Deleted dead page-original.tsx (934 LOC) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
69
studio-v2/lib/messages/helpers.ts
Normal file
69
studio-v2/lib/messages/helpers.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { Contact } from './types'
|
||||
|
||||
export function formatMessageTime(timestamp: string): string {
|
||||
const date = new Date(timestamp)
|
||||
const now = new Date()
|
||||
const diffMs = now.getTime() - date.getTime()
|
||||
const diffMins = Math.floor(diffMs / 60000)
|
||||
const diffHours = Math.floor(diffMs / 3600000)
|
||||
const diffDays = Math.floor(diffMs / 86400000)
|
||||
|
||||
if (diffMins < 1) return 'Gerade eben'
|
||||
if (diffMins < 60) return `${diffMins} Min.`
|
||||
if (diffHours < 24) return `${diffHours} Std.`
|
||||
if (diffDays === 1) return 'Gestern'
|
||||
if (diffDays < 7) return `${diffDays} Tage`
|
||||
|
||||
return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' })
|
||||
}
|
||||
|
||||
export function formatMessageDate(timestamp: string): string {
|
||||
const date = new Date(timestamp)
|
||||
const now = new Date()
|
||||
const diffDays = Math.floor((now.getTime() - date.getTime()) / 86400000)
|
||||
|
||||
if (diffDays === 0) return 'Heute'
|
||||
if (diffDays === 1) return 'Gestern'
|
||||
if (diffDays < 7) {
|
||||
return date.toLocaleDateString('de-DE', { weekday: 'long' })
|
||||
}
|
||||
|
||||
return date.toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' })
|
||||
}
|
||||
|
||||
export function getContactInitials(name: string): string {
|
||||
const parts = name.split(' ').filter(p => p.length > 0)
|
||||
if (parts.length >= 2) {
|
||||
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
|
||||
}
|
||||
return name.slice(0, 2).toUpperCase()
|
||||
}
|
||||
|
||||
export function getRoleLabel(role: Contact['role']): string {
|
||||
const labels: Record<Contact['role'], string> = {
|
||||
parent: 'Eltern',
|
||||
teacher: 'Lehrkraft',
|
||||
staff: 'Verwaltung',
|
||||
student: 'Schueler/in'
|
||||
}
|
||||
return labels[role] || role
|
||||
}
|
||||
|
||||
export function getRoleColor(role: Contact['role'], isDark: boolean): string {
|
||||
const colors: Record<Contact['role'], { dark: string; light: string }> = {
|
||||
parent: { dark: 'bg-blue-500/20 text-blue-300', light: 'bg-blue-100 text-blue-700' },
|
||||
teacher: { dark: 'bg-purple-500/20 text-purple-300', light: 'bg-purple-100 text-purple-700' },
|
||||
staff: { dark: 'bg-amber-500/20 text-amber-300', light: 'bg-amber-100 text-amber-700' },
|
||||
student: { dark: 'bg-green-500/20 text-green-300', light: 'bg-green-100 text-green-700' }
|
||||
}
|
||||
return isDark ? colors[role].dark : colors[role].light
|
||||
}
|
||||
|
||||
// Emoji categories for picker
|
||||
export const emojiCategories = {
|
||||
'Häufig': ['👍', '❤️', '😊', '😂', '🙏', '👏', '🎉', '✅', '📝', '📚'],
|
||||
'Smileys': ['😀', '😃', '😄', '😁', '😅', '😂', '🤣', '😊', '😇', '🙂', '😉', '😌', '😍', '🥰', '😘'],
|
||||
'Gesten': ['👍', '👎', '👌', '✌️', '🤞', '🤝', '👏', '🙌', '👋', '✋', '🤚', '🖐️', '🙏'],
|
||||
'Symbole': ['❤️', '💙', '💚', '💛', '🧡', '💜', '✅', '❌', '⭐', '🌟', '💯', '📌', '📎'],
|
||||
'Schule': ['📚', '📖', '📝', '✏️', '📓', '📕', '📗', '📘', '🎓', '🏫', '📅', '⏰', '🔔']
|
||||
}
|
||||
227
studio-v2/lib/messages/mock-data.ts
Normal file
227
studio-v2/lib/messages/mock-data.ts
Normal file
@@ -0,0 +1,227 @@
|
||||
import type { Contact, Conversation, Message, MessageTemplate } from './types'
|
||||
|
||||
export const mockContacts: Contact[] = [
|
||||
{
|
||||
id: 'contact_mueller',
|
||||
name: 'Familie Mueller',
|
||||
email: 'familie.mueller@gmail.com',
|
||||
phone: '+49 170 1234567',
|
||||
role: 'parent',
|
||||
student_name: 'Max Mueller',
|
||||
class_name: '10a',
|
||||
notes: 'Bevorzugt Kommunikation per E-Mail',
|
||||
tags: ['aktiv', 'Elternbeirat'],
|
||||
preferred_channel: 'email',
|
||||
online: false,
|
||||
last_seen: new Date(Date.now() - 1800000).toISOString(),
|
||||
created_at: new Date(Date.now() - 86400000 * 30).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_schmidt',
|
||||
name: 'Petra Schmidt',
|
||||
email: 'p.schmidt@web.de',
|
||||
phone: '+49 171 9876543',
|
||||
role: 'parent',
|
||||
student_name: 'Lisa Schmidt',
|
||||
class_name: '10a',
|
||||
tags: ['responsive'],
|
||||
preferred_channel: 'pwa',
|
||||
online: true,
|
||||
created_at: new Date(Date.now() - 86400000 * 60).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_weber',
|
||||
name: 'Sabine Weber',
|
||||
email: 's.weber@schule-musterstadt.de',
|
||||
role: 'teacher',
|
||||
tags: ['Fachschaft Deutsch', 'Klassenleitung 9b'],
|
||||
preferred_channel: 'pwa',
|
||||
online: true,
|
||||
last_seen: new Date().toISOString(),
|
||||
created_at: new Date(Date.now() - 86400000 * 90).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_hoffmann',
|
||||
name: 'Thomas Hoffmann',
|
||||
email: 't.hoffmann@schule-musterstadt.de',
|
||||
role: 'teacher',
|
||||
tags: ['Fachschaft Mathe', 'Oberstufenkoordinator'],
|
||||
preferred_channel: 'pwa',
|
||||
online: false,
|
||||
last_seen: new Date(Date.now() - 3600000 * 2).toISOString(),
|
||||
created_at: new Date(Date.now() - 86400000 * 120).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_becker',
|
||||
name: 'Familie Becker',
|
||||
email: 'becker.familie@gmx.de',
|
||||
phone: '+49 172 5551234',
|
||||
role: 'parent',
|
||||
student_name: 'Tim Becker',
|
||||
class_name: '10a',
|
||||
tags: [],
|
||||
preferred_channel: 'email',
|
||||
online: false,
|
||||
last_seen: new Date(Date.now() - 86400000).toISOString(),
|
||||
created_at: new Date(Date.now() - 86400000 * 45).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_klein',
|
||||
name: 'Monika Klein',
|
||||
email: 'm.klein@schule-musterstadt.de',
|
||||
role: 'staff',
|
||||
tags: ['Sekretariat'],
|
||||
preferred_channel: 'pwa',
|
||||
online: true,
|
||||
created_at: new Date(Date.now() - 86400000 * 180).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_fischer',
|
||||
name: 'Familie Fischer',
|
||||
email: 'fischer@t-online.de',
|
||||
phone: '+49 173 4445566',
|
||||
role: 'parent',
|
||||
student_name: 'Anna Fischer',
|
||||
class_name: '11b',
|
||||
tags: ['Foerderverein'],
|
||||
preferred_channel: 'pwa',
|
||||
online: false,
|
||||
last_seen: new Date(Date.now() - 7200000).toISOString(),
|
||||
created_at: new Date(Date.now() - 86400000 * 75).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
},
|
||||
{
|
||||
id: 'contact_meyer',
|
||||
name: 'Dr. Hans Meyer',
|
||||
email: 'h.meyer@schule-musterstadt.de',
|
||||
role: 'teacher',
|
||||
tags: ['Schulleitung', 'Stellvertretender Schulleiter'],
|
||||
preferred_channel: 'email',
|
||||
online: false,
|
||||
last_seen: new Date(Date.now() - 3600000).toISOString(),
|
||||
created_at: new Date(Date.now() - 86400000 * 365).toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
}
|
||||
]
|
||||
|
||||
export const mockConversations: Conversation[] = [
|
||||
{
|
||||
id: 'conv_mueller',
|
||||
participant_ids: ['contact_mueller'],
|
||||
created_at: new Date(Date.now() - 86400000 * 7).toISOString(),
|
||||
updated_at: new Date(Date.now() - 300000).toISOString(),
|
||||
last_message: 'Vielen Dank fuer die Info! Max freut sich schon auf die Klassenfahrt 🎉',
|
||||
last_message_time: new Date(Date.now() - 300000).toISOString(),
|
||||
unread_count: 2,
|
||||
is_group: false,
|
||||
title: 'Familie Mueller',
|
||||
pinned: true
|
||||
},
|
||||
{
|
||||
id: 'conv_schmidt',
|
||||
participant_ids: ['contact_schmidt'],
|
||||
created_at: new Date(Date.now() - 86400000 * 14).toISOString(),
|
||||
updated_at: new Date(Date.now() - 3600000).toISOString(),
|
||||
last_message: 'Lisa war heute krank, sie kommt morgen wieder.',
|
||||
last_message_time: new Date(Date.now() - 3600000).toISOString(),
|
||||
unread_count: 0,
|
||||
is_group: false,
|
||||
title: 'Petra Schmidt'
|
||||
},
|
||||
{
|
||||
id: 'conv_weber',
|
||||
participant_ids: ['contact_weber'],
|
||||
created_at: new Date(Date.now() - 86400000 * 30).toISOString(),
|
||||
updated_at: new Date(Date.now() - 7200000).toISOString(),
|
||||
last_message: 'Koenntest du mir die Klausuraufgaben bis Freitag schicken? 📝',
|
||||
last_message_time: new Date(Date.now() - 7200000).toISOString(),
|
||||
unread_count: 1,
|
||||
is_group: false,
|
||||
title: 'Sabine Weber',
|
||||
typing: true
|
||||
},
|
||||
{
|
||||
id: 'conv_hoffmann',
|
||||
participant_ids: ['contact_hoffmann'],
|
||||
created_at: new Date(Date.now() - 86400000 * 5).toISOString(),
|
||||
updated_at: new Date(Date.now() - 86400000).toISOString(),
|
||||
last_message: 'Die Notenkonferenz ist am 15.02. um 14:00 Uhr.',
|
||||
last_message_time: new Date(Date.now() - 86400000).toISOString(),
|
||||
unread_count: 0,
|
||||
is_group: false,
|
||||
title: 'Thomas Hoffmann'
|
||||
},
|
||||
{
|
||||
id: 'conv_becker',
|
||||
participant_ids: ['contact_becker'],
|
||||
created_at: new Date(Date.now() - 86400000 * 3).toISOString(),
|
||||
updated_at: new Date(Date.now() - 172800000).toISOString(),
|
||||
last_message: 'Wir haben die Einverstaendniserklaerung unterschrieben.',
|
||||
last_message_time: new Date(Date.now() - 172800000).toISOString(),
|
||||
unread_count: 0,
|
||||
is_group: false,
|
||||
title: 'Familie Becker',
|
||||
muted: true
|
||||
},
|
||||
{
|
||||
id: 'conv_fachschaft',
|
||||
participant_ids: ['contact_weber', 'contact_hoffmann', 'contact_meyer'],
|
||||
created_at: new Date(Date.now() - 86400000 * 60).toISOString(),
|
||||
updated_at: new Date(Date.now() - 14400000).toISOString(),
|
||||
last_message: 'Sabine: Hat jemand die neuen Lehrplaene schon gelesen?',
|
||||
last_message_time: new Date(Date.now() - 14400000).toISOString(),
|
||||
unread_count: 3,
|
||||
is_group: true,
|
||||
title: 'Fachschaft Deutsch 📚'
|
||||
}
|
||||
]
|
||||
|
||||
export const mockMessages: Record<string, Message[]> = {
|
||||
'conv_mueller': [
|
||||
{ id: 'msg_m1', conversation_id: 'conv_mueller', sender_id: 'self', content: 'Guten Tag Frau Mueller,\n\nich moechte Sie ueber die anstehende Klassenfahrt nach Berlin informieren. Die Reise findet vom 15.-19. April statt.', content_type: 'text', timestamp: new Date(Date.now() - 86400000).toISOString(), read: true, delivered: true, send_email: true, email_sent: true, email_sent_at: new Date(Date.now() - 86400000).toISOString() },
|
||||
{ id: 'msg_m2', conversation_id: 'conv_mueller', sender_id: 'self', content: 'Die Kosten belaufen sich auf 280 Euro pro Schueler. Bitte ueberweisen Sie den Betrag bis zum 01.03. auf das Schulkonto.', content_type: 'text', timestamp: new Date(Date.now() - 86400000 + 60000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_m3', conversation_id: 'conv_mueller', sender_id: 'contact_mueller', content: 'Vielen Dank fuer die Information! Wir werden den Betrag diese Woche ueberweisen.', content_type: 'text', timestamp: new Date(Date.now() - 3600000).toISOString(), read: false, delivered: true, send_email: false, email_sent: false, reactions: [{ emoji: '👍', user_id: 'self' }] },
|
||||
{ id: 'msg_m4', conversation_id: 'conv_mueller', sender_id: 'contact_mueller', content: 'Vielen Dank fuer die Info! Max freut sich schon auf die Klassenfahrt 🎉', content_type: 'text', timestamp: new Date(Date.now() - 300000).toISOString(), read: false, delivered: true, send_email: false, email_sent: false },
|
||||
],
|
||||
'conv_schmidt': [
|
||||
{ id: 'msg_s1', conversation_id: 'conv_schmidt', sender_id: 'contact_schmidt', content: 'Guten Morgen! Lisa ist heute leider krank und kann nicht zur Schule kommen.', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 2).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_s2', conversation_id: 'conv_schmidt', sender_id: 'self', content: 'Gute Besserung an Lisa! 🤒 Soll ich ihr die Hausaufgaben zukommen lassen?', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 2 + 1800000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_s3', conversation_id: 'conv_schmidt', sender_id: 'contact_schmidt', content: 'Das waere sehr nett, vielen Dank! 🙏', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 2 + 3600000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_s4', conversation_id: 'conv_schmidt', sender_id: 'self', content: 'Hier sind die Hausaufgaben fuer diese Woche:\n\n📖 Deutsch: Seite 45-48 lesen\n📝 Mathe: Aufgaben 1-5 auf Seite 112\n🔬 Bio: Referat vorbereiten', content_type: 'text', timestamp: new Date(Date.now() - 86400000).toISOString(), read: true, delivered: true, send_email: true, email_sent: true },
|
||||
{ id: 'msg_s5', conversation_id: 'conv_schmidt', sender_id: 'contact_schmidt', content: 'Lisa war heute krank, sie kommt morgen wieder.', content_type: 'text', timestamp: new Date(Date.now() - 3600000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
],
|
||||
'conv_weber': [
|
||||
{ id: 'msg_w1', conversation_id: 'conv_weber', sender_id: 'contact_weber', content: 'Hi! Hast du schon die neuen Abi-Themen gesehen?', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 3).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_w2', conversation_id: 'conv_weber', sender_id: 'self', content: 'Ja, habe ich! Finde ich ganz gut machbar dieses Jahr. 📚', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 3 + 1800000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_w3', conversation_id: 'conv_weber', sender_id: 'contact_weber', content: 'Koenntest du mir die Klausuraufgaben bis Freitag schicken? 📝', content_type: 'text', timestamp: new Date(Date.now() - 7200000).toISOString(), read: false, delivered: true, send_email: false, email_sent: false },
|
||||
],
|
||||
'conv_hoffmann': [
|
||||
{ id: 'msg_h1', conversation_id: 'conv_hoffmann', sender_id: 'contact_hoffmann', content: 'Kurze Info: Die Notenkonferenz ist am 15.02. um 14:00 Uhr.', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 2).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_h2', conversation_id: 'conv_hoffmann', sender_id: 'self', content: 'Danke fuer die Info! Bin dabei. 👍', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 2 + 3600000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_h3', conversation_id: 'conv_hoffmann', sender_id: 'contact_hoffmann', content: 'Die Notenkonferenz ist am 15.02. um 14:00 Uhr.', content_type: 'text', timestamp: new Date(Date.now() - 86400000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
],
|
||||
'conv_becker': [
|
||||
{ id: 'msg_b1', conversation_id: 'conv_becker', sender_id: 'self', content: 'Guten Tag Familie Becker,\n\nbitte vergessen Sie nicht, die Einverstaendniserklaerung fuer den Schwimmunterricht zu unterschreiben.', content_type: 'text', timestamp: new Date(Date.now() - 86400000 * 4).toISOString(), read: true, delivered: true, send_email: true, email_sent: true },
|
||||
{ id: 'msg_b2', conversation_id: 'conv_becker', sender_id: 'contact_becker', content: 'Wir haben die Einverstaendniserklaerung unterschrieben.', content_type: 'text', timestamp: new Date(Date.now() - 172800000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
],
|
||||
'conv_fachschaft': [
|
||||
{ id: 'msg_f1', conversation_id: 'conv_fachschaft', sender_id: 'contact_meyer', content: 'Liebe Kolleginnen und Kollegen,\n\ndie neuen Lehrplaene sind jetzt online verfuegbar.', content_type: 'text', timestamp: new Date(Date.now() - 86400000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_f2', conversation_id: 'conv_fachschaft', sender_id: 'contact_hoffmann', content: 'Danke fuer die Info! Werde ich mir heute Abend anschauen.', content_type: 'text', timestamp: new Date(Date.now() - 72000000).toISOString(), read: true, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_f3', conversation_id: 'conv_fachschaft', sender_id: 'contact_weber', content: 'Hat jemand die neuen Lehrplaene schon gelesen?', content_type: 'text', timestamp: new Date(Date.now() - 14400000).toISOString(), read: false, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_f4', conversation_id: 'conv_fachschaft', sender_id: 'contact_hoffmann', content: 'Noch nicht komplett, aber sieht interessant aus! 📖', content_type: 'text', timestamp: new Date(Date.now() - 10800000).toISOString(), read: false, delivered: true, send_email: false, email_sent: false },
|
||||
{ id: 'msg_f5', conversation_id: 'conv_fachschaft', sender_id: 'contact_meyer', content: 'Wir sollten naechste Woche eine Besprechung ansetzen.', content_type: 'text', timestamp: new Date(Date.now() - 7200000).toISOString(), read: false, delivered: true, send_email: false, email_sent: false },
|
||||
]
|
||||
}
|
||||
|
||||
export const mockTemplates: MessageTemplate[] = [
|
||||
{ id: 'tpl_1', name: 'Krankmeldung bestaetigen', content: 'Vielen Dank fuer die Krankmeldung. Gute Besserung! 🤒', created_at: new Date().toISOString() },
|
||||
{ id: 'tpl_2', name: 'Hausaufgaben senden', content: 'Hier sind die Hausaufgaben fuer diese Woche:\n\n📖 Deutsch: \n📝 Mathe: \n🔬 Bio: ', created_at: new Date().toISOString() },
|
||||
{ id: 'tpl_3', name: 'Elterngespraech anfragen', content: 'Guten Tag,\n\nich wuerde gerne ein Elterngespraech mit Ihnen vereinbaren. Wann haetten Sie Zeit?', created_at: new Date().toISOString() },
|
||||
{ id: 'tpl_4', name: 'Termin bestaetigen', content: 'Vielen Dank, der Termin ist bestaetigt. Ich freue mich auf unser Gespraech! 📅', created_at: new Date().toISOString() },
|
||||
]
|
||||
99
studio-v2/lib/messages/types.ts
Normal file
99
studio-v2/lib/messages/types.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
export interface Contact {
|
||||
id: string
|
||||
name: string
|
||||
email?: string
|
||||
phone?: string
|
||||
role: 'parent' | 'teacher' | 'staff' | 'student'
|
||||
student_name?: string
|
||||
class_name?: string
|
||||
notes?: string
|
||||
tags: string[]
|
||||
avatar_url?: string
|
||||
preferred_channel: 'email' | 'matrix' | 'pwa'
|
||||
online: boolean
|
||||
last_seen?: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: string
|
||||
conversation_id: string
|
||||
sender_id: string // "self" for own messages
|
||||
content: string
|
||||
content_type: 'text' | 'file' | 'image' | 'voice'
|
||||
file_url?: string
|
||||
file_name?: string
|
||||
timestamp: string
|
||||
read: boolean
|
||||
read_at?: string
|
||||
delivered: boolean
|
||||
send_email: boolean
|
||||
email_sent: boolean
|
||||
email_sent_at?: string
|
||||
email_error?: string
|
||||
reply_to?: string // ID of message being replied to
|
||||
reactions?: { emoji: string; user_id: string }[]
|
||||
}
|
||||
|
||||
export interface Conversation {
|
||||
id: string
|
||||
participant_ids: string[]
|
||||
group_id?: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
last_message?: string
|
||||
last_message_time?: string
|
||||
unread_count: number
|
||||
is_group: boolean
|
||||
title?: string
|
||||
typing?: boolean // Someone is typing
|
||||
pinned?: boolean
|
||||
muted?: boolean
|
||||
archived?: boolean
|
||||
}
|
||||
|
||||
export interface MessageTemplate {
|
||||
id: string
|
||||
name: string
|
||||
content: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface MessagesStats {
|
||||
total_contacts: number
|
||||
total_conversations: number
|
||||
total_messages: number
|
||||
unread_messages: number
|
||||
}
|
||||
|
||||
export interface MessagesContextType {
|
||||
// Data
|
||||
contacts: Contact[]
|
||||
conversations: Conversation[]
|
||||
messages: Record<string, Message[]> // conversationId -> messages
|
||||
templates: MessageTemplate[]
|
||||
stats: MessagesStats
|
||||
|
||||
// Computed
|
||||
unreadCount: number
|
||||
recentConversations: Conversation[]
|
||||
|
||||
// Actions
|
||||
fetchContacts: () => Promise<void>
|
||||
fetchConversations: () => Promise<void>
|
||||
fetchMessages: (conversationId: string) => Promise<Message[]>
|
||||
sendMessage: (conversationId: string, content: string, sendEmail?: boolean, replyTo?: string) => Promise<Message | null>
|
||||
markAsRead: (conversationId: string) => Promise<void>
|
||||
createConversation: (contactId: string) => Promise<Conversation | null>
|
||||
addReaction: (messageId: string, emoji: string) => void
|
||||
deleteMessage: (conversationId: string, messageId: string) => void
|
||||
pinConversation: (conversationId: string) => void
|
||||
muteConversation: (conversationId: string) => void
|
||||
|
||||
// State
|
||||
isLoading: boolean
|
||||
error: string | null
|
||||
currentConversationId: string | null
|
||||
setCurrentConversationId: (id: string | null) => void
|
||||
}
|
||||
Reference in New Issue
Block a user