constants.ts3.3 KBView on GitHub import { ListTodo, Plug } from 'lucide-react';
import { primaryNavButtons } from '@/modules/conversations/components/nav-buttons';
import type { ConnectStepKind, SetupSection, SetupStep } from './types';
const navIcon = (id: string) => {
const button = primaryNavButtons.find((b) => b.id === id);
if (!button) throw new Error(`onboarding/setup: unknown nav button id "${id}"`);
return button;
};
/**
* Rail sections, in order. Icons come from `primaryNavButtons` on purpose — the
* rail is a facsimile of the real one, so a user who learns this rail has
* learned the app's. Tasks has no `primaryNavButtons` entry (the real rail
* builds it from TaskGroupsNav), so it carries the same icon that component
* uses; Connect is not a destination at all, so it gets a plug.
*/
export const SETUP_SECTIONS: SetupSection[] = [
{ id: 'connect', label: 'Connect', icon: Plug },
{ id: 'mail', label: 'Inbox', icon: navIcon('mail').icon },
{ id: 'tasks', label: 'Tasks', icon: ListTodo },
{
id: 'pipeline',
label: 'Pipeline',
icon: navIcon('pipeline').icon,
isCustomIcon: true,
},
];
/** Copy for each integration step. Which ones appear is decided at runtime. */
export const CONNECT_STEPS: Record<ConnectStepKind, Omit<SetupStep, 'section'>> = {
meeting: {
id: 'connect-meeting',
connect: 'meeting',
railLabel: 'Meeting recorder',
headline: 'Connect your recorder',
},
crm: {
id: 'connect-crm',
connect: 'crm',
railLabel: 'CRM',
headline: 'Connect your CRM',
},
slack: {
id: 'connect-slack',
connect: 'slack',
railLabel: 'Slack',
headline: 'Connect Slack',
},
mcp: {
id: 'connect-mcp',
connect: 'mcp',
railLabel: 'Extra context',
headline: 'Anything else Cedar should read',
},
linkedin: {
id: 'connect-linkedin',
connect: 'linkedin',
railLabel: 'LinkedIn',
headline: 'Connect LinkedIn',
},
whatsapp: {
id: 'connect-whatsapp',
connect: 'whatsapp',
railLabel: 'WhatsApp',
headline: 'Connect WhatsApp',
},
drive: {
id: 'connect-drive',
connect: 'drive',
railLabel: 'Google Drive',
headline: 'Connect Google Drive',
},
};
/** The product-configuration half — always present, in this order. */
export const PRODUCT_STEPS: SetupStep[] = [
{
id: 'inbox-display',
section: 'mail',
railLabel: 'Display',
headline: 'Make it yours',
},
{
id: 'inbox-splits',
section: 'mail',
railLabel: 'Sub-inboxes',
headline: 'Split your inbox',
},
{
id: 'inbox-live',
section: 'mail',
railLabel: 'Your mail',
headline: 'Your actual inbox',
},
{
id: 'tasks',
section: 'tasks',
headline: 'Tasks do the work',
},
{
id: 'pipeline',
section: 'pipeline',
headline: 'Watch your pipeline',
},
];
/**
* The full ordered step list.
*
* Connect steps are spliced in rather than hard-coded because which
* integrations exist is an org setting — a team with no CRM installed should
* never see a CRM step, and the rail must not count one toward its progress.
*/
export function buildSetupSteps(availableConnects: ConnectStepKind[]): SetupStep[] {
const connectSteps = availableConnects.map<SetupStep>((kind) => ({
...CONNECT_STEPS[kind],
section: 'connect',
}));
return [...connectSteps, ...PRODUCT_STEPS];
}