```
✨ feat(dashboard): Affiche les statistiques principales sur le tableau de bord.
```
This commit is contained in:
@@ -8,6 +8,9 @@ use App\Entity\AccountResetPasswordRequest;
|
||||
use App\Form\RequestPasswordConfirmType;
|
||||
use App\Form\RequestPasswordRequestType;
|
||||
use App\Repository\AccountRepository;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\DevisRepository;
|
||||
use App\Repository\ProductRepository;
|
||||
use App\Service\ResetPassword\Event\ResetPasswordConfirmEvent;
|
||||
use App\Service\ResetPassword\Event\ResetPasswordEvent;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -24,8 +27,12 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
class HomeController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/crm', name: 'app_crm', options: ['sitemap' => false], methods: ['GET','POST'])]
|
||||
public function crm(): Response
|
||||
public function crm(ProductRepository $productRepository,CustomerRepository $customerRepository,DevisRepository $devisRepository): Response
|
||||
{
|
||||
return $this->render('dashboard/home.twig');
|
||||
return $this->render('dashboard/home.twig',[
|
||||
'product' => $productRepository->count(),
|
||||
'devis_wait_sign' => $devisRepository->waitSign(),
|
||||
'customers' => $customerRepository->count(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,14 @@ class DevisRepository extends ServiceEntityRepository
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
public function waitSign()
|
||||
{
|
||||
return count( $this->createQueryBuilder('d')
|
||||
->andWhere('d.state != :status')
|
||||
->andWhere('d.state != :status2')
|
||||
->setParameter('status','signed')
|
||||
->setParameter('status2','cancel')
|
||||
->getQuery()->getArrayResult());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,35 @@
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{# FOOTER GLASSMORPHISM #}
|
||||
<footer class="mt-auto p-6 md:p-10">
|
||||
<div class="bg-white/40 dark:bg-slate-800/40 backdrop-blur-xl border border-white/20 dark:border-slate-700/50 rounded-[2rem] p-6 shadow-xl">
|
||||
<div class="flex flex-col md:flex-row items-center justify-between gap-4 text-center md:text-left">
|
||||
|
||||
{# Copyright & Branding #}
|
||||
<div class="space-y-1">
|
||||
<p class="text-[10px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-[0.2em]">Propulsé par</p>
|
||||
<p class="text-sm font-bold text-slate-800 dark:text-white">
|
||||
Développé par <span class="text-blue-600">SARL SITECONSEIL</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{# Versioning & Links #}
|
||||
<div class="flex flex-col items-center md:items-end space-y-1">
|
||||
<div class="flex items-center space-x-4">
|
||||
<a href="https://www.siteconseil.fr" target="_blank" class="text-xs font-medium text-slate-500 hover:text-blue-600 transition-colors underline decoration-blue-500/30 underline-offset-4">www.siteconseil.fr</a>
|
||||
<span class="w-1 h-1 bg-slate-300 dark:bg-slate-700 rounded-full"></span>
|
||||
<a href="mailto:s.com@siteconseil.fr" class="text-xs font-medium text-slate-500 hover:text-blue-600 transition-colors">s.com@siteconseil.fr</a>
|
||||
</div>
|
||||
<p class="text-[9px] font-black text-slate-400/60 uppercase tracking-widest">
|
||||
Crm Engine <span class="text-slate-500 dark:text-slate-300">1.0.0</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</main> {# Fin du main existant #}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,2 +1,63 @@
|
||||
{% extends 'dashboard/base.twig' %}
|
||||
|
||||
{% block title %}Tableau de bord{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="space-y-8">
|
||||
{# Grille principale avec effet Glass #}
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
|
||||
<div class="relative group overflow-hidden bg-white/40 dark:bg-slate-800/40 backdrop-blur-xl border border-white/20 dark:border-slate-700/50 rounded-[2.5rem] p-8 shadow-2xl transition-all hover:scale-[1.02] duration-300">
|
||||
<div class="absolute -right-4 -top-4 w-24 h-24 bg-blue-500/10 rounded-full blur-2xl group-hover:bg-blue-500/20 transition-colors"></div>
|
||||
|
||||
<div class="relative flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-[10px] font-black text-blue-600 dark:text-blue-400 uppercase tracking-[0.3em] mb-1">Inventaire</p>
|
||||
<h2 class="text-5xl font-extrabold text-slate-900 dark:text-white tracking-tight">{{ product }}</h2>
|
||||
<p class="text-sm font-medium text-slate-500 dark:text-slate-400 mt-2">Produits actifs</p>
|
||||
</div>
|
||||
<div class="w-16 h-16 bg-blue-600/10 border border-blue-600/20 rounded-2xl flex items-center justify-center text-blue-600 shadow-inner">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative group overflow-hidden bg-white/40 dark:bg-slate-800/40 backdrop-blur-xl border border-white/20 dark:border-slate-700/50 rounded-[2.5rem] p-8 shadow-2xl transition-all hover:scale-[1.02] duration-300">
|
||||
<div class="absolute -right-4 -top-4 w-24 h-24 bg-amber-500/10 rounded-full blur-2xl group-hover:bg-amber-500/20 transition-colors"></div>
|
||||
|
||||
<div class="relative flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-[10px] font-black text-amber-600 dark:text-amber-400 uppercase tracking-[0.3em] mb-1">Devis</p>
|
||||
<h2 class="text-5xl font-extrabold text-slate-900 dark:text-white tracking-tight">{{ devis_wait_sign }}</h2>
|
||||
<p class="text-sm font-medium text-slate-500 dark:text-slate-400 mt-2">Devis en attends de signature</p>
|
||||
</div>
|
||||
<div class="w-16 h-16 bg-amber-600/10 border border-amber-600/20 rounded-2xl flex items-center justify-center text-amber-600 shadow-inner">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative group overflow-hidden bg-white/40 dark:bg-slate-800/40 backdrop-blur-xl border border-white/20 dark:border-slate-700/50 rounded-[2.5rem] p-8 shadow-2xl transition-all hover:scale-[1.02] duration-300">
|
||||
<div class="absolute -right-4 -top-4 w-24 h-24 bg-emerald-500/10 rounded-full blur-2xl group-hover:bg-emerald-500/20 transition-colors"></div>
|
||||
|
||||
<div class="relative flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-[10px] font-black text-emerald-600 dark:text-emerald-400 uppercase tracking-[0.3em] mb-1">Base de données</p>
|
||||
<h2 class="text-5xl font-extrabold text-slate-900 dark:text-white tracking-tight">{{ customers }}</h2>
|
||||
<p class="text-sm font-medium text-slate-500 dark:text-slate-400 mt-2">Clients totaux</p>
|
||||
</div>
|
||||
<div class="w-16 h-16 bg-emerald-600/10 border border-emerald-600/20 rounded-2xl flex items-center justify-center text-emerald-600 shadow-inner">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -155,17 +155,41 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# --- ACTION FINALE --- #}
|
||||
<div class="mt-auto">
|
||||
<a href="{{ path('reservation_contact', {id: product.id}) }}"
|
||||
class="flex items-center justify-center w-full py-8 bg-slate-900 text-white rounded-[2.5rem] font-black uppercase text-[12px] tracking-[0.3em] hover:bg-blue-600 transition-all shadow-2xl hover:scale-[1.02] active:scale-95">
|
||||
Vérifier la disponibilité
|
||||
</a>
|
||||
{% if product.category == "2-7 ans" %}
|
||||
{# --- BLOC CONDITION SPÉCIALE (STYLE ÉPURÉ) --- #}
|
||||
<div class="mt-auto">
|
||||
<div class="mb-6 p-6 border-2 border-slate-100 rounded-[2.5rem] text-center">
|
||||
<p class="text-[12px] font-bold text-slate-800 leading-relaxed uppercase tracking-wide">h
|
||||
La réservation de cette structure est soumise à des conditions spéciales.
|
||||
</p>
|
||||
<p class="mt-2 text-[11px] text-slate-500 font-medium">
|
||||
Merci de nous contacter pour la réserver.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="text-center mt-6 text-[9px] font-black text-slate-300 uppercase tracking-widest italic">
|
||||
Devis gratuit • Ludikevent • Qualité Pro
|
||||
</p>
|
||||
</div>
|
||||
<a href="{{ path('reservation_contact', {id: product.id}) }}"
|
||||
class="flex items-center justify-center w-full py-8 bg-slate-900 text-white rounded-[2.5rem] font-black uppercase text-[12px] tracking-[0.3em] hover:bg-[#f39e36] transition-all shadow-2xl hover:scale-[1.02] active:scale-95">
|
||||
Nous contacter
|
||||
</a>
|
||||
|
||||
<p class="text-center mt-6 text-[9px] font-black text-slate-300 uppercase tracking-widest italic">
|
||||
Devis gratuit • Ludikevent • Qualité Pro
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
{# --- ACTION FINALE ORIGINALE --- #}
|
||||
<div class="mt-auto">
|
||||
<a href="{{ path('reservation_contact', {id: product.id}) }}"
|
||||
class="flex items-center justify-center w-full py-8 bg-slate-900 text-white rounded-[2.5rem] font-black uppercase text-[12px] tracking-[0.3em] hover:bg-[#f39e36] transition-all shadow-2xl hover:scale-[1.02] active:scale-95">
|
||||
Vérifier la disponibilité
|
||||
</a>
|
||||
|
||||
<p class="text-center mt-6 text-[9px] font-black text-slate-300 uppercase tracking-widest italic">
|
||||
Devis gratuit • Ludikevent • Qualité Pro
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user