Spaces:
Running
Running
| import { createClient } from "@/lib/supabase/server"; | |
| import { SubmitButton } from "../ui/submit-button"; | |
| import { manageSubscription } from "@/lib/actions/billing"; | |
| import { PlanComparison, SUBSCRIPTION_PLANS } from "../billing/plan-comparison"; | |
| import { isLocalMode } from "@/lib/config"; | |
| type Props = { | |
| accountId: string; | |
| returnUrl: string; | |
| } | |
| export default async function AccountBillingStatus({ accountId, returnUrl }: Props) { | |
| // In local development mode, show a simplified component | |
| if (isLocalMode()) { | |
| return ( | |
| <div className="rounded-xl border shadow-sm bg-card p-6"> | |
| <h2 className="text-xl font-semibold mb-4">Billing Status</h2> | |
| <div className="p-4 mb-4 bg-muted/30 border border-border rounded-lg text-center"> | |
| <p className="text-sm text-muted-foreground"> | |
| Running in local development mode - billing features are disabled | |
| </p> | |
| <p className="text-xs text-muted-foreground mt-2"> | |
| Agent usage limits are not enforced in this environment | |
| </p> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| const supabaseClient = await createClient(); | |
| // Get account subscription and usage data | |
| const { data: subscriptionData } = await supabaseClient | |
| .schema('basejump') | |
| .from('billing_subscriptions') | |
| .select('*') | |
| .eq('account_id', accountId) | |
| .eq('status', 'active') | |
| .limit(1) | |
| .order('created_at', { ascending: false }) | |
| .single(); | |
| // Get agent runs for this account | |
| // Get the account's threads | |
| const { data: threads } = await supabaseClient | |
| .from('threads') | |
| .select('thread_id') | |
| .eq('account_id', accountId); | |
| const threadIds = threads?.map(t => t.thread_id) || []; | |
| // Get current month usage | |
| const now = new Date(); | |
| const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); | |
| const isoStartOfMonth = startOfMonth.toISOString(); | |
| let totalAgentTime = 0; | |
| let usageDisplay = "No usage this month"; | |
| if (threadIds.length > 0) { | |
| const { data: agentRuns } = await supabaseClient | |
| .from('agent_runs') | |
| .select('started_at, completed_at') | |
| .in('thread_id', threadIds) | |
| .gte('started_at', isoStartOfMonth); | |
| if (agentRuns && agentRuns.length > 0) { | |
| const nowTimestamp = now.getTime(); | |
| totalAgentTime = agentRuns.reduce((total, run) => { | |
| const startTime = new Date(run.started_at).getTime(); | |
| const endTime = run.completed_at | |
| ? new Date(run.completed_at).getTime() | |
| : nowTimestamp; | |
| return total + (endTime - startTime) / 1000; // In seconds | |
| }, 0); | |
| // Convert to minutes | |
| const totalMinutes = Math.round(totalAgentTime / 60); | |
| usageDisplay = `${totalMinutes} minutes`; | |
| } | |
| } | |
| const isPlan = (planId?: string) => { | |
| return subscriptionData?.price_id === planId; | |
| }; | |
| const planName = isPlan(SUBSCRIPTION_PLANS.FREE) | |
| ? "Free" | |
| : isPlan(SUBSCRIPTION_PLANS.PRO) | |
| ? "Pro" | |
| : isPlan(SUBSCRIPTION_PLANS.ENTERPRISE) | |
| ? "Enterprise" | |
| : "Unknown"; | |
| return ( | |
| <div className="rounded-xl border shadow-sm bg-card p-6"> | |
| <h2 className="text-xl font-semibold mb-4">Billing Status</h2> | |
| {subscriptionData ? ( | |
| <> | |
| <div className="mb-6"> | |
| <div className="rounded-lg border bg-background p-4 grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <div className="flex justify-between items-center"> | |
| <span className="text-sm font-medium text-foreground/90">Current Plan</span> | |
| <span className="text-sm font-medium text-card-title">{planName}</span> | |
| </div> | |
| </div> | |
| <div className="flex justify-between items-center"> | |
| <span className="text-sm font-medium text-foreground/90">Agent Usage This Month</span> | |
| <span className="text-sm font-medium text-card-title">{usageDisplay}</span> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Plans Comparison */} | |
| <PlanComparison | |
| accountId={accountId} | |
| returnUrl={returnUrl} | |
| className="mb-6" | |
| /> | |
| {/* Manage Subscription Button */} | |
| <form> | |
| <input type="hidden" name="accountId" value={accountId} /> | |
| <input type="hidden" name="returnUrl" value={returnUrl} /> | |
| <SubmitButton | |
| pendingText="Loading..." | |
| formAction={manageSubscription} | |
| className="w-full bg-primary text-white hover:bg-primary/90 shadow-md hover:shadow-lg transition-all" | |
| > | |
| Manage Subscription | |
| </SubmitButton> | |
| </form> | |
| </> | |
| ) : ( | |
| <> | |
| <div className="mb-6"> | |
| <div className="rounded-lg border bg-background p-4 gap-4"> | |
| <div className="flex justify-between items-center"> | |
| <span className="text-sm font-medium text-foreground/90">Current Plan</span> | |
| <span className="text-sm font-medium text-card-title">Free</span> | |
| </div> | |
| <div className="flex justify-between items-center"> | |
| <span className="text-sm font-medium text-foreground/90">Agent Usage This Month</span> | |
| <span className="text-sm font-medium text-card-title">{usageDisplay}</span> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Plans Comparison */} | |
| <PlanComparison | |
| accountId={accountId} | |
| returnUrl={returnUrl} | |
| className="mb-6" | |
| /> | |
| {/* Manage Subscription Button */} | |
| <form> | |
| <input type="hidden" name="accountId" value={accountId} /> | |
| <input type="hidden" name="returnUrl" value={returnUrl} /> | |
| <SubmitButton | |
| pendingText="Loading..." | |
| formAction={manageSubscription} | |
| className="w-full bg-primary text-white hover:bg-primary/90 shadow-md hover:shadow-lg transition-all" | |
| > | |
| Manage Subscription | |
| </SubmitButton> | |
| </form> | |
| </> | |
| )} | |
| </div> | |
| ) | |
| } | |