"use client"; import { useState, useEffect } from "react"; import { useTranslations } from "next-intl"; import { getDefaultPricing, formatCost } from "@/shared/constants/pricing"; export default function PricingModal({ isOpen, onClose, onSave }) { const t = useTranslations("pricingModal"); 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(`${t("errorSaveFailed")}: ${error.error}`); } } catch (error) { console.error("Failed to save pricing:", error); alert(t("errorSaveFailed")); } finally { setSaving(false); } }; const handleReset = async () => { if (!confirm(t("resetConfirm"))) 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(t("errorResetFailed")); } }; 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 (
{t("pricingRatesFormat")}
{t.rich("ratesDescription", { strong: (c) => {c}, })}
| {t("model")} | {t("input")} | {t("output")} | {t("cached")} | {t("reasoning")} | {t("cacheCreation")} |
|---|---|---|---|---|---|
| {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" /> | ))}