'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useAuth } from '@/lib/hooks/useAuth'; import { authApi } from '@/lib/api/auth'; import type { SubscriptionAlertData } from '@/types/subscription'; const PLAN_OPTIONS = [ { id: 'solo', name: 'Solo', maxUsers: 1, price: 19 }, { id: 'small', name: 'Small', maxUsers: 5, price: 49 }, { id: 'medium', name: 'Medium', maxUsers: 10, price: 89 }, { id: 'large', name: 'Large', maxUsers: 15, price: 129 }, { id: 'enterprise', name: 'Enterprise', maxUsers: null, price: 199 }, ] as const; export default function SubscriptionsSettingsPage() { const { currentOrganization } = useAuth(); const router = useRouter(); const [alert, setAlert] = useState(null); const [selectedPlanId, setSelectedPlanId] = useState(PLAN_OPTIONS[0].id); const [purchaseNotice, setPurchaseNotice] = useState(null); useEffect(() => { if (currentOrganization && !currentOrganization.isOwner) { router.replace('/today'); } }, [currentOrganization, router]); useEffect(() => { if (!currentOrganization?.isOwner) return; void authApi.getSubscriptionAlert().then((r) => { if (r.success) setAlert(r.data); }); }, [currentOrganization?.id, currentOrganization?.isOwner]); if (!currentOrganization) { return (

Loading...

); } if (!currentOrganization.isOwner) { return (

Redirecting...

); } const plan = currentOrganization.plan; const hasActiveSubscription = Boolean(plan); const selectedPlan = PLAN_OPTIONS.find((option) => option.id === selectedPlanId); const maxUsers = plan?.maxUsers; const isUnlimited = typeof maxUsers === 'number' && maxUsers >= 999999; const seatsUsed = alert?.seatsUsed; const seatsRemaining = typeof seatsUsed === 'number' && typeof maxUsers === 'number' && !isUnlimited ? Math.max(0, maxUsers - seatsUsed) : null; const daysUntilPlanEnd = alert?.daysUntilPlanEnd ?? null; const planDayTone = daysUntilPlanEnd == null ? 'text-text-primary' : daysUntilPlanEnd > 20 ? 'text-emerald-400' : daysUntilPlanEnd >= 10 ? 'text-amber-300' : 'text-red-400'; return (
← Back to app

Subscriptions

Your DyoLink workspace plan and seats for{' '} {currentOrganization.name}. Clinic and lab income tracking stays under the sidebar{' '} Billing tab.

{!hasActiveSubscription && (

This organization has no active subscription. Select a plan below to start the purchase process.

)}

Current plan

{plan?.name ?? '—'}

Plan price

{typeof plan?.price === 'number' ? `$${plan.price}` : '—'}

Seats used

{typeof seatsUsed === 'number' ? seatsUsed : '—'} {typeof maxUsers === 'number' ? ` / ${isUnlimited ? 'Unlimited' : maxUsers}` : ''}

Seats remaining

{isUnlimited ? 'Unlimited' : seatsRemaining ?? '—'}

Days remaining

{daysUntilPlanEnd ?? '—'}

{alert?.showWarning && (
{alert.noActiveSubscription && (

No active subscription for this organization.

)} {alert.trialExpired && (

Trial period has ended. Choose a plan when checkout is available.

)} {!alert.trialExpired && alert.trialEndingSoon && (

Trial ends in {alert.daysUntilTrialEnd ?? '—'} day(s).

)} {!alert.trialExpired && !alert.trialEndingSoon && alert.seatsLow && (

Seat usage is high for this organization.

)}
)}

Choose a plan to continue. Purchase integration is not active yet, so this currently prepares the selection step only.

{PLAN_OPTIONS.map((option) => { const selected = selectedPlanId === option.id; return ( ); })}
{purchaseNotice && (

{purchaseNotice}

)}
); }