= ({
Credits
- {currentRun.total_credits_used}
+ {totalCreditsUsed}
diff --git a/frontend/src/components/common/SiteCard.tsx b/frontend/src/components/common/SiteCard.tsx
index 2c0f8071..3c6311d9 100644
--- a/frontend/src/components/common/SiteCard.tsx
+++ b/frontend/src/components/common/SiteCard.tsx
@@ -5,7 +5,7 @@ import Badge from '../ui/badge/Badge';
import SiteSetupChecklist from '../sites/SiteSetupChecklist';
import SiteTypeBadge from '../sites/SiteTypeBadge';
import { Site } from '../../services/api';
-import { BoxCubeIcon as SettingsIcon, EyeIcon, FileIcon } from '../../icons';
+import { BoxCubeIcon as SettingsIcon, EyeIcon, FileIcon, TrashBinIcon } from '../../icons';
interface SiteCardProps {
site: Site;
@@ -13,6 +13,7 @@ interface SiteCardProps {
onToggle: (siteId: number, enabled: boolean) => void;
onSettings: (site: Site) => void;
onDetails: (site: Site) => void;
+ onDelete?: (site: Site) => void;
isToggling?: boolean;
}
@@ -22,6 +23,7 @@ export default function SiteCard({
onToggle,
onSettings,
onDetails,
+ onDelete,
isToggling = false,
}: SiteCardProps) {
const handleToggle = (enabled: boolean) => {
@@ -126,6 +128,16 @@ export default function SiteCard({
>
Settings
+ {onDelete && (
+
diff --git a/frontend/src/components/dashboard/AIOperationsWidget.tsx b/frontend/src/components/dashboard/AIOperationsWidget.tsx
index 4ce16b20..a4a06cd6 100644
--- a/frontend/src/components/dashboard/AIOperationsWidget.tsx
+++ b/frontend/src/components/dashboard/AIOperationsWidget.tsx
@@ -20,7 +20,7 @@ export interface AIOperation {
}
export interface AIOperationsData {
- period: '7d' | '30d' | '90d';
+ period: 'today' | '7d' | '30d' | '90d';
operations: AIOperation[];
totals: {
count: number;
@@ -32,7 +32,7 @@ export interface AIOperationsData {
interface AIOperationsWidgetProps {
data: AIOperationsData;
- onPeriodChange?: (period: '7d' | '30d' | '90d') => void;
+ onPeriodChange?: (period: 'today' | '7d' | '30d' | '90d') => void;
loading?: boolean;
}
@@ -54,6 +54,7 @@ const operationConfig: Record([]);
const [sitesLoading, setSitesLoading] = useState(true);
const [siteFilter, setSiteFilter] = useState<'all' | number>('all');
- const [aiPeriod, setAIPeriod] = useState<'7d' | '30d' | '90d'>('7d');
+ const [aiPeriod, setAIPeriod] = useState<'today' | '7d' | '30d' | '90d'>('7d');
const [showAddSite, setShowAddSite] = useState(false);
const [loading, setLoading] = useState(true);
const [subscription, setSubscription] = useState(null);
@@ -171,7 +171,7 @@ export default function Home() {
setLoading(true);
const siteId = siteFilter === 'all' ? undefined : siteFilter;
- const periodDays = aiPeriod === '7d' ? 7 : aiPeriod === '30d' ? 30 : 90;
+ const periodDays = aiPeriod === 'today' ? 1 : aiPeriod === '7d' ? 7 : aiPeriod === '30d' ? 30 : 90;
// Fetch real dashboard stats from API
const stats = await getDashboardStats({
diff --git a/frontend/src/pages/Settings/Sites.tsx b/frontend/src/pages/Settings/Sites.tsx
index 59c54181..286a0bef 100644
--- a/frontend/src/pages/Settings/Sites.tsx
+++ b/frontend/src/pages/Settings/Sites.tsx
@@ -423,6 +423,7 @@ export default function Sites() {
onToggle={handleToggle}
onSettings={handleSettings}
onDetails={handleDetails}
+ onDelete={handleDeleteSite}
isToggling={togglingSiteId === site.id}
/>
))}
diff --git a/frontend/src/pages/Sites/Dashboard.tsx b/frontend/src/pages/Sites/Dashboard.tsx
index c1bea801..d0afd4f6 100644
--- a/frontend/src/pages/Sites/Dashboard.tsx
+++ b/frontend/src/pages/Sites/Dashboard.tsx
@@ -85,9 +85,9 @@ export default function SiteDashboard() {
});
const [operations, setOperations] = useState([]);
const [loading, setLoading] = useState(true);
- const [aiPeriod, setAiPeriod] = useState<'7d' | '30d' | '90d'>('7d');
+ const [aiPeriod, setAiPeriod] = useState<'today' | '7d' | '30d' | '90d'>('7d');
- const handlePeriodChange = (period: '7d' | '30d' | '90d') => {
+ const handlePeriodChange = (period: 'today' | '7d' | '30d' | '90d') => {
setAiPeriod(period);
};
@@ -180,7 +180,7 @@ export default function SiteDashboard() {
// Load operation stats from real API data
try {
- const periodDays = aiPeriod === '7d' ? 7 : aiPeriod === '30d' ? 30 : 90;
+ const periodDays = aiPeriod === 'today' ? 1 : 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
diff --git a/frontend/src/services/automationService.ts b/frontend/src/services/automationService.ts
index cd23c246..508bc655 100644
--- a/frontend/src/services/automationService.ts
+++ b/frontend/src/services/automationService.ts
@@ -78,6 +78,12 @@ export interface ProcessingState {
remaining_count: number;
}
+export interface CurrentProcessingResponse {
+ state: ProcessingState | null;
+ total_credits_used: number;
+ current_stage: number;
+}
+
// NEW: Types for unified run_progress endpoint
export interface StageProgress {
number: number;
@@ -257,11 +263,12 @@ export const automationService = {
/**
* Get current processing state for active automation run
+ * Returns state with total_credits_used for real-time credits tracking
*/
getCurrentProcessing: async (
siteId: number,
runId: string
- ): Promise => {
+ ): Promise => {
const response = await fetchAPI(
buildUrl('/current_processing/', { site_id: siteId, run_id: runId })
);
diff --git a/frontend/src/templates/ContentViewTemplate.tsx b/frontend/src/templates/ContentViewTemplate.tsx
index 01d12e1b..c576f8d3 100644
--- a/frontend/src/templates/ContentViewTemplate.tsx
+++ b/frontend/src/templates/ContentViewTemplate.tsx
@@ -1068,47 +1068,94 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
{/* Action Buttons - Conditional based on status */}
{content.status && (
-
- {/* Draft status: Show Edit Content + Generate Images */}
- {content.status.toLowerCase() === 'draft' && (
- <>
-
-
- >
- )}
+
+
+ {/* Draft status: Show Edit Content + Generate Images */}
+ {content.status.toLowerCase() === 'draft' && (
+ <>
+
+
+ >
+ )}
+
+ {/* Review status: Show Edit Content + Publish */}
+ {content.status.toLowerCase() === 'review' && (
+ <>
+
+
+ >
+ )}
+
- {/* Review status: Show Edit Content + Publish */}
- {content.status.toLowerCase() === 'review' && (
- <>
-
-
- >
+ {/* Publishing Status Display */}
+ {content.site_status && (
+
+
+ {content.site_status === 'published' && (
+
+ )}
+ {content.site_status === 'scheduled' && (
+
+ )}
+ {content.site_status === 'publishing' && (
+
+ )}
+ {content.site_status === 'failed' && (
+
+ )}
+ {content.site_status === 'not_published' && (
+
+ )}
+
+ {content.site_status === 'not_published' && 'Not Published'}
+ {content.site_status === 'scheduled' && 'Scheduled'}
+ {content.site_status === 'publishing' && 'Publishing...'}
+ {content.site_status === 'published' && 'Published'}
+ {content.site_status === 'failed' && 'Failed'}
+
+
+ {content.scheduled_publish_at && content.site_status === 'scheduled' && (
+
+ {formatDate(content.scheduled_publish_at)}
+
+ )}
+ {content.external_url && content.site_status === 'published' && (
+
+ View on site →
+
+ )}
+
)}