import { useEffect, useState } from 'react'; import { Mail, RefreshCw, ShieldCheck } from 'lucide-react'; import { api, type Mailboxes } from './api'; type Run=(action:()=>Promise)=>Promise; const when=(value:string|null)=>value?new Date(value).toLocaleString():'Not yet'; export function MailboxPanel({data,owner,preview,busy,run,onChange}:{data:Mailboxes;owner:boolean;preview:boolean;busy:boolean;run:Run;onChange:(value:Mailboxes)=>void}){ const [pollError,setPollError]=useState(''); async function refresh(){onChange(await api('/mailboxes'));setPollError('');} useEffect(()=>{let active=true;const timer=setInterval(()=>{if(document.hidden)return;api('/mailboxes').then(value=>{if(active){onChange(value);setPollError('');}}).catch(()=>{if(active)setPollError('Status could not be refreshed. Use Refresh status to check again.');});},30000);return()=>{active=false;clearInterval(timer);};},[onChange]); async function act(id:string,version:number,action:string,email:string){ if(action==='disconnect'&&!window.confirm(`Disconnect ${email} from GuestOps? New import and reply work will stop and saved Google credentials will be removed. An in-flight request may finish. Imported emails and drafts stay in this workspace. Google account access must be removed separately.`))return; await run(async()=>{const result=await api<{url?:string}>(`/mailboxes/${id}/${action}`,'POST',{version});if(result?.url)location.assign(result.url);else await refresh();}); } return

Google mailbox

Keep guest messages flowing into your shared inbox.

{pollError&&

{pollError}

} {data.items.map(m=>{const connected=m.status==='Connected';const waiting=!!m.nextAttemptAt&&new Date(m.nextAttemptAt)>new Date();const label=m.status==='NeedsReconnect'?'Reconnect needed':m.status==='Disconnected'?'Disconnected':m.syncError?'Waiting for retry':m.catchingUp?'Catching up':'Connected';return
G{m.email}{label}
Last successful import{when(m.lastSyncAt)}
Last attempt{when(m.lastAttemptAt)}
Next check{waiting?when(m.nextAttemptAt):connected?'Next worker cycle':'After reconnection'}
{m.syncError&&

{m.syncError}

}

{connected?(m.canSend?'Google sending permission granted. Hotel and reply approval controls still apply.':'Read-only connection. Reconnect after administrator enablement to grant sending permission.'):'GuestOps cannot start new mailbox work while disconnected or awaiting reconnection.'}

{connected&&}{m.status!=='Disconnected'&&}
{m.status==='Disconnected'&&

To also remove Google's authorization, open your Google account connections and remove GuestOps access. This may affect other sessions using the same Google app.

}
;})} {!data.items.length&&

Connect your hotel inbox

Authorize the Google account your team uses for guest messages. The first import covers seven days.

} {preview?

Sample workspace only. Real mailbox connection and recovery controls are unavailable here.

:!data.configured&&

Your administrator must configure Google before connection is available.

}
Disconnecting keeps imported messages and drafts. Requests already in progress may finish. Reconnection keeps the same mailbox history; queued replies from an earlier connection require review.
; }