Creditsupdates in fotoer wdigets adn hoemapge and singe site settigns page #Run MIgration 0033 #MAJOR
This commit is contained in:
@@ -14,6 +14,7 @@ interface CreditsUsageWidgetProps {
|
||||
aiOperations?: {
|
||||
total: number;
|
||||
period: string;
|
||||
siteName?: string;
|
||||
};
|
||||
loading?: boolean;
|
||||
}
|
||||
@@ -113,6 +114,11 @@ export default function CreditsUsageWidget({
|
||||
<div>
|
||||
<p className="text-base text-gray-500 dark:text-gray-400">
|
||||
AI Operations ({aiOperations.period})
|
||||
{aiOperations.siteName && aiOperations.total > 0 && (
|
||||
<span className="ml-2 text-sm">
|
||||
· Site: {aiOperations.siteName}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
<p className="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
{aiOperations.total.toLocaleString()}
|
||||
|
||||
@@ -20,8 +20,9 @@ interface OperationStat {
|
||||
|
||||
interface OperationsCostsWidgetProps {
|
||||
operations: OperationStat[];
|
||||
period?: '7d' | '30d' | 'total';
|
||||
period?: '7d' | '30d' | '90d';
|
||||
loading?: boolean;
|
||||
onPeriodChange?: (period: '7d' | '30d' | '90d') => void;
|
||||
}
|
||||
|
||||
const operationConfig = {
|
||||
@@ -54,9 +55,10 @@ const operationConfig = {
|
||||
export default function OperationsCostsWidget({
|
||||
operations,
|
||||
period = '7d',
|
||||
loading = false
|
||||
loading = false,
|
||||
onPeriodChange
|
||||
}: OperationsCostsWidgetProps) {
|
||||
const periodLabel = period === '7d' ? 'Last 7 Days' : period === '30d' ? 'Last 30 Days' : 'All Time';
|
||||
const periodLabel = period === '7d' ? 'Last 7 Days' : period === '30d' ? 'Last 30 Days' : 'Last 90 Days';
|
||||
|
||||
const totalOps = operations.reduce((sum, op) => sum + op.count, 0);
|
||||
const totalCredits = operations.reduce((sum, op) => sum + op.creditsUsed, 0);
|
||||
@@ -68,7 +70,25 @@ export default function OperationsCostsWidget({
|
||||
<h3 className="text-base font-semibold text-gray-800 dark:text-gray-200 uppercase tracking-wide">
|
||||
AI Operations
|
||||
</h3>
|
||||
<span className="text-xs text-gray-600 dark:text-gray-400">{periodLabel}</span>
|
||||
{onPeriodChange ? (
|
||||
<div className="flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5">
|
||||
{(['7d', '30d', '90d'] as const).map((p) => (
|
||||
<button
|
||||
key={p}
|
||||
onClick={() => onPeriodChange(p)}
|
||||
className={`px-2.5 py-1 text-xs font-medium rounded transition-colors ${
|
||||
period === p
|
||||
? 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
|
||||
}`}
|
||||
>
|
||||
{p === '7d' ? '7d' : p === '30d' ? '30d' : '90d'}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-xs text-gray-600 dark:text-gray-400">{periodLabel}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Operations List */}
|
||||
|
||||
@@ -370,11 +370,12 @@ export default function Home() {
|
||||
onAddSite={canAddMoreSites ? handleAddSiteClick : undefined}
|
||||
maxSites={maxSites}
|
||||
/>
|
||||
<CreditsUsageWidget
|
||||
<CreditsUsageWidget
|
||||
balance={balance}
|
||||
aiOperations={{
|
||||
total: aiOperations.totals.count,
|
||||
period: aiOperations.period === '7d' ? 'Last 7 days' : aiOperations.period === '30d' ? 'Last 30 days' : 'Last 90 days',
|
||||
siteName: siteFilter !== 'all' ? sites.find(s => s.id === siteFilter)?.name : undefined,
|
||||
}}
|
||||
loading={loading}
|
||||
/>
|
||||
|
||||
@@ -85,6 +85,11 @@ export default function SiteDashboard() {
|
||||
});
|
||||
const [operations, setOperations] = useState<OperationStat[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [aiPeriod, setAiPeriod] = useState<'7d' | '30d' | '90d'>('7d');
|
||||
|
||||
const handlePeriodChange = (period: '7d' | '30d' | '90d') => {
|
||||
setAiPeriod(period);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (siteId) {
|
||||
@@ -100,7 +105,7 @@ export default function SiteDashboard() {
|
||||
loadSiteData(currentSiteId);
|
||||
loadBalance();
|
||||
}
|
||||
}, [siteId]);
|
||||
}, [siteId, aiPeriod]);
|
||||
|
||||
const loadSiteData = async (currentSiteId: string) => {
|
||||
try {
|
||||
@@ -175,7 +180,8 @@ export default function SiteDashboard() {
|
||||
|
||||
// Load operation stats from real API data
|
||||
try {
|
||||
const stats = await getDashboardStats({ site_id: Number(currentSiteId), days: 7 });
|
||||
const periodDays = aiPeriod === '7d' ? 7 : aiPeriod === '30d' ? 30 : 90;
|
||||
const stats = await getDashboardStats({ site_id: Number(currentSiteId), days: periodDays });
|
||||
|
||||
// Map operation types from API to display types
|
||||
const operationTypeMap: Record<string, 'clustering' | 'ideas' | 'content' | 'images'> = {
|
||||
@@ -354,7 +360,12 @@ export default function SiteDashboard() {
|
||||
authorProfilesCount={setupState.authorProfilesCount}
|
||||
/>
|
||||
|
||||
<OperationsCostsWidget operations={operations} />
|
||||
<OperationsCostsWidget
|
||||
operations={operations}
|
||||
period={aiPeriod}
|
||||
loading={loading}
|
||||
onPeriodChange={handlePeriodChange}
|
||||
/>
|
||||
|
||||
<CreditAvailabilityWidget
|
||||
availableCredits={balance?.credits_remaining ?? 0}
|
||||
|
||||
Reference in New Issue
Block a user