parent
87c20de3c6
commit
c3ffc91150
@ -0,0 +1,76 @@
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<h1 class="text-3xl font-bold mb-8">Tableau de bord</h1>
|
||||
|
||||
<!-- Statistiques générales -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Utilisateurs</h2>
|
||||
<p class="text-3xl font-bold">{{ stats.general.total_users }}</p>
|
||||
<p class="text-sm text-gray-500">+{{ stats.last_30_days.new_users }} ce mois</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Pins</h2>
|
||||
<p class="text-3xl font-bold">{{ stats.general.total_pins }}</p>
|
||||
<p class="text-sm text-gray-500">+{{ stats.last_30_days.new_pins }} ce mois</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Images</h2>
|
||||
<p class="text-3xl font-bold">{{ stats.general.total_images }}</p>
|
||||
<p class="text-sm text-gray-500">+{{ stats.last_30_days.new_images }} ce mois</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Amis</h2>
|
||||
<p class="text-3xl font-bold">{{ stats.general.total_friends }}</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Stockage</h2>
|
||||
<p class="text-3xl font-bold">{{ formatBytes(stats.general.total_storage_bytes) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top utilisateurs -->
|
||||
<div class="bg-white rounded-lg shadow p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold mb-4">Top utilisateurs</h2>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Utilisateur</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nombre de pins</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
<tr *ngFor="let user of stats.top_users">
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ user.username }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ user.pin_count }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Top pins partagés -->
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Top pins partagés</h2>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Titre</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nombre de partages</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
<tr *ngFor="let pin of stats.top_shared_pins">
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ pin.title }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ pin.share_count }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,46 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { StatisticsService } from '../../services/statistics.service';
|
||||
import { Stats } from '../../model/Stats';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.css'],
|
||||
imports: [CommonModule]
|
||||
})
|
||||
export class DashboardComponent implements OnInit {
|
||||
stats: Stats = {
|
||||
general: {
|
||||
total_users: 0,
|
||||
total_pins: 0,
|
||||
total_images: 0,
|
||||
total_friends: 0,
|
||||
total_storage_bytes: 0
|
||||
},
|
||||
last_30_days: {
|
||||
new_users: 0,
|
||||
new_pins: 0,
|
||||
new_images: 0
|
||||
},
|
||||
top_users: [],
|
||||
top_shared_pins: []
|
||||
};
|
||||
|
||||
constructor(private http: HttpClient, private statisticsService: StatisticsService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.statisticsService.loadStats().subscribe(stats => {
|
||||
this.stats = stats;
|
||||
});
|
||||
}
|
||||
|
||||
formatBytes(bytes: number | undefined): string {
|
||||
if (!bytes) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
}
|
Loading…
Reference in new issue