@@ -52,7 +52,7 @@ import LoadingSpinner from '@/components/LoadingSpinner';
5252import AttachmentViewer from '@/components/AttachmentViewer' ;
5353import SnoozeModal from '@/components/SnoozeModal' ;
5454import { useEmail , useEmailActions , useReplyDraft } from '@/lib/hooks' ;
55- import { emailsApi , teamsApi } from '@/lib/api' ;
55+ import { emailsApi , teamsApi , calendarApi } from '@/lib/api' ;
5656import { loadTags , getEmailTags , setEmailTags , createTag , saveTags , getNextColor } from '@/lib/tags' ;
5757import { supabase } from '@/lib/supabase' ;
5858import 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