Mark GEO as coming soon and slim the SEO menu to live data.

Hide duplicate GSC/GA4 views and the manual day-load CTA so Orgánico matches Search Console, Analytics, and Métricas.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-10-06 12:40:53 +02:00
parent 81b424bd2f
commit 8a9d92cb6b
3 changed files with 60 additions and 73 deletions

View File

@@ -171,7 +171,9 @@ export default function OrganicoDashboard({
}, [load]);
useEffect(() => {
const first = ORGANICO_SECTIONS.find((s) => s.pillar === pillar);
const first = ORGANICO_SECTIONS.find(
(s) => s.pillar === pillar && !s.soon
);
if (first) setSectionId(first.id);
}, [pillar]);
@@ -214,7 +216,9 @@ export default function OrganicoDashboard({
const maxSessions = Math.max(1, ...seoDaily.map((d) => d.sessions));
const section = useMemo(
() => ORGANICO_SECTIONS.find((s) => s.id === sectionId)!,
() =>
ORGANICO_SECTIONS.find((s) => s.id === sectionId) ||
ORGANICO_SECTIONS.find((s) => s.pillar === 'seo' && !s.soon)!,
[sectionId]
);
const navGroups = useMemo(() => groupsForPillar(pillar), [pillar]);
@@ -406,11 +410,11 @@ export default function OrganicoDashboard({
<PageHeader
eyebrow="Crecimiento"
title="Orgánico"
description="SEO + GEO (visibilidad en IA). Elige un cliente en Contexto."
description="SEO con Search Console y GA4. Elige un cliente en Contexto."
actions={<SyncNowButton forceModule="organico" />}
/>
<p className="text-sm text-gray-600 border border-gray-200 rounded-xl px-4 py-8 text-center bg-gray-50">
Selecciona un cliente para abrir su suite SEO / GEO.
Selecciona un cliente para ver su SEO.
</p>
</div>
);
@@ -429,7 +433,7 @@ export default function OrganicoDashboard({
<PageHeader
eyebrow="Crecimiento · Suite"
title="Orgánico"
description={`${label} · Observa posicionamiento en búsqueda e IA, competencia y oportunidades de contenido.`}
description={`${label} · Search Console y Analytics. GEO (visibilidad en IA) llega después.`}
actions={
<div className="flex flex-wrap items-center gap-2">
<SyncNowButton forceModule="organico" />
@@ -438,20 +442,10 @@ export default function OrganicoDashboard({
onChange={(p) => setPillar(p)}
size="sm"
options={[
{ id: 'geo', label: 'GEO · IA' },
{ id: 'seo', label: 'SEO' },
{ id: 'geo', label: 'GEO · IA' },
]}
/>
{isAgency ? (
<button
type="button"
onClick={() => setShowCapture((v) => !v)}
className="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1.5 rounded-lg bg-brand-500 text-white hover:bg-brand-600"
>
<Plus className="w-3.5 h-3.5" />
{pillar === 'geo' ? 'Medición GEO' : 'Cargar día SEO'}
</button>
) : null}
</div>
}
/>
@@ -473,15 +467,6 @@ export default function OrganicoDashboard({
{[
{ title: 'Search Console', row: gsc },
{ title: 'GA4', row: ga4 },
{
title: 'GEO / IA',
row: latestGeo
? {
status: 'connected',
external_account_id: latestGeo.label || 'Medición activa',
}
: { status: 'disconnected', external_account_id: null },
},
].map((c) => (
<div
key={c.title}
@@ -498,7 +483,7 @@ export default function OrganicoDashboard({
<p className="text-sm font-medium text-gray-900 mt-1 truncate">
{c.row?.external_account_id || 'Sin vincular'}
</p>
{isAgency && tenantId && c.title !== 'GEO / IA' ? (
{isAgency && tenantId ? (
<Link
href={`/dashboard/agencia/cliente/${tenantId}`}
className="inline-flex items-center gap-1 text-[11px] font-semibold text-brand-700 mt-1.5 hover:underline"
@@ -508,10 +493,35 @@ export default function OrganicoDashboard({
) : null}
</div>
))}
<div className="rounded-xl border border-dashed border-gray-300 bg-gray-50 px-4 py-3">
<div className="flex items-center justify-between">
<p className="text-xs font-semibold text-gray-700">GEO / IA</p>
<span className="text-[10px] font-bold uppercase px-2 py-0.5 rounded-full border border-amber-200 bg-amber-50 text-amber-800">
Próximamente
</span>
</div>
<p className="text-sm text-gray-600 mt-1">
Visibilidad de marca en ChatGPT, Gemini y AI Overviews.
</p>
</div>
</div>
{/* Capture forms */}
{isAgency && showCapture && pillar === 'seo' && (
{pillar === 'geo' ? (
<div className="rounded-2xl border border-gray-200 bg-white px-6 py-14 text-center shadow-sm">
<p className="text-[11px] font-bold uppercase tracking-wider text-amber-700">
Próximamente disponible
</p>
<h2 className="text-xl font-bold text-gray-900 mt-2">GEO · visibilidad en IA</h2>
<p className="text-sm text-gray-600 mt-2 max-w-lg mx-auto">
Aquí mediremos cómo aparece la marca en respuestas de ChatGPT,
Gemini y AI Overviews (Share of Model, citas, competidores). SEO
(Google) sigue en la pestaña SEO, con datos de Search Console y
Analytics.
</p>
</div>
) : (
<>
{isAgency && showCapture && (
<CaptureSeo
form={seoForm}
setForm={setSeoForm}
@@ -519,28 +529,12 @@ export default function OrganicoDashboard({
onSave={() => void saveOrganicDay()}
/>
)}
{isAgency && showCapture && pillar === 'geo' && (
<CaptureGeo
form={geoForm}
setForm={setGeoForm}
saving={saving}
onSave={() => void saveGeo()}
/>
)}
{/* Shell: nav + content */}
<div className="grid grid-cols-1 lg:grid-cols-[240px_minmax(0,1fr)] gap-4 items-start">
<aside className="rounded-2xl border border-gray-200 bg-white p-3 shadow-sm lg:sticky lg:top-20 max-h-[calc(100vh-7rem)] overflow-y-auto">
<p className="px-2 pb-2 text-[10px] font-bold uppercase tracking-wider text-gray-500 flex items-center gap-1.5">
{pillar === 'geo' ? (
<>
<Bot className="w-3.5 h-3.5 text-brand-600" /> Análisis de IA
</>
) : (
<>
<Leaf className="w-3.5 h-3.5 text-lime-600" /> Suite SEO
</>
)}
<Leaf className="w-3.5 h-3.5 text-lime-600" /> Suite SEO
</p>
{navGroups.map((g) => (
<div key={g.group} className="mb-3">
@@ -948,7 +942,7 @@ export default function OrganicoDashboard({
<section className="rounded-xl border border-gray-200 bg-white p-4 shadow-sm space-y-2">
<h3 className="text-sm font-semibold text-gray-900 flex items-center gap-2">
<Sparkles className="w-4 h-4 text-brand-600" />
Prioridades claras · {pillar === 'geo' ? 'GEO' : 'SEO'}
Prioridades claras · SEO
</h3>
<p className="text-[11px] text-gray-600">
Una por línea. Lo que hay que mejorar primero.
@@ -989,10 +983,7 @@ export default function OrganicoDashboard({
type="button"
disabled={saving}
onClick={() => {
const def =
pillar === 'geo'
? DEFAULT_EXPERT_PRIORITIES.geo
: DEFAULT_EXPERT_PRIORITIES.seo;
const def = DEFAULT_EXPERT_PRIORITIES.seo;
setPrioritiesText(def.join('\n'));
}}
className="ml-2 inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1.5 rounded-lg border border-gray-200 text-gray-700 hover:bg-gray-50"
@@ -1059,9 +1050,9 @@ export default function OrganicoDashboard({
</p>
<p className="text-xs text-amber-800">
Competencia de dominio, keyword gap y backlinks no salen de
GSC/GA4. Hay que conectar Ahrefs/Semrush (o importar CSV) para
alimentar este panel. Mientras tanto usa las secciones con datos
reales: visión general, rankings, keywords y páginas.
Search Console ni GA4. Cuando conectemos Ahrefs o Semrush, esta
vista se activará. El SEO con datos reales está en Visión
general, Keywords y Páginas.
</p>
<ul className="space-y-1.5 pt-1">
{section.actions.map((a) => (
@@ -1100,6 +1091,8 @@ export default function OrganicoDashboard({
)}
</div>
</div>
</>
)}
</div>
);
}