feat: LinkedIn editorial, accesos agencia estables y deshacer en historial
Integra estrategias LinkedIn en calendarios (backlog publicado vs pendiente), unifica roles/cookies de vista agencia y permite deshacer cambios de brandbook dejando constancia en el historial. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,6 +18,13 @@ import {
|
||||
} from '@/lib/pipeline-calendar';
|
||||
import type { PublishedNetworkPost } from '@/lib/calendar-strategy';
|
||||
import { normalizeApprovalStatus } from '@/lib/approval-status';
|
||||
import { normalizeGenOptions } from '@/lib/calendar-gen-options';
|
||||
import {
|
||||
collectLinkedInUsage,
|
||||
loadLinkedInStrategyContext,
|
||||
pickUnpublishedStrategyPosts,
|
||||
resolveLinkedInStrategyUrl,
|
||||
} from '@/lib/linkedin-strategy';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
export const maxDuration = 60;
|
||||
@@ -57,9 +64,10 @@ export async function POST(req: NextRequest) {
|
||||
.map((t) => t.trim().slice(0, 160))
|
||||
.slice(0, 40)
|
||||
: [];
|
||||
const genOptions = (body.gen_options || body.options || null) as
|
||||
const genOptionsRaw = (body.gen_options || body.options || null) as
|
||||
| Record<string, unknown>
|
||||
| null;
|
||||
const genOptions = normalizeGenOptions(genOptionsRaw || undefined);
|
||||
|
||||
let slug = 'cliente';
|
||||
const t = await restGet<{ slug?: string }[]>(
|
||||
@@ -129,6 +137,58 @@ export async function POST(req: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
let linkedinStrategyUrl = '';
|
||||
let linkedinPrompt: string | undefined;
|
||||
let linkedinStrategyPosts:
|
||||
| import('@/lib/linkedin-strategy').LinkedInStrategyPost[]
|
||||
| undefined;
|
||||
|
||||
if (genOptions.linkedinPosts > 0 || genOptions.linkedinStrategyUrl) {
|
||||
linkedinStrategyUrl = resolveLinkedInStrategyUrl({
|
||||
brandbook,
|
||||
slug,
|
||||
overrideUrl: genOptions.linkedinStrategyUrl,
|
||||
});
|
||||
if (linkedinStrategyUrl) {
|
||||
const liCtx = await loadLinkedInStrategyContext({
|
||||
url: linkedinStrategyUrl,
|
||||
brandbook,
|
||||
mode: genOptions.linkedinMode,
|
||||
});
|
||||
if (liCtx) {
|
||||
linkedinStrategyPosts = liCtx.posts;
|
||||
const usage = collectLinkedInUsage({
|
||||
history,
|
||||
publishedPosts,
|
||||
avoidTitles,
|
||||
});
|
||||
const pick = pickUnpublishedStrategyPosts(
|
||||
liCtx.posts,
|
||||
usage,
|
||||
genOptions.linkedinPosts || liCtx.posts.length
|
||||
);
|
||||
linkedinPrompt = [
|
||||
liCtx.promptBlock,
|
||||
`ESTADO BACKLOG ESTRATEGIA: ${pick.publishedOrPlanned.length} ya publicados o planificados · ${pick.unpublished.length} pendientes.`,
|
||||
pick.publishedOrPlanned.length
|
||||
? `YA USADOS (no re-agendar): ${pick.publishedOrPlanned
|
||||
.slice(0, 40)
|
||||
.map((p) => p.id)
|
||||
.join(', ')}`
|
||||
: '',
|
||||
pick.unpublished.length
|
||||
? `PENDIENTES (priorizar en orden): ${pick.unpublished
|
||||
.slice(0, 24)
|
||||
.map((p) => `${p.id} — ${p.title}`)
|
||||
.join(' | ')}`
|
||||
: 'Backlog agotado → crear ideas nuevas en línea de marca.',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await generateMonthPreview({
|
||||
ym: month,
|
||||
slug,
|
||||
@@ -137,7 +197,10 @@ export async function POST(req: NextRequest) {
|
||||
brandbook,
|
||||
publishedPosts,
|
||||
avoidTitles,
|
||||
genOptions: genOptions || undefined,
|
||||
genOptions,
|
||||
linkedinStrategyUrl: linkedinStrategyUrl || undefined,
|
||||
linkedinPrompt,
|
||||
linkedinStrategyPosts,
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
@@ -147,6 +210,9 @@ export async function POST(req: NextRequest) {
|
||||
source: result.source,
|
||||
brand: slug,
|
||||
brandbook: !!brandbook,
|
||||
linkedin_strategy_url: linkedinStrategyUrl || null,
|
||||
linkedin_posts_from_strategy: linkedinStrategyPosts?.length || 0,
|
||||
linkedin_schedule: result.linkedinMeta || null,
|
||||
history_months: history.length,
|
||||
network_posts: publishedPosts.length,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user