"use client"; import { useState, useEffect } from "react"; import { getDefaultPricing, formatCost } from "@/shared/constants/pricing.js"; export default function PricingModal({ isOpen, onClose, onSave }) { const [pricingData, setPricingData] = useState({}); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); useEffect(() => { if (isOpen) { loadPricing(); } }, [isOpen]); const loadPricing = async () => { setLoading(true); try { const response = await fetch("/api/pricing"); if (response.ok) { const data = await response.json(); setPricingData(data); } else { // Fallback to defaults const defaults = getDefaultPricing(); setPricingData(defaults); } } catch (error) { console.error("Failed to load pricing:", error); const defaults = getDefaultPricing(); setPricingData(defaults); } finally { setLoading(false); } }; const handlePricingChange = (provider, model, field, value) => { const numValue = parseFloat(value); if (isNaN(numValue) || numValue < 0) return; setPricingData(prev => { const newData = { ...prev }; if (!newData[provider]) newData[provider] = {}; if (!newData[provider][model]) newData[provider][model] = {}; newData[provider][model][field] = numValue; return newData; }); }; const handleSave = async () => { setSaving(true); try { const response = await fetch("/api/pricing", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(pricingData) }); if (response.ok) { onSave?.(); onClose(); } else { const error = await response.json(); alert(`Failed to save pricing: ${error.error}`); } } catch (error) { console.error("Failed to save pricing:", error); alert("Failed to save pricing"); } finally { setSaving(false); } }; const handleReset = async () => { if (!confirm("Reset all pricing to defaults? This cannot be undone.")) return; try { const response = await fetch("/api/pricing", { method: "DELETE" }); if (response.ok) { const defaults = getDefaultPricing(); setPricingData(defaults); } } catch (error) { console.error("Failed to reset pricing:", error); alert("Failed to reset pricing"); } }; if (!isOpen) return null; // Get all unique providers and models for display const allProviders = Object.keys(pricingData).sort(); const pricingFields = ["input", "output", "cached", "reasoning", "cache_creation"]; return (
Pricing Rates Format
All rates are in dollars per million tokens ($/1M tokens). Example: Input rate of 2.50 means $2.50 per 1,000,000 input tokens.
| Model | Input | Output | Cached | Reasoning | Cache Creation |
|---|---|---|---|---|---|
| {model} | {pricingFields.map(field => (handlePricingChange(provider, model, field, e.target.value)} className="w-20 px-2 py-1 text-right bg-bg-base border border-border rounded focus:outline-none focus:border-primary" /> | ))}