ALwrity Version 0.5.0 (Fastapi + React )
This commit is contained in:
680
frontend/src/stores/contentPlanningStore.ts
Normal file
680
frontend/src/stores/contentPlanningStore.ts
Normal file
@@ -0,0 +1,680 @@
|
||||
import { create } from 'zustand';
|
||||
import { contentPlanningApi } from '../services/contentPlanningApi';
|
||||
|
||||
// Types
|
||||
export interface ContentStrategy {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
industry: string;
|
||||
target_audience: string;
|
||||
content_pillars: string[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
user_id?: number;
|
||||
}
|
||||
|
||||
export interface CalendarEvent {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
date: string;
|
||||
scheduled_date?: string;
|
||||
platform: string;
|
||||
content_type: string;
|
||||
status: 'draft' | 'scheduled' | 'published';
|
||||
strategy_id?: string;
|
||||
user_id?: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface ContentGapAnalysis {
|
||||
id: string;
|
||||
website_url: string;
|
||||
competitors: string[];
|
||||
keywords: string[];
|
||||
gaps: string[];
|
||||
recommendations: AIRecommendation[];
|
||||
created_at: string;
|
||||
user_id?: number;
|
||||
}
|
||||
|
||||
export interface AIRecommendation {
|
||||
id: string;
|
||||
type: 'strategy' | 'topic' | 'timing' | 'platform' | 'optimization';
|
||||
title: string;
|
||||
description: string;
|
||||
confidence: number;
|
||||
reasoning: string;
|
||||
action_items: string[];
|
||||
status: 'pending' | 'accepted' | 'rejected' | 'modified';
|
||||
}
|
||||
|
||||
export interface AIInsight {
|
||||
id: string;
|
||||
type: 'performance' | 'opportunity' | 'warning' | 'trend';
|
||||
title: string;
|
||||
description: string;
|
||||
priority: 'low' | 'medium' | 'high';
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface PerformanceMetrics {
|
||||
engagement: number;
|
||||
reach: number;
|
||||
conversion: number;
|
||||
roi: number;
|
||||
time_range: string;
|
||||
}
|
||||
|
||||
// New Calendar Generation Types
|
||||
export interface GeneratedCalendar {
|
||||
user_id: number;
|
||||
strategy_id?: number;
|
||||
calendar_type: string;
|
||||
industry: string;
|
||||
business_size: string;
|
||||
generated_at: string;
|
||||
content_pillars: string[];
|
||||
platform_strategies: any;
|
||||
content_mix: Record<string, number>;
|
||||
daily_schedule: any[];
|
||||
weekly_themes: any[];
|
||||
content_recommendations: any[];
|
||||
optimal_timing: any;
|
||||
performance_predictions: any;
|
||||
trending_topics: any[];
|
||||
repurposing_opportunities: any[];
|
||||
ai_insights: any[];
|
||||
competitor_analysis: any;
|
||||
gap_analysis_insights: any;
|
||||
strategy_insights: any;
|
||||
onboarding_insights: any;
|
||||
processing_time: number;
|
||||
ai_confidence: number;
|
||||
}
|
||||
|
||||
export interface ContentOptimization {
|
||||
user_id: number;
|
||||
event_id?: number;
|
||||
original_content: any;
|
||||
optimized_content: any;
|
||||
platform_adaptations: string[];
|
||||
visual_recommendations: string[];
|
||||
hashtag_suggestions: string[];
|
||||
keyword_optimization: any;
|
||||
tone_adjustments: any;
|
||||
length_optimization: any;
|
||||
performance_prediction: any;
|
||||
optimization_score: number;
|
||||
recommendations?: any[];
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface PerformancePrediction {
|
||||
user_id: number;
|
||||
strategy_id?: number;
|
||||
content_type: string;
|
||||
platform: string;
|
||||
predicted_engagement_rate: number;
|
||||
predicted_reach: number;
|
||||
predicted_conversions: number;
|
||||
predicted_roi: number;
|
||||
confidence_score: number;
|
||||
recommendations: string[];
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface ContentRepurposing {
|
||||
user_id: number;
|
||||
strategy_id?: number;
|
||||
original_content: any;
|
||||
platform_adaptations: any[];
|
||||
transformations: any[];
|
||||
implementation_tips: string[];
|
||||
gap_addresses: string[];
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface TrendingTopics {
|
||||
user_id: number;
|
||||
industry: string;
|
||||
trending_topics: any[];
|
||||
gap_relevance_scores: Record<string, number>;
|
||||
audience_alignment_scores: Record<string, number>;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
// Store interface
|
||||
interface ContentPlanningStore {
|
||||
// State
|
||||
strategies: ContentStrategy[];
|
||||
currentStrategy: ContentStrategy | null;
|
||||
calendarEvents: CalendarEvent[];
|
||||
gapAnalyses: ContentGapAnalysis[];
|
||||
aiRecommendations: AIRecommendation[];
|
||||
aiInsights: AIInsight[];
|
||||
performanceMetrics: PerformanceMetrics | null;
|
||||
|
||||
// New Calendar Generation State
|
||||
generatedCalendar: GeneratedCalendar | null;
|
||||
contentOptimization: ContentOptimization | null;
|
||||
performancePrediction: PerformancePrediction | null;
|
||||
contentRepurposing: ContentRepurposing | null;
|
||||
trendingTopics: TrendingTopics | null;
|
||||
calendarGenerationLoading: boolean;
|
||||
calendarGenerationError: string | null;
|
||||
|
||||
// UI state
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
activeTab: 'strategy' | 'calendar' | 'analytics' | 'gaps';
|
||||
dataLoading: boolean;
|
||||
|
||||
// Actions
|
||||
setLoading: (loading: boolean) => void;
|
||||
setError: (error: string | null) => void;
|
||||
setActiveTab: (tab: 'strategy' | 'calendar' | 'analytics' | 'gaps') => void;
|
||||
|
||||
// Strategy actions
|
||||
createStrategy: (strategy: Omit<ContentStrategy, 'id' | 'created_at' | 'updated_at'>) => Promise<void>;
|
||||
updateStrategy: (id: string, updates: Partial<ContentStrategy>) => Promise<void>;
|
||||
deleteStrategy: (id: string) => Promise<void>;
|
||||
setCurrentStrategy: (strategy: ContentStrategy | null) => void;
|
||||
|
||||
// Calendar actions
|
||||
createEvent: (event: Omit<CalendarEvent, 'id' | 'created_at' | 'updated_at'>) => Promise<void>;
|
||||
updateEvent: (id: string, updates: Partial<CalendarEvent>) => Promise<void>;
|
||||
deleteEvent: (id: string) => Promise<void>;
|
||||
|
||||
// Gap analysis actions
|
||||
createGapAnalysis: (analysis: Omit<ContentGapAnalysis, 'id' | 'created_at'>) => Promise<void>;
|
||||
updateGapAnalysis: (id: string, updates: Partial<ContentGapAnalysis>) => Promise<void>;
|
||||
analyzeContentGaps: (params: { website_url: string; competitors: string[]; keywords: string[] }) => Promise<void>;
|
||||
|
||||
// AI actions
|
||||
addAIRecommendation: (recommendation: AIRecommendation) => void;
|
||||
updateAIRecommendation: (id: string, status: AIRecommendation['status']) => void;
|
||||
addAIInsight: (insight: AIInsight) => void;
|
||||
|
||||
// Analytics actions
|
||||
setPerformanceMetrics: (metrics: PerformanceMetrics) => void;
|
||||
|
||||
// Load data
|
||||
loadStrategies: () => Promise<void>;
|
||||
loadCalendarEvents: () => Promise<void>;
|
||||
loadGapAnalyses: () => Promise<void>;
|
||||
loadAIInsights: () => Promise<void>;
|
||||
loadAIRecommendations: () => Promise<void>;
|
||||
|
||||
// Update data (for orchestrator)
|
||||
updateStrategies: (strategies: ContentStrategy[]) => void;
|
||||
updateCalendarEvents: (events: CalendarEvent[]) => void;
|
||||
updateGapAnalyses: (analyses: ContentGapAnalysis[]) => void;
|
||||
updateAIInsights: (data: { insights: AIInsight[]; recommendations: AIRecommendation[] }) => void;
|
||||
|
||||
// Health checks
|
||||
checkHealth: () => Promise<boolean>;
|
||||
checkDatabaseHealth: () => Promise<boolean>;
|
||||
|
||||
// New Calendar Generation Actions
|
||||
generateCalendar: (request: {
|
||||
user_id: number;
|
||||
strategy_id?: number;
|
||||
calendar_type: string;
|
||||
industry?: string;
|
||||
business_size: string;
|
||||
force_refresh?: boolean;
|
||||
}) => Promise<void>;
|
||||
|
||||
optimizeContent: (request: {
|
||||
user_id: number;
|
||||
event_id?: number;
|
||||
title: string;
|
||||
description: string;
|
||||
content_type: string;
|
||||
target_platform: string;
|
||||
original_content?: any;
|
||||
}) => Promise<void>;
|
||||
|
||||
predictPerformance: (request: {
|
||||
user_id: number;
|
||||
strategy_id?: number;
|
||||
content_type: string;
|
||||
platform: string;
|
||||
content_data: any;
|
||||
}) => Promise<void>;
|
||||
|
||||
repurposeContent: (request: {
|
||||
user_id: number;
|
||||
strategy_id?: number;
|
||||
original_content: any;
|
||||
target_platforms: string[];
|
||||
}) => Promise<void>;
|
||||
|
||||
getTrendingTopics: (request: {
|
||||
user_id: number;
|
||||
industry: string;
|
||||
limit?: number;
|
||||
}) => Promise<void>;
|
||||
|
||||
setCalendarGenerationLoading: (loading: boolean) => void;
|
||||
setCalendarGenerationError: (error: string | null) => void;
|
||||
clearCalendarGenerationData: () => void;
|
||||
}
|
||||
|
||||
// Store implementation
|
||||
export const useContentPlanningStore = create<ContentPlanningStore>((set, get) => ({
|
||||
// Initial state
|
||||
strategies: [],
|
||||
currentStrategy: null,
|
||||
calendarEvents: [],
|
||||
gapAnalyses: [],
|
||||
aiRecommendations: [],
|
||||
aiInsights: [],
|
||||
performanceMetrics: null,
|
||||
|
||||
// New Calendar Generation State
|
||||
generatedCalendar: null,
|
||||
contentOptimization: null,
|
||||
performancePrediction: null,
|
||||
contentRepurposing: null,
|
||||
trendingTopics: null,
|
||||
calendarGenerationLoading: false,
|
||||
calendarGenerationError: null,
|
||||
|
||||
loading: false,
|
||||
error: null,
|
||||
activeTab: 'strategy',
|
||||
dataLoading: false,
|
||||
|
||||
// UI actions
|
||||
setLoading: (loading) => set({ loading }),
|
||||
setError: (error) => set({ error }),
|
||||
setActiveTab: (activeTab) => set({ activeTab }),
|
||||
|
||||
// Strategy actions
|
||||
createStrategy: async (strategy) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const newStrategy = await contentPlanningApi.createStrategySafe({
|
||||
name: strategy.name,
|
||||
description: strategy.description,
|
||||
industry: strategy.industry,
|
||||
target_audience: strategy.target_audience,
|
||||
content_pillars: strategy.content_pillars,
|
||||
user_id: strategy.user_id
|
||||
});
|
||||
|
||||
set((state) => ({
|
||||
strategies: [...state.strategies, newStrategy],
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to create strategy', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
updateStrategy: async (id, updates) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const updatedStrategy = await contentPlanningApi.updateStrategy(id, updates);
|
||||
set((state) => ({
|
||||
strategies: state.strategies.map((strategy) =>
|
||||
strategy.id === id ? updatedStrategy : strategy
|
||||
),
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to update strategy', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
deleteStrategy: async (id) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
await contentPlanningApi.deleteStrategy(id);
|
||||
set((state) => ({
|
||||
strategies: state.strategies.filter((strategy) => strategy.id !== id),
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to delete strategy', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
setCurrentStrategy: (strategy) => set({ currentStrategy: strategy }),
|
||||
|
||||
// Calendar actions
|
||||
createEvent: async (event) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const newEvent = await contentPlanningApi.createEventSafe({
|
||||
title: event.title,
|
||||
description: event.description,
|
||||
date: event.date,
|
||||
platform: event.platform,
|
||||
content_type: event.content_type,
|
||||
status: event.status,
|
||||
strategy_id: event.strategy_id,
|
||||
user_id: event.user_id
|
||||
});
|
||||
|
||||
set((state) => ({
|
||||
calendarEvents: [...state.calendarEvents, newEvent],
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to create event', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
updateEvent: async (id, updates) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const updatedEvent = await contentPlanningApi.updateEvent(id, updates);
|
||||
set((state) => ({
|
||||
calendarEvents: state.calendarEvents.map((event) =>
|
||||
event.id === id ? updatedEvent : event
|
||||
),
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to update event', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
deleteEvent: async (id) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
await contentPlanningApi.deleteEvent(id);
|
||||
set((state) => ({
|
||||
calendarEvents: state.calendarEvents.filter((event) => event.id !== id),
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to delete event', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
// Gap analysis actions
|
||||
createGapAnalysis: async (analysis) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const newAnalysis = await contentPlanningApi.createGapAnalysisSafe({
|
||||
website_url: analysis.website_url,
|
||||
competitors: analysis.competitors,
|
||||
keywords: analysis.keywords,
|
||||
user_id: analysis.user_id
|
||||
});
|
||||
|
||||
set((state) => ({
|
||||
gapAnalyses: [...state.gapAnalyses, newAnalysis],
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to create gap analysis', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
updateGapAnalysis: async (id, updates) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const updatedAnalysis = await contentPlanningApi.updateGapAnalysis(id, updates);
|
||||
set((state) => ({
|
||||
gapAnalyses: state.gapAnalyses.map((analysis) =>
|
||||
analysis.id === id ? updatedAnalysis : analysis
|
||||
),
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to update gap analysis', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
analyzeContentGaps: async (params) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const analysisResult = await contentPlanningApi.analyzeContentGapsSafe(params);
|
||||
|
||||
// Add the analysis result to the store
|
||||
set((state) => ({
|
||||
gapAnalyses: [...state.gapAnalyses, analysisResult],
|
||||
loading: false,
|
||||
}));
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to analyze content gaps', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
// AI actions
|
||||
addAIRecommendation: (recommendation) => {
|
||||
set((state) => ({
|
||||
aiRecommendations: [...state.aiRecommendations, recommendation],
|
||||
}));
|
||||
},
|
||||
|
||||
updateAIRecommendation: (id, status) => {
|
||||
set((state) => ({
|
||||
aiRecommendations: state.aiRecommendations.map((rec) =>
|
||||
rec.id === id ? { ...rec, status } : rec
|
||||
),
|
||||
}));
|
||||
},
|
||||
|
||||
addAIInsight: (insight) => {
|
||||
set((state) => ({
|
||||
aiInsights: [...state.aiInsights, insight],
|
||||
}));
|
||||
},
|
||||
|
||||
// Analytics actions
|
||||
setPerformanceMetrics: (metrics) => set({ performanceMetrics: metrics }),
|
||||
|
||||
// Load data actions
|
||||
loadStrategies: async () => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const strategies = await contentPlanningApi.getStrategiesSafe();
|
||||
set({ strategies, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to load strategies', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
loadCalendarEvents: async () => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const events = await contentPlanningApi.getEventsSafe();
|
||||
set({ calendarEvents: events, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to load calendar events', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
loadGapAnalyses: async () => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const analyses = await contentPlanningApi.getGapAnalyses();
|
||||
set({ gapAnalyses: analyses, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to load gap analyses', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
loadAIInsights: async () => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const response = await contentPlanningApi.getAIAnalyticsSafe();
|
||||
|
||||
// Validate response structure
|
||||
if (!response || typeof response !== 'object') {
|
||||
console.warn('Invalid AI analytics response:', response);
|
||||
set({ aiInsights: [], loading: false });
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the response structure - it returns an object with insights array
|
||||
const insights = Array.isArray(response.insights) ? response.insights : [];
|
||||
|
||||
// If no insights from backend, create some default insights from recommendations
|
||||
let transformedInsights = insights;
|
||||
if (insights.length === 0 && response.recommendations && Array.isArray(response.recommendations)) {
|
||||
transformedInsights = response.recommendations.slice(0, 3).map((rec: any, index: number) => ({
|
||||
id: `insight_${Date.now()}_${index}`,
|
||||
type: 'opportunity',
|
||||
title: rec.title || 'AI Insight',
|
||||
description: rec.description || 'AI-generated insight',
|
||||
priority: rec.priority === 'High' ? 'high' : rec.priority === 'Medium' ? 'medium' : 'low',
|
||||
created_at: new Date().toISOString()
|
||||
}));
|
||||
} else {
|
||||
// Transform insights data to the expected format
|
||||
transformedInsights = insights.map((insight: any) => ({
|
||||
id: insight.id || `insight_${Date.now()}`,
|
||||
type: insight.type || 'performance',
|
||||
title: insight.title || 'AI Insight',
|
||||
description: insight.description || 'AI-generated insight',
|
||||
priority: insight.priority || 'medium',
|
||||
created_at: insight.created_at || new Date().toISOString()
|
||||
}));
|
||||
}
|
||||
|
||||
set({ aiInsights: transformedInsights, loading: false });
|
||||
} catch (error: any) {
|
||||
console.error('Error loading AI insights:', error);
|
||||
set({ error: error.message || 'Failed to load AI insights', loading: false, aiInsights: [] });
|
||||
}
|
||||
},
|
||||
|
||||
loadAIRecommendations: async () => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const response = await contentPlanningApi.getAIAnalyticsSafe();
|
||||
|
||||
// Validate response structure
|
||||
if (!response || typeof response !== 'object') {
|
||||
console.warn('Invalid AI analytics response:', response);
|
||||
set({ aiRecommendations: [], loading: false });
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the response structure - it returns an object with recommendations array
|
||||
const recommendations = Array.isArray(response.recommendations) ? response.recommendations : [];
|
||||
|
||||
// Transform recommendations data to the expected format
|
||||
const transformedRecommendations = recommendations.map((rec: any, index: number) => ({
|
||||
id: rec.id || `rec_${Date.now()}_${index}`,
|
||||
type: rec.type?.toLowerCase() || 'strategy',
|
||||
title: rec.title || 'AI Recommendation',
|
||||
description: rec.description || 'AI-generated recommendation',
|
||||
confidence: rec.ai_confidence || rec.confidence || 0.8,
|
||||
reasoning: rec.reasoning || rec.description || 'Generated by AI analysis',
|
||||
action_items: Array.isArray(rec.content_suggestions) ? rec.content_suggestions : [],
|
||||
status: rec.status || 'pending'
|
||||
}));
|
||||
|
||||
set({ aiRecommendations: transformedRecommendations, loading: false });
|
||||
} catch (error: any) {
|
||||
console.error('Error loading AI recommendations:', error);
|
||||
set({ error: error.message || 'Failed to load AI recommendations', loading: false, aiRecommendations: [] });
|
||||
}
|
||||
},
|
||||
|
||||
// Update data (for orchestrator)
|
||||
updateStrategies: (strategies: ContentStrategy[]) => {
|
||||
set({ strategies });
|
||||
},
|
||||
|
||||
updateCalendarEvents: (events: CalendarEvent[]) => {
|
||||
set({ calendarEvents: events });
|
||||
},
|
||||
|
||||
updateGapAnalyses: (analyses: ContentGapAnalysis[]) => {
|
||||
set({ gapAnalyses: analyses });
|
||||
},
|
||||
|
||||
updateAIInsights: (data: { insights: AIInsight[]; recommendations: AIRecommendation[] }) => {
|
||||
set({
|
||||
aiInsights: data.insights,
|
||||
aiRecommendations: data.recommendations
|
||||
});
|
||||
},
|
||||
|
||||
// Health checks
|
||||
checkHealth: async () => {
|
||||
try {
|
||||
const health = await contentPlanningApi.checkHealth();
|
||||
return health.status === 'healthy';
|
||||
} catch (error) {
|
||||
console.error('Health check failed:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
checkDatabaseHealth: async () => {
|
||||
try {
|
||||
const dbHealth = await contentPlanningApi.checkDatabaseHealth();
|
||||
return dbHealth.status === 'healthy';
|
||||
} catch (error) {
|
||||
console.error('Database health check failed:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// New Calendar Generation Actions
|
||||
generateCalendar: async (request) => {
|
||||
set({ calendarGenerationLoading: true, calendarGenerationError: null });
|
||||
try {
|
||||
const generatedCalendar = await contentPlanningApi.generateCalendar(request);
|
||||
set({ generatedCalendar, calendarGenerationLoading: false });
|
||||
} catch (error: any) {
|
||||
set({ calendarGenerationError: error.message || 'Failed to generate calendar', calendarGenerationLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
optimizeContent: async (request) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const optimizedContent = await contentPlanningApi.optimizeContent(request);
|
||||
set({ contentOptimization: optimizedContent, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to optimize content', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
predictPerformance: async (request) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const performancePrediction = await contentPlanningApi.predictPerformance(request);
|
||||
set({ performancePrediction, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to predict performance', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
repurposeContent: async (request) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const contentRepurposing = await contentPlanningApi.repurposeContent(request);
|
||||
set({ contentRepurposing, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to repurpose content', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
getTrendingTopics: async (request) => {
|
||||
set({ loading: true, error: null });
|
||||
try {
|
||||
const trendingTopics = await contentPlanningApi.getTrendingTopics(request);
|
||||
set({ trendingTopics, loading: false });
|
||||
} catch (error: any) {
|
||||
set({ error: error.message || 'Failed to get trending topics', loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
setCalendarGenerationLoading: (loading) => set({ calendarGenerationLoading: loading }),
|
||||
setCalendarGenerationError: (error) => set({ calendarGenerationError: error }),
|
||||
clearCalendarGenerationData: () => set({ generatedCalendar: null, contentOptimization: null, performancePrediction: null, contentRepurposing: null, trendingTopics: null }),
|
||||
}));
|
||||
Reference in New Issue
Block a user