componist/reminder-notifications
Laravel package for queued email reminder notifications with a Livewire v4 dashboard. Supports daily (HH:MM), monthly (day 1–30), and yearly (day/month) schedules, with migrations, routes, views, and configurable Livewire components.
Install Dependencies
composer require componist/reminder-notifications
composer dump-autoload
php artisan migrate
Run migrations to create the reminder_notifications table.
Publish Config & Assets
php artisan vendor:publish --provider="Componist\ReminderNotifications\ReminderNotificationsServiceProvider" --tag="config"
php artisan vendor:publish --provider="Componist\ReminderNotifications\ReminderNotificationsServiceProvider" --tag="views"
Publish config (config/reminder-notifications.php) and views to customize templates.
Configure Mail & Queue
Ensure your .env has valid mail settings (e.g., MAIL_MAILER=smtp) and a queue worker running:
php artisan queue:work
First Use Case: Create a Reminder
/dashboard/reminder-notification/create (authenticated route).ReminderNotification::create()).14:00 for daily, 15 for monthly).Use the ReminderNotification model to attach reminders to Eloquent models (e.g., User, Order):
use Componist\ReminderNotifications\Models\ReminderNotification;
// Attach a yearly reminder to a User
$user->reminders()->create([
'type' => 'yearly',
'day' => 15,
'month' => 12, // December 15th
'message' => 'Happy Anniversary!',
'trigger_at' => now()->addYear(), // Optional: Override auto-calculation
]);
trigger_at based on type/day/month during job dispatch.Customize the Dashboard:
Extend the default Livewire component (ReminderNotificationDashboard) by publishing views and overriding methods in a child component:
namespace App\Livewire;
use Componist\ReminderNotifications\Livewire\ReminderNotificationDashboard as BaseDashboard;
class CustomReminderDashboard extends BaseDashboard {
public function mount() {
parent::mount();
// Add custom logic (e.g., filter by user role)
}
public function updatedSearch($search) {
$this->reminders = $this->reminders->where('message', 'like', "%{$search}%");
}
}
Register the component in config/reminder-notifications.php:
'livewire' => App\Livewire\CustomReminderDashboard::class,
Accessing Data:
Use Livewire’s $reminders property to display/manage reminders in a table or card layout. Example:
@foreach($reminders as $reminder)
<div>
{{ $reminder->type }} on {{ $reminder->trigger_at->format('Y-m-d H:i') }}
<button wire:click="edit({{ $reminder->id }})">Edit</button>
</div>
@endforeach
Default Templates:
Located in resources/views/remindernotifications/emails. Override by publishing views:
php artisan vendor:publish --tag="remindernotifications-views"
Customize default.blade.php or create type-specific templates (e.g., monthly.blade.php).
Dynamic Data:
Pass variables via the ReminderNotification model:
$reminder->data = ['user_name' => $user->name]; // Available in email template as `$data`
ReminderNotification::dispatchNow($reminderId);
RemindNotificationJob:
php artisan queue:work --queue=reminders
Configure queue connection in .env (e.g., QUEUE_CONNECTION=database).Listen for reminder events to extend functionality:
// In EventServiceProvider
protected $listen = [
\Componist\ReminderNotifications\Events\ReminderSent::class => [
\App\Listeners\LogReminderSent::class,
],
];
Expose a JSON API for reminders:
Route::get('/api/reminders', function () {
return ReminderNotification::with('recipient')->get();
});
Use the ReminderNotification facade to test job dispatch:
$this->artisan('queue:work --once')
->expectsQuestion('Continue processing jobs? (yes/no)', 'no');
$this->assertDatabaseHas('reminder_notifications', [
'type' => 'daily',
'trigger_at' => now()->addHours(1),
]);
Queue Stuck Jobs
php artisan queue:failed-table
php artisan queue:retry <job-id>
REMINDER_NOTIFICATIONS_RETRY_AFTER in .env to control retry delays.Timezone Mismatches
trigger_at uses the server’s timezone. If users are in different timezones, reminders may send at unexpected times.$reminder->trigger_at->setTimezone($user->timezone);
Livewire Component Caching
php artisan livewire:discover
php artisan view:clear
Recipient Validation
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email');
}
Migration Conflicts
reminder_notifications may conflict with package updates.Schema::hasTable() to check before running migrations:
if (!Schema::hasTable('reminder_notifications')) {
// Run migrations
}
Log Job Dispatch Add a listener to log when reminders are queued:
ReminderNotification::created(function ($reminder) {
\Log::info("Queued reminder for {$reminder->recipient_email} at {$reminder->trigger_at}");
});
Inspect Queue Jobs List pending jobs:
php artisan queue:list
php artisan queue:work --once --verbose
Test with Immediate Triggers
Use dispatchNow() to test email delivery without waiting:
ReminderNotification::dispatchNow($reminderId);
Custom Reminder Types
Extend the ReminderNotification model to add custom types (e.g., "weekly"):
// In a service provider
ReminderNotification::addType('weekly', function ($dayOfWeek) {
return now()->next($dayOfWeek)->startOfDay();
});
Webhook Notifications Add a webhook listener to notify external services when reminders are sent:
ReminderSent::dispatch($reminder)
->then(function () {
Http::post('https://external-api.com/webhook', [
'event' => 'reminder_sent',
'data' => $reminder->toArray(),
]);
});
Bulk Actions Add bulk delete/edit to the Livewire dashboard:
// In CustomReminderDashboard
public function bulkDelete() {
ReminderNotification::whereIn('id', $this->selected)->delete();
$this->emit('alert', 'Reminders deleted!');
}
Recipient Models
Extend the recipient_email
How can I help you explore Laravel packages today?