Files
documenso/packages/lib/utils/settings-switcher.ts

58 lines
1.9 KiB
TypeScript

export type ComputeSwitcherContinuityPathArgs = {
currentPath: string;
/**
* Every settings path navigable in the destination scope — pass the destination's
* `SettingsNavGroup.items` paths from `getSettingsNavGroups`.
*
* Sourcing these from the nav builder (rather than a hardcoded list) means the switcher
* can only ever land on a page that is actually reachable there: permission and
* claim/billing gating are already applied when the group is built.
*/
destinationPaths: string[];
/** Where to land when the current section has no equivalent in the destination. */
fallbackPath: string;
};
/**
* Extract the "section" portion of a settings URL. Returns null if not a scoped
* settings URL (account settings and non-settings pages have no equivalent to carry over).
*
* Examples:
* /o/acme/settings/members → 'members'
* /o/acme/settings → 'general' (bare index redirects to General)
* /t/eng/settings/webhooks/42 → 'webhooks'
* /o/acme/documents → null
* /settings/profile → null
*/
const parseSettingsSection = (path: string): string | null => {
const match = /^\/[ot]\/[^/]+\/settings(?:\/([^/?#]+))?(?:[/?#]|$)/.exec(path);
if (!match) {
return null;
}
return match[1] ?? 'general';
};
/**
* Compute the destination URL when the user switches organisation or team via the
* unified settings sidebar's switcher.
*
* Rule: stay on the same section if the destination has one; else use the fallback.
*/
export const computeSwitcherContinuityPath = ({
currentPath,
destinationPaths,
fallbackPath,
}: ComputeSwitcherContinuityPathArgs): string => {
const currentSection = parseSettingsSection(currentPath);
if (!currentSection) {
return fallbackPath;
}
return destinationPaths.find((path) => parseSettingsSection(path) === currentSection) ?? fallbackPath;
};