- Added local scopes for Enum-based fields (status, type, decision) in models: Cooperation, VerificationRequest, PartnerMedia, CooperationProposal, CooperationMedia, and VerificationReview. - Refactored query logic in Commands, Services, and Filament Resources to use the new scopes for better readability and maintainability. - Added specific pivot status scopes in PartnerMedia model for cleaner relationship filtering. - Fixed incorrect Enum usage in ViewCooperation.php during the refactoring process. - Standardized code style for closures and string concatenation in the modified files.
322 lines
10 KiB
PHP
322 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources\Manage\Cooperations\Pages;
|
|
|
|
use App\Enums\ApprovalStatus;
|
|
use App\Filament\Resources\Manage\Cooperations\CooperationResource;
|
|
use Filament\Actions\Action;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Resources\Pages\ViewRecord;
|
|
use Filament\Schemas\Components\RepeatableEntry;
|
|
use Filament\Schemas\Components\TextEntry;
|
|
use Filament\Support\Enums\FontWeight;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class ViewCooperation extends ViewRecord
|
|
{
|
|
protected static string $resource = CooperationResource::class;
|
|
|
|
protected function getWorkflowSteps()
|
|
{
|
|
$record = $this->getRecord();
|
|
|
|
$steps = [
|
|
[
|
|
'step' => 1,
|
|
'title' => 'Pengajuan Kerja Sama',
|
|
'description' => 'Admin mengajukan kerja sama ke media',
|
|
'status' => 'completed', // Always completed since we're viewing it
|
|
'date' => $record->created_at?->format('d/m/Y H:i'),
|
|
],
|
|
[
|
|
'step' => 2,
|
|
'title' => 'Respon Media',
|
|
'description' => 'Media menerima atau menolak pengajuan',
|
|
'status' => $this->getMediaResponseStatus($record),
|
|
'date' => $this->getMediaResponseDate($record),
|
|
],
|
|
[
|
|
'step' => 3,
|
|
'title' => 'Upload Proposal',
|
|
'description' => 'Media mengupload dokumen proposal',
|
|
'status' => $this->getProposalStatus($record),
|
|
'date' => $this->getProposalDate($record),
|
|
],
|
|
[
|
|
'step' => 4,
|
|
'title' => 'Review Proposal',
|
|
'description' => 'Admin mereview dan menyetujui proposal',
|
|
'status' => $this->getProposalReviewStatus($record),
|
|
'date' => $this->getProposalReviewDate($record),
|
|
],
|
|
[
|
|
'step' => 5,
|
|
'title' => 'Penugasan',
|
|
'description' => 'Admin membuat task assignment',
|
|
'status' => $this->getTaskStatus($record),
|
|
'date' => $this->getTaskDate($record),
|
|
],
|
|
[
|
|
'step' => 6,
|
|
'title' => 'Upload Laporan',
|
|
'description' => 'Media mengupload laporan',
|
|
'status' => $this->getReportStatus($record),
|
|
'date' => $this->getReportDate($record),
|
|
],
|
|
[
|
|
'step' => 7,
|
|
'title' => 'Selesai',
|
|
'description' => 'Kerja sama telah selesai',
|
|
'status' => $this->getCompletionStatus($record),
|
|
'date' => $this->getCompletionDate($record),
|
|
],
|
|
];
|
|
|
|
return RepeatableEntry::make('workflow_steps')
|
|
->label('')
|
|
->schema([
|
|
TextEntry::make('step')
|
|
->label('Langkah')
|
|
->formatStateUsing(fn ($state) => "Langkah {$state}")
|
|
->weight(FontWeight::Bold),
|
|
|
|
TextEntry::make('title')
|
|
->label('Judul'),
|
|
|
|
TextEntry::make('description')
|
|
->label('Deskripsi'),
|
|
|
|
TextEntry::make('status')
|
|
->label('Status')
|
|
->badge()
|
|
->color(fn (string $state): string => match ($state) {
|
|
'completed' => 'success',
|
|
'in_progress' => 'warning',
|
|
'pending' => 'gray',
|
|
'rejected' => 'danger',
|
|
default => 'gray',
|
|
})
|
|
->formatStateUsing(fn (string $state): string => match ($state) {
|
|
'completed' => 'Selesai',
|
|
'in_progress' => 'Sedang Berjalan',
|
|
'pending' => 'Menunggu',
|
|
'rejected' => 'Ditolak',
|
|
default => $state,
|
|
}),
|
|
|
|
TextEntry::make('date')
|
|
->label('Tanggal')
|
|
->placeholder('Belum ada'),
|
|
])
|
|
->columns(5)
|
|
->state($steps);
|
|
}
|
|
|
|
protected function getMediaResponseStatus($record): string
|
|
{
|
|
$mediaStatuses = $record->cooperationMedia->pluck('status')->unique();
|
|
|
|
if ($mediaStatuses->contains(ApprovalStatus::ACCEPTED)) {
|
|
return 'completed';
|
|
}
|
|
|
|
if ($mediaStatuses->contains(ApprovalStatus::REJECTED)) {
|
|
return 'rejected';
|
|
}
|
|
|
|
return 'pending';
|
|
}
|
|
|
|
protected function getMediaResponseDate($record)
|
|
{
|
|
$latestResponse = $record->cooperationMedia
|
|
->whereNotNull('updated_at')
|
|
->sortByDesc('updated_at')
|
|
->first();
|
|
|
|
return $latestResponse?->updated_at?->format('d/m/Y H:i');
|
|
}
|
|
|
|
protected function getProposalStatus($record): string
|
|
{
|
|
if ($record->proposals()->exists()) {
|
|
return 'completed';
|
|
}
|
|
|
|
return 'pending';
|
|
}
|
|
|
|
protected function getProposalDate($record)
|
|
{
|
|
$latestProposal = $record->proposals->sortByDesc('created_at')->first();
|
|
|
|
return $latestProposal?->created_at?->format('d/m/Y H:i');
|
|
}
|
|
|
|
protected function getProposalReviewStatus($record): string
|
|
{
|
|
$proposals = $record->proposals;
|
|
|
|
if ($record->proposals()->accepted()->exists()) {
|
|
return 'completed';
|
|
}
|
|
|
|
if ($record->proposals()->rejected()->exists()) {
|
|
return 'rejected';
|
|
}
|
|
|
|
if ($proposals->isNotEmpty()) {
|
|
return 'in_progress';
|
|
}
|
|
|
|
return 'pending';
|
|
}
|
|
|
|
protected function getProposalReviewDate($record)
|
|
{
|
|
$latestProposal = $record->proposals->sortByDesc('updated_at')->first();
|
|
|
|
return $latestProposal?->updated_at?->format('d/m/Y H:i');
|
|
}
|
|
|
|
protected function getTaskStatus($record): string
|
|
{
|
|
if ($record->taskAssignments->isNotEmpty()) {
|
|
return 'completed';
|
|
}
|
|
|
|
return 'pending';
|
|
}
|
|
|
|
protected function getTaskDate($record)
|
|
{
|
|
$latestTask = $record->taskAssignments->sortByDesc('created_at')->first();
|
|
|
|
return $latestTask?->created_at?->format('d/m/Y H:i');
|
|
}
|
|
|
|
protected function getReportStatus($record): string
|
|
{
|
|
$tasks = $record->taskAssignments;
|
|
|
|
if ($tasks->isEmpty()) {
|
|
return 'pending';
|
|
}
|
|
|
|
$totalReports = $tasks->sum('report_amount');
|
|
$completedReports = $tasks->flatMap->reports->count();
|
|
|
|
if ($completedReports >= $totalReports && $totalReports > 0) {
|
|
return 'completed';
|
|
}
|
|
|
|
if ($completedReports > 0) {
|
|
return 'in_progress';
|
|
}
|
|
|
|
return 'pending';
|
|
}
|
|
|
|
protected function getReportDate($record)
|
|
{
|
|
$latestReport = $record->taskAssignments
|
|
->flatMap->reports
|
|
->sortByDesc('created_at')
|
|
->first();
|
|
|
|
return $latestReport?->created_at?->format('d/m/Y H:i');
|
|
}
|
|
|
|
protected function getCompletionStatus($record): string
|
|
{
|
|
// Logic for completion - could be based on all reports accepted, etc.
|
|
return 'pending';
|
|
}
|
|
|
|
protected function getCompletionDate($record)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
$isPerusahaan = Auth::user()->hasRole('Perusahaan');
|
|
$record = $this->getRecord();
|
|
|
|
$actions = [];
|
|
|
|
if (! $isPerusahaan) {
|
|
$actions[] = Action::make('mark_completed')
|
|
->label('Tandai Selesai')
|
|
->icon('heroicon-o-check-circle')
|
|
->color('success')
|
|
->action(function () {
|
|
// Logic to mark cooperation as completed
|
|
Notification::make()
|
|
->title('Kerja Sama Ditandai Selesai')
|
|
->success()
|
|
->send();
|
|
})
|
|
->visible(fn () => $this->canMarkAsCompleted());
|
|
} else {
|
|
// For Perusahaan users, add accept/reject actions if they have a cooperation media record
|
|
$cooperationMedia = $record->cooperationMedia()
|
|
->whereHas('partnerMedia', function ($query) {
|
|
$query->whereHas('company', function ($subQuery) {
|
|
$subQuery->where('user_id', Auth::id());
|
|
});
|
|
})
|
|
->first();
|
|
|
|
if ($cooperationMedia && $cooperationMedia->status === ApprovalStatus::PENDING) {
|
|
$actions[] = Action::make('accept')
|
|
->label('Terima Kerja Sama')
|
|
->icon('heroicon-o-check-circle')
|
|
->color('success')
|
|
->action(function () use ($cooperationMedia) {
|
|
$cooperationMedia->update(['status' => ApprovalStatus::ACCEPTED]);
|
|
Notification::make()
|
|
->title('Kerja Sama Diterima')
|
|
->success()
|
|
->send();
|
|
});
|
|
|
|
$actions[] = Action::make('reject')
|
|
->label('Tolak Kerja Sama')
|
|
->icon('heroicon-o-x-circle')
|
|
->color('danger')
|
|
->action(function () use ($cooperationMedia) {
|
|
$cooperationMedia->update(['status' => ApprovalStatus::REJECTED]);
|
|
Notification::make()
|
|
->title('Kerja Sama Ditolak')
|
|
->success()
|
|
->send();
|
|
});
|
|
}
|
|
}
|
|
|
|
$actions[] = Action::make('back')
|
|
->label('Kembali')
|
|
->url(fn (): string => static::getResource()::getUrl('index'))
|
|
->outlined()
|
|
->color('secondary');
|
|
|
|
return $actions;
|
|
}
|
|
|
|
protected function canMarkAsCompleted(): bool
|
|
{
|
|
$record = $this->getRecord();
|
|
|
|
// Check if all tasks have required number of reports
|
|
foreach ($record->taskAssignments as $task) {
|
|
$reportCount = $task->reports()->count();
|
|
if ($reportCount < $task->report_amount) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $record->taskAssignments->isNotEmpty();
|
|
}
|
|
}
|