simedkom/app/Filament/Pages/Verification/Services/VerificationProgressService.php

261 lines
8.6 KiB
PHP

<?php
namespace App\Filament\Pages\Verification\Services;
use App\Enums\VerificationStatus;
use App\Filament\Pages\Company\Index as CompanyPage;
use App\Filament\Pages\Media\Index as MediaPage;
use App\Filament\Resources\Manage\Journalists\Pages\ManageJournalists;
use App\Filament\Support\CheerfulNotification;
use App\Models\Company;
use App\Models\VerificationRequest;
use Illuminate\Support\Collection as SupportCollection;
class VerificationProgressService
{
public function getProgress(?Company $company, ?VerificationRequest $verificationRequest): array
{
$isComplete = $this->isDataComplete($company);
$missingData = $this->getMissingData($company);
$status = $verificationRequest?->status;
$progress = [
'currentStep' => $this->resolveStep($company, $verificationRequest),
'isDataComplete' => $isComplete,
'missingData' => $missingData,
'canSubmit' => $this->canSubmit($company, $verificationRequest),
'verification' => $verificationRequest,
'status' => [
'label' => $status?->getLabel() ?? 'Belum Mengajukan',
'color' => $status?->getColor() ?? 'gray',
],
'isApproved' => $status === VerificationStatus::APPROVED,
'isRejected' => $status === VerificationStatus::REJECTED,
'isPending' => $status === VerificationStatus::PENDING,
'needsRevision' => $status === VerificationStatus::NEED_REVISION,
'latestNotes' => $this->getLatestReviewNotes($verificationRequest),
'reviewHistory' => $this->getReviewHistory($verificationRequest),
'company' => $company,
'partnerMedia' => $company?->partnerMedia,
'journalists' => $company?->partnerMedia?->journalists ?? collect(),
'steps' => $this->getSteps($company, $verificationRequest, $isComplete),
];
$progress['missingDataButtons'] = $this->getMissingDataButtons($company);
$progress['alert'] = $this->getAlertData($verificationRequest);
$progress['lastSubmittedAt'] = $verificationRequest?->updated_at?->translatedFormat('l, d M Y H:i');
return $progress;
}
public function isDataComplete(?Company $company): bool
{
return $company !== null
&& $company->partnerMedia !== null
&& $company->partnerMedia?->journalists !== null
&& $company->partnerMedia->journalists->count() > 0;
}
public function getMissingData(?Company $company): array
{
$missing = [];
if (! $company) {
$missing[] = 'Data Perusahaan';
return $missing;
}
if (! $company->partnerMedia) {
$missing[] = 'Data Media';
}
if ($company->partnerMedia && ($company->partnerMedia?->journalists === null || $company->partnerMedia?->journalists?->count() === 0)) {
$missing[] = 'Data Jurnalis (minimal 1)';
}
return $missing;
}
public function canSubmit(?Company $company, ?VerificationRequest $verificationRequest): bool
{
if (! $this->isDataComplete($company)) {
return false;
}
// No verification yet - can submit
if (! $verificationRequest) {
return true;
}
// Can resubmit only if status is NEED_REVISION
return $verificationRequest->status === VerificationStatus::NEED_REVISION;
}
public function resolveStep(?Company $company, ?VerificationRequest $verificationRequest): int
{
if (! $this->isDataComplete($company)) {
return 1; // Data belum lengkap
}
if (! $verificationRequest) {
return 1; // Belum submit
}
return match ($verificationRequest->status) {
VerificationStatus::PENDING,
VerificationStatus::NEED_REVISION => 2, // In review or needs revision
VerificationStatus::APPROVED,
VerificationStatus::REJECTED => 3, // Final decision
default => 1,
};
}
public function getLatestReviewNotes(?VerificationRequest $verificationRequest): ?string
{
if (! $verificationRequest) {
return null;
}
$latestReview = $verificationRequest->reviews()
->where(fn ($q) => $q->needRevision()->orWhere(fn ($q) => $q->rejected()))
->latest()
->first();
return $latestReview?->note;
}
public function getReviewHistory(?VerificationRequest $verificationRequest): SupportCollection
{
if (! $verificationRequest) {
return collect();
}
return $verificationRequest->reviews()
->with('reviewer')
->latest()
->get();
}
public function getAlertData(?VerificationRequest $verificationRequest): ?array
{
if (! $verificationRequest) {
return null;
}
$status = $verificationRequest->status;
$latestNotes = $this->getLatestReviewNotes($verificationRequest);
if ($status === VerificationStatus::NEED_REVISION && $latestNotes) {
return [
'type' => 'revision',
'icon' => 'exclamation-triangle',
'title' => 'Catatan Revisi dari Admin',
'message' => $latestNotes,
'color' => 'warning',
];
}
if ($status === VerificationStatus::REJECTED && $latestNotes) {
return [
'type' => 'rejected',
'icon' => 'x-circle',
'title' => 'Pengajuan Ditolak',
'message' => $latestNotes,
'color' => 'danger',
];
}
if ($status === VerificationStatus::APPROVED) {
return [
'type' => 'approved',
'icon' => 'check-circle',
'title' => 'Verifikasi Diterima',
'message' => CheerfulNotification::getByKey('verification.alert.approved.body'),
'color' => 'success',
];
}
if ($status === VerificationStatus::PENDING) {
return [
'type' => 'pending',
'icon' => 'clock',
'title' => CheerfulNotification::getByKey('verification.alert.pending.title'),
'message' => CheerfulNotification::getByKey('verification.alert.pending.body'),
'color' => 'info',
'animate' => true,
];
}
return null;
}
public function getMissingDataButtons(?Company $company): array
{
$buttons = [];
if (! $company) {
$buttons[] = [
'label' => 'Lengkapi Data Perusahaan',
'url' => CompanyPage::getUrl(),
'icon' => 'building-office-2',
'color' => 'warning',
];
return $buttons;
}
if (! $company->partnerMedia) {
$buttons[] = [
'label' => 'Lengkapi Data Media',
'url' => MediaPage::getUrl(),
'icon' => 'newspaper',
'color' => 'warning',
];
}
if ($company->partnerMedia && ($company->partnerMedia->journalists === null || $company->partnerMedia->journalists->count() === 0)) {
$buttons[] = [
'label' => 'Lengkapi Data Jurnalis',
'url' => ManageJournalists::getUrl(),
'icon' => 'user-circle',
'color' => 'warning',
];
}
return $buttons;
}
public function getSteps(?Company $company, ?VerificationRequest $verificationRequest, bool $isComplete): array
{
$status = $verificationRequest?->status;
return [
[
'title' => 'Pengajuan',
'description' => $isComplete
? 'Data sudah lengkap, silakan ajukan verifikasi'
: 'Silakan lengkapi data',
],
[
'title' => 'Verifikasi',
'description' => match ($status) {
VerificationStatus::NEED_REVISION => 'Perlu perbaikan data',
VerificationStatus::PENDING => 'Sedang diverifikasi admin',
default => 'Menunggu pengajuan',
},
],
[
'title' => 'Selesai',
'description' => match ($status) {
VerificationStatus::APPROVED => 'Verifikasi disetujui',
VerificationStatus::REJECTED => 'Verifikasi ditolak',
default => 'Menunggu keputusan',
},
],
];
}
}