Creditsupdates in fotoer wdigets adn hoemapge and singe site settigns page #Run MIgration 0033 #MAJOR

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-12 07:22:08 +00:00
parent 368601f68c
commit b390e02aa5
17 changed files with 251 additions and 45 deletions

View File

@@ -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()}

View File

@@ -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 */}

View File

@@ -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}
/>

View File

@@ -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}