feat(onboarding): branch question on the journey done screen (#1468)
* feat(onboarding): branch question on the journey done screen Second slice of the approved activation concept: the moment the company exists, the done screen asks "Var fanns bokföringen innan?" with provider chips (real logos), SIE file, and new-business options, plus a quiet look-around escape. Choices persist initial_setup_path (fire-and-forget) and deep-link into the existing flows: providers jump straight to the migration wizard's connect step (sieViaApi providers only; Visma/Bokio land on the provider list where the SIE-first gate lives), the SIE chip opens the upload step, new business lands on Hem with step one checked off. mode='add' keeps the plain "Öppna Accounted" button: the concept's own guard, and it avoids writing the path onto the previous company if setActiveCompany silently failed. Routing lives in a pure helper with tests; anonymous onboarding_branch_chosen funnel event follows the guarded capture pattern. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(onboarding): review triage: single-choice latch, preselect reset Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: restore package-lock.json to main (worktree npm install mutated it) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
Jakob Wennberg
parent
44cff5e5e4
commit
c7dd78b0a3
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { BRANCH_PROVIDERS, branchDestination, type BranchChoice } from '../branch'
|
||||
|
||||
describe('branchDestination', () => {
|
||||
it.each(['fortnox', 'visma', 'bokio', 'bjornlunden', 'briox'] as const)(
|
||||
'routes %s into the migration wizard with the provider preselected',
|
||||
(provider) => {
|
||||
expect(branchDestination(provider)).toEqual({
|
||||
path: 'migration',
|
||||
href: `/import?mode=migration&provider=${provider}`,
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it('routes the SIE file straight to the upload step', () => {
|
||||
expect(branchDestination('sie')).toEqual({ path: 'migration', href: '/import?mode=sie' })
|
||||
})
|
||||
|
||||
it('marks a new business as fresh and lands on Hem', () => {
|
||||
expect(branchDestination('fresh')).toEqual({ path: 'fresh', href: '/' })
|
||||
})
|
||||
|
||||
it('persists nothing on a pure skip', () => {
|
||||
expect(branchDestination('skip')).toEqual({ path: null, href: '/' })
|
||||
})
|
||||
|
||||
it('keeps provider chips aligned with the routable choices', () => {
|
||||
const choices = new Set<BranchChoice>(BRANCH_PROVIDERS.map((p) => p.id))
|
||||
for (const id of choices) {
|
||||
expect(branchDestination(id).path).toBe('migration')
|
||||
}
|
||||
// Every provider entry carries a real logo path under /logos/.
|
||||
for (const p of BRANCH_PROVIDERS) {
|
||||
expect(p.logo.startsWith('/logos/')).toBe(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { InitialSetupPath } from '@/types'
|
||||
|
||||
/**
|
||||
* The done-screen branch question ("Var fanns bokföringen innan?"): the one
|
||||
* routing decision made at peak motivation, right after the company exists.
|
||||
* Providers deep-link into the migration wizard; the SIE file goes straight
|
||||
* to the upload step; a new business skips the import entirely and starts
|
||||
* on Hem where the checklist points at the bank next.
|
||||
*/
|
||||
export type BranchChoice =
|
||||
| 'fortnox'
|
||||
| 'visma'
|
||||
| 'bokio'
|
||||
| 'bjornlunden'
|
||||
| 'briox'
|
||||
| 'sie'
|
||||
| 'fresh'
|
||||
| 'skip'
|
||||
|
||||
export const BRANCH_PROVIDERS: { id: BranchChoice; name: string; logo: string }[] = [
|
||||
{ id: 'fortnox', name: 'Fortnox', logo: '/logos/fortnox.svg' },
|
||||
{ id: 'visma', name: 'Visma', logo: '/logos/visma.jpeg' },
|
||||
{ id: 'bokio', name: 'Bokio', logo: '/logos/bokio.png' },
|
||||
{ id: 'bjornlunden', name: 'Björn Lundén', logo: '/logos/bjornlunden.png' },
|
||||
{ id: 'briox', name: 'Briox', logo: '/logos/Briox_logo.png' },
|
||||
]
|
||||
|
||||
export function branchDestination(choice: BranchChoice): {
|
||||
/** initial_setup_path to persist; null = persist nothing (pure skip). */
|
||||
path: InitialSetupPath | null
|
||||
href: string
|
||||
} {
|
||||
switch (choice) {
|
||||
case 'fortnox':
|
||||
case 'visma':
|
||||
case 'bokio':
|
||||
case 'bjornlunden':
|
||||
case 'briox':
|
||||
return { path: 'migration', href: `/import?mode=migration&provider=${choice}` }
|
||||
case 'sie':
|
||||
return { path: 'migration', href: '/import?mode=sie' }
|
||||
case 'fresh':
|
||||
return { path: 'fresh', href: '/' }
|
||||
case 'skip':
|
||||
return { path: null, href: '/' }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user