react-os-shell 0.7.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/apps/Calendar.tsx"],"names":[],"mappings":"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","file":"Calendar-KCZQJ5CY.js","sourcesContent":["import { useState, useMemo, useCallback, useEffect } from 'react';\nimport Modal, { ModalActions } from '../shell/Modal';\nimport toast from '../shell/toast';\nimport useMailAuth from '../hooks/useMailAuth';\nimport { getMailClient } from '../api/mailClient';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport { useTodoTasks } from './_todoStore';\n\n// ── Types ──\ninterface CalDavMeta {\n calendarId: string;\n eventUid: string;\n etag: string;\n}\n\ninterface CalendarEvent {\n id: string;\n title: string;\n date: string; // YYYY-MM-DD\n start_time?: string;\n end_time?: string;\n color: string;\n description?: string;\n all_day?: boolean;\n // Internal markers (not persisted in useShellPrefs for non-local events):\n _caldav?: CalDavMeta;\n _todo?: boolean;\n _todoId?: string;\n _done?: boolean;\n}\n\ninterface DavCalendar {\n id: string;\n displayName: string;\n color: string | null;\n ctag: string;\n readOnly: boolean;\n}\n\ninterface DavEvent {\n uid: string;\n etag: string;\n url: string;\n summary: string;\n description: string | null;\n location: string | null;\n start: string;\n end: string;\n allDay: boolean;\n recurrence: string | null;\n status: string;\n}\n\ntype ViewMode = 'year' | 'month' | 'week';\n\nconst COLORS = [\n { key: 'blue', bg: 'bg-blue-500', light: 'bg-blue-100 text-blue-800', dot: 'bg-blue-500' },\n { key: 'green', bg: 'bg-green-500', light: 'bg-green-100 text-green-800', dot: 'bg-green-500' },\n { key: 'red', bg: 'bg-red-500', light: 'bg-red-100 text-red-800', dot: 'bg-red-500' },\n { key: 'purple', bg: 'bg-purple-500', light: 'bg-purple-100 text-purple-800', dot: 'bg-purple-500' },\n { key: 'orange', bg: 'bg-orange-500', light: 'bg-orange-100 text-orange-800', dot: 'bg-orange-500' },\n { key: 'pink', bg: 'bg-pink-500', light: 'bg-pink-100 text-pink-800', dot: 'bg-pink-500' },\n { key: 'yellow', bg: 'bg-yellow-500', light: 'bg-yellow-100 text-yellow-800', dot: 'bg-yellow-500' },\n { key: 'gray', bg: 'bg-gray-500', light: 'bg-gray-100 text-gray-800', dot: 'bg-gray-500' },\n];\n\nfunction getColor(key: string) {\n return COLORS.find(c => c.key === key) || COLORS[0];\n}\n\nconst DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n\nfunction pad(n: number) { return String(n).padStart(2, '0'); }\nfunction toDateStr(d: Date) { return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; }\n\nfunction getMonthDays(year: number, month: number) {\n const first = new Date(year, month, 1);\n const startDay = first.getDay();\n const daysInMonth = new Date(year, month + 1, 0).getDate();\n const prevDays = new Date(year, month, 0).getDate();\n\n const cells: { date: Date; isCurrentMonth: boolean }[] = [];\n for (let i = startDay - 1; i >= 0; i--) {\n cells.push({ date: new Date(year, month - 1, prevDays - i), isCurrentMonth: false });\n }\n for (let d = 1; d <= daysInMonth; d++) {\n cells.push({ date: new Date(year, month, d), isCurrentMonth: true });\n }\n const remaining = 42 - cells.length;\n for (let d = 1; d <= remaining; d++) {\n cells.push({ date: new Date(year, month + 1, d), isCurrentMonth: false });\n }\n return cells;\n}\n\nfunction getWeekDays(date: Date) {\n const start = new Date(date);\n start.setDate(start.getDate() - start.getDay());\n const days: Date[] = [];\n for (let i = 0; i < 7; i++) {\n const d = new Date(start);\n d.setDate(d.getDate() + i);\n days.push(d);\n }\n return days;\n}\n\nfunction davToLocal(ev: DavEvent, calendarId: string): CalendarEvent {\n const startIso = ev.start;\n const endIso = ev.end;\n const startDate = startIso.slice(0, 10);\n const startTime = ev.allDay ? undefined : startIso.slice(11, 16);\n const endTime = ev.allDay ? undefined : endIso.slice(11, 16);\n return {\n id: `caldav-${calendarId}-${ev.uid}`,\n title: ev.summary || '(No title)',\n date: startDate,\n start_time: startTime,\n end_time: endTime,\n color: 'blue',\n all_day: ev.allDay,\n description: ev.description || undefined,\n _caldav: { calendarId, eventUid: ev.uid, etag: ev.etag },\n };\n}\n\nfunction toDavInput(evt: CalendarEvent): {\n summary: string;\n description?: string;\n start: string;\n end: string;\n allDay: boolean;\n} {\n const start = evt.all_day\n ? evt.date\n : `${evt.date}T${evt.start_time || '09:00'}:00`;\n const end = evt.all_day\n ? evt.date\n : `${evt.date}T${evt.end_time || '10:00'}:00`;\n return {\n summary: evt.title,\n description: evt.description,\n start: new Date(start).toISOString(),\n end: new Date(end).toISOString(),\n allDay: !!evt.all_day,\n };\n}\n\n// ── Main Component ──\nexport default function Calendar() {\n const { prefs, save } = useShellPrefs();\n const { isConnected, capabilities } = useMailAuth();\n const caldavEnabled = isConnected && capabilities?.caldav === true;\n const localEvents: CalendarEvent[] = prefs.calendar_events || [];\n\n const [calendars, setCalendars] = useState<DavCalendar[]>([]);\n const [caldavEvents, setCaldavEvents] = useState<CalendarEvent[]>([]);\n\n const { tasks: todoTasks, toggleDone: toggleTodoDone } = useTodoTasks();\n const todoEvents = useMemo<CalendarEvent[]>(\n () => todoTasks\n .filter(t => !!t.dueDate)\n .map(t => ({\n id: `todo-${t.id}`,\n title: t.name,\n date: t.dueDate!,\n color: 'gray',\n _todo: true,\n _todoId: t.id,\n _done: t.done,\n })),\n [todoTasks],\n );\n\n const events = useMemo(\n () => [...localEvents, ...caldavEvents, ...todoEvents],\n [localEvents, caldavEvents, todoEvents],\n );\n\n const today = new Date();\n const [currentDate, setCurrentDate] = useState(new Date(today.getFullYear(), today.getMonth(), 1));\n const [view, setView] = useState<ViewMode>('month');\n const [editingEvent, setEditingEvent] = useState<CalendarEvent | null>(null);\n const [newEventDate, setNewEventDate] = useState<string | null>(null);\n\n // Fetch calendars once when CalDAV becomes available\n useEffect(() => {\n if (!caldavEnabled) { setCalendars([]); return; }\n getMailClient()\n .get<{ calendars: DavCalendar[] }>('/api/calendar/calendars')\n .then(r => setCalendars(r.data.calendars))\n .catch(() => setCalendars([]));\n }, [caldavEnabled]);\n\n // Fetch events when current date changes (a 3-month window for prefetch)\n useEffect(() => {\n if (!caldavEnabled || calendars.length === 0) { setCaldavEvents([]); return; }\n const y = currentDate.getFullYear();\n const m = currentDate.getMonth();\n const start = new Date(y, m - 1, 1).toISOString();\n const end = new Date(y, m + 2, 0).toISOString();\n\n let cancelled = false;\n Promise.all(\n calendars.map(cal =>\n getMailClient()\n .get<{ events: DavEvent[] }>(`/api/calendar/calendars/${encodeURIComponent(cal.id)}/events`, {\n params: { start, end },\n })\n .then(r => r.data.events.map(e => davToLocal(e, cal.id)))\n .catch(() => [] as CalendarEvent[]),\n ),\n ).then(perCalendar => {\n if (cancelled) return;\n setCaldavEvents(perCalendar.flat());\n });\n return () => { cancelled = true; };\n }, [caldavEnabled, calendars, currentDate]);\n\n const saveLocalEvents = useCallback((updated: CalendarEvent[]) => {\n save({ calendar_events: updated });\n }, [save]);\n\n const saveEvent = async (evt: CalendarEvent, targetCalendarId?: string) => {\n // Editing an existing CalDAV event\n if (evt._caldav) {\n try {\n const input = toDavInput(evt);\n const res = await getMailClient().put<{ uid: string; etag: string }>(\n `/api/calendar/calendars/${encodeURIComponent(evt._caldav.calendarId)}/events/${encodeURIComponent(evt._caldav.eventUid)}`,\n input,\n { headers: { 'If-Match': evt._caldav.etag } },\n );\n setCaldavEvents(prev => prev.map(e =>\n e.id === evt.id\n ? { ...evt, _caldav: { ...evt._caldav!, etag: res.data.etag } }\n : e\n ));\n toast.success('Event updated');\n } catch (err) {\n const status = (err as { response?: { status?: number } })?.response?.status;\n if (status === 409) {\n toast.error('Event was modified elsewhere — refresh to see latest');\n } else {\n toast.error(extractError(err));\n }\n return;\n }\n } else if (targetCalendarId) {\n // New CalDAV event\n try {\n const input = toDavInput(evt);\n const res = await getMailClient().post<{ uid: string; etag: string; url: string }>(\n `/api/calendar/calendars/${encodeURIComponent(targetCalendarId)}/events`,\n input,\n );\n const newEvt: CalendarEvent = {\n ...evt,\n id: `caldav-${targetCalendarId}-${res.data.uid}`,\n _caldav: { calendarId: targetCalendarId, eventUid: res.data.uid, etag: res.data.etag },\n };\n setCaldavEvents(prev => [...prev, newEvt]);\n toast.success('Event created');\n } catch (err) {\n toast.error(extractError(err));\n return;\n }\n } else {\n // Local event\n const existing = localEvents.find(e => e.id === evt.id);\n if (existing) {\n saveLocalEvents(localEvents.map(e => e.id === evt.id ? evt : e));\n } else {\n saveLocalEvents([...localEvents, evt]);\n }\n }\n setEditingEvent(null);\n setNewEventDate(null);\n };\n\n const deleteEvent = async (evt: CalendarEvent) => {\n if (evt._caldav) {\n try {\n await getMailClient().delete(\n `/api/calendar/calendars/${encodeURIComponent(evt._caldav.calendarId)}/events/${encodeURIComponent(evt._caldav.eventUid)}`,\n { headers: { 'If-Match': evt._caldav.etag } },\n );\n setCaldavEvents(prev => prev.filter(e => e.id !== evt.id));\n toast.success('Event deleted');\n } catch (err) {\n toast.error(extractError(err));\n return;\n }\n } else {\n saveLocalEvents(localEvents.filter(e => e.id !== evt.id));\n }\n setEditingEvent(null);\n };\n\n // ── Navigation ──\n const goToday = () => setCurrentDate(new Date(today.getFullYear(), today.getMonth(), 1));\n const goPrev = () => {\n if (view === 'year') setCurrentDate(new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), 1));\n else if (view === 'month') setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1));\n else {\n const d = new Date(currentDate);\n d.setDate(d.getDate() - 7);\n setCurrentDate(d);\n }\n };\n const goNext = () => {\n if (view === 'year') setCurrentDate(new Date(currentDate.getFullYear() + 1, currentDate.getMonth(), 1));\n else if (view === 'month') setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1));\n else {\n const d = new Date(currentDate);\n d.setDate(d.getDate() + 7);\n setCurrentDate(d);\n }\n };\n\n const monthLabel = view === 'year'\n ? String(currentDate.getFullYear())\n : currentDate.toLocaleDateString(undefined, { month: 'long', year: 'numeric' });\n\n const eventsByDate = useMemo(() => {\n const map: Record<string, CalendarEvent[]> = {};\n events.forEach(e => {\n if (!map[e.date]) map[e.date] = [];\n map[e.date].push(e);\n });\n for (const key of Object.keys(map)) {\n map[key].sort((a, b) => (a.start_time || '').localeCompare(b.start_time || ''));\n }\n return map;\n }, [events]);\n\n const handleDayClick = (dateStr: string) => {\n setNewEventDate(dateStr);\n setEditingEvent({\n id: `evt-${Date.now()}-${Math.random().toString(36).slice(2, 5)}`,\n title: '',\n date: dateStr,\n start_time: '09:00',\n end_time: '10:00',\n color: 'blue',\n all_day: false,\n });\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center justify-between px-4 py-2 border-b border-gray-200 shrink-0\">\n <div className=\"flex items-center gap-3\">\n <button onClick={goToday} className=\"px-2.5 py-1 text-xs font-medium rounded-md border border-gray-300 text-gray-700 hover:bg-gray-50\">Today</button>\n <div className=\"flex items-center gap-1\">\n <button onClick={goPrev} className=\"p-1 rounded hover:bg-gray-100\">\n <svg className=\"h-4 w-4 text-gray-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" /></svg>\n </button>\n <button onClick={goNext} className=\"p-1 rounded hover:bg-gray-100\">\n <svg className=\"h-4 w-4 text-gray-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" /></svg>\n </button>\n </div>\n <h2 className=\"text-sm font-semibold text-gray-900\">{monthLabel}</h2>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n onClick={() => window.dispatchEvent(new Event('open-mail-connect'))}\n className=\"text-[11px] text-gray-600 cursor-pointer hover:text-gray-900\"\n title=\"Open mail & calendar settings\"\n >\n {caldavEnabled\n ? `CalDAV · ${calendars.length} calendar${calendars.length === 1 ? '' : 's'}`\n : 'CalDAV not connected'}\n </span>\n <div className=\"w-px h-4 bg-gray-200\" />\n <div className=\"flex gap-1\">\n {(['year', 'month', 'week'] as const).map(v => (\n <button key={v} onClick={() => setView(v)}\n className={`px-3 py-1 text-xs font-medium rounded-md transition-colors ${view === v ? 'bg-blue-600 text-white' : 'bg-white border border-gray-300 text-gray-600 hover:bg-gray-50'}`}>\n {v.charAt(0).toUpperCase() + v.slice(1)}\n </button>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"flex-1 overflow-hidden\">\n {view === 'year' ? (\n <YearView\n year={currentDate.getFullYear()}\n eventsByDate={eventsByDate}\n today={toDateStr(today)}\n onPickMonth={(m) => { setCurrentDate(new Date(currentDate.getFullYear(), m, 1)); setView('month'); }}\n onDayClick={handleDayClick}\n />\n ) : view === 'month' ? (\n <MonthView\n year={currentDate.getFullYear()}\n month={currentDate.getMonth()}\n eventsByDate={eventsByDate}\n today={toDateStr(today)}\n onDayClick={handleDayClick}\n onEventClick={setEditingEvent}\n onToggleTodo={toggleTodoDone}\n />\n ) : (\n <WeekView\n currentDate={currentDate}\n eventsByDate={eventsByDate}\n today={toDateStr(today)}\n onDayClick={handleDayClick}\n onEventClick={setEditingEvent}\n onToggleTodo={toggleTodoDone}\n />\n )}\n </div>\n\n {editingEvent && (\n <EventEditor\n event={editingEvent}\n isNew={!!newEventDate}\n calendars={calendars}\n onSave={saveEvent}\n onDelete={() => deleteEvent(editingEvent)}\n onClose={() => { setEditingEvent(null); setNewEventDate(null); }}\n />\n )}\n </div>\n );\n}\n\nfunction extractError(err: unknown): string {\n const r = (err as { response?: { data?: { error?: string } } })?.response?.data?.error;\n if (r) return r;\n if (err instanceof Error) return err.message;\n return 'Unknown error';\n}\n\nfunction DayEventBadge({ evt, onEventClick, onToggleTodo, compact = false }: {\n evt: CalendarEvent;\n onEventClick: (e: CalendarEvent) => void;\n onToggleTodo: (id: string) => void;\n compact?: boolean;\n}) {\n if (evt._todo && evt._todoId) {\n return compact ? (\n <button onClick={(ev) => { ev.stopPropagation(); onToggleTodo(evt._todoId!); }}\n title={evt.title}\n className={`w-full text-left flex items-center gap-1 truncate rounded px-1 py-0.5 text-[10px] leading-tight font-medium hover:bg-gray-100 transition-colors ${evt._done ? 'text-gray-400' : 'text-gray-700'}`}>\n <span className=\"shrink-0\">{evt._done ? '☑' : '☐'}</span>\n <span className={`truncate ${evt._done ? 'line-through' : ''}`}>{evt.title || 'Task'}</span>\n </button>\n ) : (\n <button onClick={(ev) => { ev.stopPropagation(); onToggleTodo(evt._todoId!); }}\n className={`w-full text-left flex items-center gap-2 rounded-md px-2 py-1.5 hover:bg-gray-100 transition-colors ${evt._done ? 'text-gray-400' : 'text-gray-700'}`}>\n <span className=\"shrink-0 text-base leading-none\">{evt._done ? '☑' : '☐'}</span>\n <span className={`text-xs font-medium truncate ${evt._done ? 'line-through' : ''}`}>{evt.title || 'Task'}</span>\n </button>\n );\n }\n const c = getColor(evt.color);\n return compact ? (\n <button onClick={(ev) => { ev.stopPropagation(); onEventClick(evt); }}\n className={`w-full text-left truncate rounded px-1 py-0.5 text-[10px] leading-tight font-medium ${c.light} hover:opacity-80 transition-opacity`}>\n {!evt.all_day && evt.start_time && <span className=\"text-[9px] opacity-70 mr-0.5\">{evt.start_time}</span>}\n {evt.title || 'Untitled'}\n </button>\n ) : (\n <button onClick={(ev) => { ev.stopPropagation(); onEventClick(evt); }}\n className={`w-full text-left rounded-md px-2 py-1.5 ${c.light} hover:opacity-80 transition-opacity`}>\n <p className=\"text-xs font-medium truncate\">{evt.title || 'Untitled'}</p>\n {!evt.all_day && evt.start_time && (\n <p className=\"text-[10px] opacity-70\">{evt.start_time}{evt.end_time ? ` - ${evt.end_time}` : ''}</p>\n )}\n </button>\n );\n}\n\nfunction MonthView({ year, month, eventsByDate, today, onDayClick, onEventClick, onToggleTodo }: {\n year: number; month: number; eventsByDate: Record<string, CalendarEvent[]>;\n today: string; onDayClick: (d: string) => void; onEventClick: (e: CalendarEvent) => void;\n onToggleTodo: (id: string) => void;\n}) {\n const cells = useMemo(() => getMonthDays(year, month), [year, month]);\n\n return (\n <div className=\"h-full flex flex-col\">\n <div className=\"grid grid-cols-7 border-b border-gray-200\">\n {DAYS.map(d => (\n <div key={d} className=\"px-2 py-1.5 text-[10px] font-semibold text-gray-500 uppercase text-center\">{d}</div>\n ))}\n </div>\n <div className=\"grid grid-cols-7 flex-1 auto-rows-fr\">\n {cells.map((cell, i) => {\n const dateStr = toDateStr(cell.date);\n const isToday = dateStr === today;\n const dayEvents = eventsByDate[dateStr] || [];\n return (\n <div key={i}\n onClick={() => onDayClick(dateStr)}\n className={`border-b border-r border-gray-100 px-1 py-0.5 cursor-pointer hover:bg-blue-50/50 transition-colors overflow-hidden ${!cell.isCurrentMonth ? 'bg-gray-50/50' : ''}`}\n >\n <div className={`text-[11px] font-medium mb-0.5 w-5 h-5 flex items-center justify-center rounded-full ${isToday ? 'bg-blue-600 text-white' : cell.isCurrentMonth ? 'text-gray-900' : 'text-gray-400'}`}>\n {cell.date.getDate()}\n </div>\n <div className=\"space-y-0.5\">\n {dayEvents.slice(0, 3).map(evt => <DayEventBadge key={evt.id} evt={evt} onEventClick={onEventClick} onToggleTodo={onToggleTodo} compact />)}\n {dayEvents.length > 3 && (\n <p className=\"text-[9px] text-gray-400 pl-1\">+{dayEvents.length - 3} more</p>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction YearView({ year, eventsByDate, today, onPickMonth, onDayClick }: {\n year: number;\n eventsByDate: Record<string, CalendarEvent[]>;\n today: string;\n onPickMonth: (month: number) => void;\n onDayClick: (dateStr: string) => void;\n}) {\n const monthShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n const dowShort = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];\n\n return (\n <div className=\"h-full overflow-y-auto p-4\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-x-6 gap-y-5 max-w-5xl mx-auto\">\n {monthShort.map((label, m) => {\n const cells = getMonthDays(year, m);\n return (\n <div key={m} className=\"flex flex-col\">\n <button onClick={() => onPickMonth(m)}\n className=\"self-start text-[13px] font-semibold text-blue-600 hover:text-blue-800 mb-1 px-1 -ml-1 rounded transition-colors\">\n {label}\n </button>\n <div className=\"grid grid-cols-7 mb-0.5\">\n {dowShort.map((d, i) => (\n <div key={i} className=\"text-[9px] font-medium text-gray-400 text-center\">{d}</div>\n ))}\n </div>\n <div className=\"grid grid-cols-7\">\n {cells.map((cell, i) => {\n const dateStr = toDateStr(cell.date);\n const isToday = dateStr === today;\n const hasEvents = !!eventsByDate[dateStr]?.length;\n return (\n <button key={i}\n onClick={(e) => { e.stopPropagation(); onDayClick(dateStr); }}\n className=\"relative h-6 flex items-center justify-center group\"\n tabIndex={cell.isCurrentMonth ? 0 : -1}>\n <span className={`text-[10px] tabular-nums leading-none flex items-center justify-center w-5 h-5 rounded-full transition-colors\n ${isToday\n ? 'bg-blue-600 text-white font-semibold'\n : cell.isCurrentMonth\n ? 'text-gray-700 group-hover:bg-blue-100'\n : 'text-gray-300'}`}>\n {cell.date.getDate()}\n </span>\n {hasEvents && cell.isCurrentMonth && !isToday && (\n <span className=\"absolute bottom-0 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-blue-500\" />\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction WeekView({ currentDate, eventsByDate, today, onDayClick, onEventClick, onToggleTodo }: {\n currentDate: Date; eventsByDate: Record<string, CalendarEvent[]>;\n today: string; onDayClick: (d: string) => void; onEventClick: (e: CalendarEvent) => void;\n onToggleTodo: (id: string) => void;\n}) {\n const days = useMemo(() => getWeekDays(currentDate), [currentDate]);\n\n return (\n <div className=\"h-full flex flex-col\">\n <div className=\"grid grid-cols-7 border-b border-gray-200\">\n {days.map(d => {\n const dateStr = toDateStr(d);\n const isToday = dateStr === today;\n return (\n <div key={dateStr} className=\"px-2 py-2 text-center\">\n <p className=\"text-[10px] font-medium text-gray-500 uppercase\">{DAYS[d.getDay()]}</p>\n <p className={`text-lg font-semibold mt-0.5 ${isToday ? 'text-blue-600' : 'text-gray-900'}`}>{d.getDate()}</p>\n </div>\n );\n })}\n </div>\n <div className=\"grid grid-cols-7 flex-1 overflow-y-auto\">\n {days.map(d => {\n const dateStr = toDateStr(d);\n const dayEvents = eventsByDate[dateStr] || [];\n return (\n <div key={dateStr}\n onClick={() => onDayClick(dateStr)}\n className=\"border-r border-gray-100 px-1.5 py-2 cursor-pointer hover:bg-blue-50/30 transition-colors min-h-[200px]\">\n <div className=\"space-y-1\">\n {dayEvents.map(evt => <DayEventBadge key={evt.id} evt={evt} onEventClick={onEventClick} onToggleTodo={onToggleTodo} />)}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction EventEditor({ event, isNew, calendars, onSave, onDelete, onClose }: {\n event: CalendarEvent;\n isNew: boolean;\n calendars: DavCalendar[];\n onSave: (e: CalendarEvent, targetCalendarId?: string) => void;\n onDelete: () => void;\n onClose: () => void;\n}) {\n const [title, setTitle] = useState(event.title);\n const [date, setDate] = useState(event.date);\n const [startTime, setStartTime] = useState(event.start_time || '09:00');\n const [endTime, setEndTime] = useState(event.end_time || '10:00');\n const [color, setColor] = useState(event.color);\n const [allDay, setAllDay] = useState(event.all_day ?? false);\n const [description, setDescription] = useState(event.description || '');\n const isFromCaldav = !!event._caldav;\n const [target, setTarget] = useState<string>(isFromCaldav ? event._caldav!.calendarId : 'local');\n\n const handleSave = () => {\n if (!title.trim()) { toast.error('Event title is required.'); return; }\n const updated: CalendarEvent = {\n ...event,\n title: title.trim(),\n date,\n start_time: allDay ? undefined : startTime,\n end_time: allDay ? undefined : endTime,\n color,\n all_day: allDay,\n description: description.trim() || undefined,\n };\n const targetCal = !isFromCaldav && target !== 'local' ? target : undefined;\n onSave(updated, targetCal);\n };\n\n const inp = 'block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm';\n\n return (\n <Modal open onClose={onClose} title={isNew ? 'New Event' : 'Edit Event'} size=\"sm\">\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Title *</label>\n <input value={title} onChange={e => setTitle(e.target.value)} className={inp} placeholder=\"Event title\" autoFocus />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Date</label>\n <input type=\"date\" value={date} onChange={e => setDate(e.target.value)} className={inp} />\n </div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={allDay} onChange={e => setAllDay(e.target.checked)} className=\"h-4 w-4 rounded border-gray-300 text-blue-600\" />\n <span className=\"text-sm text-gray-700\">All day</span>\n </label>\n {!allDay && (\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Start</label>\n <input type=\"time\" value={startTime} onChange={e => setStartTime(e.target.value)} className={inp} />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">End</label>\n <input type=\"time\" value={endTime} onChange={e => setEndTime(e.target.value)} className={inp} />\n </div>\n </div>\n )}\n {(isNew && calendars.length > 0) && (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Save to</label>\n <select value={target} onChange={e => setTarget(e.target.value)} className={inp}>\n <option value=\"local\">Local (this device only)</option>\n {calendars.map(c => (\n <option key={c.id} value={c.id}>{c.displayName}</option>\n ))}\n </select>\n </div>\n )}\n {isFromCaldav && (\n <p className=\"text-[11px] text-gray-500\">\n From {calendars.find(c => c.id === event._caldav?.calendarId)?.displayName || 'CalDAV'}\n </p>\n )}\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Color</label>\n <div className=\"flex gap-2\">\n {COLORS.map(c => (\n <button key={c.key} onClick={() => setColor(c.key)}\n className={`w-6 h-6 rounded-full ${c.bg} border-2 transition-all ${color === c.key ? 'border-gray-700 scale-110' : 'border-transparent hover:border-gray-400'}`} />\n ))}\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Description</label>\n <textarea value={description} onChange={e => setDescription(e.target.value)} rows={2} className={inp} placeholder=\"Optional notes...\" />\n </div>\n </div>\n\n {!isNew && (\n <ModalActions position=\"left\">\n <button onClick={onDelete} className=\"text-sm text-red-600 hover:text-red-800 font-medium\">Delete</button>\n </ModalActions>\n )}\n <ModalActions>\n <button onClick={handleSave} className=\"bg-blue-600 text-white px-4 py-2 text-sm font-medium rounded-lg hover:bg-blue-700\">\n {isNew ? 'Create' : 'Save'}\n </button>\n </ModalActions>\n </Modal>\n );\n}\n"]}
@@ -1,475 +0,0 @@
1
- import { setEmailUnreadCount } from './chunk-PDFQNHW7.js';
2
- import { useMailAuth, getMailClient } from './chunk-VBFB3ZIN.js';
3
- import { formatDate, formatDateTime } from './chunk-NSU7OHPC.js';
4
- import { toast_default } from './chunk-WIJ45SYD.js';
5
- import { Modal, ModalActions } from './chunk-3T6SQ4UO.js';
6
- import './chunk-UBN4IUDE.js';
7
- import './chunk-ZF6AYO4G.js';
8
- import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
9
- import { jsx, jsxs } from 'react/jsx-runtime';
10
-
11
- var SMART_VIEWS = [
12
- { key: "__inbox__", label: "Inbox", icon: "\u{1F4E5}" },
13
- { key: "__starred__", label: "Starred", icon: "\u2B50" },
14
- { key: "__unread__", label: "Unread", icon: "\u25CF" },
15
- { key: "__drafts__", label: "Drafts", icon: "\u{1F4DD}" },
16
- { key: "__sent__", label: "Sent", icon: "\u{1F4E4}" },
17
- { key: "__trash__", label: "Trash", icon: "\u{1F5D1}" },
18
- { key: "__junk__", label: "Spam", icon: "\u26A0" }
19
- ];
20
- function resolveSmartView(key, folders) {
21
- if (key === "__inbox__") return folders.find((f) => f.specialUse === "inbox")?.path || "INBOX";
22
- if (key === "__sent__") return folders.find((f) => f.specialUse === "sent")?.path || "Sent";
23
- if (key === "__drafts__") return folders.find((f) => f.specialUse === "drafts")?.path || "Drafts";
24
- if (key === "__trash__") return folders.find((f) => f.specialUse === "trash")?.path || "Trash";
25
- if (key === "__junk__") return folders.find((f) => f.specialUse === "junk")?.path || "Junk";
26
- return key;
27
- }
28
- function Email() {
29
- const { isConnected, serverReachable } = useMailAuth();
30
- const [folders, setFolders] = useState([]);
31
- const [selectedKey, setSelectedKey] = useState("__inbox__");
32
- const [messages, setMessages] = useState([]);
33
- const [selectedUid, setSelectedUid] = useState(null);
34
- const [detail, setDetail] = useState(null);
35
- const [loadingFolders, setLoadingFolders] = useState(false);
36
- const [loadingList, setLoadingList] = useState(false);
37
- const [loadingDetail, setLoadingDetail] = useState(false);
38
- const [composeOpen, setComposeOpen] = useState(false);
39
- const [composeDraft, setComposeDraft] = useState(null);
40
- const [serverError, setServerError] = useState(null);
41
- const selectedFolderPath = useMemo(() => resolveSmartView(selectedKey, folders), [selectedKey, folders]);
42
- const refreshFolders = useCallback(async () => {
43
- if (!isConnected) return;
44
- setLoadingFolders(true);
45
- setServerError(null);
46
- try {
47
- const res = await getMailClient().get("/api/mail/folders");
48
- setFolders(res.data.folders);
49
- } catch (err) {
50
- setServerError(extractError(err));
51
- } finally {
52
- setLoadingFolders(false);
53
- }
54
- }, [isConnected]);
55
- const refreshList = useCallback(async () => {
56
- if (!isConnected) return;
57
- setLoadingList(true);
58
- setServerError(null);
59
- try {
60
- const res = await getMailClient().get("/api/mail/messages", {
61
- params: { folder: selectedFolderPath, page: 0, pageSize: 50 }
62
- });
63
- setMessages(res.data.messages);
64
- } catch (err) {
65
- setServerError(extractError(err));
66
- } finally {
67
- setLoadingList(false);
68
- }
69
- }, [isConnected, selectedFolderPath]);
70
- useEffect(() => {
71
- refreshFolders();
72
- }, [refreshFolders]);
73
- useEffect(() => {
74
- refreshList();
75
- setDetail(null);
76
- setSelectedUid(null);
77
- }, [refreshList]);
78
- const unreadPollRef = useRef(null);
79
- useEffect(() => {
80
- if (!isConnected) return;
81
- async function tick() {
82
- try {
83
- const res = await getMailClient().get("/api/mail/unread-counts");
84
- const inboxFolder = folders.find((f) => f.specialUse === "inbox")?.path || "INBOX";
85
- setEmailUnreadCount(res.data.counts[inboxFolder] || 0);
86
- setFolders(
87
- (prev) => prev.map((f) => ({ ...f, unreadCount: res.data.counts[f.path] ?? f.unreadCount }))
88
- );
89
- } catch {
90
- }
91
- }
92
- tick();
93
- unreadPollRef.current = window.setInterval(tick, 3e4);
94
- return () => {
95
- if (unreadPollRef.current) window.clearInterval(unreadPollRef.current);
96
- };
97
- }, [isConnected, folders]);
98
- const openMessage = useCallback(async (item) => {
99
- setSelectedUid(item.uid);
100
- setLoadingDetail(true);
101
- try {
102
- const res = await getMailClient().get(
103
- `/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${item.uid}`
104
- );
105
- setDetail(res.data);
106
- if (!item.flags.includes("\\Seen")) {
107
- await getMailClient().post(
108
- `/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${item.uid}/flags`,
109
- { add: ["\\Seen"] }
110
- );
111
- setMessages(
112
- (prev) => prev.map((m) => m.uid === item.uid ? { ...m, flags: [...m.flags, "\\Seen"] } : m)
113
- );
114
- }
115
- } catch (err) {
116
- toast_default.error(extractError(err));
117
- } finally {
118
- setLoadingDetail(false);
119
- }
120
- }, [selectedFolderPath]);
121
- const toggleStar = useCallback(async (item) => {
122
- const isFlagged = item.flags.includes("\\Flagged");
123
- try {
124
- await getMailClient().post(
125
- `/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${item.uid}/flags`,
126
- isFlagged ? { remove: ["\\Flagged"] } : { add: ["\\Flagged"] }
127
- );
128
- setMessages(
129
- (prev) => prev.map(
130
- (m) => m.uid === item.uid ? {
131
- ...m,
132
- flags: isFlagged ? m.flags.filter((f) => f !== "\\Flagged") : [...m.flags, "\\Flagged"]
133
- } : m
134
- )
135
- );
136
- } catch (err) {
137
- toast_default.error(extractError(err));
138
- }
139
- }, [selectedFolderPath]);
140
- const trashMessage = useCallback(async (uid) => {
141
- try {
142
- await getMailClient().delete(`/api/mail/messages/${encodeURIComponent(selectedFolderPath)}/${uid}`);
143
- setMessages((prev) => prev.filter((m) => m.uid !== uid));
144
- if (selectedUid === uid) {
145
- setDetail(null);
146
- setSelectedUid(null);
147
- }
148
- } catch (err) {
149
- toast_default.error(extractError(err));
150
- }
151
- }, [selectedFolderPath, selectedUid]);
152
- function openCompose(initial) {
153
- setComposeDraft(initial ?? { to: "", cc: "", subject: "", body: "" });
154
- setComposeOpen(true);
155
- }
156
- if (serverReachable === false) {
157
- return /* @__PURE__ */ jsx(
158
- EmptyState,
159
- {
160
- title: "Mail server unreachable",
161
- body: "The bridge server is not responding. Start it with `npm run server:dev`, then retry.",
162
- action: /* @__PURE__ */ jsx("button", { onClick: () => window.location.reload(), className: "px-4 py-2 bg-gray-900 text-white rounded text-sm", children: "Retry" })
163
- }
164
- );
165
- }
166
- if (!isConnected) {
167
- return /* @__PURE__ */ jsx(
168
- EmptyState,
169
- {
170
- title: "Connect your mail account",
171
- body: "Open the Mail & Calendar button in the taskbar to connect via IMAP/SMTP/CalDAV."
172
- }
173
- );
174
- }
175
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full text-sm", children: [
176
- /* @__PURE__ */ jsxs("aside", { className: "w-56 shrink-0 border-r border-gray-200 overflow-y-auto bg-gray-50/60", children: [
177
- /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsx(
178
- "button",
179
- {
180
- onClick: () => openCompose(),
181
- className: "w-full bg-gray-900 text-white rounded-lg px-3 py-2 text-sm font-medium hover:bg-gray-800",
182
- children: "Compose"
183
- }
184
- ) }),
185
- /* @__PURE__ */ jsx("div", { className: "px-2", children: SMART_VIEWS.map((view) => {
186
- const folder = view.key === "__inbox__" ? folders.find((f) => f.specialUse === "inbox") : view.key === "__sent__" ? folders.find((f) => f.specialUse === "sent") : view.key === "__drafts__" ? folders.find((f) => f.specialUse === "drafts") : view.key === "__trash__" ? folders.find((f) => f.specialUse === "trash") : view.key === "__junk__" ? folders.find((f) => f.specialUse === "junk") : null;
187
- const unread = folder?.unreadCount ?? 0;
188
- const active = selectedKey === view.key;
189
- return /* @__PURE__ */ jsxs(
190
- "button",
191
- {
192
- onClick: () => setSelectedKey(view.key),
193
- className: `w-full flex items-center gap-2 px-2 py-1.5 rounded text-left text-sm ${active ? "bg-gray-200 font-medium" : "hover:bg-gray-100"}`,
194
- children: [
195
- /* @__PURE__ */ jsx("span", { className: "w-5 text-center text-base leading-none", children: view.icon }),
196
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: view.label }),
197
- unread > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] bg-blue-500 text-white rounded-full px-1.5", children: unread })
198
- ]
199
- },
200
- view.key
201
- );
202
- }) }),
203
- /* @__PURE__ */ jsx("div", { className: "px-3 mt-4 mb-1 text-[10px] uppercase tracking-wider text-gray-500", children: "Folders" }),
204
- /* @__PURE__ */ jsx("div", { className: "px-2 pb-3", children: folders.filter((f) => !f.specialUse || f.specialUse === "archive" || f.specialUse === "flagged").filter((f) => f.path.toUpperCase() !== "INBOX").map((f) => {
205
- const active = selectedKey === f.path;
206
- return /* @__PURE__ */ jsxs(
207
- "button",
208
- {
209
- onClick: () => setSelectedKey(f.path),
210
- className: `w-full flex items-center gap-2 px-2 py-1.5 rounded text-left text-sm ${active ? "bg-gray-200 font-medium" : "hover:bg-gray-100"}`,
211
- title: f.path,
212
- children: [
213
- /* @__PURE__ */ jsx("span", { className: "w-5 text-center text-base leading-none", children: "\u{1F4C1}" }),
214
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: f.name }),
215
- f.unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] bg-gray-300 text-gray-800 rounded-full px-1.5", children: f.unreadCount })
216
- ]
217
- },
218
- f.path
219
- );
220
- }) })
221
- ] }),
222
- /* @__PURE__ */ jsxs("section", { className: "w-80 shrink-0 border-r border-gray-200 flex flex-col", children: [
223
- /* @__PURE__ */ jsxs("header", { className: "px-3 py-2 border-b border-gray-200 flex items-center justify-between", children: [
224
- /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: SMART_VIEWS.find((v) => v.key === selectedKey)?.label || selectedKey }),
225
- /* @__PURE__ */ jsx(
226
- "button",
227
- {
228
- onClick: () => {
229
- refreshList();
230
- refreshFolders();
231
- },
232
- className: "text-xs text-gray-600 hover:text-gray-900",
233
- disabled: loadingList || loadingFolders,
234
- children: loadingList || loadingFolders ? "\u2026" : "Refresh"
235
- }
236
- )
237
- ] }),
238
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: loadingList && messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-xs text-gray-500", children: "Loading\u2026" }) : messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-xs text-gray-500", children: "No messages" }) : messages.map((msg) => /* @__PURE__ */ jsx(
239
- MessageRow,
240
- {
241
- msg,
242
- active: selectedUid === msg.uid,
243
- onOpen: () => openMessage(msg),
244
- onStar: () => toggleStar(msg)
245
- },
246
- msg.uid
247
- )) })
248
- ] }),
249
- /* @__PURE__ */ jsx("section", { className: "flex-1 overflow-y-auto", children: detail ? /* @__PURE__ */ jsx(
250
- MessageDetailView,
251
- {
252
- detail,
253
- folderPath: selectedFolderPath,
254
- loading: loadingDetail,
255
- onReply: () => openCompose({
256
- to: detail.from.address,
257
- cc: "",
258
- subject: detail.subject.startsWith("Re:") ? detail.subject : `Re: ${detail.subject}`,
259
- body: "",
260
- inReplyTo: detail.threadId,
261
- references: detail.references
262
- }),
263
- onTrash: () => trashMessage(detail.uid)
264
- }
265
- ) : /* @__PURE__ */ jsx("div", { className: "h-full grid place-items-center text-xs text-gray-400", children: "Select a message" }) }),
266
- composeOpen && composeDraft && /* @__PURE__ */ jsx(
267
- ComposeModal,
268
- {
269
- open: composeOpen,
270
- initial: composeDraft,
271
- onClose: () => setComposeOpen(false),
272
- onSent: () => {
273
- setComposeOpen(false);
274
- toast_default.success("Message sent");
275
- refreshList();
276
- }
277
- }
278
- ),
279
- serverError && /* @__PURE__ */ jsx("div", { className: "absolute bottom-3 left-1/2 -translate-x-1/2 bg-red-50 border border-red-200 text-red-800 px-3 py-1 text-xs rounded", children: serverError })
280
- ] });
281
- }
282
- function MessageRow({ msg, active, onOpen, onStar }) {
283
- const unread = !msg.flags.includes("\\Seen");
284
- const starred = msg.flags.includes("\\Flagged");
285
- return /* @__PURE__ */ jsxs(
286
- "div",
287
- {
288
- onClick: onOpen,
289
- className: `px-3 py-2 border-b border-gray-100 cursor-pointer ${active ? "bg-blue-50" : "hover:bg-gray-50"}`,
290
- children: [
291
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-0.5", children: [
292
- /* @__PURE__ */ jsx(
293
- "button",
294
- {
295
- onClick: (e) => {
296
- e.stopPropagation();
297
- onStar();
298
- },
299
- className: `text-xs ${starred ? "text-yellow-500" : "text-gray-300 hover:text-gray-500"}`,
300
- title: starred ? "Unstar" : "Star",
301
- children: "\u2605"
302
- }
303
- ),
304
- /* @__PURE__ */ jsx("p", { className: `text-xs flex-1 truncate ${unread ? "font-semibold text-gray-900" : "text-gray-700"}`, children: msg.from.name || msg.from.address }),
305
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400 shrink-0", children: formatDate(msg.date) })
306
- ] }),
307
- /* @__PURE__ */ jsx("p", { className: `text-xs truncate ${unread ? "font-medium text-gray-900" : "text-gray-600"}`, children: msg.subject || "(no subject)" }),
308
- msg.hasAttachments && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: "\u{1F4CE} attachment" })
309
- ]
310
- }
311
- );
312
- }
313
- function MessageDetailView({
314
- detail,
315
- folderPath,
316
- loading,
317
- onReply,
318
- onTrash
319
- }) {
320
- const baseUrl = `/api/mail/messages/${encodeURIComponent(folderPath)}/${detail.uid}/attachments`;
321
- return /* @__PURE__ */ jsxs("div", { children: [
322
- /* @__PURE__ */ jsxs("header", { className: "px-6 py-4 border-b border-gray-200", children: [
323
- /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold mb-2", children: detail.subject || "(no subject)" }),
324
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs text-gray-600", children: [
325
- /* @__PURE__ */ jsxs("div", { children: [
326
- /* @__PURE__ */ jsxs("div", { children: [
327
- /* @__PURE__ */ jsx("strong", { children: detail.from.name || detail.from.address }),
328
- " <",
329
- detail.from.address,
330
- ">"
331
- ] }),
332
- /* @__PURE__ */ jsxs("div", { children: [
333
- "to ",
334
- detail.to.map((t) => t.address).join(", ")
335
- ] }),
336
- detail.cc.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
337
- "cc ",
338
- detail.cc.map((t) => t.address).join(", ")
339
- ] }),
340
- /* @__PURE__ */ jsx("div", { className: "text-gray-400 mt-1", children: formatDateTime(detail.date) })
341
- ] }),
342
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
343
- /* @__PURE__ */ jsx("button", { onClick: onReply, className: "px-3 py-1 text-xs border border-gray-300 rounded hover:bg-gray-50", children: "Reply" }),
344
- /* @__PURE__ */ jsx("button", { onClick: onTrash, className: "px-3 py-1 text-xs border border-red-200 text-red-700 rounded hover:bg-red-50", children: "Trash" })
345
- ] })
346
- ] })
347
- ] }),
348
- /* @__PURE__ */ jsx("article", { className: "px-6 py-4", children: loading ? /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: "Loading\u2026" }) : detail.html ? /* @__PURE__ */ jsx("div", { className: "prose prose-sm max-w-none", dangerouslySetInnerHTML: { __html: detail.html } }) : /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap text-sm font-sans", children: detail.text || "(empty)" }) }),
349
- detail.attachments.length > 0 && /* @__PURE__ */ jsxs("section", { className: "px-6 pb-6", children: [
350
- /* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold text-gray-700 mb-2", children: "Attachments" }),
351
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: detail.attachments.map((att) => /* @__PURE__ */ jsxs(
352
- "a",
353
- {
354
- href: `${getMailClient().defaults.baseURL}${baseUrl}/${encodeURIComponent(att.partId)}`,
355
- target: "_blank",
356
- rel: "noreferrer",
357
- className: "flex items-center gap-2 border border-gray-200 rounded px-3 py-2 text-xs hover:bg-gray-50",
358
- children: [
359
- /* @__PURE__ */ jsx("span", { children: "\u{1F4CE}" }),
360
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: att.filename }),
361
- /* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
362
- (att.size / 1024).toFixed(1),
363
- "KB"
364
- ] })
365
- ]
366
- },
367
- att.partId
368
- )) })
369
- ] })
370
- ] });
371
- }
372
- function ComposeModal({
373
- open,
374
- initial,
375
- onClose,
376
- onSent
377
- }) {
378
- const [draft, setDraft] = useState(initial);
379
- const [sending, setSending] = useState(false);
380
- async function send() {
381
- setSending(true);
382
- try {
383
- const toList = draft.to.split(",").map((s) => s.trim()).filter(Boolean);
384
- const ccList = draft.cc.split(",").map((s) => s.trim()).filter(Boolean);
385
- if (toList.length === 0) {
386
- toast_default.error("At least one recipient required");
387
- return;
388
- }
389
- await getMailClient().post("/api/mail/send", {
390
- to: toList,
391
- cc: ccList.length ? ccList : void 0,
392
- subject: draft.subject,
393
- text: draft.body,
394
- inReplyTo: draft.inReplyTo,
395
- references: draft.references,
396
- saveToSent: true
397
- });
398
- onSent();
399
- } catch (err) {
400
- toast_default.error(extractError(err));
401
- } finally {
402
- setSending(false);
403
- }
404
- }
405
- return /* @__PURE__ */ jsxs(Modal, { open, onClose, title: "New message", size: "lg", children: [
406
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
407
- /* @__PURE__ */ jsx(
408
- "input",
409
- {
410
- type: "text",
411
- placeholder: "To",
412
- value: draft.to,
413
- onChange: (e) => setDraft({ ...draft, to: e.target.value }),
414
- className: "w-full border border-gray-300 rounded px-3 py-2 text-sm"
415
- }
416
- ),
417
- /* @__PURE__ */ jsx(
418
- "input",
419
- {
420
- type: "text",
421
- placeholder: "Cc (optional)",
422
- value: draft.cc,
423
- onChange: (e) => setDraft({ ...draft, cc: e.target.value }),
424
- className: "w-full border border-gray-300 rounded px-3 py-2 text-sm"
425
- }
426
- ),
427
- /* @__PURE__ */ jsx(
428
- "input",
429
- {
430
- type: "text",
431
- placeholder: "Subject",
432
- value: draft.subject,
433
- onChange: (e) => setDraft({ ...draft, subject: e.target.value }),
434
- className: "w-full border border-gray-300 rounded px-3 py-2 text-sm"
435
- }
436
- ),
437
- /* @__PURE__ */ jsx(
438
- "textarea",
439
- {
440
- rows: 12,
441
- placeholder: "Write your message\u2026",
442
- value: draft.body,
443
- onChange: (e) => setDraft({ ...draft, body: e.target.value }),
444
- className: "w-full border border-gray-300 rounded px-3 py-2 text-sm font-mono"
445
- }
446
- )
447
- ] }),
448
- /* @__PURE__ */ jsx(ModalActions, { children: /* @__PURE__ */ jsx(
449
- "button",
450
- {
451
- onClick: send,
452
- disabled: sending,
453
- className: "bg-gray-900 text-white rounded-lg px-5 py-2 text-sm font-medium hover:bg-gray-800 disabled:opacity-50",
454
- children: sending ? "Sending\u2026" : "Send"
455
- }
456
- ) })
457
- ] });
458
- }
459
- function EmptyState({ title, body, action }) {
460
- return /* @__PURE__ */ jsx("div", { className: "h-full grid place-items-center p-8 text-center", children: /* @__PURE__ */ jsxs("div", { className: "max-w-sm", children: [
461
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: title }),
462
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600", children: body }),
463
- action && /* @__PURE__ */ jsx("div", { className: "mt-4", children: action })
464
- ] }) });
465
- }
466
- function extractError(err) {
467
- const response = err.response;
468
- if (response?.data?.error) return response.data.error;
469
- if (err instanceof Error) return err.message;
470
- return "Unknown error";
471
- }
472
-
473
- export { Email as default };
474
- //# sourceMappingURL=Email-ZUDCRZKB.js.map
475
- //# sourceMappingURL=Email-ZUDCRZKB.js.map