194 lines
7.3 KiB
TypeScript
194 lines
7.3 KiB
TypeScript
|
|
// Sponsored Ads — Mock Data: Campaigns, Tracking Events, Daily Stats
|
|||
|
|
|
|||
|
|
import type { Campaign, AdTrackingEvent, PlacementDailyStats } from '@/lib/types/ads';
|
|||
|
|
|
|||
|
|
// ===== MOCK CAMPAIGNS =====
|
|||
|
|
|
|||
|
|
export const MOCK_CAMPAIGNS: Campaign[] = [
|
|||
|
|
{
|
|||
|
|
id: 'camp-001',
|
|||
|
|
partnerId: 'partner-sw',
|
|||
|
|
partnerName: 'SoundWave Productions',
|
|||
|
|
name: 'Mumbai Music Festival – Premium Push',
|
|||
|
|
objective: 'AWARENESS',
|
|||
|
|
status: 'ACTIVE',
|
|||
|
|
startAt: '2026-02-01T00:00:00Z',
|
|||
|
|
endAt: '2026-03-15T23:59:59Z',
|
|||
|
|
billingModel: 'CPM',
|
|||
|
|
totalBudget: 50000,
|
|||
|
|
dailyCap: 2500,
|
|||
|
|
spent: 18750,
|
|||
|
|
targeting: { cityIds: ['mumbai', 'pune'], categoryIds: ['music'], countryCodes: ['IN'] },
|
|||
|
|
surfaceKeys: ['HOME_FEATURED_CAROUSEL', 'CITY_TRENDING'],
|
|||
|
|
eventIds: ['evt-101'],
|
|||
|
|
frequencyCap: 5,
|
|||
|
|
approvedBy: 'admin-1',
|
|||
|
|
rejectedReason: null,
|
|||
|
|
createdBy: 'admin-1',
|
|||
|
|
createdAt: '2026-01-25T10:00:00Z',
|
|||
|
|
updatedAt: '2026-02-10T08:00:00Z',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 'camp-002',
|
|||
|
|
partnerId: 'partner-sb',
|
|||
|
|
partnerName: 'Sunburn Events',
|
|||
|
|
name: 'Goa Sunburn – Early Bird Blitz',
|
|||
|
|
objective: 'SALES',
|
|||
|
|
status: 'IN_REVIEW',
|
|||
|
|
startAt: '2026-03-01T00:00:00Z',
|
|||
|
|
endAt: '2026-04-25T23:59:59Z',
|
|||
|
|
billingModel: 'CPC',
|
|||
|
|
totalBudget: 75000,
|
|||
|
|
dailyCap: 5000,
|
|||
|
|
spent: 0,
|
|||
|
|
targeting: { cityIds: [], categoryIds: ['music', 'nightlife'], countryCodes: ['IN'] },
|
|||
|
|
surfaceKeys: ['HOME_FEATURED_CAROUSEL', 'HOME_TOP_EVENTS', 'SEARCH_BOOSTED'],
|
|||
|
|
eventIds: ['evt-107'],
|
|||
|
|
frequencyCap: 3,
|
|||
|
|
approvedBy: null,
|
|||
|
|
rejectedReason: null,
|
|||
|
|
createdBy: 'admin-1',
|
|||
|
|
createdAt: '2026-02-08T14:00:00Z',
|
|||
|
|
updatedAt: '2026-02-08T14:00:00Z',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 'camp-003',
|
|||
|
|
partnerId: 'partner-tc',
|
|||
|
|
partnerName: 'TechConf India',
|
|||
|
|
name: 'Delhi Tech Summit – Sponsor Package',
|
|||
|
|
objective: 'AWARENESS',
|
|||
|
|
status: 'DRAFT',
|
|||
|
|
startAt: '2026-03-10T00:00:00Z',
|
|||
|
|
endAt: '2026-03-21T23:59:59Z',
|
|||
|
|
billingModel: 'FIXED',
|
|||
|
|
totalBudget: 30000,
|
|||
|
|
dailyCap: null,
|
|||
|
|
spent: 0,
|
|||
|
|
targeting: { cityIds: ['delhi'], categoryIds: ['technology', 'business'], countryCodes: ['IN'] },
|
|||
|
|
surfaceKeys: ['HOME_TOP_EVENTS', 'CATEGORY_FEATURED'],
|
|||
|
|
eventIds: ['evt-102'],
|
|||
|
|
frequencyCap: 0,
|
|||
|
|
approvedBy: null,
|
|||
|
|
rejectedReason: null,
|
|||
|
|
createdBy: 'admin-1',
|
|||
|
|
createdAt: '2026-02-09T11:00:00Z',
|
|||
|
|
updatedAt: '2026-02-09T11:00:00Z',
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 'camp-004',
|
|||
|
|
partnerId: 'partner-ri',
|
|||
|
|
partnerName: 'RunIndia',
|
|||
|
|
name: 'Pune Marathon – Registration Drive',
|
|||
|
|
objective: 'SALES',
|
|||
|
|
status: 'ENDED',
|
|||
|
|
startAt: '2026-01-15T00:00:00Z',
|
|||
|
|
endAt: '2026-02-05T23:59:59Z',
|
|||
|
|
billingModel: 'CPM',
|
|||
|
|
totalBudget: 20000,
|
|||
|
|
dailyCap: 1500,
|
|||
|
|
spent: 19800,
|
|||
|
|
targeting: { cityIds: ['pune', 'mumbai'], categoryIds: ['sports'], countryCodes: ['IN'] },
|
|||
|
|
surfaceKeys: ['HOME_TOP_EVENTS', 'CITY_TRENDING'],
|
|||
|
|
eventIds: ['evt-106'],
|
|||
|
|
frequencyCap: 4,
|
|||
|
|
approvedBy: 'admin-1',
|
|||
|
|
rejectedReason: null,
|
|||
|
|
createdBy: 'admin-1',
|
|||
|
|
createdAt: '2026-01-10T09:00:00Z',
|
|||
|
|
updatedAt: '2026-02-05T23:59:59Z',
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
// ===== MOCK TRACKING EVENTS (for camp-001) =====
|
|||
|
|
|
|||
|
|
function genTrackingEvents(): AdTrackingEvent[] {
|
|||
|
|
const events: AdTrackingEvent[] = [];
|
|||
|
|
const surfaces = ['HOME_FEATURED_CAROUSEL', 'CITY_TRENDING'] as const;
|
|||
|
|
const devices = ['mobile-ios', 'mobile-android', 'web-desktop', 'web-mobile'];
|
|||
|
|
const cities = ['mumbai', 'pune'];
|
|||
|
|
const baseTime = new Date('2026-02-03T00:00:00Z');
|
|||
|
|
|
|||
|
|
for (let day = 0; day < 7; day++) {
|
|||
|
|
const impressionsPerDay = 80 + Math.floor(Math.random() * 40);
|
|||
|
|
for (let i = 0; i < impressionsPerDay; i++) {
|
|||
|
|
const ts = new Date(baseTime.getTime() + day * 86400000 + Math.floor(Math.random() * 86400000));
|
|||
|
|
const surface = surfaces[Math.floor(Math.random() * surfaces.length)];
|
|||
|
|
events.push({
|
|||
|
|
id: `te-imp-${day}-${i}`,
|
|||
|
|
type: 'IMPRESSION',
|
|||
|
|
placementId: `splc-camp001-${surface}`,
|
|||
|
|
campaignId: 'camp-001',
|
|||
|
|
surfaceKey: surface,
|
|||
|
|
eventId: 'evt-101',
|
|||
|
|
userId: Math.random() > 0.4 ? `user-${100 + Math.floor(Math.random() * 50)}` : null,
|
|||
|
|
anonId: `anon-${Math.floor(Math.random() * 200)}`,
|
|||
|
|
sessionId: `sess-${day}-${Math.floor(Math.random() * 100)}`,
|
|||
|
|
timestamp: ts.toISOString(),
|
|||
|
|
device: devices[Math.floor(Math.random() * devices.length)],
|
|||
|
|
cityId: cities[Math.floor(Math.random() * cities.length)],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Clicks (~8-15% of impressions)
|
|||
|
|
const clicksPerDay = Math.floor(impressionsPerDay * (0.08 + Math.random() * 0.07));
|
|||
|
|
for (let c = 0; c < clicksPerDay; c++) {
|
|||
|
|
const ts = new Date(baseTime.getTime() + day * 86400000 + Math.floor(Math.random() * 86400000));
|
|||
|
|
const surface = surfaces[Math.floor(Math.random() * surfaces.length)];
|
|||
|
|
events.push({
|
|||
|
|
id: `te-clk-${day}-${c}`,
|
|||
|
|
type: 'CLICK',
|
|||
|
|
placementId: `splc-camp001-${surface}`,
|
|||
|
|
campaignId: 'camp-001',
|
|||
|
|
surfaceKey: surface,
|
|||
|
|
eventId: 'evt-101',
|
|||
|
|
userId: Math.random() > 0.3 ? `user-${100 + Math.floor(Math.random() * 50)}` : null,
|
|||
|
|
anonId: `anon-${Math.floor(Math.random() * 200)}`,
|
|||
|
|
sessionId: `sess-${day}-${Math.floor(Math.random() * 100)}`,
|
|||
|
|
timestamp: ts.toISOString(),
|
|||
|
|
device: devices[Math.floor(Math.random() * devices.length)],
|
|||
|
|
cityId: cities[Math.floor(Math.random() * cities.length)],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return events;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const MOCK_TRACKING_EVENTS = genTrackingEvents();
|
|||
|
|
|
|||
|
|
// ===== MOCK DAILY STATS =====
|
|||
|
|
|
|||
|
|
export function generateMockDailyStats(): PlacementDailyStats[] {
|
|||
|
|
const stats: PlacementDailyStats[] = [];
|
|||
|
|
const baseDate = new Date('2026-02-03');
|
|||
|
|
const cpmRate = 50000 / (7 * 100); // simplified: budget / (days * avg impressions per batch)
|
|||
|
|
|
|||
|
|
for (let day = 0; day < 7; day++) {
|
|||
|
|
const date = new Date(baseDate.getTime() + day * 86400000).toISOString().slice(0, 10);
|
|||
|
|
const surfaces = ['HOME_FEATURED_CAROUSEL', 'CITY_TRENDING'] as const;
|
|||
|
|
|
|||
|
|
for (const surface of surfaces) {
|
|||
|
|
const impressions = 40 + Math.floor(Math.random() * 25);
|
|||
|
|
const clicks = Math.floor(impressions * (0.08 + Math.random() * 0.07));
|
|||
|
|
const ctr = impressions > 0 ? Number((clicks / impressions).toFixed(4)) : 0;
|
|||
|
|
const spend = Number(((impressions / 1000) * 250).toFixed(2)); // ₹250 CPM
|
|||
|
|
|
|||
|
|
stats.push({
|
|||
|
|
id: `ds-${day}-${surface}`,
|
|||
|
|
campaignId: 'camp-001',
|
|||
|
|
placementId: `splc-camp001-${surface}`,
|
|||
|
|
surfaceKey: surface,
|
|||
|
|
date,
|
|||
|
|
impressions,
|
|||
|
|
clicks,
|
|||
|
|
ctr,
|
|||
|
|
spend,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return stats;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const MOCK_DAILY_STATS = generateMockDailyStats();
|