/** * Image Studio Cost Alerts Integration * * Example integration of Priority 2 alerts (cost estimation, OSS recommendations) * into the Image Studio Create Studio component. */ import React, { useEffect, useState } from 'react'; import { Box, Alert, AlertTitle, Button, Collapse, Chip, Stack, Typography } from '@mui/material'; import { usePriority2Alerts, useCostEstimationAlert } from '../../hooks/usePriority2Alerts'; import Priority2AlertBanner from '../shared/Priority2AlertBanner'; import { useSubscription } from '../../contexts/SubscriptionContext'; import { checkPreflight, PreflightOperation } from '../../services/billingService'; import { showToastNotification } from '../../utils/toastNotifications'; import AttachMoney from '@mui/icons-material/AttachMoney'; import Lightbulb from '@mui/icons-material/Lightbulb'; import TrendingUp from '@mui/icons-material/TrendingUp'; interface CreateStudioCostAlertsProps { userId?: string; provider?: string; model?: string; numVariations?: number; onGenerate?: () => void; } /** * Image Studio Cost Alerts Component * * Displays Priority 2 alerts and provides cost estimation before image generation. * Shows OSS model recommendations and cost comparisons. */ export const CreateStudioCostAlerts: React.FC = ({ userId, provider = 'auto', model, numVariations = 1, onGenerate, }) => { const { subscription } = useSubscription(); const { alerts, refreshAlerts, dismissAlert } = usePriority2Alerts({ userId, enabled: !!userId && subscription?.active, checkInterval: 120000, }); const { showEstimationAlert } = useCostEstimationAlert(); const [estimatedCost, setEstimatedCost] = useState(null); const [ossRecommendation, setOssRecommendation] = useState<{ model: string; savings: number; currentCost: number; } | null>(null); // Estimate cost for image generation useEffect(() => { const estimateCost = async () => { if (!userId || provider === 'auto') return; try { // Determine actual provider (default to wavespeed for OSS) const actualProvider = provider === 'wavespeed' ? 'stability' : provider; const actualModel = model || (provider === 'wavespeed' ? 'qwen-image' : 'stable-diffusion'); const operations: PreflightOperation[] = Array(numVariations).fill(null).map(() => ({ provider: actualProvider, model: actualModel, operation_type: 'image_generation', tokens_requested: 0, })); if (operations.length > 0) { const preflightResult = await checkPreflight(operations[0]); const cost = (preflightResult.estimated_cost || 0) * numVariations; setEstimatedCost(cost); // Check if OSS alternative would be cheaper if (provider !== 'wavespeed' && actualProvider === 'stability') { // Compare with OSS model const ossOperation: PreflightOperation = { provider: 'stability', model: 'qwen-image', operation_type: 'image_generation', tokens_requested: 0, }; const ossResult = await checkPreflight(ossOperation); const ossCost = (ossResult.estimated_cost || 0) * numVariations; if (ossCost < cost) { setOssRecommendation({ model: 'Qwen Image (OSS)', savings: cost - ossCost, currentCost: cost, }); } } } } catch (error) { console.error('[CreateStudioCostAlerts] Error estimating cost:', error); } }; estimateCost(); }, [userId, provider, model, numVariations]); const handleGenerateWithEstimation = async () => { if (!estimatedCost || estimatedCost < 0.01) { // Low cost - proceed directly if (onGenerate) onGenerate(); return; } showEstimationAlert( estimatedCost, `image generation (${numVariations} image${numVariations > 1 ? 's' : ''})`, () => { if (onGenerate) onGenerate(); }, () => { showToastNotification('Image generation cancelled', 'info'); } ); }; // Filter alerts relevant to Image Studio const imageStudioAlerts = alerts.filter(alert => alert.type === 'oss_recommendation' || alert.type === 'cost_trend' || (alert.type === 'cost_estimation' && alert.message.includes('image')) ); // Get OSS model cost info const getModelCost = (modelName: string): number => { const costs: Record = { 'qwen-image': 0.03, 'ideogram-v3-turbo': 0.05, 'stable-diffusion': 0.04, 'stability-ultra': 0.08, 'stability-core': 0.03, }; return costs[modelName] || 0.04; }; const currentModelCost = model ? getModelCost(model) : 0.03; // Default to OSS const totalEstimatedCost = currentModelCost * numVariations; return ( {/* Priority 2 Alert Banner */} {imageStudioAlerts.length > 0 && ( )} {/* Cost Estimation Display */} } sx={{ mb: 2, backgroundColor: 'rgba(59, 130, 246, 0.1)', border: '1px solid rgba(59, 130, 246, 0.2)', }} > Estimated Cost {numVariations} image{numVariations > 1 ? 's' : ''} using{' '} {model || (provider === 'wavespeed' ? 'Qwen Image (OSS)' : 'Default')}: {/* OSS Recommendation */} {ossRecommendation && ( 💡 Cost Savings Opportunity Switch to {ossRecommendation.model} to save{' '} ${ossRecommendation.savings.toFixed(4)} per generation ({((ossRecommendation.savings / ossRecommendation.currentCost) * 100).toFixed(0)}% savings). )} {/* Cost Breakdown */} Cost per image: ${currentModelCost.toFixed(4)} • Total: ${totalEstimatedCost.toFixed(4)} {subscription?.tier === 'basic' && ' (Basic tier uses OSS models by default)'} {/* Generate Button with Cost Awareness */} {onGenerate && ( )} ); }; /** * Hook for Image Studio cost estimation * Use this in Image Studio components before triggering image generation */ export const useImageStudioCostEstimation = () => { const { showEstimationAlert } = useCostEstimationAlert(); const estimateAndGenerate = async ( provider: string, model: string, numVariations: number, onGenerate: () => void, userId?: string ) => { if (!userId) { onGenerate(); return; } try { const actualProvider = provider === 'wavespeed' ? 'stability' : provider; const operations: PreflightOperation[] = Array(numVariations).fill(null).map(() => ({ provider: actualProvider, model: model || (provider === 'wavespeed' ? 'qwen-image' : 'stable-diffusion'), operation_type: 'image_generation', tokens_requested: 0, })); if (operations.length > 0) { const preflightResult = await checkPreflight(operations[0]); const estimatedCost = (preflightResult.estimated_cost || 0) * numVariations; if (estimatedCost > 0.01) { showEstimationAlert( estimatedCost, `image generation (${numVariations} image${numVariations > 1 ? 's' : ''})`, onGenerate, () => showToastNotification('Image generation cancelled', 'info') ); } else { onGenerate(); } } else { onGenerate(); } } catch (error) { console.error('[ImageStudioCostEstimation] Error:', error); onGenerate(); } }; return { estimateAndGenerate }; }; export default CreateStudioCostAlerts;