Files
igny8/frontend/src/components/dashboard/UsageChartWidget.tsx

84 lines
3.4 KiB
TypeScript

import { useEffect, useState } from 'react';
import { useBillingStore } from '../../store/billingStore';
import ComponentCard from '../common/ComponentCard';
export default function UsageChartWidget() {
const { usageSummary, loading, loadUsageSummary } = useBillingStore();
const [dateRange, setDateRange] = useState<'week' | 'month' | 'year'>('month');
useEffect(() => {
const now = new Date();
let startDate: string;
if (dateRange === 'week') {
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
startDate = weekAgo.toISOString().split('T')[0];
} else if (dateRange === 'month') {
startDate = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().split('T')[0];
} else {
startDate = new Date(now.getFullYear(), 0, 1).toISOString().split('T')[0];
}
const endDate = now.toISOString().split('T')[0];
loadUsageSummary(startDate, endDate);
}, [dateRange, loadUsageSummary]);
if (loading && !usageSummary) {
return (
<ComponentCard title="Usage Summary" desc="Loading...">
<div className="animate-pulse">Loading usage data...</div>
</ComponentCard>
);
}
if (!usageSummary) return null;
return (
<ComponentCard
title="Usage Summary"
desc="Credit usage breakdown by operation and model"
>
<div className="space-y-4">
<div className="flex justify-end items-center mb-4">
<select
className="h-9 rounded-lg border border-gray-300 bg-transparent px-3 py-2 text-sm shadow-theme-xs text-gray-800 focus:border-brand-300 focus:outline-hidden focus:ring-3 focus:ring-brand-500/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white/90 dark:focus:border-brand-800"
value={dateRange}
onChange={(e) => setDateRange(e.target.value as 'week' | 'month' | 'year')}
>
<option value="week">Last 7 Days</option>
<option value="month">This Month</option>
<option value="year">This Year</option>
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<div className="text-sm text-gray-600 dark:text-gray-400">Total Credits Used</div>
<div className="text-2xl font-bold">{usageSummary.total_credits_used}</div>
</div>
<div>
<div className="text-sm text-gray-600 dark:text-gray-400">Total Cost</div>
<div className="text-2xl font-bold">${(Number(usageSummary.total_cost_usd) || 0).toFixed(2)}</div>
</div>
</div>
<div>
<h4 className="text-sm font-semibold mb-2">By Operation</h4>
<div className="space-y-2">
{usageSummary.by_operation && Object.entries(usageSummary.by_operation).map(([op, stats]) => (
<div key={op} className="flex justify-between items-center text-sm">
<span className="capitalize">{op.replace('_', ' ')}</span>
<span className="font-medium">{stats.credits} credits (${(Number(stats.cost) || 0).toFixed(2)})</span>
</div>
))}
{(!usageSummary.by_operation || Object.keys(usageSummary.by_operation || {}).length === 0) && (
<div className="text-sm text-gray-500 dark:text-gray-400">No usage data available</div>
)}
</div>
</div>
</div>
</ComponentCard>
);
}