diff --git a/ui/litellm-dashboard/src/components/common_components/DurationSelect.test.tsx b/ui/litellm-dashboard/src/components/common_components/DurationSelect.test.tsx new file mode 100644 index 00000000000..296ef1ae632 --- /dev/null +++ b/ui/litellm-dashboard/src/components/common_components/DurationSelect.test.tsx @@ -0,0 +1,49 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { describe, it, expect, vi } from "vitest"; +import DurationSelect from "./DurationSelect"; + +describe("DurationSelect", () => { + it("should render", () => { + render(); + expect(screen.getByRole("combobox")).toBeInTheDocument(); + }); + + it("should render all three duration options", async () => { + const user = userEvent.setup(); + render(); + + const select = screen.getByRole("combobox"); + await user.click(select); + + expect(screen.getByText("Daily")).toBeInTheDocument(); + expect(screen.getByText("Weekly")).toBeInTheDocument(); + expect(screen.getByText("Monthly")).toBeInTheDocument(); + }); + + it("should apply className prop", () => { + render(); + const select = screen.getByRole("combobox"); + expect(select.closest(".test-class")).toBeInTheDocument(); + }); + + it("should call onChange when an option is selected", async () => { + const user = userEvent.setup(); + const onChange = vi.fn(); + render(); + + const select = screen.getByRole("combobox"); + await user.click(select); + + const dailyOption = screen.getByText("Daily"); + await user.click(dailyOption); + + expect(onChange).toHaveBeenCalledWith("24h", expect.any(Object)); + }); + + it("should accept and pass value prop to Select", () => { + render(); + const select = screen.getByRole("combobox"); + expect(select).toBeInTheDocument(); + }); +}); diff --git a/ui/litellm-dashboard/src/components/common_components/DurationSelect.tsx b/ui/litellm-dashboard/src/components/common_components/DurationSelect.tsx new file mode 100644 index 00000000000..a84e8aeb110 --- /dev/null +++ b/ui/litellm-dashboard/src/components/common_components/DurationSelect.tsx @@ -0,0 +1,17 @@ +import { Select } from "antd"; + +interface DurationSelectProps { + className?: string; + value?: string; + onChange?: (value: string) => void; +} + +export default function DurationSelect({ className, value, onChange }: DurationSelectProps) { + return ( + + ); +} diff --git a/ui/litellm-dashboard/src/components/team/team_info.tsx b/ui/litellm-dashboard/src/components/team/team_info.tsx index d2d1c885931..fd7994aa1da 100644 --- a/ui/litellm-dashboard/src/components/team/team_info.tsx +++ b/ui/litellm-dashboard/src/components/team/team_info.tsx @@ -48,6 +48,7 @@ import EditLoggingSettings from "./EditLoggingSettings"; import MemberModal from "./EditMembership"; import MemberPermissions from "./member_permissions"; import TeamMembersComponent from "./team_member_view"; +import DurationSelect from "../common_components/DurationSelect"; export interface TeamMembership { user_id: string; @@ -413,6 +414,7 @@ const TeamInfoView: React.FC = ({ }; updateData.max_budget = mapEmptyStringToNull(updateData.max_budget); + updateData.team_member_budget_duration = values.team_member_budget_duration; if (values.team_member_budget !== undefined) { updateData.team_member_budget = Number(values.team_member_budget); @@ -650,6 +652,8 @@ const TeamInfoView: React.FC = ({ budget_duration: info.budget_duration, team_member_tpm_limit: info.team_member_budget_table?.tpm_limit, team_member_rpm_limit: info.team_member_budget_table?.rpm_limit, + team_member_budget: info.team_member_budget_table?.max_budget, + team_member_budget_duration: info.team_member_budget_table?.budget_duration, guardrails: info.metadata?.guardrails || [], disable_global_guardrails: info.metadata?.disable_global_guardrails || false, metadata: info.metadata @@ -747,6 +751,13 @@ const TeamInfoView: React.FC = ({ + + form.setFieldValue("team_member_budget_duration", value)} + value={form.getFieldValue("team_member_budget_duration")} + /> + + = ({
Max Budget: {info.team_member_budget_table?.max_budget || "No Limit"}
+
Budget Duration: {info.team_member_budget_table?.budget_duration || "No Limit"}
Key Duration: {info.metadata?.team_member_key_duration || "No Limit"}
TPM Limit: {info.team_member_budget_table?.tpm_limit || "No Limit"}
RPM Limit: {info.team_member_budget_table?.rpm_limit || "No Limit"}