// ============================================================================ // Demo API - Mock responses for demo mode // ============================================================================ import type { PaginatedResponse, Workspace, Project, Channel, Creative, Placement, PurchasePlanChannel, WorkspaceMember, SpendingAnalytics, CreativeAnalyticsItem, ChannelAnalyticsItem, } from "@/lib/types/api"; import { demoWorkspace, demoMember, demoProjects, demoChannels, demoCreatives, demoPlacements, demoPurchasePlanChannels, demoSpendingAnalytics, demoCreativeAnalytics, demoChannelAnalytics, } from "./mock-data"; import { DEMO_USER } from "./constants"; // ============================================================================ // Helper to create paginated response // ============================================================================ const paginate = (items: T[], page = 1, size = 50): PaginatedResponse => ({ items: items.slice((page - 1) * size, page * size), total: items.length, page, size, pages: Math.ceil(items.length / size), }); // ============================================================================ // Demo API Methods // ============================================================================ export const demoApi = { // Auth auth: { me: () => Promise.resolve(DEMO_USER), }, // Workspaces workspaces: { list: () => Promise.resolve(paginate([demoWorkspace])), get: () => Promise.resolve(demoWorkspace), }, // Members members: { list: () => Promise.resolve(paginate([demoMember])), }, // Projects projects: { list: (params?: { project_id?: string }) => { let items = demoProjects; if (params?.project_id) { items = items.filter((p) => p.id === params.project_id); } return Promise.resolve(paginate(items)); }, }, // Channels channels: { list: () => Promise.resolve(paginate(demoChannels)), }, // Creatives creatives: { list: (params?: { project_id?: string; include_archived?: boolean }) => { let items = demoCreatives; if (params?.project_id) { items = items.filter((c) => c.project_id === params.project_id); } if (!params?.include_archived) { items = items.filter((c) => c.status === "active"); } return Promise.resolve(paginate(items)); }, get: (id: string) => { const creative = demoCreatives.find((c) => c.id === id); if (!creative) throw new Error("Creative not found"); return Promise.resolve(creative); }, }, // Placements placements: { list: (params?: { project_id?: string; placement_channel_id?: string; creative_id?: string; include_archived?: boolean; }) => { let items = demoPlacements; if (params?.project_id) { items = items.filter((p) => p.project_id === params.project_id); } if (params?.placement_channel_id) { items = items.filter( (p) => p.placement_channel_id === params.placement_channel_id ); } if (params?.creative_id) { items = items.filter((p) => p.creative_id === params.creative_id); } if (!params?.include_archived) { items = items.filter((p) => p.status === "active"); } return Promise.resolve(paginate(items)); }, get: (id: string) => { const placement = demoPlacements.find((p) => p.id === id); if (!placement) throw new Error("Placement not found"); return Promise.resolve(placement); }, }, // Purchase Plan purchasePlan: { list: (projectId: string) => { const items = demoPurchasePlanChannels[projectId] || []; return Promise.resolve(paginate(items)); }, }, // Analytics analytics: { spending: (params?: { project_id?: string; grouping?: string }) => { // Filter by project if specified if (params?.project_id) { const projectPlacements = demoPlacements.filter( (p) => p.project_id === params.project_id && p.status === "active" ); const totalCost = projectPlacements.reduce( (sum, p) => sum + (p.cost || 0), 0 ); const totalSubs = projectPlacements.reduce( (sum, p) => sum + (p.subscriptions_count || 0), 0 ); const totalViews = projectPlacements.reduce( (sum, p) => sum + (p.views_count || 0), 0 ); return Promise.resolve({ total_cost: totalCost, total_subscriptions: totalSubs, total_views: totalViews, avg_cpf: totalSubs > 0 ? totalCost / totalSubs : null, avg_cpm: totalViews > 0 ? (totalCost / totalViews) * 1000 : null, chart_data: demoSpendingAnalytics.chart_data.slice(0, 3), } as SpendingAnalytics); } return Promise.resolve(demoSpendingAnalytics); }, creatives: (params?: { project_id?: string }) => { let items = demoCreativeAnalytics; if (params?.project_id) { const projectCreativeIds = demoCreatives .filter((c) => c.project_id === params.project_id) .map((c) => c.id); items = items.filter((a) => projectCreativeIds.includes(a.id)); } return Promise.resolve(paginate(items)); }, channels: (params?: { project_id?: string }) => { let items = demoChannelAnalytics; if (params?.project_id) { const projectPlacementChannelIds = new Set( demoPlacements .filter((p) => p.project_id === params.project_id) .map((p) => p.placement_channel_id) ); items = items.filter((a) => projectPlacementChannelIds.has(a.channel_id)); } return Promise.resolve(paginate(items)); }, }, };