Skip to content

Commit 99bc4ff

Browse files
authored
Merge pull request #29 from Deal-Scale/codex/fix-dropdown-display-and-agent-modal
Fix agent modal dropdowns and monetization summary
2 parents 1b2d798 + 2adba50 commit 99bc4ff

9 files changed

Lines changed: 667 additions & 28 deletions

File tree

‎components/Sidebar/AgentModal.tsx‎

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import React, { useMemo, useState } from "react";
66
import { z } from "zod";
77

88
import AgentPreview from "./AgentPreview";
9+
import { AgentMonetizationSummary } from "./AgentMonetizationSummary";
910

1011
import { Button } from "@/components/ui/button";
1112
import {
@@ -28,6 +29,7 @@ import {
2829
useKnowledgeBaseOptionsQuery,
2930
} from "@/data/options";
3031
import { AgentConfigSchema } from "@/lib/schemas/agent";
32+
import { getAgentUsageProfile } from "@/lib/agents/monetization";
3133
import {
3234
Tooltip,
3335
TooltipContent,
@@ -247,6 +249,26 @@ export default function AgentModal(props: {
247249
const monetizationEnabled = isCreate
248250
? Boolean(form.watch("monetize" as any))
249251
: false;
252+
const roleValue = isCreate
253+
? (form.watch("role" as any) as string | undefined)
254+
: undefined;
255+
const multiplierValueRaw = isCreate
256+
? form.watch("rateMultiplier" as any)
257+
: undefined;
258+
const multiplierValue = Number(multiplierValueRaw ?? 1) || 1;
259+
const usageProfile = React.useMemo(
260+
() => getAgentUsageProfile(roleValue),
261+
[roleValue],
262+
);
263+
const currencyFormatter = React.useMemo(
264+
() =>
265+
new Intl.NumberFormat("en-US", {
266+
style: "currency",
267+
currency: usageProfile.currency,
268+
maximumFractionDigits: 2,
269+
}),
270+
[usageProfile.currency],
271+
);
250272

251273
const fields = useMemo(() => {
252274
const base: FieldsConfig<Record<string, unknown>> & Record<string, any> = {
@@ -423,14 +445,25 @@ export default function AgentModal(props: {
423445
};
424446

425447
if (isCreate) {
426-
base.monetize = { label: "Enable Monetization" };
448+
const baseRateText = currencyFormatter.format(usageProfile.baseAmount);
449+
base.monetize = {
450+
label: "Enable Monetization",
451+
widget: "switch",
452+
helpText: monetizationEnabled
453+
? "Monetized agents become eligible for payouts."
454+
: "Switch on to price this agent and enable payouts.",
455+
};
427456
base.rateMultiplier = {
428457
label: "Rate Multiplier",
429458
widget: "select",
430459
options: RATE_MULTIPLIER_OPTIONS,
431460
placeholder: monetizationEnabled
432461
? undefined
433462
: "Enable monetization first",
463+
disabled: !monetizationEnabled,
464+
helpText: monetizationEnabled
465+
? `Applies to the ${usageProfile.label.toLowerCase()} base of ${baseRateText}.`
466+
: `Current base for ${usageProfile.label.toLowerCase()}: ${baseRateText}.`,
434467
};
435468
}
436469

@@ -442,6 +475,9 @@ export default function AgentModal(props: {
442475
mcpServerOptions,
443476
monetizationEnabled,
444477
isCreate,
478+
currencyFormatter,
479+
usageProfile.baseAmount,
480+
usageProfile.label,
445481
]);
446482

447483
return (
@@ -506,8 +542,9 @@ export default function AgentModal(props: {
506542
</TooltipTrigger>
507543
<TooltipContent>
508544
<p className="max-w-xs text-xs">
509-
To monetize your agent, multiply by the current base
510-
agent rate.
545+
{`Base ${usageProfile.label.toLowerCase()} rate: ${currencyFormatter.format(
546+
usageProfile.baseAmount,
547+
)}. Multipliers scale your payout per active session.`}
511548
</p>
512549
</TooltipContent>
513550
</Tooltip>
@@ -559,6 +596,13 @@ export default function AgentModal(props: {
559596
onOpenChange(false);
560597
}}
561598
/>
599+
{isCreate && (
600+
<AgentMonetizationSummary
601+
enabled={monetizationEnabled}
602+
multiplier={multiplierValue}
603+
profile={usageProfile}
604+
/>
605+
)}
562606
</>
563607
)}
564608
</div>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"use client";
2+
3+
import React from "react";
4+
import clsx from "clsx";
5+
6+
import {
7+
calculateMonetizedRate,
8+
type AgentUsageProfile,
9+
} from "@/lib/agents/monetization";
10+
11+
const formatCurrency = (value: number, currency: string) =>
12+
new Intl.NumberFormat("en-US", {
13+
style: "currency",
14+
currency,
15+
maximumFractionDigits: 2,
16+
}).format(value);
17+
18+
type AgentMonetizationSummaryProps = {
19+
enabled: boolean;
20+
profile: AgentUsageProfile;
21+
multiplier: number;
22+
};
23+
24+
export function AgentMonetizationSummary({
25+
enabled,
26+
profile,
27+
multiplier,
28+
}: AgentMonetizationSummaryProps) {
29+
const { baseAmount, currency, description, label, usageStates } = profile;
30+
const effectiveMultiplier = enabled ? multiplier : 1;
31+
const totalRate = calculateMonetizedRate(baseAmount, effectiveMultiplier);
32+
33+
const summaryNote = enabled
34+
? `${formatCurrency(baseAmount, currency)} base × ${effectiveMultiplier.toFixed(2)}x`
35+
: `${formatCurrency(baseAmount, currency)} base rate`;
36+
37+
return (
38+
<section
39+
aria-label="Monetization summary"
40+
className={clsx(
41+
"mt-4 space-y-3 rounded-md border border-border p-3 text-sm transition-opacity",
42+
enabled ? "opacity-100" : "opacity-75",
43+
)}
44+
>
45+
<header className="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
46+
<div>
47+
<h3 className="text-base font-semibold text-foreground">{label}</h3>
48+
<p className="text-xs text-muted-foreground">{description}</p>
49+
</div>
50+
<div className="text-right">
51+
<div className="text-xs uppercase tracking-wide text-muted-foreground">
52+
Estimated payout
53+
</div>
54+
<div className="text-lg font-semibold text-foreground">
55+
{formatCurrency(totalRate, currency)}
56+
</div>
57+
<div className="text-xs text-muted-foreground">{summaryNote}</div>
58+
</div>
59+
</header>
60+
61+
<dl className="grid gap-2 text-xs sm:grid-cols-2">
62+
{usageStates.map((state) => (
63+
<div
64+
key={`${state.label}-${state.value}`}
65+
className="rounded-md bg-muted/50 px-3 py-2"
66+
>
67+
<dt className="font-medium text-foreground">{state.label}</dt>
68+
<dd className="text-muted-foreground">{state.value}</dd>
69+
</div>
70+
))}
71+
</dl>
72+
73+
{!enabled && (
74+
<p className="text-xs text-muted-foreground">
75+
Toggle monetization to apply your multiplier and publish this pricing
76+
guidance.
77+
</p>
78+
)}
79+
</section>
80+
);
81+
}

0 commit comments

Comments
 (0)