integer('days', 30))); $from = now()->subDays($days - 1)->startOfDay(); $events = AnalyticsEvent::query()->where('occurred_at', '>=', $from); return view('analytics::index', [ 'days' => $days, 'pageViews' => $events->clone()->where('event_type', 'page_view')->count(), 'visitors' => $events->clone()->whereNotNull('visitor_hash')->distinct('visitor_hash')->count('visitor_hash'), 'conversions' => $events->clone()->where('event_type', 'conversion')->count(), 'searches' => $events->clone()->where('event_type', 'search')->count(), 'topPages' => $events->clone()->where('event_type', 'page_view')->selectRaw('path, count(*) as total')->groupBy('path')->orderByDesc('total')->limit(10)->get(), 'recentEvents' => $events->clone()->latest('occurred_at')->limit(20)->get(), 'reports' => AnalyticsReport::latest()->limit(20)->get(), ]); } public function storeReport(Request $request): RedirectResponse { AnalyticsReport::create($request->validate(['name' => 'required|string|max:255', 'report_type' => 'required|in:overview,content,search,conversion,commerce', 'schedule' => 'nullable|string|max:50', 'format' => 'required|in:csv,json', 'is_active' => 'nullable|boolean']) + ['created_by' => $request->user()->id, 'is_active' => $request->boolean('is_active', true)]); return back()->with('status', 'Report created.'); } public function destroyReport(AnalyticsReport $report): RedirectResponse { $report->delete(); return back()->with('status','Report deleted.'); } }