Files
billing/app/commerce/components/billing-toggle.tsx
zeekay d41f2b6a0e feat: add commerce landing page with plans, coupons, referrals
- app/commerce/page.tsx: server-rendered landing page; fetches plans from
  pricing.hanzo.ai/v1/pricing/subscriptions (ISR 1h), falls back to
  hardcoded plans; renders hero, stats row, plan cards, feature grid,
  referral section, and footer
- app/commerce/components/plan-card.tsx: plan card with monthly/annual
  pricing, popular badge, feature list, idle-resale payout callout, CTA
  linking to billing.hanzo.ai or cal.com/hanzo for Enterprise
- app/commerce/components/billing-toggle.tsx: client toggle for
  monthly/annual interval; renders PlanCard grid
- app/commerce/components/coupon-input.tsx: client coupon field with
  optimistic validation against commerce API
- app/commerce/components/referral-section.tsx: affiliate sign-up form
  (20% recurring commission copy + email capture)
- k8s/deployment.yaml: add commerce.hanzo.ai host to ingress TLS + rules
  pointing to existing billing service
2026-03-01 15:39:02 -08:00

77 lines
2.3 KiB
TypeScript

'use client'
import { useState } from 'react'
import { PlanCard, type PricingPlan } from './plan-card'
interface BillingToggleProps {
plans: PricingPlan[]
}
export function BillingToggle({ plans }: BillingToggleProps) {
const [interval, setInterval] = useState<'monthly' | 'annual'>('monthly')
return (
<>
{/* Toggle */}
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: '40px' }}>
<div style={{
display: 'inline-flex',
background: 'rgba(255,255,255,0.04)',
border: '1px solid rgba(255,255,255,0.1)',
borderRadius: '10px',
padding: '4px',
gap: '4px',
}}>
{(['monthly', 'annual'] as const).map((iv) => (
<button
key={iv}
type="button"
onClick={() => setInterval(iv)}
style={{
background: interval === iv ? 'rgba(255,255,255,0.1)' : 'transparent',
border: interval === iv ? '1px solid rgba(255,255,255,0.15)' : '1px solid transparent',
borderRadius: '7px',
padding: '6px 16px',
color: interval === iv ? '#fafafa' : 'rgba(255,255,255,0.4)',
fontSize: '13px',
fontWeight: 500,
cursor: 'pointer',
transition: 'all 0.15s',
display: 'flex',
alignItems: 'center',
gap: '6px',
}}
>
{iv === 'monthly' ? 'Monthly' : 'Annual'}
{iv === 'annual' && (
<span style={{
background: 'rgba(74,222,128,0.15)',
color: '#4ade80',
fontSize: '10px',
fontWeight: 700,
padding: '1px 5px',
borderRadius: '4px',
letterSpacing: '0.03em',
}}>
Save 20%
</span>
)}
</button>
))}
</div>
</div>
{/* Plans grid */}
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))',
gap: '20px',
}}>
{plans.map((plan) => (
<PlanCard key={plan.id} plan={plan} billingInterval={interval} />
))}
</div>
</>
)
}