Skip to content

Commit

Permalink
Add analytics section to dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
caendesilva committed Nov 30, 2024
1 parent 8d314b0 commit 8a27015
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 12 deletions.
55 changes: 44 additions & 11 deletions app/Http/Controllers/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Models\Post;
use App\Models\User;
use App\Models\Comment;
use App\Models\PageView;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

Expand All @@ -24,28 +25,60 @@ public function show(Request $request)
abort(403);
}

$data = [];

// If the user is an admin they can manage all posts and users
if ($request->user()->is_admin) {
$posts = Post::all();

$users = User::all();
$data['posts'] = Post::all();
$data['users'] = User::all();

// If comments are enabled or if there are comments we load them
if (config('blog.allowComments') || Comment::count()) {
$comments = Comment::all();
$data['comments'] = Comment::all();
}
}

// Add analytics data if enabled
if (config('analytics.enabled')) {
$pageViews = PageView::all();

// Get traffic data for the last 30 days
$thirtyDaysAgo = now()->subDays(30);
$trafficData = PageView::where('created_at', '>=', $thirtyDaysAgo)
->get()
->groupBy(function ($view) {
return $view->created_at->format('Y-m-d');
});

$data['analytics'] = [
'total_views' => $pageViews->count(),
'unique_visitors' => $pageViews->groupBy('anonymous_id')->count(),
'popular_pages' => PageView::select('page')
->selectRaw('COUNT(*) as views')
->groupBy('page')
->orderByDesc('views')
->limit(10)
->get(),
'top_referrers' => PageView::whereNotNull('referrer')
->select('referrer')
->selectRaw('COUNT(*) as count')
->groupBy('referrer')
->orderByDesc('count')
->limit(10)
->get(),
'traffic_data' => [
'dates' => $trafficData->keys(),
'views' => $trafficData->map->count(),
'unique' => $trafficData->map(fn ($views) => $views->groupBy('anonymous_id')->count()),
],
];
}
}
// Otherwise if the user is an author we show their posts
elseif ($request->user()->is_author) {
$posts = $request->user()->posts;
$data['posts'] = $request->user()->posts;
}

// Return the view with the data we prepared
return view('dashboard', [
'posts' => $posts ?? false,
'users' => $users ?? false,
'comments' => $comments ?? false,
]);
return view('dashboard', $data);
}
}
2 changes: 1 addition & 1 deletion public/css/app.css

Large diffs are not rendered by default.

111 changes: 111 additions & 0 deletions resources/views/dashboard.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,117 @@
</section>
@endif

@if(isset($analytics))
<section class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg my-5">
<div class="p-6">
<header class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">Analytics Overview</h3>
</header>

<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div class="bg-gray-100 dark:bg-gray-700 p-4 rounded-lg">
<div class="text-2xl font-bold">{{ number_format($analytics['total_views']) }}</div>
<div class="text-gray-600 dark:text-gray-400">Total Page Views</div>
</div>
<div class="bg-gray-100 dark:bg-gray-700 p-4 rounded-lg">
<div class="text-2xl font-bold">{{ number_format($analytics['unique_visitors']) }}</div>
<div class="text-gray-600 dark:text-gray-400">Unique Visitors</div>
</div>
</div>

<!-- Traffic Chart -->
<div class="mb-6">
<h4 class="text-lg font-semibold mb-2">Traffic (Last 30 Days)</h4>
<canvas id="trafficChart" height="200" style="max-height: 200px;"></canvas>
</div>

<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Popular Pages -->
<div>
<h4 class="text-lg font-semibold mb-2">Popular Pages</h4>
<div class="overflow-x-auto">
<table class="w-full">
<thead>
<tr>
<x-th>Page</x-th>
<x-th>Views</x-th>
</tr>
</thead>
<tbody>
@foreach($analytics['popular_pages'] as $page)
<tr>
<x-td>{{ $page->page }}</x-td>
<x-td>{{ number_format($page->views) }}</x-td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>

<!-- Top Referrers -->
<div>
<h4 class="text-lg font-semibold mb-2">Top Referrers</h4>
<div class="overflow-x-auto">
<table class="w-full">
<thead>
<tr>
<x-th>Source</x-th>
<x-th>Visits</x-th>
</tr>
</thead>
<tbody>
@foreach($analytics['top_referrers'] as $referrer)
<tr>
<x-td>{{ $referrer->referrer }}</x-td>
<x-td>{{ number_format($referrer->count) }}</x-td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>

@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('trafficChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: @json($analytics['traffic_data']['dates']),
datasets: [{
label: 'Page Views',
data: @json($analytics['traffic_data']['views']),
borderColor: 'rgb(59, 130, 246)',
tension: 0.1
}, {
label: 'Unique Visitors',
data: @json($analytics['traffic_data']['unique']),
borderColor: 'rgb(239, 68, 68)',
tension: 0.1
}]
},
options: {
responsive: true,
interaction: {
intersect: false,
mode: 'index'
},
scales: {
y: {
beginAtZero: true
}
}
}
});
</script>
@endpush
@endif

@push('scripts')
<livewire:edit-user-form-modal />

Expand Down

0 comments on commit 8a27015

Please sign in to comment.