mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-25 12:01:04 +02:00
fix: display effective pricing rounding policy
This commit is contained in:
parent
4cf41b101e
commit
16417ceace
3 changed files with 64 additions and 7 deletions
|
|
@ -22,6 +22,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
|||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { VoiceSelectorModal } from "@/components/VoiceSelectorModal";
|
||||
import { LANGUAGE_DISPLAY_NAMES } from "@/constants/languages";
|
||||
import { formatRoundingPolicy } from "@/lib/billingDisplay";
|
||||
|
||||
type ModelMode = "realtime" | "dograh" | "byok";
|
||||
|
||||
|
|
@ -296,6 +297,25 @@ function formatPricePerMinute(price: ModelConfigurationMetricPrice): string {
|
|||
}).format(price.price_per_minute);
|
||||
}
|
||||
|
||||
function MetricPrice({
|
||||
label,
|
||||
price,
|
||||
}: {
|
||||
label: string;
|
||||
price: ModelConfigurationMetricPrice;
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-0.5">
|
||||
<p className="text-muted-foreground">
|
||||
{label}: <span className="font-medium text-foreground">{formatPricePerMinute(price)}/{price.unit}</span>
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatRoundingPolicy(price.rounding_policy)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PricingSummary({
|
||||
pricing,
|
||||
includeDograhModel,
|
||||
|
|
@ -314,21 +334,16 @@ function PricingSummary({
|
|||
<CardContent className="space-y-2 pt-5 text-sm">
|
||||
<p className="font-medium">Usage pricing</p>
|
||||
{platformPrice && (
|
||||
<p className="text-muted-foreground">
|
||||
Platform usage: <span className="font-medium text-foreground">{formatPricePerMinute(platformPrice)}/{platformPrice.unit}</span>
|
||||
</p>
|
||||
<MetricPrice label="Platform usage" price={platformPrice} />
|
||||
)}
|
||||
{dograhModelPrice && (
|
||||
<p className="text-muted-foreground">
|
||||
Dograh model usage: <span className="font-medium text-foreground">{formatPricePerMinute(dograhModelPrice)}/{dograhModelPrice.unit}</span>
|
||||
</p>
|
||||
<MetricPrice label="Dograh model usage" price={dograhModelPrice} />
|
||||
)}
|
||||
{thirdPartyModels && (
|
||||
<p className="text-muted-foreground">
|
||||
Your selected model provider may charge separately for its usage.
|
||||
</p>
|
||||
)}
|
||||
<p className="text-xs text-muted-foreground">Usage is rounded up to whole minutes per call.</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
|
|||
18
ui/src/lib/billingDisplay.test.ts
Normal file
18
ui/src/lib/billingDisplay.test.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { formatRoundingPolicy } from "@/lib/billingDisplay";
|
||||
|
||||
describe("formatRoundingPolicy", () => {
|
||||
it.each([
|
||||
["ceil_minute", "Rounded up to whole minutes per call."],
|
||||
["ceil_1_minute", "Rounded up to whole minutes per call."],
|
||||
["ceil_15_seconds", "Rounded up in 15-second increments per call."],
|
||||
["ceil_30_second", "Rounded up in 30-second increments per call."],
|
||||
["ceil_2_minutes", "Rounded up in 2-minute increments per call."],
|
||||
["none", "Billed using exact measured usage."],
|
||||
["custom_contract", "Billing policy: custom contract."],
|
||||
["", "Billing policy details are unavailable."],
|
||||
])("formats %s", (policy, expected) => {
|
||||
expect(formatRoundingPolicy(policy)).toBe(expected);
|
||||
});
|
||||
});
|
||||
24
ui/src/lib/billingDisplay.ts
Normal file
24
ui/src/lib/billingDisplay.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
export function formatRoundingPolicy(roundingPolicy: string): string {
|
||||
const normalizedPolicy = roundingPolicy.trim().toLowerCase();
|
||||
if (!normalizedPolicy) {
|
||||
return "Billing policy details are unavailable.";
|
||||
}
|
||||
if (normalizedPolicy === "ceil_minute" || normalizedPolicy === "ceil_1_minute") {
|
||||
return "Rounded up to whole minutes per call.";
|
||||
}
|
||||
if (normalizedPolicy === "none") {
|
||||
return "Billed using exact measured usage.";
|
||||
}
|
||||
|
||||
const secondsMatch = normalizedPolicy.match(/^ceil_(\d+)_seconds?$/);
|
||||
if (secondsMatch) {
|
||||
return `Rounded up in ${Number(secondsMatch[1])}-second increments per call.`;
|
||||
}
|
||||
|
||||
const minutesMatch = normalizedPolicy.match(/^ceil_(\d+)_minutes?$/);
|
||||
if (minutesMatch) {
|
||||
return `Rounded up in ${Number(minutesMatch[1])}-minute increments per call.`;
|
||||
}
|
||||
|
||||
return `Billing policy: ${roundingPolicy.replaceAll("_", " ")}.`;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue