Approved pieces can be timed for IG/FB from the agency board; cron queues due jobs and calendar uses scheduled_at. Meta publish comes next. Co-authored-by: Cursor <cursoragent@cursor.com>
57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
/** Agency scheduling helpers for creative_pipeline. */
|
|
|
|
export const PUBLISH_CHANNELS = ['instagram', 'facebook'] as const;
|
|
export type PublishChannel = (typeof PUBLISH_CHANNELS)[number];
|
|
|
|
export const PUBLISH_STATUSES = [
|
|
'idle',
|
|
'queued',
|
|
'publishing',
|
|
'published',
|
|
'failed',
|
|
] as const;
|
|
export type PublishStatus = (typeof PUBLISH_STATUSES)[number];
|
|
|
|
export function normalizeChannels(raw: unknown): PublishChannel[] {
|
|
const list = Array.isArray(raw)
|
|
? raw.map((x) => String(x).toLowerCase().trim())
|
|
: typeof raw === 'string'
|
|
? raw.split(',').map((x) => x.toLowerCase().trim())
|
|
: [];
|
|
const out = PUBLISH_CHANNELS.filter((c) => list.includes(c));
|
|
return out.length ? [...out] : ['instagram', 'facebook'];
|
|
}
|
|
|
|
/** Parse datetime-local or ISO into timestamptz ISO, or null to clear. */
|
|
export function parseScheduledAt(raw: unknown): string | null | undefined {
|
|
if (raw === null) return null;
|
|
if (raw === undefined) return undefined;
|
|
if (typeof raw !== 'string') return undefined;
|
|
const t = raw.trim();
|
|
if (!t) return null;
|
|
const d = new Date(t);
|
|
if (Number.isNaN(d.getTime())) return undefined;
|
|
return d.toISOString();
|
|
}
|
|
|
|
export function toDatetimeLocalValue(iso?: string | null): string {
|
|
if (!iso) return '';
|
|
const d = new Date(iso);
|
|
if (Number.isNaN(d.getTime())) return '';
|
|
const pad = (n: number) => String(n).padStart(2, '0');
|
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
}
|
|
|
|
export function scheduleLabel(iso?: string | null): string | null {
|
|
if (!iso) return null;
|
|
const d = new Date(iso);
|
|
if (Number.isNaN(d.getTime())) return null;
|
|
return d.toLocaleString('es-ES', {
|
|
weekday: 'short',
|
|
day: 'numeric',
|
|
month: 'short',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
});
|
|
}
|