Files
zeekay e981114824 chat: a signed-out reader asks the buying agent, and it routes them to pay
/chat signed out is the buying agent (components/sales/Guest, Agent): the
question the home composer carried in ?q= is asked of cloud's
POST /v1/ai/sales, the reply is drawn as text, and each next step the
server built is a control: a call (the lead is filed first, then the
calendar opens on it), the sign-up, a plan's card checkout, Add funds. A
quiet line says it is a limited preview and how many messages are left; at
the ceiling the sign-up takes the composer's place. A conversation's own
address still signs in, and a signed-in reader keeps the app.

/buying-specialist is the same agent; its keyword script, its typed prices
and its claims to see an account are gone. The model pages' no-key card is
the real lane, POST /v1/chat/public, not a guest key that answers 401.

Measured in the site's names: chat_started, cta_clicked {cta: kind, plan,
agent: sales}, sales_contacted. The floating privacy button is hidden as
room.css meant: the rule names its tag to outrank gui's atomic class.
2026-10-27 01:29:38 -07:00

87 lines
2.7 KiB
TypeScript

'use client'
/**
* The buying agent's whole window: a header that is the way in (Sign in, Sign up
* free) and the conversation (components/sales/Agent) under it. /chat draws it for
* a reader who is not signed in, and /buying-specialist for everyone.
*/
import Link from 'next/link'
import { HanzoMark } from '@hanzogui/shell'
import { useIam } from '@hanzo/iam/react'
import { Box, Text, View } from '@hanzo/ui'
import { LOGIN, signUp } from '@hanzo/app/lib/destination'
import { CHAT } from '@hanzo/app/lib/host'
import { Agent } from './Agent'
/** First questions, one per way a visitor buys. */
export const STARTERS = [
'We are a team of 8. Which plan fits?',
'What does Pro include?',
'I only need the API. How do I pay?',
'We need single sign-on and our own cloud',
'I am an AI agent with a crypto wallet. How do I pay?',
]
export function Guest({ seed, source }: { seed?: string; source: string }) {
const { isAuthenticated } = useIam()
return (
<Box display="flex" flexDirection="column" height="100dvh" width="100%" bg="var(--background)">
<View
render="header"
display="flex"
flexDirection="row"
items="center"
justify="space-between"
gap={12}
height={56}
px={16}
borderBottomWidth={1}
borderColor="var(--border)"
>
<Text render={<Link href="/" aria-label="Hanzo home" />} display="inline-flex" items="center" gap={10} color="var(--foreground)" textDecorationLine="none">
<HanzoMark size={22} />
<Text fontSize="$3" fontWeight="600" color="var(--foreground)">
Buying agent
</Text>
</Text>
<Box display="flex" flexDirection="row" items="center" gap={8}>
{isAuthenticated ? (
<Pill href={CHAT} label="Open Hanzo" strong />
) : (
<>
<Pill href={LOGIN} label="Sign in" />
<Pill href={signUp()} label="Sign up free" strong />
</>
)}
</Box>
</View>
<Box flex={1} minH={0}>
<Agent seed={seed} source={source} starters={STARTERS} />
</Box>
</Box>
)
}
function Pill({ href, label, strong = false }: { href: string; label: string; strong?: boolean }) {
return (
<Text
render={<Link href={href} />}
display="inline-flex"
items="center"
minH={36}
px={14}
rounded={9999}
borderWidth={1}
borderColor={strong ? 'var(--foreground)' : 'var(--border)'}
bg={strong ? 'var(--foreground)' : 'transparent'}
color={strong ? 'var(--background)' : 'var(--foreground)'}
fontSize="$2"
fontWeight="600"
textDecorationLine="none"
>
{label}
</Text>
)
}