Receta Dashboard Starter Charts Sidebar

Receta: App Starter / Dashboard

Plantilla base completa con navbar, sidebar, KPIs, tabla de datos, gráficos, timeline y estado vacío. El punto de partida ideal para cualquier aplicación.

Código fuente del template

template.html
{% extends "showcase/base_empty.html" %}
{% load components_ui %}

{% block title %}Receta: App Starter — Django Components UI{% endblock %}

{% block content %}
<!--
    ╔══════════════════════════════════════════════════════╗
    ║  PLANTILLA DE INICIO — django-components-ui          ║
    ║  Copia este archivo como base para tu aplicación     ║
    ║  Personaliza los menu_items, el título y el contenido║
    ╚══════════════════════════════════════════════════════╝
-->
<div class="h-full flex flex-col overflow-hidden bg-gray-50" id="app-root">

    <!-- ══ NAVBAR ══
         comp_navbar renderiza barra superior con logo, usuario y menú móvil.
         Pasa show_user=True para mostrar el avatar del usuario de sesión. -->
    <div class="z-30 flex-shrink-0">
        {% comp_navbar title="Mi Aplicación" show_user=True %}
    </div>

    <div class="flex flex-1 overflow-hidden">

        <!-- ══ SIDEBAR ══
             Pasa menu_items desde la view. Cada item puede tener 'children' para submenús.
             is_open controla si empieza expandido o colapsado. -->
        <div id="sidebar-wrapper"
             class="flex-shrink-0 bg-gray-900 hidden lg:block shadow-xl relative z-20 transition-all duration-300">
            {% comp_sidebar_menu menu_items=menu_items title="Mi App" is_open=True footer_text="v1.0 — Powered by django-components-ui" %}
        </div>

        <!-- ══ MAIN CONTENT ══ -->
        <main class="flex-1 overflow-y-auto focus:outline-none" tabindex="-1">
            <div class="p-6 lg:p-10 space-y-8 max-w-7xl mx-auto">

                <!-- ── Page Header ─────────────────────────────────── -->
                <header class="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
                    <div>
                        {% comp_title text="Dashboard" level=1 %}
                        <p class="text-gray-500 text-sm mt-1 font-medium">
                            Resumen del sistema — {{ fecha_actual }}
                        </p>
                    </div>
                    <div class="flex items-center gap-2.5">
                        <!-- Acción principal de la página -->
                        {% comp_button text="Nueva acción" color="primary" icon="PlusIcon" onclick="alert('¡Personaliza esta acción!')" %}
                    </div>
                </header>

                <!-- ── KPI Cards ────────────────────────────────────── -->
                <section>
                    <h2 class="text-xs font-black text-gray-400 uppercase tracking-widest mb-4">Resumen</h2>
                    <div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4">
                        {% for kpi in kpis %}
                        {% comp_data_card title=kpi.title value=kpi.value trend=kpi.trend color=kpi.color icon=kpi.icon sparkline_data=kpi.sparkline %}
                        {% endfor %}
                    </div>
                </section>

                <!-- ── Main Grid ────────────────────────────────────── -->
                <div class="grid grid-cols-1 xl:grid-cols-3 gap-6">

                    <!-- Tabla principal (ocupa 2/3) -->
                    <div class="xl:col-span-2 space-y-4">
                        <div class="flex items-center justify-between">
                            <h2 class="text-xs font-black text-gray-400 uppercase tracking-widest">Datos Recientes</h2>
                            <a href="#" class="text-xs text-primary-600 hover:text-primary-700 font-semibold">Ver todo →</a>
                        </div>
                        {% comp_tabla id="main-table" data_url="/api/mock-data/" columns=tabla_columnas searchable=True page_size=8 height="380px" %}
                    </div>

                    <!-- Panel lateral derecho (ocupa 1/3) -->
                    <div class="space-y-6">
                        <!-- Estadísticas rápidas -->
                        <div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-5">
                            {% comp_stat_list title="Métricas Clave" items=stat_items %}
                        </div>

                        <!-- Actividad reciente -->
                        <div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-5">
                            <h3 class="text-xs font-black text-gray-400 uppercase tracking-widest mb-4">Actividad Reciente</h3>
                            {% comp_timeline items=timeline_items %}
                        </div>
                    </div>
                </div>

                <!-- ── Sección con estado vacío (ejemplo) ──────────── -->
                <section class="bg-white rounded-2xl border border-gray-200 shadow-sm">
                    <div class="px-6 py-4 border-b border-gray-100 flex items-center justify-between">
                        <h2 class="text-sm font-bold text-gray-700 flex items-center gap-2">
                            {% comp_icon name="BellIcon" size="w-4 h-4 text-warning-500" %}
                            Notificaciones
                        </h2>
                        {% comp_badge text="0 nuevas" color="warning" %}
                    </div>
                    <!-- comp_empty_state: muestra cuando no hay datos -->
                    {% comp_empty_state title="Sin notificaciones pendientes" description="Cuando haya alertas o mensajes nuevos aparecerán aquí." icon="BellSlashIcon" color="warning" action_text="Configurar alertas" action_onclick="alert('Ir a configuración de alertas')" %}
                </section>

                <!-- ── Gráfico ──────────────────────────────────────── -->
                <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
                    <div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
                        <h3 class="text-sm font-bold text-gray-800 mb-4">Evolución Mensual</h3>
                        {% comp_chart id="starter-chart" type="line" data=chart_data height="220px" %}
                    </div>
                    <div class="bg-white rounded-2xl border border-gray-200 shadow-sm p-6">
                        <h3 class="text-sm font-bold text-gray-800 mb-4">Distribución por Categoría</h3>
                        {% comp_chart id="starter-donut" type="doughnut" data=donut_data height="220px" %}
                    </div>
                </div>

                <div class="h-8"></div>
            </div>
        </main>
    </div>
</div>

<!-- ══ TIP PARA DESARROLLADORES ══ -->
<div id="dev-tip"
     class="fixed bottom-4 right-4 z-50 max-w-xs bg-gray-900 text-white rounded-2xl p-4 shadow-2xl text-xs leading-relaxed">
    <div class="flex items-start gap-2.5 mb-2">
        {% comp_icon name="CodeBracketIcon" size="w-4 h-4 text-primary-400" %}
        <span class="font-bold text-primary-400">Plantilla de inicio</span>
        <button onclick="document.getElementById('dev-tip').remove()"
                class="ml-auto text-gray-500 hover:text-gray-300 transition-colors">✕</button>
    </div>
    <p class="text-gray-400">Copia esta página como base. Sustituye los datos de contexto en tu <code class="text-primary-300">views.py</code> y personaliza el contenido.</p>
</div>
{% endblock %}

Vista previa

Pantalla completa
/recipes/starter/