feat: increase gallery grid from 4 to 5 columns per row on desktopfeat: increase gallery grid from 4 to 5 columns per row on desktop
This commit is contained in:
132
app/Services/ArtworkAwardService.php
Normal file
132
app/Services/ArtworkAwardService.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Jobs\IndexArtworkJob;
|
||||
use App\Models\Artwork;
|
||||
use App\Models\ArtworkAward;
|
||||
use App\Models\ArtworkAwardStat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class ArtworkAwardService
|
||||
{
|
||||
/**
|
||||
* Award an artwork with the given medal.
|
||||
* Throws ValidationException if the user already awarded this artwork.
|
||||
*/
|
||||
public function award(Artwork $artwork, User $user, string $medal): ArtworkAward
|
||||
{
|
||||
$this->validateMedal($medal);
|
||||
|
||||
$existing = ArtworkAward::where('artwork_id', $artwork->id)
|
||||
->where('user_id', $user->id)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
throw ValidationException::withMessages([
|
||||
'medal' => 'You have already awarded this artwork. Use change to update.',
|
||||
]);
|
||||
}
|
||||
|
||||
$award = ArtworkAward::create([
|
||||
'artwork_id' => $artwork->id,
|
||||
'user_id' => $user->id,
|
||||
'medal' => $medal,
|
||||
'weight' => ArtworkAward::WEIGHTS[$medal],
|
||||
]);
|
||||
|
||||
$this->recalcStats($artwork->id);
|
||||
$this->syncToSearch($artwork);
|
||||
|
||||
return $award;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change an existing award medal for a user/artwork pair.
|
||||
*/
|
||||
public function changeAward(Artwork $artwork, User $user, string $medal): ArtworkAward
|
||||
{
|
||||
$this->validateMedal($medal);
|
||||
|
||||
$award = ArtworkAward::where('artwork_id', $artwork->id)
|
||||
->where('user_id', $user->id)
|
||||
->firstOrFail();
|
||||
|
||||
$award->update([
|
||||
'medal' => $medal,
|
||||
'weight' => ArtworkAward::WEIGHTS[$medal],
|
||||
]);
|
||||
|
||||
$this->recalcStats($artwork->id);
|
||||
$this->syncToSearch($artwork);
|
||||
|
||||
return $award->fresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an award for a user/artwork pair.
|
||||
*/
|
||||
public function removeAward(Artwork $artwork, User $user): void
|
||||
{
|
||||
ArtworkAward::where('artwork_id', $artwork->id)
|
||||
->where('user_id', $user->id)
|
||||
->delete();
|
||||
|
||||
$this->recalcStats($artwork->id);
|
||||
$this->syncToSearch($artwork);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate and persist stats for the given artwork.
|
||||
*/
|
||||
public function recalcStats(int $artworkId): ArtworkAwardStat
|
||||
{
|
||||
$counts = DB::table('artwork_awards')
|
||||
->where('artwork_id', $artworkId)
|
||||
->selectRaw('
|
||||
SUM(medal = \'gold\') AS gold_count,
|
||||
SUM(medal = \'silver\') AS silver_count,
|
||||
SUM(medal = \'bronze\') AS bronze_count
|
||||
')
|
||||
->first();
|
||||
|
||||
$gold = (int) ($counts->gold_count ?? 0);
|
||||
$silver = (int) ($counts->silver_count ?? 0);
|
||||
$bronze = (int) ($counts->bronze_count ?? 0);
|
||||
$score = ($gold * 3) + ($silver * 2) + ($bronze * 1);
|
||||
|
||||
$stat = ArtworkAwardStat::updateOrCreate(
|
||||
['artwork_id' => $artworkId],
|
||||
[
|
||||
'gold_count' => $gold,
|
||||
'silver_count' => $silver,
|
||||
'bronze_count' => $bronze,
|
||||
'score_total' => $score,
|
||||
'updated_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a non-blocking reindex for the artwork after award stats change.
|
||||
*/
|
||||
public function syncToSearch(Artwork $artwork): void
|
||||
{
|
||||
IndexArtworkJob::dispatch($artwork->id);
|
||||
}
|
||||
|
||||
private function validateMedal(string $medal): void
|
||||
{
|
||||
if (! in_array($medal, ArtworkAward::MEDALS, true)) {
|
||||
throw ValidationException::withMessages([
|
||||
'medal' => 'Invalid medal. Must be gold, silver, or bronze.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user