feat(ai): finalize AI magic edits epic rollout and operations
This commit is contained in:
@@ -144,6 +144,10 @@ function formatLog(
|
||||
const used = typeof ctx.used === 'number' ? ctx.used : null;
|
||||
const remaining = typeof ctx.remaining === 'number' ? ctx.remaining : null;
|
||||
const days = typeof ctx.day === 'number' ? ctx.day : null;
|
||||
const spendUsd = typeof ctx.spend_usd === 'number' ? ctx.spend_usd : null;
|
||||
const softCapUsd = typeof ctx.soft_cap_usd === 'number' ? ctx.soft_cap_usd : null;
|
||||
const hardCapUsd = typeof ctx.hard_cap_usd === 'number' ? ctx.hard_cap_usd : null;
|
||||
const failureCode = typeof ctx.failure_code === 'string' ? ctx.failure_code : null;
|
||||
const ctxEventId = ctx.event_id ?? ctx.eventId;
|
||||
const eventId = typeof ctxEventId === 'string' ? Number(ctxEventId) : (typeof ctxEventId === 'number' ? ctxEventId : null);
|
||||
const name = eventName ?? t('mobileNotifications.unknownEvent', 'Event');
|
||||
@@ -165,6 +169,12 @@ function formatLog(
|
||||
case 'package_expiring':
|
||||
case 'package_expired':
|
||||
return 'package';
|
||||
case 'ai_edit_succeeded':
|
||||
case 'ai_edit_failed':
|
||||
case 'ai_edit_blocked':
|
||||
case 'ai_budget_soft_cap':
|
||||
case 'ai_budget_hard_cap':
|
||||
return 'ai';
|
||||
default:
|
||||
return 'general';
|
||||
}
|
||||
@@ -276,6 +286,80 @@ function formatLog(
|
||||
is_read: isRead,
|
||||
scope,
|
||||
};
|
||||
case 'ai_edit_succeeded':
|
||||
return {
|
||||
id: String(log.id),
|
||||
title: t('notificationLogs.aiEditSucceeded.title', 'AI edit completed'),
|
||||
body: t('notificationLogs.aiEditSucceeded.body', '{{event}} has a completed AI edit ready.', {
|
||||
event: name,
|
||||
}),
|
||||
time: log.sent_at ?? log.failed_at ?? '',
|
||||
tone: 'info',
|
||||
eventId,
|
||||
eventName,
|
||||
is_read: isRead,
|
||||
scope,
|
||||
};
|
||||
case 'ai_edit_failed':
|
||||
return {
|
||||
id: String(log.id),
|
||||
title: t('notificationLogs.aiEditFailed.title', 'AI edit failed'),
|
||||
body: t('notificationLogs.aiEditFailed.body', '{{event}} could not finish an AI edit. Reason: {{reason}}.', {
|
||||
event: name,
|
||||
reason: failureCode ?? t('notificationLogs.aiEditFailed.reasonUnknown', 'unknown'),
|
||||
}),
|
||||
time: log.sent_at ?? log.failed_at ?? '',
|
||||
tone: 'warning',
|
||||
eventId,
|
||||
eventName,
|
||||
is_read: isRead,
|
||||
scope,
|
||||
};
|
||||
case 'ai_edit_blocked':
|
||||
return {
|
||||
id: String(log.id),
|
||||
title: t('notificationLogs.aiEditBlocked.title', 'AI edit blocked'),
|
||||
body: t('notificationLogs.aiEditBlocked.body', '{{event}} AI edit was blocked by safety checks.', {
|
||||
event: name,
|
||||
}),
|
||||
time: log.sent_at ?? log.failed_at ?? '',
|
||||
tone: 'warning',
|
||||
eventId,
|
||||
eventName,
|
||||
is_read: isRead,
|
||||
scope,
|
||||
};
|
||||
case 'ai_budget_soft_cap':
|
||||
return {
|
||||
id: String(log.id),
|
||||
title: t('notificationLogs.aiBudgetSoftCap.title', 'AI budget warning'),
|
||||
body: t('notificationLogs.aiBudgetSoftCap.body', '{{event}} reached {{spend}} USD of {{cap}} USD AI budget.', {
|
||||
event: name,
|
||||
spend: spendUsd ?? '—',
|
||||
cap: softCapUsd ?? '—',
|
||||
}),
|
||||
time: log.sent_at ?? log.failed_at ?? '',
|
||||
tone: 'info',
|
||||
eventId,
|
||||
eventName,
|
||||
is_read: isRead,
|
||||
scope,
|
||||
};
|
||||
case 'ai_budget_hard_cap':
|
||||
return {
|
||||
id: String(log.id),
|
||||
title: t('notificationLogs.aiBudgetHardCap.title', 'AI budget exhausted'),
|
||||
body: t('notificationLogs.aiBudgetHardCap.body', '{{event}} reached the hard AI budget cap of {{cap}} USD.', {
|
||||
event: name,
|
||||
cap: hardCapUsd ?? '—',
|
||||
}),
|
||||
time: log.sent_at ?? log.failed_at ?? '',
|
||||
tone: 'warning',
|
||||
eventId,
|
||||
eventName,
|
||||
is_read: isRead,
|
||||
scope,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
id: String(log.id),
|
||||
@@ -379,6 +463,16 @@ export default function MobileNotificationsPage() {
|
||||
};
|
||||
}, [reload]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const interval = window.setInterval(() => {
|
||||
void reload();
|
||||
}, 90_000);
|
||||
|
||||
return () => {
|
||||
window.clearInterval(interval);
|
||||
};
|
||||
}, [reload]);
|
||||
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
@@ -588,6 +682,7 @@ export default function MobileNotificationsPage() {
|
||||
{ key: 'gallery', label: t('notificationLogs.scope.gallery', 'Gallery') },
|
||||
{ key: 'events', label: t('notificationLogs.scope.events', 'Events') },
|
||||
{ key: 'package', label: t('notificationLogs.scope.package', 'Package') },
|
||||
{ key: 'ai', label: t('notificationLogs.scope.ai', 'AI') },
|
||||
{ key: 'general', label: t('notificationLogs.scope.general', 'General') },
|
||||
] as Array<{ key: NotificationScope | 'all'; label: string }>).map((filter) => {
|
||||
const isActive = (scopeParam ?? 'all') === filter.key;
|
||||
|
||||
Reference in New Issue
Block a user