"use client" import { useEffect, useRef, useState } from "react" import { AnimatePresence, motion } from "motion/react" import { Button } from "@ui/components/button" import { Input } from "@ui/components/input" import { Textarea } from "@ui/components/textarea" import { ArrowRight, Brain, Building2, LayoutGrid, Loader2, Plug, Terminal, UserPlus, Users2, Wand2, } from "lucide-react" import { cn } from "@lib/utils" import { dmSans125ClassName } from "@/lib/fonts" import type { BrainMode } from "./types" const BACKEND = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai" export interface AboutValues { name: string about: string workspaceName: string workspaceDomain: string } interface Props { mode: BrainMode domain: string | null suggestedWorkspaceName: string defaultName: string avatarUrl: string | null values: AboutValues onChange: (next: AboutValues) => void onContinue: () => void submitting?: boolean } export const cardSurfaceStyle = { boxShadow: "0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset", } export const inputBevelStyle = { boxShadow: "0px 1px 2px 0px rgba(0,43,87,0.1), inset 0px 0px 0px 1px rgba(43,49,67,0.08), inset 0px 1px 1px 0px rgba(0,0,0,0.08), inset 0px 2px 4px 0px rgba(0,0,0,0.02)", } export const fieldLabel = "pl-2 pb-2 font-semibold text-[14px] text-[#737373]" export const inputClass = "bg-[#0F1217] border border-[rgba(82,89,102,0.2)] rounded-[12px] text-[#fafafa] text-[14px] placeholder:text-[#525D6E] h-12 px-4 shadow-none focus-visible:ring-0 focus-visible:border-[rgba(115,115,115,0.3)] transition-colors" export function StepAbout({ mode, domain, suggestedWorkspaceName, defaultName, avatarUrl, values, onChange, onContinue, submitting, }: Props) { // biome-ignore lint/correctness/useExhaustiveDependencies: one-time initialization when defaults become available useEffect(() => { const patch: Partial = {} if (!values.name && defaultName) patch.name = defaultName if (!values.workspaceName && suggestedWorkspaceName) { patch.workspaceName = suggestedWorkspaceName } if (!values.workspaceDomain && domain) { patch.workspaceDomain = domain } if (Object.keys(patch).length > 0) onChange({ ...values, ...patch }) }, [defaultName, suggestedWorkspaceName, domain]) const isTeam = mode === "team" // Default the workspace name per mode: name-derived for Personal (field hidden), // email-derived for Team unless the user has typed their own. const workspaceTouched = useRef(false) // biome-ignore lint/correctness/useExhaustiveDependencies: derive on mode/name changes only useEffect(() => { if (mode === "personal") { const first = values.name.trim().split(/\s+/)[0] const derived = first ? `${first}'s Brain` : suggestedWorkspaceName || "My brain" if (values.workspaceName !== derived) { onChange({ ...values, workspaceName: derived }) } } else if (!workspaceTouched.current) { const derived = suggestedWorkspaceName || "" if (values.workspaceName !== derived) { onChange({ ...values, workspaceName: derived }) } } }, [mode, values.name, suggestedWorkspaceName]) // Auto-draft the "what does your company do" blurb from the domain. const valuesRef = useRef(values) valuesRef.current = values const aboutTouched = useRef(false) const summarizedDomain = useRef(null) const latestDraftDomain = useRef(null) const [drafting, setDrafting] = useState(false) const [drafted, setDrafted] = useState(false) const draftCompany = async (rawDomain: string) => { const d = rawDomain.trim().toLowerCase() if (!d || summarizedDomain.current === d) return if (aboutTouched.current && valuesRef.current.about.trim()) return summarizedDomain.current = d latestDraftDomain.current = d setDrafting(true) try { const res = await fetch(`${BACKEND}/brain/company-summary`, { method: "POST", credentials: "include", headers: { "content-type": "application/json" }, body: JSON.stringify({ domain: d }), }) // Ignore a stale response if the domain changed mid-flight. if (latestDraftDomain.current !== d) return if (!res.ok) return const data = (await res.json()) as { summary?: string | null } if ( data.summary && !aboutTouched.current && latestDraftDomain.current === d ) { onChange({ ...valuesRef.current, about: data.summary }) setDrafted(true) } } catch { if (latestDraftDomain.current === d) summarizedDomain.current = null } finally { if (latestDraftDomain.current === d) setDrafting(false) } } // Draft once when entering Team with a domain already filled (e.g. from email). // biome-ignore lint/correctness/useExhaustiveDependencies: run on team-entry only useEffect(() => { if (!isTeam) return const d = (values.workspaceDomain || domain || "").trim() if (d && !values.about.trim()) draftCompany(d) }, [isTeam]) const canContinue = values.name.trim().length > 0 && values.workspaceName.trim().length > 0 return (

Tell us about you

So your brain sounds like yours, not the docs.

Your name

onChange({ ...values, name: e.target.value })} placeholder="e.g. Mahesh" className={inputClass} style={inputBevelStyle} />
{isTeam && (

Workspace name

{ workspaceTouched.current = true onChange({ ...values, workspaceName: e.target.value }) }} placeholder={suggestedWorkspaceName || "Acme"} className={inputClass} style={inputBevelStyle} />
)}
{/* Company domain slides in only for Team mode. */} {isTeam && (

Company domain

{values.workspaceDomain || domain ? ( ) : ( )}
onChange({ ...values, workspaceDomain: e.target.value }) } onBlur={(e) => { const d = e.target.value.trim() if (d !== values.workspaceDomain) { onChange({ ...values, workspaceDomain: d }) } draftCompany(d) }} placeholder="your-team.com" className={cn(inputClass, "pl-14")} style={inputBevelStyle} />
)}

{isTeam ? ( "What does your company do?" ) : ( <> What are you here for?{" "} (optional) )}

{isTeam && (drafting ? ( Drafting from your site… ) : drafted ? ( Drafted from your site · edit anything ) : null)}