Skip to content

Commit c9862b5

Browse files
Sai Sridharclaude
andcommitted
Wire Google Calendar: create event directly from meeting detection banner
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f8d64f4 commit c9862b5

1 file changed

Lines changed: 31 additions & 11 deletions

File tree

frontend/pages/email/[id].tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import LoadingSpinner from '@/components/LoadingSpinner';
5252
import AttachmentViewer from '@/components/AttachmentViewer';
5353
import SnoozeModal from '@/components/SnoozeModal';
5454
import { useEmail, useEmailActions, useReplyDraft } from '@/lib/hooks';
55-
import { emailsApi, teamsApi } from '@/lib/api';
55+
import { emailsApi, teamsApi, calendarApi } from '@/lib/api';
5656
import { loadTags, getEmailTags, setEmailTags, createTag, saveTags, getNextColor } from '@/lib/tags';
5757
import { supabase } from '@/lib/supabase';
5858
import type { Action, QuoteData, MeetingInfo, InternalNote, OrgMember } from '@/lib/types';
@@ -162,7 +162,9 @@ export default function EmailDetailPage() {
162162
const [generatedQuote, setGeneratedQuote] = useState<QuoteData | null>(null);
163163

164164
// Meeting detection state
165-
const [meetingInfo, setMeetingInfo] = useState<MeetingInfo | null>(null);
165+
const [meetingInfo, setMeetingInfo] = useState<MeetingInfo | null>(null);
166+
const [gcalConnected, setGcalConnected] = useState(false);
167+
const [addingToCalendar, setAddingToCalendar] = useState(false);
166168

167169
// Team collaboration state
168170
const [notes, setNotes] = useState<InternalNote[]>([]);
@@ -263,6 +265,7 @@ export default function EmailDetailPage() {
263265
emailsApi.getMeetingInfo(emailId)
264266
.then((info) => { if (info.is_meeting_request) setMeetingInfo(info); })
265267
.catch(() => {});
268+
calendarApi.getStatus().then((s) => setGcalConnected(s.connected)).catch(() => {});
266269
}, [emailId, email?.id]);
267270

268271
// Load team notes + org members when email is available
@@ -986,17 +989,34 @@ export default function EmailDetailPage() {
986989
</div>
987990
<div className="flex items-center gap-1 flex-shrink-0">
988991
<button
989-
onClick={() => {
990-
const title = encodeURIComponent(email.subject || 'Meeting');
991-
const details = encodeURIComponent(meetingInfo.agenda || '');
992-
const calUrl = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${title}&details=${details}`;
993-
window.open(calUrl, '_blank', 'noopener');
992+
disabled={addingToCalendar}
993+
onClick={async () => {
994+
if (gcalConnected) {
995+
setAddingToCalendar(true);
996+
try {
997+
const result = await calendarApi.createEvent({
998+
title: email.subject || 'Meeting',
999+
description: `${meetingInfo.agenda || ''}\n\nFrom: ${email.from_name || email.from_email}\nProposed: ${(meetingInfo.proposed_times || []).join(', ')}`,
1000+
duration_hours: meetingInfo.duration_hint?.includes('30') ? 0.5 : 1,
1001+
});
1002+
toast.success('Event added to Google Calendar!');
1003+
if (result.html_link) window.open(result.html_link, '_blank', 'noopener');
1004+
} catch {
1005+
toast.error('Failed to create event. Try again.');
1006+
} finally {
1007+
setAddingToCalendar(false);
1008+
}
1009+
} else {
1010+
const title = encodeURIComponent(email.subject || 'Meeting');
1011+
const details = encodeURIComponent(meetingInfo.agenda || '');
1012+
window.open(`https://calendar.google.com/calendar/render?action=TEMPLATE&text=${title}&details=${details}`, '_blank', 'noopener');
1013+
}
9941014
}}
995-
className="inline-flex items-center gap-1.5 rounded-md border border-amber-300 dark:border-amber-600 bg-amber-100 dark:bg-amber-800/30 px-2 py-1 text-xs font-medium text-amber-800 dark:text-amber-300 hover:bg-amber-200 dark:hover:bg-amber-700/40 transition-colors"
996-
title="Add to Google Calendar"
1015+
className="inline-flex items-center gap-1.5 rounded-md border border-amber-300 dark:border-amber-600 bg-amber-100 dark:bg-amber-800/30 px-2 py-1 text-xs font-medium text-amber-800 dark:text-amber-300 hover:bg-amber-200 dark:hover:bg-amber-700/40 transition-colors disabled:opacity-50"
1016+
title={gcalConnected ? 'Create event in Google Calendar' : 'Add to Google Calendar (connect in Settings for auto-create)'}
9971017
>
998-
<CalendarPlus className="h-3 w-3" />
999-
Add to Calendar
1018+
{addingToCalendar ? <Loader2 className="h-3 w-3 animate-spin" /> : <CalendarPlus className="h-3 w-3" />}
1019+
{gcalConnected ? 'Create Event' : 'Add to Calendar'}
10001020
</button>
10011021
<button
10021022
onClick={() => setMeetingInfo(null)}

0 commit comments

Comments
 (0)