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

  const rubro = data.rubro;
  const padres = data.padres;
  const hijos = data.hijos;

  function parseDescripciones(descripcionesStr) {
    if (!descripcionesStr) return [];
    try {
      const parsed = JSON.parse(descripcionesStr);
      return parsed.sort((a, b) => {
        const maxYearA = getMaxYear(a.rangos);
        const maxYearB = getMaxYear(b.rangos);
        return maxYearB - maxYearA;
      });
    } 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 = { tipo: 'Tipo', clase: 'Clase', cuenta: 'Cuenta', sub_cuenta: 'Subcuenta' };
    return labels[nivel] || nivel;
  }

  // Obtener la descripción correcta según el nivel
  function getDescripcion(item) {
    if (item.nivel === 'tipo') return item.desc_tipo;
    if (item.nivel === 'clase') return item.desc_clase;
    if (item.nivel === 'cuenta') return item.desc_cuenta;
    if (item.nivel === 'sub_cuenta') return item.desc_sub_cuenta;
    return item.desc_rubros;
  }

  function getHijosLabel(nivel) {
    const labels = { tipo: 'Clases', clase: 'Cuentas', cuenta: 'Subcuentas' };
    return labels[nivel] || 'Hijos';
  }

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

<svelte:head>
  <title>{getDescripcion(rubro)} | 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/rubros" class="hover:text-slate-700">Rubros</a>
        {#each padres as padre}
          <span>/</span>
          <a href="/rubro/{padre.rubro}" class="hover:text-slate-700">{getDescripcion(padre)}</a>
        {/each}
        <span>/</span>
        <span class="text-slate-900">{getDescripcion(rubro)}</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(rubro.nivel)}</p>
      <div class="flex items-baseline gap-4">
        <span class="font-mono text-2xl text-slate-400">{rubro.rubro}</span>
        <h1 class="text-2xl font-medium text-slate-900">{getDescripcion(rubro)}</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="/rubro/{padre.rubro}"
                class="text-sm text-slate-600 hover:text-blue-600"
              >
                <span class="font-mono text-xs text-slate-400">{padre.rubro}</span>
                {getDescripcion(padre)}
              </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">{rubro.rubro}</span>
              {getDescripcion(rubro)}
            </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">
          {getHijosLabel(rubro.nivel)} ({hijos.length})
        </h2>

        <div class="border rounded-lg divide-y">
          {#each hijos as hijo}
            {@const hijoDescs = parseDescripciones(hijo.descripciones)}
            <a
              href="/rubro/{hijo.rubro}"
              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.rubro}</span>
                <span class="text-slate-900">{getDescripcion(hijo)}</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/rubros"
        class="text-sm text-blue-600 hover:underline"
      >
        Volver al clasificador
      </a>
    </div>
  </main>
</div>