122 lines
3.5 KiB
PHP
122 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Artwork;
|
|
use App\Models\ArtworkAward;
|
|
use App\Services\ArtworkAwardService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
|
|
final class ArtworkAwardController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly ArtworkAwardService $service
|
|
) {}
|
|
|
|
/**
|
|
* POST /api/artworks/{id}/award
|
|
* Award the artwork with a medal.
|
|
*/
|
|
public function store(Request $request, int $id): JsonResponse
|
|
{
|
|
$user = $request->user();
|
|
$artwork = Artwork::findOrFail($id);
|
|
|
|
$this->authorize('award', [ArtworkAward::class, $artwork]);
|
|
|
|
$data = $request->validate([
|
|
'medal' => ['required', 'string', 'in:gold,silver,bronze'],
|
|
]);
|
|
|
|
$award = $this->service->award($artwork, $user, $data['medal']);
|
|
|
|
return response()->json(
|
|
$this->buildPayload($artwork->id, $user->id),
|
|
201
|
|
);
|
|
}
|
|
|
|
/**
|
|
* PUT /api/artworks/{id}/award
|
|
* Change an existing award medal.
|
|
*/
|
|
public function update(Request $request, int $id): JsonResponse
|
|
{
|
|
$user = $request->user();
|
|
$artwork = Artwork::findOrFail($id);
|
|
|
|
$existingAward = ArtworkAward::where('artwork_id', $artwork->id)
|
|
->where('user_id', $user->id)
|
|
->firstOrFail();
|
|
|
|
$this->authorize('change', $existingAward);
|
|
|
|
$data = $request->validate([
|
|
'medal' => ['required', 'string', 'in:gold,silver,bronze'],
|
|
]);
|
|
|
|
$award = $this->service->changeAward($artwork, $user, $data['medal']);
|
|
|
|
return response()->json($this->buildPayload($artwork->id, $user->id));
|
|
}
|
|
|
|
/**
|
|
* DELETE /api/artworks/{id}/award
|
|
* Remove the user's award for this artwork.
|
|
*/
|
|
public function destroy(Request $request, int $id): JsonResponse
|
|
{
|
|
$user = $request->user();
|
|
$artwork = Artwork::findOrFail($id);
|
|
|
|
$existingAward = ArtworkAward::where('artwork_id', $artwork->id)
|
|
->where('user_id', $user->id)
|
|
->firstOrFail();
|
|
|
|
$this->authorize('remove', $existingAward);
|
|
|
|
$this->service->removeAward($artwork, $user);
|
|
|
|
return response()->json($this->buildPayload($artwork->id, $user->id));
|
|
}
|
|
|
|
/**
|
|
* GET /api/artworks/{id}/awards
|
|
* Return award stats + viewer's current award.
|
|
*/
|
|
public function show(Request $request, int $id): JsonResponse
|
|
{
|
|
$artwork = Artwork::findOrFail($id);
|
|
|
|
return response()->json($this->buildPayload($artwork->id, $request->user()?->id));
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// All authorization is delegated to ArtworkAwardPolicy via $this->authorize().
|
|
|
|
private function buildPayload(int $artworkId, ?int $userId): array
|
|
{
|
|
$stat = \App\Models\ArtworkAwardStat::find($artworkId);
|
|
|
|
$userAward = $userId
|
|
? ArtworkAward::where('artwork_id', $artworkId)
|
|
->where('user_id', $userId)
|
|
->value('medal')
|
|
: null;
|
|
|
|
return [
|
|
'awards' => [
|
|
'gold' => $stat?->gold_count ?? 0,
|
|
'silver' => $stat?->silver_count ?? 0,
|
|
'bronze' => $stat?->bronze_count ?? 0,
|
|
'score' => $stat?->score_total ?? 0,
|
|
],
|
|
'viewer_award' => $userAward,
|
|
];
|
|
}
|
|
}
|