lots of improvements

This commit is contained in:
Doar Mihai
2026-02-22 20:02:34 +02:00
parent 83fc389755
commit 29b5eca900
69 changed files with 3460 additions and 434 deletions
@@ -9,6 +9,7 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
@@ -37,6 +38,7 @@ class RegisteredUserController extends Controller
$user = User::create([
'name' => $request->name,
// 'slug' => $this->generateSlug($request->name),
'email' => $request->email,
'password' => Hash::make($request->password),
]);
@@ -47,4 +49,17 @@ class RegisteredUserController extends Controller
return redirect(route('dashboard', absolute: false));
}
private function generateSlug(string $name): string
{
$slug = Str::slug($name);
$originalSlug = $slug;
$count = 1;
while (User::where('slug', $slug)->exists()) {
$slug = $originalSlug . '-' . $count++;
}
return $slug;
}
}
@@ -0,0 +1,105 @@
<?php
namespace App\Http\Controllers;
use App\Models\ForumCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ForumCategoryController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$categories = ForumCategory::orderBy('order')->get();
return view('forum.index', compact('categories'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
// This would be restricted to admins in a middleware
return view('forum.categories.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// This would be restricted to admins in a middleware
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'order' => 'nullable|integer',
]);
$validated['slug'] = Str::slug($validated['name']);
ForumCategory::create($validated);
return redirect()->route('forum.index')
->with('success', 'Category created successfully.');
}
/**
* Display the specified resource.
*/
public function show(ForumCategory $category)
{
$threads = $category->threads()
->with('user')
->orderBy('is_sticky', 'desc')
->orderBy('last_activity_at', 'desc')
->paginate(20);
return view('forum.categories.show', compact('category', 'threads'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(ForumCategory $category)
{
// This would be restricted to admins in a middleware
return view('forum.categories.edit', compact('category'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, ForumCategory $category)
{
// This would be restricted to admins in a middleware
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'order' => 'nullable|integer',
]);
if ($request->name !== $category->name) {
$validated['slug'] = Str::slug($validated['name']);
}
$category->update($validated);
return redirect()->route('forum.index')
->with('success', 'Category updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(ForumCategory $category)
{
// This would be restricted to admins in a middleware
$category->delete();
return redirect()->route('forum.index')
->with('success', 'Category deleted successfully.');
}
}
@@ -0,0 +1,177 @@
<?php
namespace App\Http\Controllers;
use App\Models\ForumPost;
use App\Models\ForumTopic;
use App\Models\ForumThread;
use Illuminate\Http\Request;
class ForumPostController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
// Not needed as posts are displayed within topics
return redirect()->route('forum.index');
}
/**
* Show the form for creating a new resource.
*/
public function create(Request $request)
{
$topic_id = $request->query('topic_id');
if (!$topic_id) {
return redirect()->route('forum.index')
->with('error', 'Topic ID is required to create a post.');
}
$topic = ForumTopic::findOrFail($topic_id);
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot create new posts.');
}
return view('forum.posts.create', compact('topic', 'thread'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'content' => 'required|string',
'topic_id' => 'required|exists:forum_topics,id',
]);
$topic = ForumTopic::findOrFail($validated['topic_id']);
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot create new posts.');
}
// Create the post
$post = new ForumPost();
$post->topic_id = $validated['topic_id'];
$post->user_id = auth()->id();
$post->content = $validated['content'];
$post->save();
// Update topic and thread last activity
$topic->last_activity_at = now();
$topic->save();
$thread->last_activity_at = now();
$thread->save();
return redirect()->route('forum.topics.show', $topic)
->with('success', 'Post created successfully.');
}
/**
* Display the specified resource.
*/
public function show(ForumPost $post)
{
// Redirect to the topic with an anchor to the post
return redirect()->route('forum.topics.show', $post->topic) . '#post-' . $post->id;
}
/**
* Show the form for editing the specified resource.
*/
public function edit(ForumPost $post)
{
// Check if user is authorized to edit this post
if (auth()->id() !== $post->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.topics.show', $post->topic)
->with('error', 'You are not authorized to edit this post.');
}
$topic = $post->topic;
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot edit posts.');
}
return view('forum.posts.edit', compact('post', 'topic', 'thread'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, ForumPost $post)
{
// Check if user is authorized to edit this post
if (auth()->id() !== $post->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.topics.show', $post->topic)
->with('error', 'You are not authorized to edit this post.');
}
$topic = $post->topic;
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot edit posts.');
}
$validated = $request->validate([
'content' => 'required|string',
]);
// Update the post
$post->content = $validated['content'];
$post->edited_at = now();
$post->save();
return redirect()->route('forum.topics.show', $topic)
->with('success', 'Post updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(ForumPost $post)
{
// Check if user is authorized to delete this post
if (auth()->id() !== $post->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.topics.show', $post->topic)
->with('error', 'You are not authorized to delete this post.');
}
$topic = $post->topic;
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot delete posts.');
}
// Check if this is the only post in the topic
if ($topic->posts()->count() <= 1) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'Cannot delete the only post in a topic. Delete the topic instead.');
}
$post->delete();
return redirect()->route('forum.topics.show', $topic)
->with('success', 'Post deleted successfully.');
}
}
@@ -0,0 +1,159 @@
<?php
namespace App\Http\Controllers;
use App\Models\ForumCategory;
use App\Models\ForumThread;
use App\Models\ForumTopic;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ForumThreadController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$threads = ForumThread::with(['user', 'category'])
->orderBy('is_sticky', 'desc')
->orderBy('last_activity_at', 'desc')
->paginate(20);
return view('forum.threads.index', compact('threads'));
}
/**
* Show the form for creating a new resource.
*/
public function create(Request $request)
{
$categories = ForumCategory::orderBy('order')->get();
$category_id = $request->query('category_id');
return view('forum.threads.create', compact('categories', 'category_id'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
'category_id' => 'required|exists:forum_categories,id',
]);
// Create the thread
$thread = new ForumThread();
$thread->title = $validated['title'];
$thread->slug = Str::slug($validated['title']) . '-' . uniqid();
$thread->category_id = $validated['category_id'];
$thread->user_id = auth()->id();
$thread->last_activity_at = now();
$thread->save();
// Create the initial topic
$topic = new ForumTopic();
$topic->thread_id = $thread->id;
$topic->user_id = auth()->id();
$topic->title = $validated['title'];
$topic->content = $validated['content'];
$topic->last_activity_at = now();
$topic->save();
return redirect()->route('forum.threads.show', $thread)
->with('success', 'Thread created successfully.');
}
/**
* Display the specified resource.
*/
public function show(ForumThread $thread)
{
// Increment view count
$thread->increment('views');
// Get topics with pagination
$topics = $thread->topics()
->with('user')
->orderBy('is_pinned', 'desc')
->orderBy('created_at', 'asc')
->paginate(15);
return view('forum.threads.show', compact('thread', 'topics'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(ForumThread $thread)
{
// Check if user is authorized to edit this thread
if (auth()->id() !== $thread->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.threads.show', $thread)
->with('error', 'You are not authorized to edit this thread.');
}
$categories = ForumCategory::orderBy('order')->get();
$initialTopic = $thread->topics()->oldest()->first();
return view('forum.threads.edit', compact('thread', 'categories', 'initialTopic'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, ForumThread $thread)
{
// Check if user is authorized to edit this thread
if (auth()->id() !== $thread->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.threads.show', $thread)
->with('error', 'You are not authorized to edit this thread.');
}
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
'category_id' => 'required|exists:forum_categories,id',
]);
// Update the thread
$thread->title = $validated['title'];
if ($thread->isDirty('title')) {
$thread->slug = Str::slug($validated['title']) . '-' . uniqid();
}
$thread->category_id = $validated['category_id'];
$thread->save();
// Update the initial topic
$initialTopic = $thread->topics()->oldest()->first();
if ($initialTopic) {
$initialTopic->title = $validated['title'];
$initialTopic->content = $validated['content'];
$initialTopic->save();
}
return redirect()->route('forum.threads.show', $thread)
->with('success', 'Thread updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(ForumThread $thread)
{
// Check if user is authorized to delete this thread
if (auth()->id() !== $thread->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.threads.show', $thread)
->with('error', 'You are not authorized to delete this thread.');
}
$categoryId = $thread->category_id;
$thread->delete();
return redirect()->route('forum.categories.show', ['category' => ForumCategory::find($categoryId)])
->with('success', 'Thread deleted successfully.');
}
}
@@ -0,0 +1,180 @@
<?php
namespace App\Http\Controllers;
use App\Models\ForumThread;
use App\Models\ForumTopic;
use App\Models\ForumPost;
use Illuminate\Http\Request;
class ForumTopicController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
// Not needed as topics are displayed within threads
return redirect()->route('forum.index');
}
/**
* Show the form for creating a new resource.
*/
public function create(Request $request)
{
$thread_id = $request->query('thread_id');
if (!$thread_id) {
return redirect()->route('forum.index')
->with('error', 'Thread ID is required to create a topic.');
}
$thread = ForumThread::findOrFail($thread_id);
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.threads.show', $thread)
->with('error', 'This thread is locked. You cannot create new topics.');
}
return view('forum.topics.create', compact('thread'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
'thread_id' => 'required|exists:forum_threads,id',
]);
$thread = ForumThread::findOrFail($validated['thread_id']);
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.threads.show', $thread)
->with('error', 'This thread is locked. You cannot create new topics.');
}
// Create the topic
$topic = new ForumTopic();
$topic->thread_id = $validated['thread_id'];
$topic->user_id = auth()->id();
$topic->title = $validated['title'];
$topic->content = $validated['content'];
$topic->last_activity_at = now();
$topic->save();
// Update thread's last activity
$thread->last_activity_at = now();
$thread->save();
return redirect()->route('forum.topics.show', $topic)
->with('success', 'Topic created successfully.');
}
/**
* Display the specified resource.
*/
public function show(ForumTopic $topic)
{
$thread = $topic->thread;
// Get posts with pagination
$posts = $topic->posts()
->with('user')
->orderBy('created_at', 'asc')
->paginate(15);
return view('forum.topics.show', compact('topic', 'thread', 'posts'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(ForumTopic $topic)
{
// Check if user is authorized to edit this topic
if (auth()->id() !== $topic->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'You are not authorized to edit this topic.');
}
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot edit topics.');
}
return view('forum.topics.edit', compact('topic', 'thread'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, ForumTopic $topic)
{
// Check if user is authorized to edit this topic
if (auth()->id() !== $topic->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'You are not authorized to edit this topic.');
}
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot edit topics.');
}
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);
// Update the topic
$topic->title = $validated['title'];
$topic->content = $validated['content'];
$topic->save();
return redirect()->route('forum.topics.show', $topic)
->with('success', 'Topic updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(ForumTopic $topic)
{
// Check if user is authorized to delete this topic
if (auth()->id() !== $topic->user_id && !auth()->user()->hasRole('admin')) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'You are not authorized to delete this topic.');
}
$thread = $topic->thread;
// Check if thread is locked
if ($thread->is_locked) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'This thread is locked. You cannot delete topics.');
}
// Check if this is the only topic in the thread
if ($thread->topics()->count() <= 1) {
return redirect()->route('forum.topics.show', $topic)
->with('error', 'Cannot delete the only topic in a thread. Delete the thread instead.');
}
$topic->delete();
return redirect()->route('forum.threads.show', $thread)
->with('success', 'Topic deleted successfully.');
}
}
+72 -2
View File
@@ -101,7 +101,77 @@ class GameController extends Controller
public function show(Game $game)
{
$game->load(['platforms', 'genres', 'screenshots', 'videos', 'similar_games', 'dlcs', 'reviews.user']);
return view('games.show', compact('game'));
// Load game relationships except reviews
$game->load(['platforms', 'genres', 'screenshots', 'videos', 'similar_games', 'dlcs']);
// Load reviews with users separately (could be paginated if needed)
$reviews = $game->reviews()->with('user')->get();
// Calculate rating distribution percentages
$ratingDistribution = $this->calculateRatingDistribution($game);
return view('games.show', compact('game', 'ratingDistribution', 'reviews'));
}
/**
* Calculate the rating distribution percentages for a game
*
* @param Game $game
* @return array
*/
private function calculateRatingDistribution(Game $game)
{
$distribution = [];
// Get the total number of reviews for this game
$totalReviews = $game->reviews()->count();
// If there are no reviews, return empty distribution
if ($totalReviews === 0) {
for ($i = 10; $i >= 1; $i--) {
$distribution[] = [
'range' => $i,
'count' => 0,
'percentage' => 0
];
}
return $distribution;
}
// Get the count of reviews for each rating range directly from the database
$ratingCounts = $game->reviews()
->selectRaw('
CASE
WHEN rating = 1 THEN 1
WHEN rating = 2 THEN 2
WHEN rating = 3 THEN 3
WHEN rating = 4 THEN 4
WHEN rating = 5 THEN 5
WHEN rating = 6 THEN 6
WHEN rating = 7 THEN 7
WHEN rating = 8 THEN 8
WHEN rating = 9 THEN 9
WHEN rating = 10 THEN 10
END as range_id,
COUNT(*) as count
')
->groupBy('range_id')
->orderBy('range_id', 'desc')
->get()
->keyBy('range_id');
// Build the distribution array with percentages
for ($i = 10; $i >= 1; $i--) {
$count = $ratingCounts->get($i)->count ?? 0;
$percentage = ($count / $totalReviews) * 100;
$distribution[] = [
'range' => $i,
'count' => $count,
'percentage' => $percentage
];
}
return $distribution;
}
}
+7 -3
View File
@@ -22,7 +22,8 @@ class ReviewController extends Controller
public function create(Game $game)
{
return view('reviews.create', compact('game'));
$platforms = $game->platforms()->get();
return view('reviews.create', compact('game', 'platforms'));
}
public function store(Request $request, Game $game)
@@ -31,6 +32,7 @@ class ReviewController extends Controller
'content' => 'required|string|min:10|max:1000',
'recommended' => 'sometimes|nullable|boolean',
'rating' => 'required|between:1,10',
'platform_id' => 'required|exists:platforms,id',
]);
if (!isset($validated['recommended'])) {
@@ -54,7 +56,8 @@ class ReviewController extends Controller
public function edit(Game $game, Review $review)
{
$this->authorize('update', $review);
return view('reviews.edit', compact('game', 'review'));
$platforms = $game->platforms;
return view('reviews.edit', compact('game', 'review', 'platforms'));
}
public function update(Request $request, Game $game, Review $review)
@@ -64,7 +67,8 @@ class ReviewController extends Controller
$validated = $request->validate([
'content' => 'required|string|min:10|max:1000',
'recommended' => 'required|boolean',
'rating' => 'required|integer|between:1,20',
'rating' => 'required|integer|between:1,10',
'platform_id' => 'required|exists:platforms,id',
]);
$review->update($validated);