diff --git a/services/web/frontend/js/utils/meta.ts b/services/web/frontend/js/utils/meta.ts index 077c91db9a..12f46b451c 100644 --- a/services/web/frontend/js/utils/meta.ts +++ b/services/web/frontend/js/utils/meta.ts @@ -44,7 +44,10 @@ import { } from '../../../types/settings-page' import { SuggestedLanguage } from '../../../types/system-message' import type { TeamInvite } from '../../../types/team-invite' -import { GroupPlans } from '../../../types/subscription/dashboard/group-plans' +import { + GroupPlans, + GroupPlansData, +} from '../../../types/subscription/dashboard/group-plans' import { GroupSSOLinkingStatus, SSOConfig, @@ -125,6 +128,7 @@ export interface Meta { 'ol-groupId': string 'ol-groupName': string 'ol-groupPlans': GroupPlans + 'ol-groupPlansData': GroupPlansData 'ol-groupPolicy': GroupPolicy 'ol-groupSSOActive': boolean 'ol-groupSSOConfig'?: SSOConfig diff --git a/services/web/types/subscription/dashboard/group-plans.ts b/services/web/types/subscription/dashboard/group-plans.ts index de93fe6a6d..a400db2604 100644 --- a/services/web/types/subscription/dashboard/group-plans.ts +++ b/services/web/types/subscription/dashboard/group-plans.ts @@ -1,3 +1,7 @@ +// this import fails linting in CI if from '@ol-types/utils' so as a temporary workaround we'll use the relative path +import { mkLiteralUnionTypeguard } from '../../utils' +import { CurrencyCode } from '../currency' + export type GroupPlans = { plans: { display: string @@ -5,3 +9,28 @@ export type GroupPlans = { }[] sizes: string[] } + +export const planTypeGroup = ['collaborator', 'professional'] as const +export type PlanTypeGroup = (typeof planTypeGroup)[number] +export const isPlanTypeGroup = mkLiteralUnionTypeguard(planTypeGroup) + +export const planUsageType = ['enterprise', 'educational'] as const +export type PlanUsageType = (typeof planUsageType)[number] +export const isPlanUsageType = mkLiteralUnionTypeguard(planUsageType) + +export const licenseSize = ['2', '3', '4', '5', '10', '20'] as const +export type LicenseSize = (typeof licenseSize)[number] +export const isLicenseSize = mkLiteralUnionTypeguard(licenseSize) + +export type LicensePrice = { + price_in_cents: number + additional_license_legacy_price_in_cents: number +} + +export type PlanPriceByLicenseSize = Record + +export type PlanByCurrencyCode = Record + +export type PlansByPlanTypeGroup = Record + +export type GroupPlansData = Record diff --git a/services/web/types/utils.ts b/services/web/types/utils.ts index 646658a5c8..4c38c9d4cd 100644 --- a/services/web/types/utils.ts +++ b/services/web/types/utils.ts @@ -20,3 +20,35 @@ export type DeepPartial = Partial<{ [P in keyof T]: DeepPartial }> export type MergeAndOverride = Own & Omit export type Keys = (keyof T)[] + +/** + * Helper to create type guards for literal unions + * + * @example + * ```ts + * const fruit = ['apple', 'banana', 'cherry'] as const; + * type Fruit = typeof fruit[number]; + * const isFruit = mkLiteralUnionTypeguard(fruit); + * + * // Usage example: + * function eatFood(food: unknown[]) { + * food.forEach(item => { + * if (isFruit(item)) { + * eatFruit(item) + * } else { + * console.log(`Not fruit ${item}`) + * } + * }) + * } + * eatFood(['banana', 'pizza']) + * ``` + * + * @param xs A readonly tuple of allowed values (strings, numbers, or symbols). + * @returns A type guard function `(value: unknown) => value is T[number]`. + */ +export function mkLiteralUnionTypeguard< + const T extends readonly (string | number | symbol)[], +>(xs: T) { + return (v: unknown): v is T[number] => + (xs as readonly (string | number | symbol)[]).includes(v as any) +}