id())->first(); return response()->json($feedback); } // USER: submit or update feedback (one editable row per user). public function store(Request $request) { $data = $request->validate([ 'stars' => 'nullable|integer|min:1|max:5', 'content' => 'nullable|string|max:2000', ]); if (!$request->filled('stars') && !$request->filled('content')) { throw ValidationException::withMessages([ 'content' => ['Either a rating or a comment is required.'], ]); } $feedback = AppFeedback::firstOrNew(['user_id' => auth()->id()]); if ($request->has('stars')) { $feedback->stars = $data['stars'] ?? null; } if ($request->has('content')) { $feedback->content = $data['content'] ?? null; } $feedback->save(); return response()->json([ 'message' => 'Feedback submitted successfully', 'feedback' => $feedback, ]); } // ADMIN: monitor all feedback, with a summary header. public function adminIndex(Request $request) { $query = AppFeedback::with('user'); if ($request->filled('has_comment')) { $query->whereNotNull('content')->where('content', '!=', ''); } if ($request->filled('stars')) { $query->where('stars', $request->integer('stars')); } $feedback = $query->latest()->paginate($request->integer('per_page', 20)); $base = AppFeedback::query(); return response()->json([ 'summary' => [ 'total' => (clone $base)->count(), 'rated' => (clone $base)->whereNotNull('stars')->count(), 'with_comment' => (clone $base)->whereNotNull('content')->where('content', '!=', '')->count(), 'average_stars' => round((float) (clone $base)->whereNotNull('stars')->avg('stars'), 2), ], 'feedback' => $feedback, ]); } // ADMIN: remove a feedback entry (moderation). public function adminDestroy($id) { $feedback = AppFeedback::findOrFail($id); $feedback->delete(); return response()->json(['message' => 'Feedback deleted successfully']); } }