sls/app/Actions/Interview/SendUpcomingInterviewRemindersAction.php
kushal.saha e4fabef1d3 feat(interview): add icalendar invites, white date pickers, and drawer validation feedback
- integrate spatie/icalendar-generator for candidate & panelist .ics invitations (RSVP & 15m alerts)
    - add StoreInterviewRequest, ScheduleInterviewDto, and invitation/reminder queued actions
    - add migration for job_title, round, description, and reminder_sent_at on interviews table
    - style datetime-local picker indicators to pure white on dark input backgrounds
    - support button loading spinners with :showLoader="true" and loadingText
    - auto-open schedule drawer on validation failure with inline @error alerts and old() bindings
2026-08-27 10:16:46 +00:00

67 lines
2.3 KiB
PHP

<?php
namespace App\Actions\Interview;
use App\Mail\InterviewReminderMail;
use App\Models\Interview;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class SendUpcomingInterviewRemindersAction
{
/**
* Scan and dispatch 15-minute advance email reminders to candidates and panelists.
*
* @return int Count of reminded interview sessions
*/
public function execute(int $windowMinutes = 20): int
{
$now = now();
$targetWindow = $now->copy()->addMinutes($windowMinutes);
$interviews = Interview::where('status', 'scheduled')
->whereNull('reminder_sent_at')
->whereNotNull('scheduled_at')
->where('scheduled_at', '>=', $now->subMinutes(5)) // Within 5m grace
->where('scheduled_at', '<=', $targetWindow)
->get();
$processedCount = 0;
foreach ($interviews as $interview) {
// 1. Candidate reminder email
if (! empty($interview->candidate_email)) {
try {
Mail::to($interview->candidate_email)
->queue(new InterviewReminderMail($interview, 'candidate', $interview->candidate_name));
} catch (\Throwable $e) {
Log::error('Failed to send 15m reminder to candidate: '.$e->getMessage(), [
'interview_id' => $interview->id,
]);
}
}
// 2. Panelists reminder emails
$assignedUsers = $interview->assignedUsers();
foreach ($assignedUsers as $interviewer) {
if (! empty($interviewer->email)) {
try {
Mail::to($interviewer->email)
->queue(new InterviewReminderMail($interview, 'interviewer', $interviewer->name));
} catch (\Throwable $e) {
Log::error('Failed to send 15m reminder to interviewer: '.$e->getMessage(), [
'interview_id' => $interview->id,
'interviewer_id' => $interviewer->id,
]);
}
}
}
$interview->update(['reminder_sent_at' => now()]);
$processedCount++;
}
return $processedCount;
}
}