mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-26 11:14:04 +00:00
style(view_users.tsx): cleanup ui to show filters in consistent style
This commit is contained in:
parent
72dd00d418
commit
f887dc6bff
1 changed files with 130 additions and 40 deletions
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
Title,
|
Title,
|
||||||
|
@ -131,6 +131,9 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
max_spend: null
|
max_spend: null
|
||||||
});
|
});
|
||||||
const [showFilters, setShowFilters] = useState(false);
|
const [showFilters, setShowFilters] = useState(false);
|
||||||
|
const [showColumnDropdown, setShowColumnDropdown] = useState(false);
|
||||||
|
const [selectedFilter, setSelectedFilter] = useState("Email");
|
||||||
|
const filtersRef = useRef(null);
|
||||||
|
|
||||||
// check if window is not undefined
|
// check if window is not undefined
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
|
@ -374,56 +377,143 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
<div className="border-b px-6 py-4">
|
<div className="border-b px-6 py-4">
|
||||||
<div className="flex flex-col space-y-4">
|
<div className="flex flex-col space-y-4">
|
||||||
{/* Search and Filter Controls */}
|
{/* Search and Filter Controls */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
<div className="flex-1 max-w-md">
|
{/* Email Search */}
|
||||||
<TextInput
|
<div className="relative w-64">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
placeholder="Search by email..."
|
placeholder="Search by email..."
|
||||||
|
className="w-full px-3 py-2 pl-8 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
value={filters.email}
|
value={filters.email}
|
||||||
onChange={(e) => handleFilterChange('email', e.target.value)}
|
onChange={(e) => handleFilterChange('email', e.target.value)}
|
||||||
className="w-full"
|
|
||||||
/>
|
/>
|
||||||
|
<svg
|
||||||
|
className="absolute left-2.5 top-2.5 h-4 w-4 text-gray-500"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
variant="secondary"
|
{/* Filter Button */}
|
||||||
|
<button
|
||||||
|
className={`px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2 ${showFilters ? 'bg-gray-100' : ''}`}
|
||||||
onClick={() => setShowFilters(!showFilters)}
|
onClick={() => setShowFilters(!showFilters)}
|
||||||
className="ml-4"
|
|
||||||
>
|
>
|
||||||
{showFilters ? "Hide Filters" : "Show Filters"}
|
<svg
|
||||||
</Button>
|
className="w-4 h-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Filters
|
||||||
|
{(filters.user_id || filters.user_role || filters.team) && (
|
||||||
|
<span className="w-2 h-2 rounded-full bg-blue-500"></span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Reset Filters Button */}
|
||||||
|
<button
|
||||||
|
className="px-3 py-2 text-sm border rounded-md hover:bg-gray-50 flex items-center gap-2"
|
||||||
|
onClick={() => {
|
||||||
|
setFilters({
|
||||||
|
email: "",
|
||||||
|
user_id: "",
|
||||||
|
user_role: "",
|
||||||
|
team: "",
|
||||||
|
model: "",
|
||||||
|
min_spend: null,
|
||||||
|
max_spend: null
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-4 h-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Reset Filters
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Advanced Filters */}
|
{/* Additional Filters */}
|
||||||
{showFilters && (
|
{showFilters && (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4">
|
<div className="flex flex-wrap items-center gap-3 mt-3">
|
||||||
<TextInput
|
{/* User ID Search */}
|
||||||
placeholder="Filter by User ID"
|
<div className="relative w-64">
|
||||||
value={filters.user_id}
|
<input
|
||||||
onChange={(e) => handleFilterChange('user_id', e.target.value)}
|
type="text"
|
||||||
/>
|
placeholder="Filter by User ID"
|
||||||
|
className="w-full px-3 py-2 pl-8 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
value={filters.user_id}
|
||||||
|
onChange={(e) => handleFilterChange('user_id', e.target.value)}
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
className="absolute left-2.5 top-2.5 h-4 w-4 text-gray-500"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M5.121 17.804A13.937 13.937 0 0112 16c2.5 0 4.847.655 6.879 1.804M15 10a3 3 0 11-6 0 3 3 0 016 0zm6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Select
|
{/* Role Dropdown */}
|
||||||
value={filters.user_role}
|
<div className="w-64">
|
||||||
onValueChange={(value) => handleFilterChange('user_role', value)}
|
<Select
|
||||||
placeholder="Select Role"
|
value={filters.user_role}
|
||||||
>
|
onValueChange={(value) => handleFilterChange('user_role', value)}
|
||||||
{Object.entries(possibleUIRoles).map(([key, value]) => (
|
placeholder="Select Role"
|
||||||
<SelectItem key={key} value={key}>
|
>
|
||||||
{value.ui_label}
|
{Object.entries(possibleUIRoles).map(([key, value]) => (
|
||||||
</SelectItem>
|
<SelectItem key={key} value={key}>
|
||||||
))}
|
{value.ui_label}
|
||||||
</Select>
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Select
|
{/* Team Dropdown */}
|
||||||
value={filters.team}
|
<div className="w-64">
|
||||||
onValueChange={(value) => handleFilterChange('team', value)}
|
<Select
|
||||||
placeholder="Select Team"
|
value={filters.team}
|
||||||
>
|
onValueChange={(value) => handleFilterChange('team', value)}
|
||||||
{teams?.map((team) => (
|
placeholder="Select Team"
|
||||||
<SelectItem key={team.team_id} value={team.team_id}>
|
>
|
||||||
{team.team_alias || team.team_id}
|
{teams?.map((team) => (
|
||||||
</SelectItem>
|
<SelectItem key={team.team_id} value={team.team_id}>
|
||||||
))}
|
{team.team_alias || team.team_id}
|
||||||
</Select>
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue