From 2622bf55a2b954bde91312433564a0fe68a31fc9 Mon Sep 17 00:00:00 2001 From: alorig <220087330+alorig@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:30:25 +0500 Subject: [PATCH] Update AdminCreditCostsPage.tsx --- .../src/pages/Admin/AdminCreditCostsPage.tsx | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/frontend/src/pages/Admin/AdminCreditCostsPage.tsx b/frontend/src/pages/Admin/AdminCreditCostsPage.tsx index 3cfad9a7..d8472730 100644 --- a/frontend/src/pages/Admin/AdminCreditCostsPage.tsx +++ b/frontend/src/pages/Admin/AdminCreditCostsPage.tsx @@ -158,4 +158,164 @@ export default function AdminCreditCostsPage() { ); } +/** + * Admin Credit Costs Page + * Manage credit pricing per billable action + */ +import { useEffect, useState } from 'react'; +import { AlertCircle, Loader2, Check } from 'lucide-react'; +import PageMeta from '../../components/common/PageMeta'; +import { Card } from '../../components/ui/card'; +import Button from '../../components/ui/button/Button'; +import { + getCreditCosts, + updateCreditCosts, + type CreditCostConfig, +} from '../../services/billing.api'; + +export default function AdminCreditCostsPage() { + const [costs, setCosts] = useState([]); + const [loading, setLoading] = useState(true); + const [savingId, setSavingId] = useState(null); + const [error, setError] = useState(''); + + useEffect(() => { + loadCosts(); + }, []); + + const loadCosts = async () => { + try { + setLoading(true); + const data = await getCreditCosts(); + setCosts(data.results || []); + } catch (err: any) { + setError(err.message || 'Failed to load credit costs'); + } finally { + setLoading(false); + } + }; + + const handleSave = async (cost: CreditCostConfig) => { + try { + setSavingId(cost.id); + await updateCreditCosts([ + { operation_type: cost.operation_type, credits_cost: Number(cost.credits_cost) || 0 }, + ]); + await loadCosts(); + } catch (err: any) { + setError(err.message || 'Failed to update credit cost'); + } finally { + setSavingId(null); + } + }; + + const updateLocalCost = (id: number, value: string) => { + setCosts((prev) => + prev.map((c) => (c.id === id ? { ...c, credits_cost: value as any } : c)), + ); + }; + + if (loading) { + return ( +
+ +
+ ); + } + + return ( +
+ + +
+

Credit Costs

+

+ Configure credits required for each billable operation. +

+
+ + {error && ( +
+ +

{error}

+
+ )} + + +
+ + + + + + + + + + + + + {costs.length === 0 ? ( + + + + ) : ( + costs.map((cost) => ( + + + + + + + + + )) + )} + +
+ Operation + + Display Name + + Credits Cost + + Unit + + Description + + Actions +
+ No credit costs configured +
+ {cost.operation_type} + + {cost.display_name || '-'} + + updateLocalCost(cost.id, e.target.value)} + className="w-24 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white" + /> + + {cost.unit} + + {cost.description} + + +
+
+
+
+ ); +}