sls/app/DTOs/Interview/ScheduleInterviewDto.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

89 lines
3.4 KiB
PHP

<?php
namespace App\DTOs\Interview;
use App\Http\Requests\Interview\StoreInterviewRequest;
use Carbon\Carbon;
use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;
class ScheduleInterviewDto implements Arrayable, JsonSerializable
{
/**
* @param array<int> $assignedInterviewers
*/
public function __construct(
public readonly string $candidateName,
public readonly string $candidateEmail,
public readonly string $candidatePhone,
public readonly string $jobTitle,
public readonly string $round,
public readonly ?Carbon $scheduledAt,
public readonly int $validHours,
public readonly string $language,
public readonly array $assignedInterviewers = [],
public readonly ?string $description = null,
) {}
public static function fromRequest(StoreInterviewRequest $request): self
{
$scheduledAt = $request->filled('scheduled_at')
? Carbon::parse($request->input('scheduled_at'))
: now();
return new self(
candidateName: trim($request->input('candidate_name')),
candidateEmail: strtolower(trim($request->input('candidate_email'))),
candidatePhone: trim($request->input('candidate_phone')),
jobTitle: trim($request->input('job_title', 'Software Engineer')),
round: trim($request->input('round', 'R1')) ?: 'R1',
scheduledAt: $scheduledAt,
validHours: (int) $request->input('valid_hours', 2),
language: $request->input('language', 'python'),
assignedInterviewers: array_map('intval', (array) $request->input('assigned_interviewers', [])),
description: $request->filled('description') ? trim($request->input('description')) : null,
);
}
public static function fromArray(array $data): self
{
$scheduledAt = isset($data['scheduled_at'])
? ($data['scheduled_at'] instanceof Carbon ? $data['scheduled_at'] : Carbon::parse($data['scheduled_at']))
: now();
return new self(
candidateName: trim($data['candidate_name'] ?? ''),
candidateEmail: strtolower(trim($data['candidate_email'] ?? '')),
candidatePhone: trim($data['candidate_phone'] ?? ''),
jobTitle: trim($data['job_title'] ?? 'Software Engineer'),
round: trim($data['round'] ?? 'R1') ?: 'R1',
scheduledAt: $scheduledAt,
validHours: (int) ($data['valid_hours'] ?? 2),
language: $data['language'] ?? 'python',
assignedInterviewers: array_map('intval', (array) ($data['assigned_interviewers'] ?? [])),
description: isset($data['description']) && filled($data['description']) ? trim($data['description']) : null,
);
}
public function toArray(): array
{
return [
'candidate_name' => $this->candidateName,
'candidate_email' => $this->candidateEmail,
'candidate_phone' => $this->candidatePhone,
'job_title' => $this->jobTitle,
'round' => $this->round,
'scheduled_at' => $this->scheduledAt?->toDateTimeString(),
'valid_hours' => $this->validHours,
'language' => $this->language,
'assigned_interviewers' => $this->assignedInterviewers,
'description' => $this->description,
];
}
public function jsonSerialize(): array
{
return $this->toArray();
}
}