- Added detailed notifications for users and admins upon acceptance, rejection, and submission of proposals, verifications, and reports. - Improved user experience with personalized messages and actionable links in notifications. - Refactored notification logic across various actions to ensure consistent messaging and clarity. - Introduced new notification titles and bodies to better reflect the status of actions taken.
265 lines
7.9 KiB
PHP
265 lines
7.9 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\Infolists\Components\RepeatableEntry;
|
|
use Filament\Infolists\Components\TextEntry;
|
|
use Filament\Resources\Pages\ViewRecord;
|
|
use Filament\Support\Enums\FontWeight;
|
|
|
|
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 (int $state): string => "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
|
|
{
|
|
return [
|
|
Action::make('back')
|
|
->label('Kembali')
|
|
->url(fn (): string => static::getResource()::getUrl('index'))
|
|
->outlined()
|
|
->color('secondary'),
|
|
];
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|