Skip to content

Commit 1b9733a

Browse files
authored
@ (#15)
Standardize pricing + wire real Analytics/Usage pages Pricing: new lib/pricing.ts is the single source of truth for the tier ladder (free/pro/scale/enterprise) with the agreed numbers (pro 500 docs/20 GB, scale $99 5,000 docs/100 GB). The marketing Pricing section and the dashboard billing page both render from it, so the site, the app, and the CP quota plans can no longer drift. Adds the Scale tier and a 4-up grid on both surfaces. Analytics + Usage (were fully mocked): both pages now fetch real data. - /api/dashboard/analytics and /api/dashboard/usage proxy to the CP analytics + quota endpoints for the caller org. - Analytics: live summary (requests, success rate, avg latency, tokens), usage-by-source breakdown, daily request-volume chart, and a recent- calls feed with per-request source attribution. - Usage: real quota meters (queries / documents / tokens), usage-by- source bars, and plan ceilings derived from lib/pricing.ts. - lib/usage-sources.ts gives web/sdk/mcp/api consistent labels + colours (no purple, per brand). @
1 parent b30b0ee commit 1b9733a

9 files changed

Lines changed: 903 additions & 461 deletions

File tree

apps/web/app/(dashboard)/dashboard/analytics/page.tsx

Lines changed: 307 additions & 128 deletions
Large diffs are not rendered by default.

apps/web/app/(dashboard)/dashboard/billing/page.tsx

Lines changed: 18 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -12,89 +12,27 @@ import {
1212
import { Button } from "@/components/ui/button";
1313
import { Badge } from "@/components/ui/badge";
1414
import { Separator } from "@/components/ui/separator";
15-
import { Check, CreditCard, Sparkles, Building2 } from "lucide-react";
15+
import { Check, CreditCard, Sparkles, Building2, Zap } from "lucide-react";
1616
import { useSession } from "@/lib/auth-client";
17+
import { PLANS, type Plan } from "@/lib/pricing";
1718

18-
interface PlanFeature {
19-
label: string;
20-
included: boolean;
21-
}
19+
const PLAN_ICONS: Record<string, React.ReactNode> = {
20+
free: <Sparkles className="h-5 w-5" />,
21+
pro: <CreditCard className="h-5 w-5" />,
22+
scale: <Zap className="h-5 w-5" />,
23+
enterprise: <Building2 className="h-5 w-5" />,
24+
};
2225

23-
interface PlanCard {
24-
key: string;
25-
name: string;
26-
price: string;
27-
period: string;
28-
description: string;
29-
features: PlanFeature[];
30-
cta: string;
31-
popular?: boolean;
32-
icon: React.ReactNode;
26+
function ctaFor(key: string, current: string): string {
27+
if (key === current) return "Current Plan";
28+
if (key === "enterprise") return "Contact Sales";
29+
return `Upgrade to ${PLANS.find((p) => p.key === key)?.name ?? key}`;
3330
}
3431

35-
const plans: PlanCard[] = [
36-
{
37-
key: "free",
38-
name: "Free",
39-
price: "$0",
40-
period: "forever",
41-
description: "Perfect for exploring Vectorless and building prototypes.",
42-
icon: <Sparkles className="h-5 w-5" />,
43-
features: [
44-
{ label: "500 queries / month", included: true },
45-
{ label: "500 pages ingested / month", included: true },
46-
{ label: "25 documents stored", included: true },
47-
{ label: "100 MB storage", included: true },
48-
{ label: "20 queries / min rate limit", included: true },
49-
{ label: "Community support", included: true },
50-
{ label: "MCP server access", included: true },
51-
],
52-
cta: "Current Plan",
53-
},
54-
{
55-
key: "pro",
56-
name: "Pro",
57-
price: "$49",
58-
period: "/ month",
59-
description:
60-
"For teams and individuals using Vectorless in production.",
61-
icon: <CreditCard className="h-5 w-5" />,
62-
popular: true,
63-
features: [
64-
{ label: "20,000 queries / month", included: true },
65-
{ label: "10,000 pages ingested / month", included: true },
66-
{ label: "500 documents stored", included: true },
67-
{ label: "10 GB storage", included: true },
68-
{ label: "200 queries / min rate limit", included: true },
69-
{ label: "Priority email support", included: true },
70-
{ label: "OAuth app integrations", included: true },
71-
],
72-
cta: "Upgrade to Pro",
73-
},
74-
{
75-
key: "enterprise",
76-
name: "Enterprise",
77-
price: "Custom",
78-
period: "",
79-
description:
80-
"For organizations with custom requirements, SLAs, and dedicated support.",
81-
icon: <Building2 className="h-5 w-5" />,
82-
features: [
83-
{ label: "Unlimited queries", included: true },
84-
{ label: "Unlimited ingestion", included: true },
85-
{ label: "Unlimited documents", included: true },
86-
{ label: "Unlimited storage", included: true },
87-
{ label: "1,000 queries / min rate limit", included: true },
88-
{ label: "Dedicated support + SLA", included: true },
89-
{ label: "Custom integrations", included: true },
90-
],
91-
cta: "Contact Sales",
92-
},
93-
];
94-
9532
export default function BillingPage() {
9633
const { data: session } = useSession();
9734
const [currentPlan] = useState("free"); // TODO: Fetch from API
35+
const plans: Plan[] = PLANS;
9836

9937
return (
10038
<div className="space-y-6">
@@ -133,7 +71,7 @@ export default function BillingPage() {
13371
</Card>
13472

13573
{/* Plan Cards */}
136-
<div className="grid gap-6 md:grid-cols-3">
74+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
13775
{plans.map((plan) => {
13876
const isCurrent = plan.key === currentPlan;
13977

@@ -156,7 +94,7 @@ export default function BillingPage() {
15694

15795
<CardHeader className="text-center pt-8">
15896
<div className="mx-auto mb-2 flex h-10 w-10 items-center justify-center rounded-full bg-muted">
159-
{plan.icon}
97+
{PLAN_ICONS[plan.key]}
16098
</div>
16199
<CardTitle className="font-display text-xl">
162100
{plan.name}
@@ -181,13 +119,11 @@ export default function BillingPage() {
181119
<ul className="space-y-2.5">
182120
{plan.features.map((feature) => (
183121
<li
184-
key={feature.label}
122+
key={feature}
185123
className="flex items-start gap-2 text-sm"
186124
>
187125
<Check className="h-4 w-4 text-emerald-500 mt-0.5 shrink-0" />
188-
<span className="text-muted-foreground">
189-
{feature.label}
190-
</span>
126+
<span className="text-muted-foreground">{feature}</span>
191127
</li>
192128
))}
193129
</ul>
@@ -205,7 +141,7 @@ export default function BillingPage() {
205141
}
206142
disabled={isCurrent}
207143
>
208-
{isCurrent ? "Current Plan" : plan.cta}
144+
{ctaFor(plan.key, currentPlan)}
209145
</Button>
210146
</CardFooter>
211147
</Card>

0 commit comments

Comments
 (0)