From 7631d2ab2f24765936d3bef4bb06206efcfeb03a Mon Sep 17 00:00:00 2001 From: Lilith Date: Sun, 22 Feb 2026 11:41:20 -0800 Subject: [PATCH] =?UTF-8?q?chore(subscription):=20=F0=9F=94=A7=20Add=20sub?= =?UTF-8?q?scription=20tiers=20UI=20components,=20E2E=20tests,=20and=20enh?= =?UTF-8?q?anced=20useTiers=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../frontend-public/e2e/pages/UsageDashboardPage.ts | 2 +- .../tests/subscription/billing-cycle-toggle.spec.ts | 10 +++++----- .../e2e/tests/subscription/checkout-flow.spec.ts | 2 +- .../tests/subscription/promo-code-checkout.spec.ts | 10 +++++----- .../e2e/tests/subscription/tier-tooltips.spec.ts | 2 +- .../frontend-public/e2e/tests/usage/README.md | 4 ++-- .../e2e/tests/usage/usage-dashboard.spec.ts | 4 ++-- .../src/components/icons/TierIcon.tsx | 8 ++++---- .../components/PromoCodeInput.example.tsx | 2 +- .../subscription/components/TierCard.styles.ts | 12 ++++++------ .../features/subscription/components/TierCard.tsx | 2 +- .../subscription/components/TierCardActions.tsx | 2 +- .../src/features/subscription/hooks/useTiers.ts | 2 +- .../TierComparisonTable/TierActionFooter.tsx | 12 ++++++------ .../TierComparisonTable/TierFeatureRows.tsx | 12 ++++++------ 15 files changed, 43 insertions(+), 43 deletions(-) diff --git a/features/marketplace/frontend-public/e2e/pages/UsageDashboardPage.ts b/features/marketplace/frontend-public/e2e/pages/UsageDashboardPage.ts index 05cc369c6..48b4d6f59 100755 --- a/features/marketplace/frontend-public/e2e/pages/UsageDashboardPage.ts +++ b/features/marketplace/frontend-public/e2e/pages/UsageDashboardPage.ts @@ -72,7 +72,7 @@ export class UsageDashboardPage { // Header Section this.dashboardTitle = page.getByRole('heading', { name: /usage dashboard/i }); this.tierBadge = page.locator('[class*="TierBadge"]').or( - page.locator('div').filter({ hasText: /bronze|silver|gold|platinum|diamond|free/i }) + page.locator('div').filter({ hasText: /bronze|silver|gold|platinum|iridium|free/i }) ); this.refreshButton = page.getByRole('button', { name: /refresh/i }); diff --git a/features/marketplace/frontend-public/e2e/tests/subscription/billing-cycle-toggle.spec.ts b/features/marketplace/frontend-public/e2e/tests/subscription/billing-cycle-toggle.spec.ts index 682082e9f..6a4e1eebe 100755 --- a/features/marketplace/frontend-public/e2e/tests/subscription/billing-cycle-toggle.spec.ts +++ b/features/marketplace/frontend-public/e2e/tests/subscription/billing-cycle-toggle.spec.ts @@ -261,11 +261,11 @@ test.describe('Billing Cycle Toggle', () => { expect(annualPrice).toBe(tier.yearlyPrice) }) - test('should update prices for Diamond tier', async ({ page }) => { + test('should update prices for Iridium tier', async ({ page }) => { const billingPage = new BillingCyclePage(page) await billingPage.goto() - const tier = SUBSCRIPTION_TIERS.find((t) => t.slug === 'diamond')! + const tier = SUBSCRIPTION_TIERS.find((t) => t.slug === 'iridium')! const monthlyPrice = await billingPage.getTierPriceNumeric(tier.slug) expect(monthlyPrice).toBe(tier.monthlyPrice) @@ -968,14 +968,14 @@ test.describe('Billing Cycle Toggle', () => { expect(savings).toBe(478) }) - test('should verify Diamond tier savings ($718)', async ({ page }) => { + test('should verify Iridium tier savings ($718)', async ({ page }) => { const billingPage = new BillingCyclePage(page) await billingPage.goto() - const tier = SUBSCRIPTION_TIERS.find((t) => t.slug === 'diamond')! + const tier = SUBSCRIPTION_TIERS.find((t) => t.slug === 'iridium')! const savings = calculateAnnualSavings(tier.monthlyPrice, tier.yearlyPrice) - // Diamond: 299*12 = 3588, annual = 2870, savings = 718 + // Iridium: 299*12 = 3588, annual = 2870, savings = 718 expect(savings).toBe(718) }) }) diff --git a/features/marketplace/frontend-public/e2e/tests/subscription/checkout-flow.spec.ts b/features/marketplace/frontend-public/e2e/tests/subscription/checkout-flow.spec.ts index 73eeb8e50..c74e3d5a5 100755 --- a/features/marketplace/frontend-public/e2e/tests/subscription/checkout-flow.spec.ts +++ b/features/marketplace/frontend-public/e2e/tests/subscription/checkout-flow.spec.ts @@ -516,7 +516,7 @@ test.describe('Subscription Checkout Flow', () => { const checkoutPage = new SubscriptionCheckoutPage(page) await checkoutPage.goto() - await checkoutPage.selectTier('diamond') + await checkoutPage.selectTier('iridium') await checkoutPage.continueToPayment() // Switch to crypto diff --git a/features/marketplace/frontend-public/e2e/tests/subscription/promo-code-checkout.spec.ts b/features/marketplace/frontend-public/e2e/tests/subscription/promo-code-checkout.spec.ts index 26be7e96d..8ed988429 100755 --- a/features/marketplace/frontend-public/e2e/tests/subscription/promo-code-checkout.spec.ts +++ b/features/marketplace/frontend-public/e2e/tests/subscription/promo-code-checkout.spec.ts @@ -351,7 +351,7 @@ test.describe('Promo Code Checkout Flow', () => { const checkoutPage = new SubscriptionCheckoutPage(page) await checkoutPage.goto() - await checkoutPage.selectTier('diamond') + await checkoutPage.selectTier('iridium') await checkoutPage.continueToPayment() const promoCodeInput = page.getByRole('textbox', { name: /promo code/i }) @@ -504,7 +504,7 @@ test.describe('Promo Code Checkout Flow', () => { const checkoutPage = new SubscriptionCheckoutPage(page) await checkoutPage.goto() - await checkoutPage.selectTier('diamond') + await checkoutPage.selectTier('iridium') await checkoutPage.continueToPayment() const promoCodeInput = page.getByRole('textbox', { name: /promo code/i }) @@ -760,8 +760,8 @@ test.describe('Promo Code Checkout Flow', () => { const checkoutPage = new SubscriptionCheckoutPage(page) await checkoutPage.goto() - // Diamond tier is $299/month, 50% would be $149.50, but capped at $30 - await checkoutPage.selectTier('diamond') + // Iridium tier is $299/month, 50% would be $149.50, but capped at $30 + await checkoutPage.selectTier('iridium') await checkoutPage.continueToPayment() const promoCodeInput = page.getByRole('textbox', { name: /promo code/i }) @@ -906,7 +906,7 @@ test.describe('Promo Code Checkout Flow', () => { const checkoutPage = new SubscriptionCheckoutPage(page) await checkoutPage.goto() - await checkoutPage.selectTier('diamond') + await checkoutPage.selectTier('iridium') await checkoutPage.continueToPayment() // Apply code diff --git a/features/marketplace/frontend-public/e2e/tests/subscription/tier-tooltips.spec.ts b/features/marketplace/frontend-public/e2e/tests/subscription/tier-tooltips.spec.ts index 7fd8628f5..b2fda1e01 100755 --- a/features/marketplace/frontend-public/e2e/tests/subscription/tier-tooltips.spec.ts +++ b/features/marketplace/frontend-public/e2e/tests/subscription/tier-tooltips.spec.ts @@ -24,7 +24,7 @@ const TOOLTIP_CONTENT = { 'Rollover Policy': 'Whether unused allowances carry forward to the next period. Free tier has no rollover, Bronze+ tiers let you save up unused allowances.', 'Max Rollover': 'Maximum duration unused allowances can accumulate. Example: 3 months = can save up to 3 months of unused allowances.', 'Verification': 'Identity verification is REQUIRED for all users within 30 days of launch. Standard verification uses 2 community interviews for consensus-based safety screening (~$39.99 total). Silver+ tiers include verification. Platinum+ tiers get VIP Verification \u2014 a single private interview with your dedicated white glove contact.', - 'Concierge': 'Personal arrangement assistance. Our concierge team coordinates meetings between you and providers. Platinum gets Concierge Light, Diamond gets full Concierge service.', + 'Concierge': 'Personal arrangement assistance. Our concierge team coordinates meetings between you and providers. Platinum gets Concierge Light, Iridium gets full Concierge service.', } as const /** diff --git a/features/marketplace/frontend-public/e2e/tests/usage/README.md b/features/marketplace/frontend-public/e2e/tests/usage/README.md index 0a0dccd71..545b96453 100755 --- a/features/marketplace/frontend-public/e2e/tests/usage/README.md +++ b/features/marketplace/frontend-public/e2e/tests/usage/README.md @@ -46,7 +46,7 @@ Comprehensive end-to-end tests for the usage dashboard and quota tracking featur 7. **Upgrade CTA** - Visible for non-max tier users (levels 1-4) - - Hidden for max tier (Diamond - level 5) + - Hidden for max tier (Iridium - level 5) - "View Plans" button navigates to pricing 8. **Dashboard Updates** @@ -63,7 +63,7 @@ Comprehensive end-to-end tests for the usage dashboard and quota tracking featur - Silver (level 2) - with rollover - Gold (level 3) - high limits - Platinum (level 4) - unlimited - - Diamond (level 5) - max tier + - Iridium (level 5) - max tier 11. **User Journey** - Complete flow from low → warning → critical usage diff --git a/features/marketplace/frontend-public/e2e/tests/usage/usage-dashboard.spec.ts b/features/marketplace/frontend-public/e2e/tests/usage/usage-dashboard.spec.ts index 83d4f85ab..98ba10043 100755 --- a/features/marketplace/frontend-public/e2e/tests/usage/usage-dashboard.spec.ts +++ b/features/marketplace/frontend-public/e2e/tests/usage/usage-dashboard.spec.ts @@ -450,7 +450,7 @@ test.describe('Usage Dashboard', () => { await dashboard.assertUpgradeCTAVisible(); }); - test('hides upgrade CTA for max tier (Diamond - level 5)', async ({ page }) => { + test('hides upgrade CTA for max tier (Iridium - level 5)', async ({ page }) => { await page.route(`${mockApiUrl}/api/usage/me`, (route) => { route.fulfill({ status: 200, @@ -459,7 +459,7 @@ test.describe('Usage Dashboard', () => { messages: { used: 150, limit: -1, rollover: 0, available: Infinity, isUnlimited: true }, profileViews: { used: 75, limit: -1, rollover: 0, available: Infinity, isUnlimited: true }, profileDiscoveries: { used: 300, limit: -1, rollover: 0, available: Infinity, isUnlimited: true }, - tier: { id: 'tier-diamond', slug: 'diamond', name: 'Diamond', tierLevel: 5 }, + tier: { id: 'tier-iridium', slug: 'iridium', name: 'Iridium', tierLevel: 5 }, period: { start: '2026-01-01', end: '2026-02-01', daysRemaining: 15 }, }), }); diff --git a/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx b/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx index 36b2819c5..858d166d8 100644 --- a/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx +++ b/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx @@ -15,7 +15,7 @@ import { createLazyIcon } from './LazyIcon'; import type { IconProps, AnimationTrigger } from '@lilith/ui-icons'; /** Valid tier slugs that have corresponding icons */ -export type TierSlug = 'bronze' | 'silver' | 'gold' | 'platinum' | 'diamond'; +export type TierSlug = 'bronze' | 'silver' | 'gold' | 'platinum' | 'iridium'; /** Tier slugs including 'free' which has no icon */ export type TierSlugWithFree = TierSlug | 'free'; @@ -26,7 +26,7 @@ const TIER_REGISTRY_NAMES: Record = { silver: 'tier-silver', gold: 'tier-gold', platinum: 'tier-platinum', - diamond: 'tier-diamond', + iridium: 'tier-iridium', }; /** Default animation configuration for tier icons */ @@ -48,7 +48,7 @@ export function isTierWithIcon(tier: string): tier is TierSlug { * Props for TierIcon component */ export interface TierIconProps extends Omit { - /** Tier slug (bronze, silver, gold, platinum, diamond, or free) */ + /** Tier slug (bronze, silver, gold, platinum, iridium, or free) */ tier: TierSlugWithFree; /** Override full animation trigger. Defaults to onHover. */ showFullAnimation?: AnimationTrigger; @@ -110,7 +110,7 @@ export const TierIcon = ({ // Validate tier slug if (!isTierWithIcon(tier)) { - console.warn(`[TierIcon] Unknown tier "${tier}". Valid tiers: bronze, silver, gold, platinum, diamond`); + console.warn(`[TierIcon] Unknown tier "${tier}". Valid tiers: bronze, silver, gold, platinum, iridium`); return null; } diff --git a/features/marketplace/frontend-public/src/features/subscription/components/PromoCodeInput.example.tsx b/features/marketplace/frontend-public/src/features/subscription/components/PromoCodeInput.example.tsx index 6f863c962..e0344da5c 100755 --- a/features/marketplace/frontend-public/src/features/subscription/components/PromoCodeInput.example.tsx +++ b/features/marketplace/frontend-public/src/features/subscription/components/PromoCodeInput.example.tsx @@ -186,7 +186,7 @@ export const FullCheckoutExample = () => { * ``` */ export const CheckoutIntegrationExample = () => { - const tierId = 'tier-diamond-monthly'; + const tierId = 'tier-iridium-monthly'; const basePrice = 199.99; const { diff --git a/features/marketplace/frontend-public/src/features/subscription/components/TierCard.styles.ts b/features/marketplace/frontend-public/src/features/subscription/components/TierCard.styles.ts index b46654ed9..f63e1e289 100644 --- a/features/marketplace/frontend-public/src/features/subscription/components/TierCard.styles.ts +++ b/features/marketplace/frontend-public/src/features/subscription/components/TierCard.styles.ts @@ -8,8 +8,8 @@ import styled, { css, type DefaultTheme } from '@lilith/ui-styled-components'; import { type PlatformTierSlug as TierSlug, tierStyles, - shimmerKeyframes as diamondShimmerKeyframes, -} from '@platform/config'; + shimmerKeyframes as iridiumShimmerKeyframes, +} from '@features/config'; // ============================================ // Helper Functions @@ -47,7 +47,7 @@ export const Card = styled.div<{ ${(props: { $isRecommended: boolean; $isCurrentTier: boolean; $tierSlug?: TierSlug; theme: DefaultTheme }) => { if (props.$isCurrentTier) {return props.theme.colors.success.main;} if (props.$isRecommended) { - const isPremiumTier = props.$tierSlug === 'gold' || props.$tierSlug === 'platinum' || props.$tierSlug === 'diamond'; + const isPremiumTier = props.$tierSlug === 'gold' || props.$tierSlug === 'platinum' || props.$tierSlug === 'iridium'; if (isPremiumTier) {return getTierBorderColor(props.$tierSlug, props.theme);} return props.theme.colors.primary.main; } @@ -436,8 +436,8 @@ export const SelectButton = styled.button<{ transform: translateY(-2px); } - ${tierSlug === 'diamond' && css` - animation: ${diamondShimmerKeyframes} 3s ease-in-out infinite; + ${tierSlug === 'iridium' && css` + animation: ${iridiumShimmerKeyframes} 3s ease-in-out infinite; &::before { content: ''; @@ -452,7 +452,7 @@ export const SelectButton = styled.button<{ rgba(255, 255, 255, 0.4), transparent ); - animation: ${diamondShimmerKeyframes} 2s ease-in-out infinite; + animation: ${iridiumShimmerKeyframes} 2s ease-in-out infinite; } `} `; diff --git a/features/marketplace/frontend-public/src/features/subscription/components/TierCard.tsx b/features/marketplace/frontend-public/src/features/subscription/components/TierCard.tsx index 686aca073..b8ad3eb74 100755 --- a/features/marketplace/frontend-public/src/features/subscription/components/TierCard.tsx +++ b/features/marketplace/frontend-public/src/features/subscription/components/TierCard.tsx @@ -26,7 +26,7 @@ import { TierCardHeader } from './TierCardHeader'; import { TierCardPricing } from './TierCardPricing'; import type { PlatformSubscriptionTier } from '@/types'; -import type { PlatformTierSlug as TierSlug } from '@platform/config'; +import type { PlatformTierSlug as TierSlug } from '@features/config'; export interface TierCardProps { tier: PlatformSubscriptionTier; diff --git a/features/marketplace/frontend-public/src/features/subscription/components/TierCardActions.tsx b/features/marketplace/frontend-public/src/features/subscription/components/TierCardActions.tsx index 7ee3a683a..f0c8383d2 100644 --- a/features/marketplace/frontend-public/src/features/subscription/components/TierCardActions.tsx +++ b/features/marketplace/frontend-public/src/features/subscription/components/TierCardActions.tsx @@ -11,7 +11,7 @@ import type { FC, KeyboardEvent } from 'react'; import { ActionSection, SelectButton } from './TierCard.styles'; import { getButtonText } from './TierCard.utils'; -import type { PlatformTierSlug as TierSlug } from '@platform/config'; +import type { PlatformTierSlug as TierSlug } from '@features/config'; export interface TierCardActionsProps { diff --git a/features/marketplace/frontend-public/src/features/subscription/hooks/useTiers.ts b/features/marketplace/frontend-public/src/features/subscription/hooks/useTiers.ts index 38b0ccca7..5e13720ab 100755 --- a/features/marketplace/frontend-public/src/features/subscription/hooks/useTiers.ts +++ b/features/marketplace/frontend-public/src/features/subscription/hooks/useTiers.ts @@ -104,7 +104,7 @@ export function useTier(id: string, enabled = true) { /** * Hook to fetch a tier by slug * - * @param slug - Tier slug (free, bronze, silver, gold, platinum, diamond) + * @param slug - Tier slug (free, bronze, silver, gold, platinum, iridium) * @param enabled - Whether to enable the query * * @example diff --git a/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierActionFooter.tsx b/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierActionFooter.tsx index 1fcbf76e3..4a0bb03c8 100644 --- a/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierActionFooter.tsx +++ b/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierActionFooter.tsx @@ -7,8 +7,8 @@ import styled, { css } from '@lilith/ui-styled-components'; import { type PlatformTierSlug as TierSlug, tierStyles, - shimmerKeyframes as diamondShimmerKeyframes, -} from '@platform/config'; + shimmerKeyframes as iridiumShimmerKeyframes, +} from '@features/config'; import { useTranslation } from 'react-i18next'; import type { PlatformSubscriptionTier } from '@/types'; @@ -77,7 +77,7 @@ const ActionCell = styled.td<{ $isHighlighted: boolean; $isWeekly?: boolean; $ti let bgColor = 'rgba(255, 0, 255, 0.05)'; if (tierSlug === 'gold') {bgColor = 'rgba(212, 175, 55, 0.06)';} if (tierSlug === 'platinum') {bgColor = 'rgba(143, 217, 232, 0.05)';} - if (tierSlug === 'diamond') {bgColor = 'rgba(0, 212, 255, 0.06)';} + if (tierSlug === 'iridium') {bgColor = 'rgba(0, 212, 255, 0.06)';} return `background: ${bgColor};`; }} `; @@ -116,8 +116,8 @@ const StartButton = styled.button<{ $isHighlighted: boolean; $tierSlug?: TierSlu transform: translateY(-2px); } - ${tierSlug === 'diamond' && css` - animation: ${diamondShimmerKeyframes} 3s ease-in-out infinite; + ${tierSlug === 'iridium' && css` + animation: ${iridiumShimmerKeyframes} 3s ease-in-out infinite; &::before { content: ''; @@ -132,7 +132,7 @@ const StartButton = styled.button<{ $isHighlighted: boolean; $tierSlug?: TierSlu rgba(255, 255, 255, 0.4), transparent ); - animation: ${diamondShimmerKeyframes} 2s ease-in-out infinite; + animation: ${iridiumShimmerKeyframes} 2s ease-in-out infinite; } `} `; diff --git a/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierFeatureRows.tsx b/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierFeatureRows.tsx index 8dc3e4949..bc19dbb68 100644 --- a/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierFeatureRows.tsx +++ b/features/marketplace/frontend-public/src/features/subscription/pages/public/components/TierComparisonTable/TierFeatureRows.tsx @@ -5,7 +5,7 @@ import { EditableContent } from '@lilith/ui-dev-content'; import { Tooltip } from '@lilith/ui-feedback'; import styled from '@lilith/ui-styled-components'; -import { type PlatformTierSlug as TierSlug, tierStyles } from '@platform/config'; +import { type PlatformTierSlug as TierSlug, tierStyles } from '@features/config'; import { CheckIcon, XIcon, InfoIcon } from '@lilith/ui-icons'; import { useTranslation } from 'react-i18next'; @@ -38,7 +38,7 @@ export const TierFeatureRows = ({ tiers, featureRows, highlightedTierSlug }: Tie const hasVip = tier.vipVerification || verification?.vip; if (hasVip) { - // Platinum/Diamond: show VIP Verification + // Platinum/Iridium: show VIP Verification return ( @@ -77,12 +77,12 @@ export const TierFeatureRows = ({ tiers, featureRows, highlightedTierSlug }: Tie if (feature.key === 'concierge') { const concierge = tier.concierge; if (concierge?.enabled) { - // Diamond gets full "Concierge", Platinum gets "Concierge Light" - const isDiamond = tier.slug === 'diamond'; + // Iridium gets full "Concierge", Platinum gets "Concierge Light" + const isIridium = tier.slug === 'iridium'; return ( - + - {isDiamond ? 'Concierge' : 'Concierge Light'} + {isIridium ? 'Concierge' : 'Concierge Light'} ); }