final polish phase 1

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-27 21:27:37 +00:00
parent 627938aa95
commit 5f9a4b8dca
25 changed files with 3286 additions and 1397 deletions

View File

@@ -7,13 +7,15 @@ import React, { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import PageMeta from '../../components/common/PageMeta';
import PageHeader from '../../components/common/PageHeader';
import ComponentCard from '../../components/common/ComponentCard';
import { Card } from '../../components/ui/card';
import Button from '../../components/ui/button/Button';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { fetchAPI, fetchSiteSectors } from '../../services/api';
import SiteSetupChecklist from '../../components/sites/SiteSetupChecklist';
import { integrationApi } from '../../services/integration.api';
import SiteConfigWidget from '../../components/dashboard/SiteConfigWidget';
import OperationsCostsWidget from '../../components/dashboard/OperationsCostsWidget';
import CreditAvailabilityWidget from '../../components/dashboard/CreditAvailabilityWidget';
import { useBillingStore } from '../../store/billingStore';
import {
FileIcon,
PlugInIcon,
@@ -21,7 +23,6 @@ import {
BoltIcon,
PageIcon,
ArrowRightIcon,
ArrowUpIcon
} from '../../icons';
interface Site {
@@ -42,28 +43,46 @@ interface Site {
interface SiteSetupState {
hasIndustry: boolean;
hasSectors: boolean;
sectorsCount: number;
hasWordPressIntegration: boolean;
hasKeywords: boolean;
keywordsCount: number;
hasAuthorProfiles: boolean;
authorProfilesCount: number;
}
interface OperationStat {
type: 'clustering' | 'ideas' | 'content' | 'images';
count: number;
creditsUsed: number;
avgCreditsPerOp: number;
}
export default function SiteDashboard() {
const { id: siteId } = useParams<{ id: string }>();
const navigate = useNavigate();
const toast = useToast();
const { balance, loadBalance } = useBillingStore();
const [site, setSite] = useState<Site | null>(null);
const [setupState, setSetupState] = useState<SiteSetupState>({
hasIndustry: false,
hasSectors: false,
sectorsCount: 0,
hasWordPressIntegration: false,
hasKeywords: false,
keywordsCount: 0,
hasAuthorProfiles: false,
authorProfilesCount: 0,
});
const [operations, setOperations] = useState<OperationStat[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (siteId) {
loadSiteData();
loadBalance();
}
}, [siteId]);
}, [siteId, loadBalance]);
const loadSiteData = async () => {
try {
@@ -79,9 +98,11 @@ export default function SiteDashboard() {
// Load sectors
let hasSectors = false;
let sectorsCount = 0;
try {
const sectors = await fetchSiteSectors(Number(siteId));
hasSectors = sectors && sectors.length > 0;
sectorsCount = sectors?.length || 0;
} catch (err) {
console.log('Could not load sectors');
}
@@ -97,20 +118,47 @@ export default function SiteDashboard() {
// Check keywords - try to load keywords for this site
let hasKeywords = false;
let keywordsCount = 0;
try {
const { fetchKeywords } = await import('../../services/api');
const keywordsData = await fetchKeywords({ site_id: Number(siteId), page_size: 1 });
hasKeywords = keywordsData?.results?.length > 0 || keywordsData?.count > 0;
keywordsCount = keywordsData?.count || 0;
} catch (err) {
// No keywords is fine
}
// Check author profiles
let hasAuthorProfiles = false;
let authorProfilesCount = 0;
try {
const authorsData = await fetchAPI(`/v1/thinker/author-profiles/?site_id=${siteId}&page_size=1`);
hasAuthorProfiles = authorsData?.count > 0;
authorProfilesCount = authorsData?.count || 0;
} catch (err) {
// No profiles is fine
}
setSetupState({
hasIndustry,
hasSectors,
sectorsCount,
hasWordPressIntegration,
hasKeywords,
keywordsCount,
hasAuthorProfiles,
authorProfilesCount,
});
// Load operation stats (mock data for now - would come from backend)
// In real implementation, fetch from /api/v1/dashboard/site/{siteId}/operations/
const mockOperations: OperationStat[] = [
{ type: 'clustering', count: 8, creditsUsed: 80, avgCreditsPerOp: 10 },
{ type: 'ideas', count: 12, creditsUsed: 24, avgCreditsPerOp: 2 },
{ type: 'content', count: 28, creditsUsed: 1400, avgCreditsPerOp: 50 },
{ type: 'images', count: 45, creditsUsed: 225, avgCreditsPerOp: 5 },
];
setOperations(mockOperations);
}
} catch (error: any) {
toast.error(`Failed to load site data: ${error.message}`);
@@ -185,6 +233,28 @@ export default function SiteDashboard() {
/>
</div>
{/* Site Insights - 3 Column Grid */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
<SiteConfigWidget
setupState={{
hasIndustry: setupState.hasIndustry,
sectorsCount: setupState.sectorsCount,
hasWordPressIntegration: setupState.hasWordPressIntegration,
keywordsCount: setupState.keywordsCount,
authorProfilesCount: setupState.authorProfilesCount
}}
siteId={Number(siteId)}
/>
<OperationsCostsWidget operations={operations} siteId={Number(siteId)} />
<CreditAvailabilityWidget
availableCredits={balance?.credits_remaining ?? 0}
totalCredits={balance?.plan_credits_per_month ?? 0}
loading={loading}
/>
</div>
{/* Quick Actions */}
<ComponentCard title="Quick Actions" desc="Common site management tasks">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">