Files
ludikevent_crm/templates/dashboard/home.twig
2026-02-06 14:20:28 +01:00

133 lines
11 KiB
Twig

{% extends 'dashboard/base.twig' %}
{% block title %}Tableau de bord{% endblock %}
{% macro business_card(title, value, subtitle, color) %}
<div class="group relative">
<div class="absolute inset-0 bg-{{ color }}-600/20 blur-3xl opacity-0 group-hover:opacity-100 transition-opacity"></div>
<div class="relative overflow-hidden backdrop-blur-2xl bg-white/5 border border-white/10 rounded-[3rem] p-8 transition-all hover:-translate-y-2">
<p class="text-[10px] font-black text-{{ color }}-400 uppercase tracking-[0.4em] mb-4 italic">{{ title }}</p>
<h2 class="text-7xl font-black text-white tracking-tighter italic leading-none">{{ value }}</h2>
<p class="text-[11px] font-bold text-slate-400 mt-4 uppercase">{{ subtitle }}</p>
</div>
</div>
{% endmacro %}
{% macro web_vital(label, value, unit, is_good, good_text, bad_text) %}
<div class="backdrop-blur-xl bg-slate-900/40 border border-white/5 p-6 rounded-3xl">
<p class="text-[9px] font-black text-slate-300 uppercase tracking-widest mb-3">{{ label }}</p>
<div class="flex items-end gap-3">
<span class="text-3xl font-black text-white italic leading-none">{{ value }}{{ unit }}</span>
<span class="text-[10px] px-2 py-0.5 rounded {{ is_good ? 'bg-emerald-500/10 text-emerald-400' : 'bg-rose-500/10 text-rose-400' }} font-bold uppercase italic">
{{ is_good ? good_text : bad_text }}
</span>
</div>
</div>
{% endmacro %}
{% macro traffic_source(label, value, color, icon_path) %}
<div class="flex items-center justify-between p-4 rounded-2xl bg-white/5 border border-white/5 hover:bg-white/10 transition-colors">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl bg-{{ color }}-500/20 flex items-center justify-center text-{{ color }}-400">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="{{ icon_path }}"/></svg>
</div>
<div>
<p class="text-[9px] font-black text-slate-400 uppercase tracking-widest mb-0.5">{{ label }}</p>
<p class="text-lg font-black text-white leading-none">{{ value|default(0) }}</p>
</div>
</div>
</div>
{% endmacro %}
{% import _self as macros %}
{% block body %}
<div class="min-h-screen p-4 md:p-8 space-y-10">
{# --- HEADER STATS (GLASS PILLS) --- #}
<section class="flex flex-wrap gap-4 items-center mb-8" aria-label="Statistiques rapides">
<div class="flex flex-col md:flex-row md:items-center gap-4 w-full md:w-auto">
<div class="flex items-center gap-2 px-2">
<h1 class="text-xl font-black italic text-slate-900 dark:text-white uppercase tracking-tighter">Analytics</h1>
<a href="{{ statview }}" target="_blank" class="group flex items-center gap-2 bg-white/5 px-4 py-2 rounded-xl border border-white/10 hover:bg-blue-600 transition-all duration-300">
<span class="text-[10px] font-bold text-slate-300 group-hover:text-white transition-colors uppercase tracking-widest">reservation.ludikevent.fr</span>
<svg class="w-3 h-3 text-slate-400 group-hover:text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>
</a>
</div>
<div class="flex gap-3">
<div class="backdrop-blur-md bg-white/10 border border-white/10 px-6 py-2.5 rounded-full shadow-lg flex items-center gap-3">
<div class="w-2 h-2 bg-emerald-500 rounded-full animate-pulse"></div>
<span class="text-[11px] font-black uppercase tracking-widest text-slate-300"><span class="text-white text-sm">{{ nbVisitor }}</span> Visiteurs</span>
</div>
<div class="backdrop-blur-md bg-white/10 border border-white/10 px-6 py-2.5 rounded-full shadow-lg flex items-center gap-3">
<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
<span class="text-[11px] font-black uppercase tracking-widest text-slate-300"><span class="text-white text-sm">{{ nbView }}</span> Vues</span>
</div>
</div>
</div>
</section>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
{# --- CARTES BUSINESS --- #}
{{ macros.business_card('Inventaire', product, 'Produits actifs', 'blue') }}
{{ macros.business_card('Devis', devis_wait_sign, 'À faire signer', 'amber') }}
{{ macros.business_card('Clients', customers, 'Fiches uniques', 'emerald') }}
{# --- SOURCES DE TRAFIC --- #}
<section class="md:col-span-3 grid grid-cols-2 md:grid-cols-5 gap-4 bg-white/5 p-6 rounded-[2.5rem] border border-white/10 shadow-inner" aria-label="Sources de trafic">
<div class="col-span-2 md:col-span-5 flex items-center gap-4 mb-2 px-4">
<span class="h-[1px] flex-1 bg-white/10"></span>
<h4 class="text-[10px] font-black text-slate-300 uppercase tracking-[0.3em]">Sources de Trafic</h4>
<span class="h-[1px] flex-1 bg-white/10"></span>
</div>
{{ macros.traffic_source('Google', source_google, 'blue', 'M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z') }}
{{ macros.traffic_source('Facebook', source_facebook, 'indigo', 'M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z') }}
{{ macros.traffic_source('Instagram', source_instagram, 'pink', 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z') }}
{{ macros.traffic_source('TikTok', source_tiktok, 'slate', 'M19.59 6.69a4.83 4.83 0 01-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 01-5.2 1.74 2.89 2.89 0 012.31-4.64 2.93 2.93 0 01.88.13V9.4a6.84 6.84 0 00-1-.05A6.33 6.33 0 005 20.1a6.34 6.34 0 0010.86-4.43v-7a8.16 8.16 0 004.77 1.52v-3.4a4.85 4.85 0 01-1-.1z') }}
{{ macros.traffic_source('Autre', source_other, 'orange', 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z') }}
</section>
{# --- SECTION PERFORMANCE (Core Web Vitals) --- #}
<section class="md:col-span-3 grid grid-cols-1 md:grid-cols-3 gap-6 bg-white/5 p-6 rounded-[2.5rem] border border-white/10 shadow-inner" aria-label="Performance Web Vitals">
<div class="md:col-span-3 flex items-center gap-4 mb-2 px-4">
<span class="h-[1px] flex-1 bg-white/10"></span>
<h4 class="text-[10px] font-black text-slate-300 uppercase tracking-[0.3em]">Core Web Vitals (24h)</h4>
<span class="h-[1px] flex-1 bg-white/10"></span>
</div>
{{ macros.web_vital('Moyenne LCP', avg_lcp|number_format(2), 's', avg_lcp < 2.5, 'Bon', 'Lent') }}
{{ macros.web_vital('Moyenne CLS', avg_cls|number_format(3), '', avg_cls < 0.1, 'Stable', 'Instable') }}
{{ macros.web_vital('Moyenne INP', avg_inp|number_format(0), 'ms', avg_inp < 200, 'Fluide', 'Lent') }}
</section>
{# --- JOURNAL DE MAINTENANCE --- #}
<section class="group relative md:col-span-3" aria-label="Journal de maintenance">
<div class="absolute inset-0 bg-gradient-to-r from-purple-600/10 via-transparent to-blue-600/10 blur-3xl opacity-0 group-hover:opacity-100 transition-opacity"></div>
<div class="relative overflow-hidden backdrop-blur-2xl bg-white/5 border border-white/10 rounded-[3rem] p-10">
<div class="flex items-center justify-between mb-8">
<div>
<p class="text-[10px] font-black text-purple-400 uppercase tracking-[0.4em] mb-2 italic">Journal système</p>
<h3 class="text-2xl font-black text-white uppercase tracking-tighter">Mises à jour & Maintenance</h3>
</div>
<div class="hidden md:block px-4 py-2 bg-purple-500/10 border border-purple-500/20 rounded-xl text-purple-500 text-[10px] font-black uppercase italic">{{ updates|length }} logs</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-12 gap-y-8">
{% for update in updates %}
{% set tag_bg_class = update.tag_color|replace({'text-': 'bg-'})|split(' ')[0] %}
<div class="relative pl-8 border-l-2 border-slate-700/50 hover:border-purple-500 transition-colors">
<div class="absolute -left-[9px] top-0 w-4 h-4 rounded-full border-4 border-slate-900 {{ tag_bg_class }}"></div>
<div class="flex items-center gap-3 mb-2">
<span class="px-2 py-0.5 rounded-md border text-[8px] font-black uppercase {{ update.tag_color }}">{{ update.type }}</span>
<span class="text-[10px] font-bold text-slate-400 uppercase">{{ update.date|date('d/m/Y') }}</span>
</div>
<p class="text-xs font-bold text-slate-200 leading-relaxed">{{ update.message }}</p>
</div>
{% endfor %}
</div>
</div>
</section>
</div>
</div>
{% endblock %}