+page.svelte 5.69 KB
<script>
  let { data } = $props();

  const objeto = data.objeto;
  const padres = data.padres;
  const hijos = data.hijos;

  function parseDescripciones(descripcionesStr) {
    if (!descripcionesStr) return [];
    try {
      const parsed = JSON.parse(descripcionesStr);
      // Ordenar por año más reciente (extraer el máximo año de cada rango)
      return parsed.sort((a, b) => {
        const maxYearA = getMaxYear(a.rangos);
        const maxYearB = getMaxYear(b.rangos);
        return maxYearB - maxYearA; // Descendente, más reciente primero
      });
    } catch {
      return [];
    }
  }

  function getMaxYear(rangos) {
    if (!rangos) return 0;
    const years = rangos.match(/\d{4}/g);
    if (!years) return 0;
    return Math.max(...years.map(y => parseInt(y)));
  }

  function getNivelLabel(nivel) {
    const labels = { grupo: 'Grupo', subgrupo: 'Subgrupo', partida: 'Partida', subpartida: 'Subpartida' };
    return labels[nivel] || nivel;
  }

  const descripciones = parseDescripciones(objeto.descripciones);
</script>

<svelte:head>
  <title>{objeto.desc_objeto} | Presupuesto Público</title>
</svelte:head>

<div class="min-h-screen bg-white">
  <header class="border-b bg-slate-50">
    <div class="max-w-4xl mx-auto px-6 py-4">
      <nav class="text-sm text-slate-500 mb-2 flex flex-wrap items-center gap-1">
        <a href="/" class="hover:text-slate-700">Inicio</a>
        <span>/</span>
        <a href="/clasificadores/objeto-gasto" class="hover:text-slate-700">Objeto del Gasto</a>
        {#each padres as padre}
          <span>/</span>
          <a href="/objeto/{padre.objeto}" class="hover:text-slate-700">{padre.desc_objeto}</a>
        {/each}
        <span>/</span>
        <span class="text-slate-900">{objeto.desc_objeto}</span>
      </nav>
    </div>
  </header>

  <main class="max-w-4xl mx-auto px-6 py-8">
    <!-- Encabezado -->
    <div class="mb-8">
      <p class="text-xs text-slate-500 uppercase tracking-wide mb-1">{getNivelLabel(objeto.nivel)}</p>
      <div class="flex items-baseline gap-4">
        <span class="font-mono text-2xl text-slate-400">{objeto.objeto}</span>
        <h1 class="text-2xl font-medium text-slate-900">{objeto.desc_objeto}</h1>
      </div>
    </div>

    <!-- Descripciones -->
    <section class="mb-10">
      <h2 class="text-sm font-medium text-slate-700 mb-4">
        {#if descripciones.length > 1}
          Descripciones ({descripciones.length} variaciones)
        {:else}
          Descripción
        {/if}
      </h2>

      <div class="space-y-4">
        {#each descripciones as desc, i}
          <div class="border-l-2 {i === 0 ? 'border-blue-500 bg-blue-50/50' : 'border-slate-200 bg-slate-50/50'} pl-4 py-3 rounded-r">
            <p class="text-xs text-slate-500 mb-2">
              {#if i === 0 && descripciones.length > 1}
                <span class="text-blue-600 font-medium">Vigente</span>
                <span class="mx-1">·</span>
              {/if}
              {desc.rangos}
            </p>
            <p class="text-slate-700 leading-relaxed">{desc.descripcion}</p>
          </div>
        {/each}
      </div>
    </section>

    <!-- Jerarquía -->
    {#if padres.length > 0}
      <section class="mb-10">
        <h2 class="text-sm font-medium text-slate-700 mb-4">Jerarquía</h2>
        <div class="space-y-2">
          {#each padres as padre, i}
            <div class="flex items-center gap-2" style="margin-left: {i * 1.5}rem">
              <span class="text-slate-300">└</span>
              <a
                href="/objeto/{padre.objeto}"
                class="text-sm text-slate-600 hover:text-blue-600"
              >
                <span class="font-mono text-xs text-slate-400">{padre.objeto}</span>
                {padre.desc_objeto}
              </a>
            </div>
          {/each}
          <div class="flex items-center gap-2" style="margin-left: {padres.length * 1.5}rem">
            <span class="text-blue-500">└</span>
            <span class="text-sm font-medium text-blue-600">
              <span class="font-mono text-xs">{objeto.objeto}</span>
              {objeto.desc_objeto}
            </span>
          </div>
        </div>
      </section>
    {/if}

    <!-- Hijos -->
    {#if hijos.length > 0}
      <section class="mb-10">
        <h2 class="text-sm font-medium text-slate-700 mb-4">
          {#if objeto.nivel === 'grupo'}
            Subgrupos ({hijos.length})
          {:else if objeto.nivel === 'subgrupo'}
            Partidas ({hijos.length})
          {:else if objeto.nivel === 'partida'}
            Subpartidas ({hijos.length})
          {/if}
        </h2>

        <div class="border rounded-lg divide-y">
          {#each hijos as hijo}
            {@const hijoDescs = parseDescripciones(hijo.descripciones)}
            <a
              href="/objeto/{hijo.objeto}"
              class="block px-4 py-3 hover:bg-slate-50 transition-colors"
            >
              <div class="flex items-baseline gap-3">
                <span class="font-mono text-sm text-slate-400">{hijo.objeto}</span>
                <span class="text-slate-900">{hijo.desc_objeto}</span>
                {#if hijo.n_variaciones > 1}
                  <span class="text-xs text-orange-500">({hijo.n_variaciones} var.)</span>
                {/if}
              </div>
              {#if hijoDescs.length > 0}
                <p class="text-sm text-slate-500 mt-1 ml-16">{hijoDescs[0].descripcion}</p>
              {/if}
            </a>
          {/each}
        </div>
      </section>
    {/if}

    <!-- Volver -->
    <div class="pt-6 border-t">
      <a
        href="/clasificadores/objeto-gasto"
        class="text-sm text-blue-600 hover:underline"
      >
        Volver al clasificador
      </a>
    </div>
  </main>
</div>