Users can now control which in-app and email notifications they receive from their Settings tab on their channel page. Bell (in-app) preferences: - New comment on my video (default: on) - Reply to my comment (default: on) - Comment liked (default: on) - Video liked (default: on) - New subscriber (default: on) - New video from channels I follow (default: on) - New post from channels I follow (default: on) - New user registration — super admins only (default: on) Email preferences (same set plus): - Comment liked (default: off — too noisy) - Video liked (default: off — too noisy) - New post from channels I follow (default: off) - My video finished processing (default: on) - Weekly activity digest every Monday (default: on) - New user registration — super admins only (default: on) Implementation: - Migration: notification_preferences JSON column on users table - User::notificationPref($key) helper with typed defaults - All existing notification classes updated to check prefs in via() - 4 new notification classes: NewSubscriberNotification, VideoLikedNotification, NewPostNotification, WeeklyDigestNotification - 8 new email views matching existing dark theme - SendWeeklyDigest artisan command, scheduled every Monday 09:00 - NewSubscriberNotification wired into UserController::toggleSubscribe - VideoLikedNotification wired into UserController::toggleLike - NewPostNotification wired into PostController::store (to all subscribers) - Bell renderer updated for new_subscriber, video_like, new_post types - Preferences saved via AJAX (POST /settings/notifications) — instant toggle with automatic revert on failure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
61 lines
1.7 KiB
PHP
61 lines
1.7 KiB
PHP
<?php
|
|
|
|
namespace App\Notifications;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Notifications\Messages\MailMessage;
|
|
use Illuminate\Notifications\Notification;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class WeeklyDigestNotification extends Notification
|
|
{
|
|
public array $stats;
|
|
|
|
public function __construct(public User $creator)
|
|
{
|
|
$videoIds = $creator->videos()->pluck('id');
|
|
|
|
$views = DB::table('video_views')
|
|
->whereIn('video_id', $videoIds)
|
|
->where('created_at', '>=', now()->subWeek())
|
|
->count();
|
|
|
|
$likes = DB::table('video_likes')
|
|
->whereIn('video_id', $videoIds)
|
|
->where('created_at', '>=', now()->subWeek())
|
|
->count();
|
|
|
|
$newSubs = DB::table('user_subscriptions')
|
|
->where('channel_id', $creator->id)
|
|
->where('created_at', '>=', now()->subWeek())
|
|
->count();
|
|
|
|
$topVideo = $creator->videos()
|
|
->withCount(['viewers as week_views' => fn($q) => $q->where('video_views.created_at', '>=', now()->subWeek())])
|
|
->orderByDesc('week_views')
|
|
->first();
|
|
|
|
$this->stats = [
|
|
'views' => $views,
|
|
'likes' => $likes,
|
|
'new_subs' => $newSubs,
|
|
'top_video' => $topVideo,
|
|
];
|
|
}
|
|
|
|
public function via(object $notifiable): array
|
|
{
|
|
return $notifiable->notificationPref('email_weekly_digest') ? ['mail'] : [];
|
|
}
|
|
|
|
public function toMail(object $notifiable): MailMessage
|
|
{
|
|
return (new MailMessage)
|
|
->subject('Your weekly TAKEONE summary 📊')
|
|
->view('emails.weekly-digest', [
|
|
'creator' => $this->creator,
|
|
'stats' => $this->stats,
|
|
]);
|
|
}
|
|
}
|