feat(onboarding): ChatGPT side door on the Connect to Claude step (#1981)
The checklist's closing step keeps Anslut till Claude as the one-click primary and gains a collapsed Anvander du ChatGPT? expander with the manual custom-connector path (Settings > Apps > Advanced settings > Developer mode) and a copy-server-address button built from the page origin. Expanding fires onboarding_setup_step_started { step: 'chatgpt' }.
This commit is contained in:
@@ -92,6 +92,10 @@ export default function NewUserChecklist({
|
||||
// step (companies whose completedAt arrives from the server never see it).
|
||||
const [retiring, setRetiring] = useState<'verdict' | 'closing' | 'done' | null>(null)
|
||||
const retireStartedRef = useRef(false)
|
||||
// The ChatGPT side door on the Claude step: collapsed by default so the
|
||||
// one-click Claude path stays the visual primary.
|
||||
const [chatGptOpen, setChatGptOpen] = useState(false)
|
||||
const [serverUrlCopied, setServerUrlCopied] = useState(false)
|
||||
|
||||
const hasMigration = ENABLED_EXTENSION_IDS.has('arcim-migration')
|
||||
const hasBanking = ENABLED_EXTENSION_IDS.has('enable-banking')
|
||||
@@ -231,6 +235,24 @@ export default function NewUserChecklist({
|
||||
const link = `https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=${encodeURIComponent(appName)}&connectorUrl=${encodeURIComponent(serverUrl)}`
|
||||
window.open(link, '_blank', 'noopener')
|
||||
}
|
||||
// ChatGPT has no add-connector deep link (the user pastes the server URL
|
||||
// into Developer mode manually), so the side door copies the URL instead.
|
||||
const toggleChatGpt = () => {
|
||||
setChatGptOpen((open) => {
|
||||
if (!open) captureSetup('onboarding_setup_step_started', { step: 'chatgpt' })
|
||||
return !open
|
||||
})
|
||||
}
|
||||
const copyServerUrl = async () => {
|
||||
const serverUrl = `${window.location.origin}/api/extensions/ext/mcp-server/mcp?tool_namespace=accounted`
|
||||
try {
|
||||
await navigator.clipboard.writeText(serverUrl)
|
||||
setServerUrlCopied(true)
|
||||
window.setTimeout(() => setServerUrlCopied(false), 2000)
|
||||
} catch {
|
||||
// Clipboard access can be denied; the button simply stays on "Kopiera".
|
||||
}
|
||||
}
|
||||
const dismiss = () =>
|
||||
void persist({ dismissed: true }, 'dismiss').then((updated) => {
|
||||
if (updated) captureSetup('onboarding_setup_dismissed', {})
|
||||
@@ -404,6 +426,30 @@ export default function NewUserChecklist({
|
||||
{t('step_claude_action')}
|
||||
</Button>
|
||||
)}
|
||||
footnote={
|
||||
<div className="mt-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleChatGpt}
|
||||
aria-expanded={chatGptOpen}
|
||||
className="text-xs text-muted-foreground underline decoration-border underline-offset-4 transition-colors hover:text-foreground"
|
||||
>
|
||||
{t('step_claude_chatgpt_link')}
|
||||
</button>
|
||||
{chatGptOpen && (
|
||||
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-2">
|
||||
<p className="max-w-prose text-xs leading-5 text-muted-foreground">
|
||||
{t('step_claude_chatgpt_steps', { appName })}
|
||||
</p>
|
||||
<Button size="sm" variant="outline" onClick={() => void copyServerUrl()}>
|
||||
{serverUrlCopied
|
||||
? t('step_claude_chatgpt_copied')
|
||||
: t('step_claude_chatgpt_copy')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{t('step_claude_description')}
|
||||
</Step>
|
||||
@@ -431,6 +477,7 @@ function Step({
|
||||
action,
|
||||
marks,
|
||||
doneNote,
|
||||
footnote,
|
||||
last = false,
|
||||
children,
|
||||
}: {
|
||||
@@ -445,6 +492,10 @@ function Step({
|
||||
* exception to "done steps collapse to their title" (e.g. the bank step's
|
||||
* sweep outcome, which is the payoff the migrator is waiting for). */
|
||||
doneNote?: React.ReactNode
|
||||
/** Block content below the pitch while the step is open. Unlike `children`
|
||||
* (which lives inside a <p>), this may hold nested block elements, e.g.
|
||||
* the Claude step's ChatGPT side door. */
|
||||
footnote?: React.ReactNode
|
||||
last?: boolean
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
@@ -502,6 +553,7 @@ function Step({
|
||||
{marks && <span className="flex items-center gap-2">{marks}</span>}
|
||||
</div>
|
||||
)}
|
||||
{open && footnote}
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
|
||||
+5
-1
@@ -1543,7 +1543,11 @@
|
||||
"step_receipts_channels_no_wa": "Email · upload",
|
||||
"step_claude_title": "Connect to Claude",
|
||||
"step_claude_description": "Do your bookkeeping from the chat: drop receipts and SIE files, reconcile the tax account and ask about your numbers. Everything is already connected.",
|
||||
"step_claude_action": "Connect to Claude"
|
||||
"step_claude_action": "Connect to Claude",
|
||||
"step_claude_chatgpt_link": "Using ChatGPT?",
|
||||
"step_claude_chatgpt_steps": "In ChatGPT (Plus, Pro or Business): Settings → Apps → Advanced settings → turn on Developer mode. Choose Add custom connector, name it {appName} and paste the server address. Then start a new chat and ask for a walkthrough of your books.",
|
||||
"step_claude_chatgpt_copy": "Copy server address",
|
||||
"step_claude_chatgpt_copied": "Copied"
|
||||
},
|
||||
"tax_assessment_notices": {
|
||||
"title": "Final tax notices and remaining tax",
|
||||
|
||||
+5
-1
@@ -1543,7 +1543,11 @@
|
||||
"step_receipts_channels_no_wa": "Mejl · uppladdning",
|
||||
"step_claude_title": "Anslut till Claude",
|
||||
"step_claude_description": "Bokför via chatten: släpp kvitton och SIE-filer, stäm av skattekontot och ställ frågor om siffrorna. Allt är redan kopplat.",
|
||||
"step_claude_action": "Anslut till Claude"
|
||||
"step_claude_action": "Anslut till Claude",
|
||||
"step_claude_chatgpt_link": "Använder du ChatGPT?",
|
||||
"step_claude_chatgpt_steps": "I ChatGPT (Plus, Pro eller Business): Inställningar → Appar → Avancerade inställningar → slå på Utvecklarläge. Välj Lägg till anpassad connector, namnge den {appName} och klistra in serveradressen. Starta sedan en ny chatt och be om en genomgång av bokföringen.",
|
||||
"step_claude_chatgpt_copy": "Kopiera serveradress",
|
||||
"step_claude_chatgpt_copied": "Kopierad"
|
||||
},
|
||||
"tax_assessment_notices": {
|
||||
"title": "Slutskattebesked och kvarskatt",
|
||||
|
||||
Reference in New Issue
Block a user