import { ThreadPrimitive } from '@assistant-ui/react'; import { useTranslation } from '../../i18n'; import { useAssistantStore } from '../../store/assistantStore'; import EmptyState from '../shared/EmptyState'; import AssistantHints, { MAX_VISIBLE_HINTS } from './AssistantHints'; import { useAssistantScope, useAssistantView } from './assistantViewContext'; import { useAssistantHints } from './useAssistantHints'; import type { ReadySuggestion } from './useAssistantSuggestions'; /** Suggestions left under a full list of hints, so both fit the smallest window. */ const SUGGESTIONS_UNDER_HINTS = 2; /** * The empty chat: the mascot, one question, and a few things to ask that fit * where the trip stands. A suggestion sends itself; there is nothing to edit * first. On the phone the suggestions sit by the composer instead, where the * thumb is, so this shows them only when `withSuggestions` asks for it. * Between the two sit the plan hints, when the trip has any. */ export default function AssistantWelcome({ suggestions, canEdit, withSuggestions, }: { suggestions: ReadySuggestion[]; canEdit: boolean; withSuggestions: boolean; }) { const { t } = useTranslation(); const { tripId, variant } = useAssistantView(); // The Studio's chat is about a book, not a plan; the journey's chat on its own page about the journal, // the home chat about all of the user's travels. A journey's chat the Studio does not host is the journal's. const hosted = useAssistantStore((s) => !!s.studioHosts[tripId]); const about = useAssistantScope().kind; const scope: WelcomeScope = about === 'journey' && !hosted ? 'journal' : about; const hints = useAssistantHints(tripId, { withStays: true }); const crowded = Math.min(hints.hints.length, MAX_VISIBLE_HINTS) > SUGGESTIONS_UNDER_HINTS; const offered = crowded ? suggestions.slice(0, SUGGESTIONS_UNDER_HINTS) : suggestions; return (
{!canEdit &&

{readOnlyNote(scope, t)}

} {withSuggestions && offered.length > 0 && }
); } /** What an empty chat is about: a trip, a journey's book in the Studio, a journal on its page, or all of them. */ type WelcomeScope = 'trip' | 'journey' | 'journal' | 'home'; /** The question over the empty chat, by what the chat is about. */ function welcomeTitle(scope: WelcomeScope, t: (key: string) => string): string { if (scope === 'journey') return t('journey.studio.assistant.welcome'); if (scope === 'journal') return t('assistant.journal.welcome'); return scope === 'home' ? t('assistant.home.welcome') : t('assistant.empty.title'); } /** What the empty chat tells someone who may only read. */ function readOnlyNote(scope: WelcomeScope, t: (key: string) => string): string { if (scope === 'journey') return t('journey.studio.assistant.readOnly'); return scope === 'journal' ? t('assistant.journal.readOnly') : t('assistant.empty.readOnly'); } export function AssistantSuggestions({ suggestions, layout, }: { suggestions: ReadySuggestion[]; /** 'stack' under the mascot, 'row' as a strip of chips over the composer. */ layout: 'stack' | 'row'; }) { return (
{suggestions.map((s) => ( {s.prompt} ))}
); }