feat: leaderboard with top (by period) and new tabs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
25e1dd2413
commit
3f8fa9f22f
@@ -284,6 +284,42 @@ class Product extends Model
|
||||
return $query->withCount('upvotes')->orderBy('upvotes_count', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Leaderboard periods: key => label.
|
||||
*/
|
||||
public const LEADERBOARD_PERIODS = [
|
||||
'today' => 'Today',
|
||||
'week' => 'This week',
|
||||
'month' => 'This month',
|
||||
'all' => 'All time',
|
||||
];
|
||||
|
||||
/**
|
||||
* Approved products ranked by the upvotes they received in the period,
|
||||
* then by total upvotes, then newest. Products with no upvotes in the
|
||||
* period are left out. Adds `period_upvotes_count` and `total_upvotes_count`.
|
||||
*/
|
||||
public function scopeTopFor(Builder $query, string $period): Builder
|
||||
{
|
||||
$since = match ($period) {
|
||||
'today' => now()->startOfDay(),
|
||||
'week' => now()->subDays(7),
|
||||
'month' => now()->subDays(30),
|
||||
default => null,
|
||||
};
|
||||
|
||||
$inPeriod = fn (Builder $upvotes) => $since ? $upvotes->where('created_at', '>=', $since) : $upvotes;
|
||||
|
||||
return $query->approved()
|
||||
->whereHas('upvotes', $inPeriod)
|
||||
->withCount(['upvotes as period_upvotes_count' => $inPeriod])
|
||||
->withCount('upvotes as total_upvotes_count')
|
||||
->orderByDesc('period_upvotes_count')
|
||||
->orderByDesc('total_upvotes_count')
|
||||
->orderByDesc('products.created_at')
|
||||
->orderByDesc('products.id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope a query to sort products.
|
||||
*/
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Upvote extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user