withCount('votes'); if ($request->filled('anime_id')) { $query->where('anime_id', $request->anime_id); } if ($request->filled('status')) { $query->where('status', $request->status); } $tribunals = $query->latest()->paginate(15); return response()->json([ 'data' => collect($tribunals->items())->map(fn($t) => $this->formatTribunal($t))->values(), 'has_more' => $tribunals->hasMorePages(), 'next_page' => $tribunals->hasMorePages() ? $tribunals->currentPage() + 1 : null, ]); } public function show(Tribunal $tribunal) { $tribunal->load(['anime:id,title,slug,cover_image', 'creator:id,name,username']); $me = Auth::id(); $sides = $tribunal->allSides(); $vcounts = []; foreach (array_keys($sides) as $key) { $vcounts[$key] = TribunalVote::where('tribunal_id', $tribunal->id)->where('side', $key)->count(); } $myVote = $me ? TribunalVote::where('tribunal_id', $tribunal->id)->where('user_id', $me)->value('side') : null; $myArg = $me ? TribunalArgument::where('tribunal_id', $tribunal->id)->where('user_id', $me)->first() : null; $arguments = TribunalArgument::with('user:id,name,username') ->where('tribunal_id', $tribunal->id) ->orderByDesc('vote_count') ->get() ->map(fn($a) => [ 'id' => $a->id, 'side' => $a->side, 'body' => $a->body, 'vote_count' => $a->vote_count, 'username' => $a->user?->username, 'is_mine' => $me && $a->user_id === $me, 'voted' => $me ? TribunalArgumentVote::where('argument_id', $a->id)->where('user_id', $me)->exists() : false, ]); return response()->json([ 'tribunal' => $this->formatTribunal($tribunal), 'sides' => $sides, 'vote_counts' => $vcounts, 'total_votes' => array_sum($vcounts), 'my_vote' => $myVote, 'my_argument' => $myArg ? ['id' => $myArg->id, 'side' => $myArg->side, 'body' => $myArg->body] : null, 'arguments' => $arguments, ]); } public function store(Request $request) { $data = $request->validate([ 'anime_id' => 'required|exists:animes,id', 'question' => 'required|string|min:10|max:280', 'side_a' => 'required|string|min:2|max:100', 'side_b' => 'required|string|min:2|max:100', 'extra_sides' => 'nullable|array|max:4', 'extra_sides.*'=> 'required|string|min:2|max:100', 'closes_at' => 'nullable|date|after:today', ]); $me = Auth::user(); $tribunal = Tribunal::create([ 'anime_id' => $data['anime_id'], 'created_by' => $me->id, 'question' => $data['question'], 'side_a' => $data['side_a'], 'side_b' => $data['side_b'], 'extra_sides' => $data['extra_sides'] ?? [], 'status' => 'open', 'closes_at' => $data['closes_at'] ?? now()->addDays(7), ]); return response()->json(['ok' => true, 'id' => $tribunal->id]); } public function vote(Request $request, Tribunal $tribunal) { if ($tribunal->status !== 'open') { return response()->json(['error' => 'Bu dava kapalı.'], 422); } $sides = array_keys($tribunal->allSides()); $data = $request->validate(['side' => 'required|in:' . implode(',', $sides)]); $me = Auth::id(); $existing = TribunalVote::where('tribunal_id', $tribunal->id)->where('user_id', $me)->first(); if ($existing) { if ($existing->side === $data['side']) { $existing->delete(); $voted = null; } else { $existing->update(['side' => $data['side']]); $voted = $data['side']; } } else { TribunalVote::create(['tribunal_id' => $tribunal->id, 'user_id' => $me, 'side' => $data['side']]); $voted = $data['side']; } $vcounts = []; foreach (array_keys($tribunal->allSides()) as $key) { $vcounts[$key] = TribunalVote::where('tribunal_id', $tribunal->id)->where('side', $key)->count(); } return response()->json(['voted' => $voted, 'vote_counts' => $vcounts, 'total_votes' => array_sum($vcounts)]); } public function argue(Request $request, Tribunal $tribunal) { if ($tribunal->status !== 'open') { return response()->json(['error' => 'Bu dava kapalı.'], 422); } $sides = array_keys($tribunal->allSides()); $data = $request->validate([ 'side' => 'required|in:' . implode(',', $sides), 'body' => 'required|string|min:5|max:500', ]); $me = Auth::user(); $existing = TribunalArgument::where('tribunal_id', $tribunal->id)->where('user_id', $me->id)->first(); if ($existing) { $existing->update(['side' => $data['side'], 'body' => $data['body']]); return response()->json(['ok' => true, 'id' => $existing->id, 'updated' => true]); } $arg = TribunalArgument::create([ 'tribunal_id' => $tribunal->id, 'user_id' => $me->id, 'side' => $data['side'], 'body' => $data['body'], ]); return response()->json(['ok' => true, 'id' => $arg->id, 'updated' => false]); } public function argVote(TribunalArgument $argument) { $me = Auth::id(); $existing = TribunalArgumentVote::where('argument_id', $argument->id)->where('user_id', $me)->first(); if ($existing) { $existing->delete(); $argument->decrement('vote_count'); return response()->json(['voted' => false, 'vote_count' => $argument->fresh()->vote_count]); } TribunalArgumentVote::create(['argument_id' => $argument->id, 'user_id' => $me]); $argument->increment('vote_count'); return response()->json(['voted' => true, 'vote_count' => $argument->fresh()->vote_count]); } private function formatTribunal(Tribunal $t): array { return [ 'id' => $t->id, 'question' => $t->question, 'status' => $t->status, 'sides' => $t->allSides(), 'votes_count' => $t->votes_count ?? TribunalVote::where('tribunal_id', $t->id)->count(), 'closes_at' => $t->closes_at?->toIso8601String(), 'created_at' => $t->created_at->diffForHumans(), 'anime' => $t->anime ? [ 'id' => $t->anime->id, 'title' => $t->anime->title, 'slug' => $t->anime->slug, 'cover' => $t->anime->cover_image ? MediaUrl::fromStoragePath($t->anime->cover_image) : null, ] : null, 'creator' => $t->creator ? [ 'name' => $t->creator->name, 'username' => $t->creator->username, ] : null, ]; } }