"use client" import { useState, useEffect } from "react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Alert, AlertDescription } from "@/components/ui/alert" import { Badge } from "@/components/ui/badge" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Edit2, Save, X, Loader2, RefreshCw } from "lucide-react" const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:5000/api/v1" // Atualizar a interface ModelPrice para refletir a nova estrutura da API: interface ModelPrice { _id: { $oid: string } provider: string product: string type: string billingBy: string billingUnit: number currency: string price: string clientPrice?: string // Campo opcional que pode não vir da API createdAt: { $date: string } updatedAt: { $date: string } __v: number } // Interface para a resposta da API: interface ApiResponse { success: boolean data: ModelPrice[] } export default function ModelPricesTable() { const [data, setData] = useState([]) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState("") const [editingId, setEditingId] = useState(null) // Atualizar editValues para incluir todos os campos editáveis: const [editValues, setEditValues] = useState<{ product: string provider: string type: string billingBy: string billingUnit: string currency: string clientPrice: string price: string }>({ product: "", provider: "", type: "", billingBy: "", billingUnit: "", currency: "", clientPrice: "", price: "", }) const [isSaving, setIsSaving] = useState(false) // Filtros const [typeFilter, setTypeFilter] = useState("stt") const [providerFilter, setProviderFilter] = useState("") const getAuthHeaders = () => { const token = localStorage.getItem("access_token") return { Authorization: `Bearer ${token}`, "Content-Type": "application/json", } } const fetchData = async () => { setIsLoading(true) setError("") try { const params = new URLSearchParams() if (typeFilter) params.append("type", typeFilter) if (providerFilter) params.append("provider", providerFilter) const response = await fetch(`${API_BASE_URL}/usage/model/prices?${params}`, { headers: getAuthHeaders(), }) if (response.ok) { // Atualizar o processamento da resposta para a nova estrutura: const result: ApiResponse = await response.json() if (result.success && Array.isArray(result.data)) { setData(result.data) } else { setData([]) } } else { const errorData = await response.json() setError(errorData.message || "Erro ao buscar dados") } } catch (err) { console.log("====> Erro de conexão com o servidor: ", err) setError("Erro de conexão com o servidor") } finally { setIsLoading(false) } } // Atualizar a função startEdit para trabalhar com todos os campos: const startEdit = (item: ModelPrice) => { const id = item._id.$oid setEditingId(id) setEditValues({ product: item.product, provider: item.provider, type: item.type, billingBy: item.billingBy, billingUnit: item.billingUnit.toString(), currency: item.currency, clientPrice: item.clientPrice || "", price: item.price, }) } const cancelEdit = () => { setEditingId(null) setEditValues({ product: "", provider: "", type: "", billingBy: "", billingUnit: "", currency: "", clientPrice: "", price: "", }) } // Atualizar a função saveEdit para enviar todos os campos: const saveEdit = async (id: string) => { setIsSaving(true) setError("") try { const response = await fetch(`${API_BASE_URL}/usage/model/prices/${id}`, { method: "PATCH", headers: getAuthHeaders(), body: JSON.stringify({ product: editValues.product, provider: editValues.provider, type: editValues.type, billingBy: editValues.billingBy, billingUnit: Number.parseInt(editValues.billingUnit), currency: editValues.currency, clientPrice: editValues.clientPrice, price: editValues.price, }), }) if (response.ok) { await fetchData() // Recarrega os dados setEditingId(null) setEditValues({ product: "", provider: "", type: "", billingBy: "", billingUnit: "", currency: "", clientPrice: "", price: "", }) } else { const errorData = await response.json() setError(errorData.message || "Erro ao salvar alterações") } } catch (err) { console.log("====> Erro de conexão com o servidor: ", err) setError("Erro de conexão com o servidor") } finally { setIsSaving(false) } } useEffect(() => { fetchData() }, []) // Opções para os selects const typeOptions = ["stt", "tts", "llm", "embedding", "vision"] const providerOptions = ["openai", "aws", "google", "anthropic", "mistral", "azure"] const currencyOptions = ["dollar", "real", "euro"] const billingByOptions = ["second", "minute", "character", "token", "image", "request"] return (
{/* Filtros */} Filtros
setTypeFilter(e.target.value)} placeholder="stt,tts" />
setProviderFilter(e.target.value)} placeholder="openai,aws" />
{error && ( {error} )} {/* Tabela de Preços */} Preços dos Modelos ({data.length} modelos) {data.length > 0 ? (
{/* Atualizar a tabela para exibir os novos campos: */} Produto Provedor Tipo Cobrança Por Unidade Moeda Preço Preço Cliente Ações {data.map((item) => { const itemId = item._id.$oid const isEditing = editingId === itemId return ( {isEditing ? ( setEditValues((prev) => ({ ...prev, product: e.target.value }))} className="w-32" /> ) : ( item.product || "-" )} {isEditing ? ( ) : ( {item.provider} )} {isEditing ? ( ) : ( {item.type} )} {isEditing ? ( ) : ( item.billingBy )} {isEditing ? ( setEditValues((prev) => ({ ...prev, billingUnit: e.target.value }))} className="w-20" /> ) : ( item.billingUnit )} {isEditing ? ( ) : ( {item.currency} )} {isEditing ? ( setEditValues((prev) => ({ ...prev, price: e.target.value }))} className="w-24" /> ) : ( `$${item.price}` )} {isEditing ? ( setEditValues((prev) => ({ ...prev, clientPrice: e.target.value }))} className="w-24" placeholder="0.000" /> ) : item.clientPrice ? ( `$${item.clientPrice}` ) : ( "-" )} {isEditing ? (
) : ( )}
) })}
) : (
{isLoading ? "Carregando..." : "Nenhum modelo encontrado."}
)}
) }