diff --git a/.env.docker.dev b/.env.docker.dev index ce43a6f..8428360 100644 --- a/.env.docker.dev +++ b/.env.docker.dev @@ -33,11 +33,7 @@ CLERK_SECRET_KEY=placeholder NODE_ENV=development CORS_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:3002,http://localhost:4000,http://127.0.0.1:3000,http://127.0.0.1:3001,http://127.0.0.1:3002,http://127.0.0.1:4000 -# Stripe subscription checkout -# STRIPE_API_KEY must be a Stripe secret/restricted key (sk_ or rk_). -# STRIPE_WEBHOOK_SECRET must be a Stripe webhook signing secret (whsec_). -STRIPE_API_KEY=placeholder -STRIPE_WEBHOOK_SECRET=placeholder + # Email — Resend (primary) with SMTP fallback # Get your API key at https://resend.com/api-keys RESEND_API_KEY=re_PLACEHOLDER @@ -53,3 +49,10 @@ MAIL_FROM_ADDRESS=rentaldrivego@gmail.com MAIL_FROM_NAME=RentalDriveGo MAIL_REPLY_TO_ADDRESS=rentaldrivego@gmail.com MAIL_REPLY_TO_NAME=RentalDriveGo + + +# Stripe subscription checkout +# STRIPE_API_KEY must be a Stripe secret/restricted key (sk_ or rk_). +# STRIPE_WEBHOOK_SECRET must be a Stripe webhook signing secret (whsec_). +STRIPE_API_KEY=sk_test_51TvTsb9SpDRZn9yJyBAlUSXcTp9zpwQfhJYNKxfyYaZbqT6NN8W4pXu0zOUvpunrDPdtC0I6OZPzq0B5RRI1Ybub00OcYvj28K +STRIPE_WEBHOOK_SECRET=whsec_c5e0a6b2dd5e2f6ac804b428fe46f04e3af9b55c562f4124de20c52866f3c211 \ No newline at end of file diff --git a/apps/homepage/src/components/homepage/sections/PricingSection.module.css b/apps/homepage/src/components/homepage/sections/PricingSection.module.css index cbcd438..58896ca 100644 --- a/apps/homepage/src/components/homepage/sections/PricingSection.module.css +++ b/apps/homepage/src/components/homepage/sections/PricingSection.module.css @@ -14,14 +14,15 @@ margin-inline: auto; } +.pricingContainer { + inline-size: min(100%, 104rem); +} + .controls { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(16rem, 0.5fr); gap: var(--space-5); - position: relative; - left: 50%; - inline-size: min(100vw - (var(--layout-gutter) * 2), 104rem); - transform: translateX(-50%); + inline-size: 100%; padding: var(--space-5); border: 1px solid var(--border-standard); border-radius: var(--radius-lg); @@ -111,12 +112,9 @@ .planGrid { display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: stretch; - position: relative; - left: 50%; - inline-size: min(100vw - (var(--layout-gutter) * 2), 104rem); - transform: translateX(-50%); + inline-size: 100%; gap: var(--space-5); } diff --git a/apps/homepage/src/components/homepage/sections/PricingSection.tsx b/apps/homepage/src/components/homepage/sections/PricingSection.tsx index 74f750a..8372bca 100644 --- a/apps/homepage/src/components/homepage/sections/PricingSection.tsx +++ b/apps/homepage/src/components/homepage/sections/PricingSection.tsx @@ -33,7 +33,6 @@ interface PricingSectionProps { const accountSubscriptionPlanByPricingPlan: Record, AccountSubscriptionPlan> = { launch: 'STARTER', growth: 'GROWTH', - pro: 'PRO', }; function analyticsContext( @@ -105,7 +104,7 @@ export function PricingSection({ return (
- + { expect(content.modules.items).toHaveLength(6); expect(content.faq.items).toHaveLength(6); expect(content.pricing.fleetBands).toHaveLength(4); - expect(content.pricing.plans).toHaveLength(4); + expect(content.pricing.plans).toHaveLength(3); expect(content.hero.preview.rows).toHaveLength(2); }); diff --git a/apps/homepage/tests/unit/pricing-section.test.tsx b/apps/homepage/tests/unit/pricing-section.test.tsx index 427a507..3956a59 100644 --- a/apps/homepage/tests/unit/pricing-section.test.tsx +++ b/apps/homepage/tests/unit/pricing-section.test.tsx @@ -39,11 +39,11 @@ describe('PricingSection', () => { await user.click(screen.getByLabelText('76–150 vehicles')); - expect(container.querySelector('[data-plan="pro"]')).toHaveAttribute( + expect(container.querySelector('[data-plan="growth"]')).toHaveAttribute( 'data-recommended', 'true', ); - expect(container.querySelector('[data-plan="growth"]')).not.toHaveAttribute('data-recommended'); + expect(container.querySelector('[data-plan="launch"]')).not.toHaveAttribute('data-recommended'); }); it('renders approved public prices except for Enterprise custom pricing', async () => { @@ -62,15 +62,14 @@ describe('PricingSection', () => { expect(screen.queryByText('Starting price pending approval')).not.toBeInTheDocument(); expect(screen.getByText(/149/)).toBeInTheDocument(); expect(screen.getByText(/299/)).toBeInTheDocument(); - expect(screen.getByText(/399/)).toBeInTheDocument(); expect(screen.getByText('Custom pricing')).toBeInTheDocument(); await user.click(screen.getByLabelText(/Annual/)); expect(screen.getByText(/Save 20%/)).toBeInTheDocument(); expect(screen.getByText(/1,430/)).toBeInTheDocument(); - expect(screen.getAllByText('/ year')).toHaveLength(3); - expect(screen.getAllByText('billed annually after full-payment discount')).toHaveLength(3); + expect(screen.getAllByText('/ year')).toHaveLength(2); + expect(screen.getAllByText('billed annually after full-payment discount')).toHaveLength(2); }); it('links self-serve plan CTAs to account creation and opens a pricing form for Enterprise', () => { @@ -93,10 +92,6 @@ describe('PricingSection', () => { 'href', '/dashboard/sign-up?lang=en&theme=dark&plan=GROWTH', ); - expect(screen.getByRole('link', { name: 'Book a Pro demo' })).toHaveAttribute( - 'href', - '/dashboard/sign-up?lang=en&theme=dark&plan=PRO', - ); expect(screen.getByRole('button', { name: 'Talk to sales' })).toHaveAttribute( 'data-demo-source', 'pricing', diff --git a/apps/homepage/tests/unit/pricing.test.ts b/apps/homepage/tests/unit/pricing.test.ts index 1a58051..5055af3 100644 --- a/apps/homepage/tests/unit/pricing.test.ts +++ b/apps/homepage/tests/unit/pricing.test.ts @@ -11,8 +11,8 @@ describe('homepage pricing configuration', () => { expect(pricingCommercialConfig.annualDiscountPercent).toBe(20); expect(pricingCommercialConfig.monthlyPrices.launch.small).toBe(149); expect(pricingCommercialConfig.monthlyPrices.growth.growing).toBe(299); - expect(pricingCommercialConfig.monthlyPrices.pro.scale).toBe(399); expect(pricingCommercialConfig.monthlyPrices.enterprise.enterprise).toBeNull(); + expect(pricingCommercialConfig.recommendedPlanByFleetBand.scale).toBe('growth'); }); it('maps every fleet band and plan from localized content', () => { @@ -24,6 +24,6 @@ describe('homepage pricing configuration', () => { 'scale', 'enterprise', ]); - expect(pricing.plans.map((plan) => plan.id)).toEqual(['launch', 'growth', 'pro', 'enterprise']); + expect(pricing.plans.map((plan) => plan.id)).toEqual(['launch', 'growth', 'enterprise']); }); });