"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 (
{/* Header */}

Pricing Configuration

{/* Content */}
{loading ? (
Loading pricing data...
) : (
{/* Instructions */}

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.

{/* Pricing Tables */} {allProviders.map(provider => { const models = Object.keys(pricingData[provider]).sort(); return (
{provider.toUpperCase()}
{models.map(model => ( {pricingFields.map(field => ( ))} ))}
Model Input Output Cached Reasoning Cache Creation
{model} 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" />
); })} {allProviders.length === 0 && (
No pricing data available
)}
)}
{/* Footer */}
); }