mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-04 05:12:38 +02:00
feat: unified credits and its cost calculations
This commit is contained in:
parent
451a98936e
commit
ae9d36d77f
61 changed files with 5835 additions and 272 deletions
|
|
@ -127,7 +127,7 @@ const FAQ_ITEMS = [
|
|||
{
|
||||
question: "What happens after I use my free tokens?",
|
||||
answer:
|
||||
"After your free tokens, create a free SurfSense account to unlock 3 million more premium tokens. Additional tokens can be purchased at $1 per million. Non-premium models remain unlimited for registered users.",
|
||||
"After your free tokens, create a free SurfSense account to unlock $5 of premium credit. Additional credit can be topped up at $1 for $1 of credit, billed at the actual provider cost. Non-premium models remain unlimited for registered users.",
|
||||
},
|
||||
{
|
||||
question: "Is Claude AI available without login?",
|
||||
|
|
@ -329,7 +329,7 @@ export default async function FreeHubPage() {
|
|||
<section className="max-w-3xl mx-auto text-center">
|
||||
<h2 className="text-2xl font-bold mb-3">Want More Features?</h2>
|
||||
<p className="text-muted-foreground mb-6 leading-relaxed">
|
||||
Create a free SurfSense account to unlock 3 million tokens, document uploads with
|
||||
Create a free SurfSense account to unlock $5 of premium credit, document uploads with
|
||||
citations, team collaboration, and integrations with Slack, Google Drive, Notion, and
|
||||
30+ more tools.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
|||
export const metadata: Metadata = {
|
||||
title: "Pricing | SurfSense - Free AI Search Plans",
|
||||
description:
|
||||
"Explore SurfSense plans and pricing. Start free with 500 pages & 3M premium tokens. Use ChatGPT, Claude AI, and premium AI models. Pay-as-you-go tokens at $1 per million.",
|
||||
"Explore SurfSense plans and pricing. Start free with 500 pages & $5 of premium credit. Use ChatGPT, Claude AI, and premium AI models. Pay as you go at provider cost — $1 buys $1 of credit.",
|
||||
alternates: {
|
||||
canonical: "https://surfsense.com/pricing",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { cn } from "@/lib/utils";
|
|||
|
||||
const TABS = [
|
||||
{ id: "pages", label: "Pages" },
|
||||
{ id: "tokens", label: "Premium Tokens" },
|
||||
{ id: "tokens", label: "Premium Credit" },
|
||||
] as const;
|
||||
|
||||
type TabId = (typeof TABS)[number]["id"];
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ type UnifiedPurchase = {
|
|||
kind: PurchaseKind;
|
||||
created_at: string;
|
||||
status: PagePurchaseStatus;
|
||||
/**
|
||||
* Granted units. Interpretation depends on ``kind``:
|
||||
* - ``"pages"`` — integer number of indexed pages.
|
||||
* - ``"tokens"`` — integer micro-USD of credit (1_000_000 = $1.00).
|
||||
* The ``Granted`` column formats accordingly.
|
||||
*/
|
||||
granted: number;
|
||||
amount_total: number | null;
|
||||
currency: string | null;
|
||||
|
|
@ -58,7 +64,7 @@ const KIND_META: Record<
|
|||
iconClass: "text-sky-500",
|
||||
},
|
||||
tokens: {
|
||||
label: "Premium Tokens",
|
||||
label: "Premium Credit",
|
||||
icon: Coins,
|
||||
iconClass: "text-amber-500",
|
||||
},
|
||||
|
|
@ -97,12 +103,25 @@ function normalizeTokenPurchase(p: TokenPurchase): UnifiedPurchase {
|
|||
kind: "tokens",
|
||||
created_at: p.created_at,
|
||||
status: p.status,
|
||||
granted: p.tokens_granted,
|
||||
granted: p.credit_micros_granted,
|
||||
amount_total: p.amount_total,
|
||||
currency: p.currency,
|
||||
};
|
||||
}
|
||||
|
||||
function formatGranted(p: UnifiedPurchase): string {
|
||||
if (p.kind === "tokens") {
|
||||
const dollars = p.granted / 1_000_000;
|
||||
// Premium credit packs are always whole dollars at the moment, but
|
||||
// future fractional grants (refunds, partial top-ups) shouldn't
|
||||
// silently round to "$0".
|
||||
if (dollars >= 1) return `$${dollars.toFixed(2)} of credit`;
|
||||
if (dollars > 0) return `$${dollars.toFixed(3)} of credit`;
|
||||
return "$0 of credit";
|
||||
}
|
||||
return p.granted.toLocaleString();
|
||||
}
|
||||
|
||||
export function PurchaseHistoryContent() {
|
||||
const results = useQueries({
|
||||
queries: [
|
||||
|
|
@ -143,7 +162,7 @@ export function PurchaseHistoryContent() {
|
|||
<ReceiptText className="h-8 w-8 text-muted-foreground" />
|
||||
<p className="text-sm font-medium">No purchases yet</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Your page and premium token purchases will appear here after checkout.
|
||||
Your page and premium credit purchases will appear here after checkout.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -177,7 +196,7 @@ export function PurchaseHistoryContent() {
|
|||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="text-right tabular-nums text-sm">
|
||||
{p.granted.toLocaleString()}
|
||||
{formatGranted(p)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right tabular-nums text-sm">
|
||||
{formatAmount(p.amount_total, p.currency)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue