123 lines
4.0 KiB
PHP
123 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Concerns\ParsesDateRange;
|
|
use App\Models\DashboardWidget;
|
|
use App\Models\Website;
|
|
use App\Services\AnalyticsQueryService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
|
|
class CustomDashboardController extends Controller
|
|
{
|
|
use ParsesDateRange;
|
|
|
|
public function show(Request $request, Website $website): View
|
|
{
|
|
$this->authorize('view', $website);
|
|
|
|
[$from, $to] = $this->parseDateRange($request);
|
|
$service = AnalyticsQueryService::for($website, $from, $to);
|
|
|
|
$widgets = $website->dashboardWidgets()->orderBy('sort_order')->get();
|
|
|
|
$widgetData = [];
|
|
foreach ($widgets as $widget) {
|
|
$widgetData[$widget->id] = $this->resolveWidgetData($widget, $service);
|
|
}
|
|
|
|
return view('custom-dashboard.show', [
|
|
'website' => $website,
|
|
'widgets' => $widgets,
|
|
'widgetData' => $widgetData,
|
|
'from' => $from,
|
|
'to' => $to,
|
|
]);
|
|
}
|
|
|
|
public function manage(Website $website): View
|
|
{
|
|
$this->authorize('view', $website);
|
|
|
|
return view('custom-dashboard.manage', [
|
|
'website' => $website,
|
|
'widgets' => $website->dashboardWidgets()->orderBy('sort_order')->get(),
|
|
'types' => DashboardWidget::$types,
|
|
'metrics' => DashboardWidget::$metrics,
|
|
]);
|
|
}
|
|
|
|
public function store(Request $request, Website $website): RedirectResponse
|
|
{
|
|
$this->authorize('view', $website);
|
|
|
|
$validated = $request->validate([
|
|
'title' => 'required|string|max:255',
|
|
'widget_type' => 'required|string|in:' . implode(',', array_keys(DashboardWidget::$types)),
|
|
'size' => 'required|in:full,half,third',
|
|
'config' => 'nullable|array',
|
|
'config.metric' => 'nullable|string',
|
|
'config.limit' => 'nullable|integer|min:1|max:50',
|
|
]);
|
|
|
|
$maxSort = $website->dashboardWidgets()->max('sort_order') ?? 0;
|
|
$validated['sort_order'] = $maxSort + 1;
|
|
|
|
$website->dashboardWidgets()->create($validated);
|
|
|
|
return redirect()
|
|
->route('custom-dashboard.manage', $website)
|
|
->with('success', 'Widget added.');
|
|
}
|
|
|
|
public function reorder(Request $request, Website $website): RedirectResponse
|
|
{
|
|
$this->authorize('view', $website);
|
|
|
|
$request->validate([
|
|
'order' => 'required|array',
|
|
'order.*' => 'integer|exists:dashboard_widgets,id',
|
|
]);
|
|
|
|
foreach ($request->order as $position => $widgetId) {
|
|
$website->dashboardWidgets()->where('id', $widgetId)->update(['sort_order' => $position]);
|
|
}
|
|
|
|
return redirect()
|
|
->route('custom-dashboard.manage', $website)
|
|
->with('success', 'Widget order updated.');
|
|
}
|
|
|
|
public function destroy(Website $website, DashboardWidget $widget): RedirectResponse
|
|
{
|
|
$this->authorize('view', $website);
|
|
|
|
$widget->delete();
|
|
|
|
return redirect()
|
|
->route('custom-dashboard.manage', $website)
|
|
->with('success', 'Widget removed.');
|
|
}
|
|
|
|
private function resolveWidgetData(DashboardWidget $widget, AnalyticsQueryService $service): mixed
|
|
{
|
|
$config = $widget->config ?? [];
|
|
$limit = $config['limit'] ?? 5;
|
|
|
|
return match ($widget->widget_type) {
|
|
'metric' => $service->summary()[$config['metric'] ?? 'page_views'] ?? 0,
|
|
'chart' => $service->visitorsOverTime(),
|
|
'top_pages' => $service->topPages($limit),
|
|
'top_sources' => $service->trafficSources($limit),
|
|
'events' => $service->eventsOverview($limit),
|
|
'conversions' => $service->conversionsReport(),
|
|
'new_vs_returning' => $service->newVsReturning(),
|
|
'browsers' => $service->visitorsByBrowser($limit),
|
|
'countries' => $service->visitorsByCountry($limit),
|
|
default => null,
|
|
};
|
|
}
|
|
}
|