Initial commit: Animexe Laravel platform
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Tribunal;
|
||||
use App\Models\TribunalArgument;
|
||||
use App\Models\TribunalArgumentVote;
|
||||
use App\Models\TribunalVote;
|
||||
use App\Support\MediaUrl;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class TribunalApiController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = Tribunal::with(['anime:id,title,slug,cover_image', 'creator:id,name,username'])
|
||||
->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,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user