197 lines
11 KiB
PHP
197 lines
11 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
require_once __DIR__ . '/includes/app.php';
|
||
app_boot();
|
||
|
||
$user = current_user();
|
||
$stats = fetch_dashboard_stats($user['id'] ?? null);
|
||
$topSports = top_values('sport_name');
|
||
$topClubs = top_values('club_name');
|
||
|
||
render_header('Tableau de bord', [
|
||
'description' => 'RJLRESAKA centralise les sportifs, clubs et disciplines dans une interface nette et sécurisée.',
|
||
'body_class' => 'app-shell',
|
||
]);
|
||
?>
|
||
<main>
|
||
<section class="hero-section border-bottom">
|
||
<div class="container-xxl py-5">
|
||
<div class="row g-4 align-items-center">
|
||
<div class="col-lg-7">
|
||
<span class="eyebrow">Gestion sportive sécurisée</span>
|
||
<h1 class="display-title mt-3 mb-3">Pilotez vos sportifs, clubs et disciplines dans un espace unique.</h1>
|
||
<p class="hero-copy mb-4">Ce premier MVP livre une base réellement exploitable : authentification sécurisée, verrouillage après 5 échecs, réinitialisation par token, création de fiches sportifs, tableau de bord, liste filtrable et fiche détaillée.</p>
|
||
<div class="d-flex flex-wrap gap-2">
|
||
<?php if ($user): ?>
|
||
<a href="athlete_new.php" class="btn btn-dark btn-lg">Ajouter un sportif</a>
|
||
<a href="athletes.php" class="btn btn-outline-secondary btn-lg">Voir le registre</a>
|
||
<?php else: ?>
|
||
<a href="register.php" class="btn btn-dark btn-lg">Créer un compte</a>
|
||
<a href="login.php" class="btn btn-outline-secondary btn-lg">Se connecter</a>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-5">
|
||
<div class="panel-card p-4">
|
||
<div class="d-flex justify-content-between align-items-start mb-4">
|
||
<div>
|
||
<p class="text-secondary text-uppercase small mb-1">Vue synthèse</p>
|
||
<h2 class="h5 mb-0">Indicateurs clés</h2>
|
||
</div>
|
||
<span class="badge text-bg-light border">MVP initial</span>
|
||
</div>
|
||
<div class="row g-3">
|
||
<div class="col-6">
|
||
<div class="metric-card">
|
||
<span>Total sportifs</span>
|
||
<strong><?= e((string) $stats['total']) ?></strong>
|
||
</div>
|
||
</div>
|
||
<div class="col-6">
|
||
<div class="metric-card">
|
||
<span>Sports suivis</span>
|
||
<strong><?= e((string) $stats['sports']) ?></strong>
|
||
</div>
|
||
</div>
|
||
<div class="col-6">
|
||
<div class="metric-card">
|
||
<span>Clubs actifs</span>
|
||
<strong><?= e((string) $stats['clubs']) ?></strong>
|
||
</div>
|
||
</div>
|
||
<div class="col-6">
|
||
<div class="metric-card">
|
||
<span>Statuts suivis</span>
|
||
<strong><?= e((string) count($stats['status_breakdown'])) ?></strong>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<hr class="my-4">
|
||
<div class="d-flex flex-wrap gap-2">
|
||
<?php if (!empty($stats['status_breakdown'])): ?>
|
||
<?php foreach ($stats['status_breakdown'] as $row): ?>
|
||
<span class="badge rounded-pill text-bg-<?= e(stat_badge_class((string) $row['status'])) ?>"><?= e(ucfirst((string) $row['status'])) ?> · <?= e((string) $row['total']) ?></span>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<span class="text-secondary small">Aucun sportif enregistré pour le moment.</span>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="container-xxl py-5">
|
||
<div class="row g-4">
|
||
<div class="col-lg-8">
|
||
<div class="panel-card p-4 h-100">
|
||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||
<div>
|
||
<p class="section-kicker mb-1">Workflow livré</p>
|
||
<h2 class="h4 mb-0">Parcours utilisateur disponible maintenant</h2>
|
||
</div>
|
||
<a href="athletes.php" class="link-dark text-decoration-none">Ouvrir le registre</a>
|
||
</div>
|
||
<div class="workflow-grid">
|
||
<article>
|
||
<span>01</span>
|
||
<h3>Accès sécurisé</h3>
|
||
<p>Inscription, connexion, verrouillage temporaire après 5 tentatives et réinitialisation via token.</p>
|
||
</article>
|
||
<article>
|
||
<span>02</span>
|
||
<h3>Création guidée</h3>
|
||
<p>Ajoutez un sportif avec discipline, club, statut, statistiques clés et note de parcours.</p>
|
||
</article>
|
||
<article>
|
||
<span>03</span>
|
||
<h3>Suivi exploitable</h3>
|
||
<p>Filtrez le registre, consultez la fiche détaillée et surveillez la répartition par sport et par club.</p>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4">
|
||
<div class="panel-card p-4 h-100">
|
||
<p class="section-kicker mb-1">Navigation rapide</p>
|
||
<h2 class="h4 mb-3">Actions recommandées</h2>
|
||
<div class="list-group list-group-flush quick-links">
|
||
<a class="list-group-item list-group-item-action" href="register.php">Créer un espace gestionnaire</a>
|
||
<a class="list-group-item list-group-item-action" href="athlete_new.php">Ajouter une fiche sportif</a>
|
||
<a class="list-group-item list-group-item-action" href="athletes.php">Consulter et filtrer la base</a>
|
||
<a class="list-group-item list-group-item-action" href="change_password.php">Sécuriser le mot de passe</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="container-xxl pb-5">
|
||
<div class="row g-4">
|
||
<div class="col-lg-6">
|
||
<div class="panel-card p-4 h-100">
|
||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||
<h2 class="h5 mb-0">Sports les plus représentés</h2>
|
||
<span class="text-secondary small">Aperçu agrégé</span>
|
||
</div>
|
||
<?php if ($topSports): ?>
|
||
<div class="stack-list">
|
||
<?php foreach ($topSports as $item): ?>
|
||
<div class="stack-item">
|
||
<div>
|
||
<strong><?= e((string) $item['label']) ?></strong>
|
||
<p class="mb-0 text-secondary small">Discipline suivie</p>
|
||
</div>
|
||
<span class="badge text-bg-light border"><?= e((string) $item['total']) ?> sportifs</span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="empty-card">
|
||
<h3 class="h6">Aucun sport disponible</h3>
|
||
<p class="mb-0">Ajoutez votre premier sportif pour faire apparaître les disciplines suivies.</p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-6">
|
||
<div class="panel-card p-4 h-100">
|
||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||
<h2 class="h5 mb-0">Clubs récents</h2>
|
||
<span class="text-secondary small">Vue opérationnelle</span>
|
||
</div>
|
||
<?php if (!empty($stats['recent'])): ?>
|
||
<div class="table-responsive">
|
||
<table class="table align-middle app-table mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th>Sportif</th>
|
||
<th>Club</th>
|
||
<th>Statut</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($stats['recent'] as $athlete): ?>
|
||
<tr>
|
||
<td><a href="athlete.php?id=<?= e((string) $athlete['id']) ?>" class="link-dark fw-semibold text-decoration-none"><?= e($athlete['first_name'] . ' ' . $athlete['last_name']) ?></a></td>
|
||
<td><?= e((string) $athlete['club_name']) ?></td>
|
||
<td><span class="badge text-bg-<?= e(stat_badge_class((string) $athlete['status'])) ?>"><?= e(ucfirst((string) $athlete['status'])) ?></span></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="empty-card">
|
||
<h3 class="h6">Registre vide</h3>
|
||
<p class="mb-0">Le tableau de bord s’enrichira dès la première fiche créée.</p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
<?php render_footer(); ?>
|