+page.svelte 12.4 KB
<script>
  import { onMount } from 'svelte';

  // Datos del servidor (reactivos)
  let { data } = $props();
  let organismoData = $derived(data.organismo);
  let hermanos = $derived(data.hermanos);

  // Estado
  let mounted = $state(false);

  onMount(() => {
    setTimeout(() => { mounted = true; }, 50);
  });
</script>

<svelte:head>
  <title>{organismoData.organismo_desc_organismo || organismoData.organismo} | Clasificador de Organismos</title>
  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@400;500&family=Instrument+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
</svelte:head>

<div class="page" class:mounted>
  <!-- Link a clasificadores -->
  <nav class="page-nav">
    <a href="/clasificadores/organismos" class="back-link">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <path d="M19 12H5M12 19l-7-7 7-7"/>
      </svg>
      Clasificador
    </a>
  </nav>

  <div class="dashboard-layout">
    <!-- CONTEXTO IZQUIERDO -->
    <aside class="dashboard-context">
      <div class="context-card">
        <h2 class="context-main-title">Contexto</h2>

        <!-- Info del grupo y subgrupo -->
        <div class="context-section">
          <h3 class="context-subtitle">Ubicación</h3>
          <div class="ubicacion-info">
            <div class="ubicacion-item">
              <span class="ubicacion-label">Grupo {organismoData.organismo_grupo}</span>
              <span class="ubicacion-value">{organismoData.organismo_desc_grupo}</span>
            </div>
            <div class="ubicacion-item">
              <span class="ubicacion-label">Subgrupo {organismoData.organismo_sub_grupo}</span>
              <span class="ubicacion-value">{organismoData.organismo_desc_sub_grupo}</span>
            </div>
          </div>
        </div>

        <!-- Hermanos -->
        {#if hermanos.length > 0}
          <div class="context-separator"></div>
          <div class="context-section">
            <h3 class="context-subtitle">Mismo subgrupo ({hermanos.length})</h3>
            <p class="context-hint">Otros organismos del mismo subgrupo.</p>
            <div class="hermanos-list">
              {#each hermanos.slice(0, 10) as hermano}
                <a href="/organismo/{hermano.organismo}" class="hermano-link">
                  <span class="hermano-code">{hermano.organismo}</span>
                  <span class="hermano-name">{hermano.organismo_desc_organismo}</span>
                </a>
              {/each}
              {#if hermanos.length > 10}
                <span class="hermanos-more">+{hermanos.length - 10} más</span>
              {/if}
            </div>
          </div>
        {/if}
      </div>
    </aside>

    <!-- CONTENIDO PRINCIPAL -->
    <main class="dashboard-main">
      <div class="main-content">
        <!-- Header -->
        <div class="main-header">
          <div class="main-title-pills">
            <span class="pill pill-codigo">{organismoData.organismo}</span>
          </div>
          <h1 class="main-title-name">{organismoData.organismo_desc_organismo}</h1>
          {#if organismoData.organismo_sigla_organismo && organismoData.organismo_sigla_organismo !== 'NC'}
            <p class="main-sigla">{organismoData.organismo_sigla_organismo}</p>
          {/if}
        </div>

        <!-- Info cards -->
        <div class="info-grid">
          <div class="info-card">
            <span class="info-label">Grupo</span>
            <span class="info-value">{organismoData.organismo_grupo}</span>
            <span class="info-desc">{organismoData.organismo_desc_grupo}</span>
          </div>

          <div class="info-card">
            <span class="info-label">Subgrupo</span>
            <span class="info-value">{organismoData.organismo_sub_grupo}</span>
            <span class="info-desc">{organismoData.organismo_desc_sub_grupo}</span>
          </div>

          {#if organismoData.gestiones}
            <div class="info-card">
              <span class="info-label">Gestiones</span>
              <span class="info-value">{organismoData.n_gestiones || ''} años</span>
              <span class="info-desc">{organismoData.gestiones}</span>
            </div>
          {/if}
        </div>
      </div>
    </main>
  </div>
</div>

<style>
  /* ═══════════════════════════════════════════════════════════════
     BASE
     ═══════════════════════════════════════════════════════════════ */
  .page {
    min-height: 100vh;
    padding: 1rem;
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.4s ease, transform 0.4s ease;
  }

  .page.mounted {
    opacity: 1;
    transform: translateY(0);
  }

  /* ═══════════════════════════════════════════════════════════════
     NAV
     ═══════════════════════════════════════════════════════════════ */
  .page-nav {
    max-width: 1400px;
    margin: 0 auto 1.5rem;
  }

  .back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-secondary, #888);
    text-decoration: none;
    font-size: 0.875rem;
    transition: color 0.2s;
  }

  .back-link:hover {
    color: var(--text-primary, #fff);
  }

  /* ═══════════════════════════════════════════════════════════════
     LAYOUT
     ═══════════════════════════════════════════════════════════════ */
  .dashboard-layout {
    display: grid;
    grid-template-columns: 300px 1fr;
    gap: 2rem;
    max-width: 1400px;
    margin: 0 auto;
  }

  @media (max-width: 900px) {
    .dashboard-layout {
      grid-template-columns: 1fr;
    }

    .dashboard-context {
      order: 2;
    }
  }

  /* ═══════════════════════════════════════════════════════════════
     SIDEBAR
     ═══════════════════════════════════════════════════════════════ */
  .dashboard-context {
    position: sticky;
    top: 5rem;
    height: fit-content;
  }

  .context-card {
    background: var(--card-bg, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.08));
    border-radius: 16px;
    padding: 1.5rem;
  }

  .context-main-title {
    font-family: 'Instrument Sans', sans-serif;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-tertiary, #666);
    margin-bottom: 1.5rem;
  }

  .context-section {
    margin-bottom: 1.5rem;
  }

  .context-subtitle {
    font-family: 'Instrument Sans', sans-serif;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--text-secondary, #aaa);
    margin-bottom: 0.75rem;
  }

  .context-hint {
    font-size: 0.75rem;
    color: var(--text-tertiary, #666);
    margin-bottom: 1rem;
  }

  .context-separator {
    height: 1px;
    background: var(--border-color, rgba(255, 255, 255, 0.08));
    margin: 1.5rem 0;
  }

  /* ═══════════════════════════════════════════════════════════════
     UBICACION INFO
     ═══════════════════════════════════════════════════════════════ */
  .ubicacion-info {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
  }

  .ubicacion-item {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.75rem;
    background: var(--hover-bg, rgba(255, 255, 255, 0.03));
    border-radius: 8px;
  }

  .ubicacion-label {
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    color: var(--text-tertiary, #666);
    text-transform: uppercase;
  }

  .ubicacion-value {
    font-size: 0.85rem;
    color: var(--text-primary, #fff);
  }

  /* ═══════════════════════════════════════════════════════════════
     HERMANOS LIST
     ═══════════════════════════════════════════════════════════════ */
  .hermanos-list {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
  }

  .hermano-link {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-radius: 6px;
    text-decoration: none;
    color: var(--text-secondary, #aaa);
    font-size: 0.8rem;
    transition: all 0.2s ease;
  }

  .hermano-link:hover {
    background: var(--hover-bg, rgba(255, 255, 255, 0.05));
    color: var(--text-primary, #fff);
  }

  .hermano-code {
    font-family: 'DM Mono', monospace;
    font-size: 0.7rem;
    opacity: 0.6;
    flex-shrink: 0;
    min-width: 2.5rem;
  }

  .hermano-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .hermanos-more {
    font-size: 0.75rem;
    color: var(--text-tertiary, #666);
    padding: 0.5rem 0.75rem;
  }

  /* ═══════════════════════════════════════════════════════════════
     MAIN CONTENT
     ═══════════════════════════════════════════════════════════════ */
  .dashboard-main {
    min-width: 0;
  }

  .main-content {
    background: var(--card-bg, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.08));
    border-radius: 16px;
    padding: 2rem;
  }

  .main-header {
    margin-bottom: 2rem;
  }

  .main-title-pills {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
  }

  .pill {
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
  }

  .pill-codigo {
    background: var(--hover-bg, rgba(255, 255, 255, 0.05));
    color: var(--text-secondary, #aaa);
    font-family: 'DM Mono', monospace;
  }

  .main-title-name {
    font-family: 'DM Serif Display', serif;
    font-size: 2rem;
    font-weight: 400;
    color: var(--text-primary, #fff);
    line-height: 1.2;
    margin: 0;
  }

  .main-sigla {
    font-family: 'DM Mono', monospace;
    font-size: 0.9rem;
    color: var(--text-tertiary, #666);
    margin-top: 0.5rem;
  }

  /* ═══════════════════════════════════════════════════════════════
     INFO GRID
     ═══════════════════════════════════════════════════════════════ */
  .info-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
  }

  .info-card {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 1rem;
    background: var(--hover-bg, rgba(255, 255, 255, 0.03));
    border-radius: 12px;
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.05));
  }

  .info-label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-tertiary, #666);
  }

  .info-value {
    font-family: 'DM Mono', monospace;
    font-size: 1.25rem;
    color: var(--text-primary, #fff);
  }

  .info-desc {
    font-size: 0.8rem;
    color: var(--text-secondary, #aaa);
    line-height: 1.4;
  }
</style>