feat: ship creator journey v2 and profile updates

This commit is contained in:
2026-04-12 21:42:07 +02:00
parent a2457f4e49
commit d5cff21ea2
335 changed files with 20147 additions and 1545 deletions

View File

@@ -7,14 +7,16 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Artwork;
use App\Models\ArtworkAward;
use App\Services\ArtworkAwardService;
use App\Models\ArtworkMedal;
use App\Models\ArtworkMedalStat;
use App\Services\ArtworkMedalService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
final class ArtworkAwardController extends Controller
{
public function __construct(
private readonly ArtworkAwardService $service
private readonly ArtworkMedalService $service
) {}
/**
@@ -32,7 +34,7 @@ final class ArtworkAwardController extends Controller
'medal' => ['required', 'string', 'in:gold,silver,bronze'],
]);
$award = $this->service->award($artwork, $user, $data['medal']);
$this->service->award($artwork, $user, $data['medal']);
// Record activity event
try {
@@ -51,6 +53,32 @@ final class ArtworkAwardController extends Controller
);
}
public function upsert(Request $request, int $id): JsonResponse
{
$user = $request->user();
$artwork = Artwork::findOrFail($id);
$this->authorize('award', [ArtworkAward::class, $artwork]);
$data = $request->validate([
'medal_type' => ['required', 'string', 'in:gold,silver,bronze'],
]);
$existed = ArtworkMedal::query()
->where('artwork_id', $artwork->id)
->where('user_id', $user->id)
->exists();
$this->service->upsert($artwork, $user, $data['medal_type']);
return response()->json(
array_merge($this->buildPayload($artwork->id, $user->id), [
'message' => $existed ? 'Medal updated.' : 'Medal added.',
]),
$existed ? 200 : 201,
);
}
/**
* PUT /api/artworks/{id}/award
* Change an existing award medal.
@@ -60,7 +88,7 @@ final class ArtworkAwardController extends Controller
$user = $request->user();
$artwork = Artwork::findOrFail($id);
$existingAward = ArtworkAward::where('artwork_id', $artwork->id)
$existingAward = ArtworkMedal::where('artwork_id', $artwork->id)
->where('user_id', $user->id)
->firstOrFail();
@@ -70,7 +98,7 @@ final class ArtworkAwardController extends Controller
'medal' => ['required', 'string', 'in:gold,silver,bronze'],
]);
$award = $this->service->changeAward($artwork, $user, $data['medal']);
$this->service->changeMedal($artwork, $user, $data['medal']);
return response()->json($this->buildPayload($artwork->id, $user->id));
}
@@ -84,17 +112,29 @@ final class ArtworkAwardController extends Controller
$user = $request->user();
$artwork = Artwork::findOrFail($id);
$existingAward = ArtworkAward::where('artwork_id', $artwork->id)
$existingAward = ArtworkMedal::where('artwork_id', $artwork->id)
->where('user_id', $user->id)
->firstOrFail();
$this->authorize('remove', $existingAward);
$this->service->removeAward($artwork, $user);
$this->service->removeMedal($artwork, $user);
return response()->json($this->buildPayload($artwork->id, $user->id));
}
public function destroyMedal(Request $request, int $id): JsonResponse
{
$user = $request->user();
$artwork = Artwork::findOrFail($id);
$this->service->removeMedal($artwork, $user);
return response()->json(array_merge($this->buildPayload($artwork->id, $user->id), [
'message' => 'Medal removed.',
]));
}
/**
* GET /api/artworks/{id}/awards
* Return award stats + viewer's current award.
@@ -111,22 +151,29 @@ final class ArtworkAwardController extends Controller
private function buildPayload(int $artworkId, ?int $userId): array
{
$stat = \App\Models\ArtworkAwardStat::find($artworkId);
$stat = ArtworkMedalStat::find($artworkId);
$userAward = $userId
? ArtworkAward::where('artwork_id', $artworkId)
? ArtworkMedal::where('artwork_id', $artworkId)
->where('user_id', $userId)
->value('medal')
->value('medal_type')
: null;
$medals = [
'gold' => (int) ($stat?->gold_count ?? 0),
'silver' => (int) ($stat?->silver_count ?? 0),
'bronze' => (int) ($stat?->bronze_count ?? 0),
'score' => (int) ($stat?->score_total ?? 0),
'score_7d' => (int) ($stat?->score_7d ?? 0),
'score_30d' => (int) ($stat?->score_30d ?? 0),
'last_medaled_at' => $stat?->last_medaled_at?->toIsoString(),
];
return [
'awards' => [
'gold' => $stat?->gold_count ?? 0,
'silver' => $stat?->silver_count ?? 0,
'bronze' => $stat?->bronze_count ?? 0,
'score' => $stat?->score_total ?? 0,
],
'awards' => $medals,
'medals' => $medals,
'viewer_award' => $userAward,
'current_user_medal' => $userAward,
];
}
}