sls/app/Mail/InterviewerAssessmentNotificationMail.php
kushal.saha 1541c8193e feat(interview): add candidate resume upload, lightbox viewer, and panelist email attachments
- Add resume file upload to schedule drawer with instant preview and validation
- Create resume lightbox modal viewer with background scroll lock and CV SVG icon
- Integrate CV tab into inspector panel with enlarge action and state 
- Attach candidate resume to panelist notification emails when 
- Fix Outlook RFC 5546 iTIP element mismatch and add table credentials copy button
2026-08-27 11:37:01 +00:00

81 lines
2.4 KiB
PHP

<?php
namespace App\Mail;
use App\Models\Interview;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class InterviewerAssessmentNotificationMail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(
public readonly Interview $interview,
public readonly User $interviewer,
public readonly string $icsContent,
public readonly string $icsFilename = 'invitation.ics',
) {
$this->afterCommit();
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$jobTitle = $this->interview->job_title ?: 'Candidate Assessment';
$round = $this->interview->round ?: 'R1';
return new Envelope(
subject: "Panelist Assignment: {$this->interview->candidate_name} - {$jobTitle} ({$round})",
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'emails.interview.interviewer-notification',
);
}
/**
* Get the attachments for the message.
*
* @return array<int, Attachment>
*/
public function attachments(): array
{
$attachments = [
Attachment::fromData(fn () => $this->icsContent, $this->icsFilename)
->withMime('text/calendar; charset=UTF-8; method=REQUEST'),
];
if (! empty($this->interview->resume_path) && Storage::disk('public')->exists($this->interview->resume_path)) {
$resumeFullPath = Storage::disk('public')->path($this->interview->resume_path);
$cleanCandidateName = Str::slug($this->interview->candidate_name ?: 'Candidate');
$ext = pathinfo($this->interview->resume_path, PATHINFO_EXTENSION) ?: 'pdf';
$downloadFilename = "Resume_{$cleanCandidateName}.{$ext}";
$attachments[] = Attachment::fromPath($resumeFullPath)
->as($downloadFilename);
}
return $attachments;
}
}