Merge branch 'dev' into 'main'
refactor: Adjust password field to set a default value only on creation and be... See merge request pratama/purwakarta/diskominfo/simedkom!3
This commit is contained in:
commit
f781741a3d
@ -34,7 +34,7 @@ public function getColor(): string|array|null
|
||||
self::PENDING => 'warning',
|
||||
self::ASSIGNMENT => 'info',
|
||||
self::VERIFICATION => 'primary',
|
||||
self::PAYMENT => 'secondary',
|
||||
self::PAYMENT => 'slate',
|
||||
self::COMPLETED => 'success',
|
||||
};
|
||||
}
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
use App\Models\User;
|
||||
use App\Models\VerificationRequest;
|
||||
use App\Models\VerificationReview;
|
||||
use App\Notifications\BroadcastNotification;
|
||||
use App\Services\VerificationService;
|
||||
use BackedEnum;
|
||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||
use Filament\Actions\Action;
|
||||
@ -19,7 +19,9 @@
|
||||
use Filament\Forms\Concerns\InteractsWithForms;
|
||||
use Filament\Forms\Contracts\HasForms;
|
||||
use Filament\Pages\Page;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use UnitEnum;
|
||||
|
||||
@ -41,15 +43,8 @@ class AdminVerification extends Page implements HasActions, HasForms
|
||||
|
||||
protected static ?string $title = 'Verifikasi Rekanan';
|
||||
|
||||
protected VerificationService $verificationService;
|
||||
|
||||
protected string $view = 'filament.pages.admin-verification';
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->verificationService = app(VerificationService::class);
|
||||
}
|
||||
|
||||
public static function getNavigationBadge(): ?string
|
||||
{
|
||||
return VerificationRequest::query()->pending()->count();
|
||||
@ -95,7 +90,7 @@ public function getStatusCounts(): array
|
||||
*/
|
||||
public function getCompanyName(VerificationRequest $request): string
|
||||
{
|
||||
return $this->verificationService->getCompanyName($request);
|
||||
return $request->company?->name ?? 'Data tidak ditemukan';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,7 +110,27 @@ public function getDetailUrl(VerificationRequest $request): ?string
|
||||
*/
|
||||
public function getVerificationSummary(VerificationRequest $request): array
|
||||
{
|
||||
return $this->verificationService->getVerificationSummary($request);
|
||||
$company = $request->company;
|
||||
$media = $company?->partnerMedia;
|
||||
$journalists = $media?->journalists ?? collect();
|
||||
|
||||
return [
|
||||
'company' => [
|
||||
'name' => $company?->name ?? 'Belum diisi',
|
||||
'email' => $company?->email ?? '-',
|
||||
'exists' => $company !== null,
|
||||
],
|
||||
'media' => [
|
||||
'name' => $media?->name ?? 'Belum diisi',
|
||||
'type' => $media?->type?->getLabel() ?? '-',
|
||||
'exists' => $media !== null,
|
||||
],
|
||||
'journalists' => [
|
||||
'count' => $journalists->count(),
|
||||
'names' => $journalists->pluck('name')->take(3)->toArray(),
|
||||
'exists' => $journalists->count() > 0,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,13 +201,14 @@ public function revisionAction(): Action
|
||||
Textarea::make('note')
|
||||
->label('Catatan Revisi')
|
||||
->required()
|
||||
->placeholder('Jelaskan bagian yang perlu diperbaiki (Perusahaan, Media, atau Jurnalis)...')
|
||||
->placeholder('Jelaskan bagian yang perlu diperbaiki...')
|
||||
->autocomplete(false)
|
||||
->autofocus(),
|
||||
])
|
||||
->action(function (array $arguments, array $data): void {
|
||||
$this->processReview($arguments['id'], DecisionAdmin::NEED_REVISION, $data['note']);
|
||||
});
|
||||
})
|
||||
->modalWidth(Width::Large);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,7 +256,28 @@ protected function processReview(int $requestId, DecisionAdmin $decision, ?strin
|
||||
}
|
||||
|
||||
try {
|
||||
$this->verificationService->processReview($verificationRequest, $decision, $note);
|
||||
DB::beginTransaction();
|
||||
|
||||
// Create review record
|
||||
VerificationReview::create([
|
||||
'verification_request_id' => $verificationRequest->id,
|
||||
'reviewer_id' => auth()->id(),
|
||||
'decision' => $decision,
|
||||
'note' => $note,
|
||||
]);
|
||||
|
||||
// Update verification request status
|
||||
$newStatus = match ($decision) {
|
||||
DecisionAdmin::APPROVED => VerificationStatus::APPROVED,
|
||||
DecisionAdmin::NEED_REVISION => VerificationStatus::NEED_REVISION,
|
||||
DecisionAdmin::REJECTED => VerificationStatus::REJECTED,
|
||||
};
|
||||
|
||||
$verificationRequest->update([
|
||||
'status' => $newStatus,
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
$actionLabel = match ($decision) {
|
||||
DecisionAdmin::APPROVED => 'disetujui',
|
||||
@ -284,6 +321,7 @@ protected function processReview(int $requestId, DecisionAdmin $decision, ?strin
|
||||
]));
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
Log::error('Verification processing failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
@ -292,8 +330,8 @@ protected function processReview(int $requestId, DecisionAdmin $decision, ?strin
|
||||
]);
|
||||
|
||||
CheerfulNotification::danger(
|
||||
'Belum ketemu nih 🙌',
|
||||
'Data verifikasi belum kami temukan atau terjadi kesalahan sistem. Coba sebentar lagi, ya.',
|
||||
'Terjadi Kesalahan ⚠️',
|
||||
'Proses verifikasi gagal karena kesalahan sistem. Tim kami sudah mencatat masalah ini. Silakan coba lagi nanti.',
|
||||
)
|
||||
->send();
|
||||
}
|
||||
|
||||
@ -91,6 +91,15 @@ public function authenticate(): ?LoginResponse
|
||||
$this->throwFailureValidationException();
|
||||
}
|
||||
|
||||
if ($user instanceof FilamentUser && (! $user->canAccessPanel(Filament::getCurrentOrDefaultPanel()))) {
|
||||
CheerfulNotification::danger(
|
||||
'Akun Tidak Aktif 🚫',
|
||||
'Maaf, akun Anda saat ini tidak aktif. Silakan hubungi Administrator. 📞'
|
||||
)->send();
|
||||
|
||||
throw ValidationException::withMessages([]);
|
||||
}
|
||||
|
||||
if (
|
||||
filled($this->userUndertakingMultiFactorAuthentication) &&
|
||||
(decrypt($this->userUndertakingMultiFactorAuthentication) === $user->getAuthIdentifier())
|
||||
|
||||
@ -38,6 +38,8 @@ class Company extends Page implements HasForms
|
||||
|
||||
public array $originalDocuments = [];
|
||||
|
||||
public bool $isVerificationStage = false;
|
||||
|
||||
protected static string|UnitEnum|null $navigationGroup = 'Kelola';
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::BuildingOffice2;
|
||||
@ -64,6 +66,11 @@ public function mount(): void
|
||||
return;
|
||||
}
|
||||
|
||||
$this->isVerificationStage = in_array($company->verificationRequest?->status, [
|
||||
VerificationStatus::PENDING,
|
||||
VerificationStatus::REJECTED,
|
||||
]) || $company->verificationRequest()->pending()->exists();
|
||||
|
||||
$this->verificationRequest = $company->verificationRequest()
|
||||
->latest()
|
||||
->first();
|
||||
@ -271,7 +278,7 @@ public function save(): void
|
||||
|
||||
public function saveAction(): Action
|
||||
{
|
||||
$needsReview = $this->company?->status === VerificationStatus::APPROVED;
|
||||
$needsReview = $this->company?->verificationRequest?->status !== null;
|
||||
|
||||
return Action::make('save')
|
||||
->label('Simpan')
|
||||
@ -284,7 +291,8 @@ public function saveAction(): Action
|
||||
->label('Alasan')
|
||||
->placeholder('Jelaskan alasan perubahan data ini...')
|
||||
->autocomplete(false)
|
||||
->autofocus(),
|
||||
->autofocus()
|
||||
->required(),
|
||||
]
|
||||
: []
|
||||
)
|
||||
|
||||
@ -59,6 +59,8 @@ class Media extends Page implements HasForms
|
||||
|
||||
public bool $restricted = false;
|
||||
|
||||
public bool $isVerificationStage = false;
|
||||
|
||||
protected static ?string $slug = 'manage/media';
|
||||
|
||||
protected static ?string $title = 'Media';
|
||||
@ -85,6 +87,11 @@ public function mount(): void
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->isVerificationStage = in_array($company?->verificationRequest?->status, [
|
||||
VerificationStatus::PENDING,
|
||||
VerificationStatus::REJECTED,
|
||||
]) || $company->verificationRequest()->pending()->exists();
|
||||
|
||||
$verificationRequest = $this->company->verificationRequest()
|
||||
->latest()
|
||||
->first();
|
||||
@ -225,7 +232,7 @@ public function save(): void
|
||||
|
||||
public function saveAction(): Action
|
||||
{
|
||||
$needsReview = $this->media?->status === VerificationStatus::APPROVED;
|
||||
$needsReview = $this->media?->company?->verificationRequest?->status !== null;
|
||||
|
||||
return Action::make('save')
|
||||
->label('Simpan')
|
||||
@ -236,10 +243,10 @@ public function saveAction(): Action
|
||||
? [
|
||||
Textarea::make('change_reason')
|
||||
->label('Alasan')
|
||||
->required()
|
||||
->placeholder('Jelaskan alasan perubahan data ini...')
|
||||
->autocomplete(false)
|
||||
->autofocus(),
|
||||
->autofocus()
|
||||
->required(),
|
||||
]
|
||||
: []
|
||||
)
|
||||
@ -251,7 +258,7 @@ public function saveAction(): Action
|
||||
|
||||
public function performSave(array $data = [], bool $needsReview = false): void
|
||||
{
|
||||
if ($needsReview && $this->media !== null) {
|
||||
if ($needsReview) {
|
||||
$existingRequest = DataChangeRequest::where('entity_type', PartnerMedia::class)
|
||||
->where('entity_id', $this->media->id)
|
||||
->where('status', DataChangeStatus::PENDING)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Filament\Pages\Settings;
|
||||
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
use App\Settings\GeneralSettings;
|
||||
use BackedEnum;
|
||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||
@ -9,6 +10,7 @@
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\SettingsPage;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
@ -98,4 +100,9 @@ public function form(Schema $schema): Schema
|
||||
])
|
||||
->columns(3);
|
||||
}
|
||||
|
||||
public function getSavedNotification(): ?Notification
|
||||
{
|
||||
return CheerfulNotification::update()->send();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
|
||||
namespace App\Filament\Pages\Settings;
|
||||
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
use App\Settings\SeoSettings;
|
||||
use BackedEnum;
|
||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\SettingsPage;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
@ -58,4 +60,9 @@ public function form(Schema $schema): Schema
|
||||
->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getSavedNotification(): ?Notification
|
||||
{
|
||||
return CheerfulNotification::update()->send();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,12 @@
|
||||
|
||||
namespace App\Filament\Pages\Settings;
|
||||
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
use App\Settings\SocialMediaSettings;
|
||||
use BackedEnum;
|
||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\SettingsPage;
|
||||
use Filament\Schemas\Components\Grid;
|
||||
use Filament\Schemas\Components\Section;
|
||||
@ -67,4 +69,9 @@ public function form(Schema $schema): Schema
|
||||
->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getSavedNotification(): ?Notification
|
||||
{
|
||||
return CheerfulNotification::update()->send();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,13 @@
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Filament\Pages\Company as PagesCompany;
|
||||
use App\Filament\Resources\Manage\Journalists\Pages\ManageJournalists;
|
||||
use App\Filament\Resources\Manage\Partners\PartnerResource;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use App\Models\VerificationRequest;
|
||||
use App\Notifications\BroadcastNotification;
|
||||
use App\Services\VerificationService;
|
||||
use BackedEnum;
|
||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||
use Filament\Actions\Action;
|
||||
@ -19,6 +20,7 @@
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Page;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Illuminate\Support\Collection;
|
||||
use UnitEnum;
|
||||
|
||||
class Verification extends Page implements HasActions, HasForms
|
||||
@ -41,15 +43,8 @@ class Verification extends Page implements HasActions, HasForms
|
||||
|
||||
public ?VerificationRequest $verificationRequest = null;
|
||||
|
||||
protected VerificationService $verificationService;
|
||||
|
||||
protected string $view = 'filament.pages.verification';
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->verificationService = app(VerificationService::class);
|
||||
}
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$user = auth()->user();
|
||||
@ -69,14 +64,35 @@ public function mount(): void
|
||||
*/
|
||||
public function getVerificationProgress(): array
|
||||
{
|
||||
$progress = $this->verificationService->getVerificationProgress(
|
||||
$this->company,
|
||||
$this->verificationRequest
|
||||
);
|
||||
$isComplete = $this->isDataComplete();
|
||||
$missingData = $this->getMissingData();
|
||||
$status = $this->verificationRequest?->status;
|
||||
|
||||
$progress = [
|
||||
'currentStep' => $this->resolveStep(),
|
||||
'isDataComplete' => $isComplete,
|
||||
'missingData' => $missingData,
|
||||
'canSubmit' => $this->canSubmit(),
|
||||
'verification' => $this->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(),
|
||||
'reviewHistory' => $this->getReviewHistory(),
|
||||
'company' => $this->company,
|
||||
'partnerMedia' => $this->company?->partnerMedia,
|
||||
'journalists' => $this->company?->partnerMedia?->journalists ?? collect(),
|
||||
'steps' => $this->getSteps($isComplete),
|
||||
];
|
||||
|
||||
// Add additional data for view
|
||||
$progress['missingDataButtons'] = $this->verificationService->getMissingDataButtons($this->company);
|
||||
$progress['alert'] = $this->verificationService->getAlertData($this->verificationRequest);
|
||||
$progress['missingDataButtons'] = $this->getMissingDataButtons();
|
||||
$progress['alert'] = $this->getAlertData();
|
||||
$progress['lastSubmittedAt'] = $this->verificationRequest?->updated_at?->translatedFormat('l, d M Y H:i');
|
||||
|
||||
return $progress;
|
||||
@ -120,10 +136,7 @@ public function submitVerificationAction(): Action
|
||||
|
||||
$isRevision = $this->verificationRequest && $this->verificationRequest->status === VerificationStatus::NEED_REVISION;
|
||||
|
||||
$this->verificationRequest = $this->verificationService->submitVerification(
|
||||
$this->company,
|
||||
$this->verificationRequest
|
||||
);
|
||||
$this->verificationRequest = $this->submitVerification();
|
||||
|
||||
Notification::make()
|
||||
->title('Berhasil Diajukan! 🚀')
|
||||
@ -151,6 +164,261 @@ public function submitVerificationAction(): Action
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all required data is complete for verification
|
||||
*/
|
||||
protected function isDataComplete(): bool
|
||||
{
|
||||
return $this->company !== null
|
||||
&& $this->company->partnerMedia !== null
|
||||
&& $this->company->partnerMedia?->journalists !== null
|
||||
&& $this->company->partnerMedia->journalists->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get missing data items for verification
|
||||
*/
|
||||
protected function getMissingData(): array
|
||||
{
|
||||
$missing = [];
|
||||
|
||||
if (! $this->company) {
|
||||
$missing[] = 'Data Perusahaan';
|
||||
}
|
||||
|
||||
if ($this->company && ! $this->company->partnerMedia) {
|
||||
$missing[] = 'Data Media';
|
||||
}
|
||||
|
||||
if ($this->company && $this->company->partnerMedia && ($this->company->partnerMedia?->journalists === null || $this->company->partnerMedia?->journalists?->count() === 0)) {
|
||||
$missing[] = 'Data Jurnalis (minimal 1)';
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can submit verification
|
||||
*/
|
||||
protected function canSubmit(): bool
|
||||
{
|
||||
if (! $this->isDataComplete()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No verification yet - can submit
|
||||
if (! $this->verificationRequest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can resubmit only if status is NEED_REVISION
|
||||
return $this->verificationRequest->status === VerificationStatus::NEED_REVISION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the current step based on status
|
||||
*/
|
||||
protected function resolveStep(): int
|
||||
{
|
||||
if (! $this->isDataComplete()) {
|
||||
return 1; // Data belum lengkap
|
||||
}
|
||||
|
||||
if (! $this->verificationRequest) {
|
||||
return 1; // Belum submit
|
||||
}
|
||||
|
||||
return match ($this->verificationRequest->status) {
|
||||
VerificationStatus::PENDING,
|
||||
VerificationStatus::NEED_REVISION => 2, // In review or needs revision
|
||||
|
||||
VerificationStatus::APPROVED,
|
||||
VerificationStatus::REJECTED => 3, // Final decision
|
||||
|
||||
default => 1, // Draft / not submitted yet
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest review notes
|
||||
*/
|
||||
protected function getLatestReviewNotes(): ?string
|
||||
{
|
||||
if (! $this->verificationRequest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$latestReview = $this->verificationRequest->reviews()
|
||||
->where(fn ($q) => $q->needRevision()->orWhere(fn ($q) => $q->rejected()))
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
return $latestReview?->note;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all reviews history
|
||||
*/
|
||||
protected function getReviewHistory(): Collection
|
||||
{
|
||||
if (! $this->verificationRequest) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return $this->verificationRequest->reviews()
|
||||
->with('reviewer')
|
||||
->latest()
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit unified verification
|
||||
*/
|
||||
protected function submitVerification(): VerificationRequest
|
||||
{
|
||||
if ($this->verificationRequest && $this->verificationRequest->status === VerificationStatus::NEED_REVISION) {
|
||||
// Resubmit - update existing request
|
||||
$this->verificationRequest->update([
|
||||
'status' => VerificationStatus::PENDING,
|
||||
]);
|
||||
|
||||
return $this->verificationRequest->fresh(['reviews.reviewer']);
|
||||
}
|
||||
|
||||
// New submission
|
||||
return VerificationRequest::create([
|
||||
'company_id' => $this->company->id,
|
||||
'submitted_by' => auth()->id(),
|
||||
'status' => VerificationStatus::PENDING,
|
||||
])->load(['reviews.reviewer']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alert data for verification status
|
||||
*/
|
||||
protected function getAlertData(): ?array
|
||||
{
|
||||
if (! $this->verificationRequest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$status = $this->verificationRequest->status;
|
||||
$latestNotes = $this->getLatestReviewNotes();
|
||||
|
||||
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' => 'Verifikasi Anda telah diterima dan disetujui oleh admin. Sekarang Anda sudah resmi terverifikasi dan bekerja sama dengan kami!',
|
||||
'color' => 'success',
|
||||
];
|
||||
}
|
||||
|
||||
if ($status === VerificationStatus::PENDING) {
|
||||
return [
|
||||
'type' => 'pending',
|
||||
'icon' => 'clock',
|
||||
'title' => 'Menunggu Verifikasi',
|
||||
'message' => 'Data Anda sedang dalam proses verifikasi oleh admin. Mohon tunggu.',
|
||||
'color' => 'info',
|
||||
'animate' => true,
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get missing data buttons configuration
|
||||
*/
|
||||
protected function getMissingDataButtons(): array
|
||||
{
|
||||
$buttons = [];
|
||||
|
||||
if (! $this->company) {
|
||||
$buttons[] = [
|
||||
'label' => 'Lengkapi Data Perusahaan',
|
||||
'url' => PagesCompany::getUrl(),
|
||||
'icon' => 'building-office-2',
|
||||
'color' => 'warning',
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->company && ! $this->company->partnerMedia) {
|
||||
$buttons[] = [
|
||||
'label' => 'Lengkapi Data Media',
|
||||
'url' => Media::getUrl(),
|
||||
'icon' => 'newspaper',
|
||||
'color' => 'warning',
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->company && $this->company->partnerMedia && ($this->company->partnerMedia->journalists === null || $this->company->partnerMedia->journalists->count() === 0)) {
|
||||
$buttons[] = [
|
||||
'label' => 'Lengkapi Data Jurnalis',
|
||||
'url' => ManageJournalists::getUrl(),
|
||||
'icon' => 'user-circle',
|
||||
'color' => 'warning',
|
||||
];
|
||||
}
|
||||
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get steps array for stepper
|
||||
*/
|
||||
protected function getSteps(bool $isComplete): array
|
||||
{
|
||||
$status = $this->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',
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getViewData(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@ -54,7 +54,7 @@ protected function setUp(): void
|
||||
|
||||
$record->update([
|
||||
'payment_amount' => $totalPayment,
|
||||
'payment_date' => now(),
|
||||
'completed_at' => now(),
|
||||
'status' => CooperationStatus::COMPLETED,
|
||||
]);
|
||||
|
||||
|
||||
@ -23,7 +23,10 @@ protected function setUp(): void
|
||||
->modalHeading('Lanjutkan ke Pembayaran?')
|
||||
->modalDescription('Apakah Anda yakin ingin melanjutkan kerja sama ini ke tahap pembayaran? Pastikan semua laporan telah diverifikasi.')
|
||||
->action(function (Cooperation $record): void {
|
||||
$record->update(['status' => CooperationStatus::PAYMENT]);
|
||||
$record->update([
|
||||
'status' => CooperationStatus::PAYMENT,
|
||||
'payment_date' => now()->toDateString(),
|
||||
]);
|
||||
|
||||
CheerfulNotification::success(
|
||||
'Tahap Pembayaran Dimulai! 💸✨',
|
||||
|
||||
@ -34,7 +34,9 @@ protected function setUp(): void
|
||||
->autocomplete(false)
|
||||
->autofocus()
|
||||
->nullable()
|
||||
->url(),
|
||||
->url()
|
||||
->required()
|
||||
->maxLength(200),
|
||||
|
||||
Textarea::make('description')
|
||||
->label('Deskripsi')
|
||||
|
||||
@ -4,8 +4,10 @@
|
||||
|
||||
use App\Enums\ApprovalStatus;
|
||||
use App\Enums\CooperationStatus;
|
||||
use App\Filament\Resources\Manage\Cooperations\CooperationResource;
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
use App\Models\CooperationMedia;
|
||||
use App\Notifications\BroadcastNotification;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
@ -64,6 +66,19 @@ protected function setUp(): void
|
||||
'Pembayaran Berhasil! 💸✨',
|
||||
"Pembayaran untuk {$record->partnerMedia->name} telah berhasil dicatat."
|
||||
)->send();
|
||||
|
||||
$partnerUser = $record->partnerMedia->company?->user;
|
||||
if ($partnerUser) {
|
||||
$partnerUser->notify(new BroadcastNotification([
|
||||
'title' => 'Pembayaran Telah Dikirim! 💸✨',
|
||||
'body' => "Halo! Pembayaran untuk kerja sama \"{$record->cooperation->title}\" telah berhasil dikirim oleh Admin. Silakan cek detailnya ya! 😊",
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
->url(CooperationResource::getUrl('view', ['record' => $record->cooperation_id, 'relation' => 0])),
|
||||
],
|
||||
]));
|
||||
}
|
||||
})
|
||||
->modalWidth(Width::Large);
|
||||
}
|
||||
|
||||
@ -32,28 +32,21 @@ protected function setUp(): void
|
||||
->success()
|
||||
->send();
|
||||
|
||||
// Notify all partners in this cooperation (since reports might be per media even if shared in DB)
|
||||
$partners = $record->taskAssignment?->cooperation?->partnerMedia()
|
||||
->wherePivot('status', ApprovalStatus::ACCEPTED)
|
||||
->get();
|
||||
|
||||
foreach ($partners as $media) {
|
||||
$partnerUser = $media->company?->user;
|
||||
if ($partnerUser) {
|
||||
$partnerUser->notify(new BroadcastNotification([
|
||||
'title' => 'Mantap! Laporan Diterima 🎊✨',
|
||||
'body' => "Hore! Laporan \"{$record->title}\" pada kerja sama \"{$record->taskAssignment->cooperation->title}\" telah disetujui oleh Admin. Satu langkah lebih dekat! 🚀",
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
->url(CooperationResource::getUrl('view', ['record' => $record->taskAssignment->cooperation_id, 'relation' => 3])),
|
||||
],
|
||||
]));
|
||||
}
|
||||
$partnerUser = $record->mediaTaskAssignment?->partnerMedia?->company?->user;
|
||||
if ($partnerUser) {
|
||||
$partnerUser->notify(new BroadcastNotification([
|
||||
'title' => 'Mantap! Laporan Diterima 🎊✨',
|
||||
'body' => "Hore! Laporan \"{$record->title}\" pada kerja sama \"{$record->mediaTaskAssignment->taskAssignment->cooperation->title}\" telah disetujui oleh Admin. Satu langkah lebih dekat! 🚀",
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
->url(CooperationResource::getUrl('view', ['record' => $record->mediaTaskAssignment->taskAssignment->cooperation_id, 'relation' => 3])),
|
||||
],
|
||||
]));
|
||||
}
|
||||
})
|
||||
->visible(
|
||||
fn (Report $record): bool => $record->taskAssignment?->cooperation?->status === CooperationStatus::VERIFICATION &&
|
||||
fn (Report $record): bool => $record->mediaTaskAssignment?->taskAssignment?->cooperation?->status === CooperationStatus::VERIFICATION &&
|
||||
! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value) &&
|
||||
$record->status === ApprovalStatus::PENDING
|
||||
);
|
||||
|
||||
@ -42,28 +42,21 @@ protected function setUp(): void
|
||||
->warning()
|
||||
->send();
|
||||
|
||||
// Notify all partners in this cooperation (since we can't tell which specific one)
|
||||
$partners = $record->taskAssignment?->cooperation?->partnerMedia()
|
||||
->wherePivot('status', ApprovalStatus::ACCEPTED)
|
||||
->get();
|
||||
|
||||
foreach ($partners as $media) {
|
||||
$partnerUser = $media->company?->user;
|
||||
if ($partnerUser) {
|
||||
$partnerUser->notify(new BroadcastNotification([
|
||||
'title' => 'Yah, Laporan Perlu Diperbaiki nih 📝',
|
||||
'body' => "Halo! Laporan \"{$record->title}\" pada kerja sama \"{$record->taskAssignment->cooperation->title}\" ditolak oleh Admin. 💪\n\nCatatan Admin: {$data['reason']}",
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
->url(CooperationResource::getUrl('view', ['record' => $record->taskAssignment->cooperation_id])),
|
||||
],
|
||||
]));
|
||||
}
|
||||
$partnerUser = $record->mediaTaskAssignment?->partnerMedia?->company?->user;
|
||||
if ($partnerUser) {
|
||||
$partnerUser->notify(new BroadcastNotification([
|
||||
'title' => 'Yah, Laporan Ditolak 🙁',
|
||||
'body' => "Halo! Laporan \"{$record->title}\" pada kerja sama \"{$record->mediaTaskAssignment->taskAssignment->cooperation->title}\" ditolak oleh Admin. 💪\n\nCatatan Admin: {$data['reason']}",
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
->url(CooperationResource::getUrl('view', ['record' => $record->mediaTaskAssignment->taskAssignment->cooperation_id])),
|
||||
],
|
||||
]));
|
||||
}
|
||||
})
|
||||
->visible(
|
||||
fn (Report $record): bool => $record->taskAssignment?->cooperation?->status === CooperationStatus::VERIFICATION &&
|
||||
fn (Report $record): bool => $record->mediaTaskAssignment?->taskAssignment?->cooperation?->status === CooperationStatus::VERIFICATION &&
|
||||
! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value) &&
|
||||
$record->status === ApprovalStatus::PENDING
|
||||
)
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
use App\Filament\Resources\Manage\Cooperations\Pages\ListCooperations;
|
||||
use App\Filament\Resources\Manage\Cooperations\Pages\ViewCooperation;
|
||||
use App\Filament\Resources\Manage\Cooperations\RelationManagers\CooperationMediaRelationManager;
|
||||
use App\Filament\Resources\Manage\Cooperations\RelationManagers\CooperationPaymentRelationManager;
|
||||
use App\Filament\Resources\Manage\Cooperations\RelationManagers\CooperationProposalRelationManager;
|
||||
use App\Filament\Resources\Manage\Cooperations\RelationManagers\ReportRelationManager;
|
||||
use App\Filament\Resources\Manage\Cooperations\RelationManagers\TaskAssignmentRelationManager;
|
||||
@ -120,6 +121,11 @@ public static function infolist(Schema $schema): Schema
|
||||
->label('Tanggal Pembayaran')
|
||||
->date('l, d F Y')
|
||||
->placeholder('Belum dibayar'),
|
||||
|
||||
TextEntry::make('completed_at')
|
||||
->label('Tanggal Selesai')
|
||||
->date('l, d F Y')
|
||||
->placeholder('Masih berjalan'),
|
||||
]),
|
||||
|
||||
Grid::make(3)
|
||||
@ -153,6 +159,7 @@ public static function getRelations(): array
|
||||
CooperationProposalRelationManager::class,
|
||||
TaskAssignmentRelationManager::class,
|
||||
ReportRelationManager::class,
|
||||
CooperationPaymentRelationManager::class,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -12,19 +12,22 @@
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Components\Grid;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CooperationMediaRelationManager extends RelationManager
|
||||
{
|
||||
protected static ?string $recordTitleAttribute = 'partnerMedia.name';
|
||||
|
||||
protected static string $relationship = 'cooperationMedia';
|
||||
|
||||
protected static ?string $title = 'Media';
|
||||
|
||||
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
|
||||
{
|
||||
return auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value);
|
||||
return ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value);
|
||||
}
|
||||
|
||||
public static function getBadge(Model $ownerRecord, string $pageClass): ?string
|
||||
@ -57,7 +60,9 @@ public function table(Table $table): Table
|
||||
ViewAction::make()
|
||||
->visible(fn (CooperationMedia $record): bool => $record->status === ApprovalStatus::ACCEPTED && $record->payment()->exists()),
|
||||
])
|
||||
->recordAction(null);
|
||||
->emptyStateIcon(Heroicon::Newspaper)
|
||||
->emptyStateDescription('Tidak ada media yang diikutsertakan.')
|
||||
->defaultSort('created_at', 'desc');
|
||||
}
|
||||
|
||||
public function infolist(Schema $infolist): Schema
|
||||
@ -68,11 +73,11 @@ public function infolist(Schema $infolist): Schema
|
||||
->schema([
|
||||
TextEntry::make('payment.amount')
|
||||
->label('Nominal')
|
||||
->money('IDR'),
|
||||
->money('IDR', decimalPlaces: 0),
|
||||
|
||||
TextEntry::make('payment.payment_date')
|
||||
->label('Tanggal Bayar')
|
||||
->dateTime(),
|
||||
->dateTime('l, d F Y'),
|
||||
]),
|
||||
|
||||
TextEntry::make('payment.description')
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Manage\Cooperations\RelationManagers;
|
||||
|
||||
use App\Enums\ApprovalStatus;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Models\CooperationPayment;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\ImageColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CooperationPaymentRelationManager extends RelationManager
|
||||
{
|
||||
protected static ?string $recordTitleAttribute = 'description';
|
||||
|
||||
protected static string $relationship = 'payments';
|
||||
|
||||
protected static ?string $title = 'Pembayaran';
|
||||
|
||||
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
|
||||
{
|
||||
if (! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ownerRecord->cooperationMedia()
|
||||
->whereHas('partnerMedia', function ($query) {
|
||||
$query->whereHas('company', function ($query) {
|
||||
$query->where('user_id', auth()->id());
|
||||
});
|
||||
})
|
||||
->where('status', ApprovalStatus::ACCEPTED)
|
||||
->exists();
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('amount')
|
||||
->label('Nominal')
|
||||
->money('IDR', decimalPlaces: 0),
|
||||
|
||||
TextColumn::make('payment_date')
|
||||
->label('Tanggal Bayar')
|
||||
->date('l, d F Y'),
|
||||
|
||||
TextColumn::make('description')
|
||||
->label('Keterangan')
|
||||
->limit(50),
|
||||
|
||||
ImageColumn::make('payment_proof')
|
||||
->label('Bukti Pembayaran')
|
||||
->getStateUsing(fn (CooperationPayment $record): ?string => optional($record->cooperationMedia->getMedia('cooperations')->where('custom_properties.doc_type', 'payment-proof')->sortByDesc('created_at')->first())->getPathRelativeToRoot())
|
||||
->disk(config('filesystems.default')),
|
||||
])
|
||||
->filters([])
|
||||
->headerActions([])
|
||||
->recordActions([])
|
||||
->emptyStateIcon(Heroicon::CreditCard)
|
||||
->emptyStateDescription('Belum ada data pembayaran.')
|
||||
->defaultSort('created_at', 'desc')
|
||||
->modifyQueryUsing(function ($query) {
|
||||
$user = auth()->user();
|
||||
|
||||
return $query->whereHas('cooperationMedia.partnerMedia.company', function ($q) use ($user) {
|
||||
$q->where('user_id', $user->id);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Components\Grid;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@ -22,6 +23,8 @@
|
||||
|
||||
class CooperationProposalRelationManager extends RelationManager
|
||||
{
|
||||
protected static ?string $recordTitleAttribute = 'e_catalog';
|
||||
|
||||
protected static string $relationship = 'proposal';
|
||||
|
||||
protected static ?string $title = 'Proposal';
|
||||
@ -107,6 +110,9 @@ public function table(Table $table): Table
|
||||
),
|
||||
]),
|
||||
])
|
||||
->emptyStateIcon(Heroicon::DocumentText)
|
||||
->emptyStateDescription('Tidak ada proposal yang diajukan.')
|
||||
->defaultSort('created_at', 'desc')
|
||||
->modifyQueryUsing(function ($query) {
|
||||
$user = auth()->user();
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Enums\Width;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@ -31,6 +32,11 @@ class ReportRelationManager extends RelationManager
|
||||
|
||||
protected static ?string $title = 'Laporan';
|
||||
|
||||
public function isReadOnly(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
|
||||
{
|
||||
if (auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)) {
|
||||
@ -47,13 +53,16 @@ public static function canViewForRecord(Model $ownerRecord, string $pageClass):
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isReadOnly(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getBadge(Model $ownerRecord, string $pageClass): ?string
|
||||
{
|
||||
if (auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)) {
|
||||
return $ownerRecord->reports()
|
||||
->whereHas('mediaTaskAssignment.partnerMedia.company', function ($q) {
|
||||
$q->where('user_id', auth()->id());
|
||||
})
|
||||
->count();
|
||||
}
|
||||
|
||||
return $ownerRecord->reports()->count();
|
||||
}
|
||||
|
||||
@ -105,6 +114,11 @@ public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('mediaTaskAssignment.partnerMedia.name')
|
||||
->label('Media')
|
||||
->searchable()
|
||||
->visible(! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
||||
|
||||
TextColumn::make('title')
|
||||
->label('Judul')
|
||||
->searchable(),
|
||||
@ -139,7 +153,17 @@ public function table(Table $table): Table
|
||||
->modalWidth(Width::Large)
|
||||
->modalHeading('Buat Laporan')
|
||||
->mutateDataUsing(function (array $data): array {
|
||||
$data['task_assignment_id'] = $this->getOwnerRecord()->taskAssignment?->id;
|
||||
$taskAssignment = $this->getOwnerRecord()->taskAssignment;
|
||||
|
||||
if (auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)) {
|
||||
$mediaTaskAssignment = $taskAssignment?->mediaTaskAssignments()
|
||||
->whereHas('partnerMedia.company', function ($query) {
|
||||
$query->where('user_id', auth()->id());
|
||||
})
|
||||
->first();
|
||||
|
||||
$data['media_task_assignment_id'] = $mediaTaskAssignment?->id;
|
||||
}
|
||||
|
||||
return $data;
|
||||
})
|
||||
@ -184,10 +208,25 @@ public function table(Table $table): Table
|
||||
&& $taskAssignment->start_date->toDateString() <= now()->toDateString()
|
||||
&& $taskAssignment->end_date->toDateString() >= now()->toDateString()
|
||||
&& $taskAssignment->reports()
|
||||
->where('status', '!=', ApprovalStatus::REJECTED)
|
||||
->whereHas('mediaTaskAssignment.partnerMedia.company', fn ($q) => $q->where('user_id', auth()->id()))
|
||||
->where('reports.status', '!=', ApprovalStatus::REJECTED)
|
||||
->count() < $taskAssignment->report_amount;
|
||||
}),
|
||||
])
|
||||
->toolbarActions([]);
|
||||
->toolbarActions([])
|
||||
->emptyStateIcon(Heroicon::InboxArrowDown)
|
||||
->emptyStateDescription('Tidak ada laporan yang diajukan.')
|
||||
->defaultSort('created_at', 'desc')
|
||||
->modifyQueryUsing(function ($query) {
|
||||
$user = auth()->user();
|
||||
|
||||
if (! $user->hasRole(RoleEnum::PERUSAHAAN->value)) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
$query->whereHas('mediaTaskAssignment.partnerMedia.company', function ($q) use ($user) {
|
||||
$q->where('user_id', $user->id);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@ -102,6 +103,8 @@ public function table(Table $table): Table
|
||||
->success()
|
||||
),
|
||||
]),
|
||||
]);
|
||||
])
|
||||
->emptyStateIcon(Heroicon::ArchiveBoxXMark)
|
||||
->emptyStateDescription('Tidak ada penugasan yang ditugaskan.');
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
use Filament\Schemas\Components\Utilities\Get;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Enums\FiltersLayout;
|
||||
use Filament\Tables\Filters\Filter;
|
||||
use Filament\Tables\Filters\SelectFilter;
|
||||
use Filament\Tables\Filters\TrashedFilter;
|
||||
@ -131,6 +132,13 @@ public static function configure(Table $table): Table
|
||||
->placeholder('Belum dibayar')
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
|
||||
TextColumn::make('completed_at')
|
||||
->label('Tanggal Selesai')
|
||||
->date('l, d F Y')
|
||||
->sortable()
|
||||
->placeholder('Masih berjalan')
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
|
||||
TextColumn::make('description')
|
||||
->label('Deskripsi')
|
||||
->searchable()
|
||||
@ -140,105 +148,121 @@ public static function configure(Table $table): Table
|
||||
|
||||
...TimestampColumns::make(),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make()->native(false),
|
||||
->filters(
|
||||
auth()->user()->hasRole(RoleEnum::DEVELOPER->value) || auth()->user()->hasRole(RoleEnum::ADMINISTRATOR->value)
|
||||
? [
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn (): bool => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
|
||||
SelectFilter::make('status')
|
||||
->label('Status')
|
||||
->options(CooperationStatus::class),
|
||||
SelectFilter::make('status')
|
||||
->label('Status')
|
||||
->options(CooperationStatus::class)
|
||||
->native(false),
|
||||
|
||||
SelectFilter::make('partnerMedia')
|
||||
->label('Media')
|
||||
->relationship('partnerMedia', 'name')
|
||||
->searchable()
|
||||
->preload(),
|
||||
SelectFilter::make('partnerMedia')
|
||||
->label('Media')
|
||||
->relationship('partnerMedia', 'name')
|
||||
->searchable()
|
||||
->preload(),
|
||||
|
||||
Filter::make('title')
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label('Nama Kegiatan')
|
||||
->placeholder('Cari nama kegiatan...'),
|
||||
])
|
||||
->query(function (Builder $query, array $data): Builder {
|
||||
return $query->when(
|
||||
$data['title'],
|
||||
fn (Builder $query, $title): Builder => $query->where('title', 'like', "%{$title}%"),
|
||||
);
|
||||
}),
|
||||
|
||||
Filter::make('date_filter')
|
||||
->schema([
|
||||
Select::make('date_type')
|
||||
->label('Jenis Filter Tanggal')
|
||||
->options([
|
||||
'date' => 'Tanggal Penyerahan Awal',
|
||||
'month' => 'Bulan & Tahun',
|
||||
'year' => 'Tahun',
|
||||
'range' => 'Rentang Tanggal',
|
||||
Filter::make('title')
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->label('Nama Kegiatan')
|
||||
->placeholder('Cari nama kegiatan...'),
|
||||
])
|
||||
->default('date')
|
||||
->live(),
|
||||
->query(function (Builder $query, array $data): Builder {
|
||||
return $query->when(
|
||||
$data['title'],
|
||||
fn (Builder $query, $title): Builder => $query->where('title', 'like', "%{$title}%"),
|
||||
);
|
||||
}),
|
||||
|
||||
DatePicker::make('specific_date')
|
||||
->label('Tanggal')
|
||||
->visible(fn (Get $get) => $get('date_type') === 'date'),
|
||||
Filter::make('date_filter')
|
||||
->schema([
|
||||
Select::make('date_type')
|
||||
->label('Jenis Filter Tanggal')
|
||||
->options([
|
||||
'date' => 'Tanggal Penyerahan Awal',
|
||||
'month' => 'Bulan & Tahun',
|
||||
'year' => 'Tahun',
|
||||
'range' => 'Rentang Tanggal',
|
||||
])
|
||||
->live()
|
||||
->native(false),
|
||||
|
||||
Select::make('month')
|
||||
->label('Bulan')
|
||||
->options([
|
||||
1 => 'Januari',
|
||||
2 => 'Februari',
|
||||
3 => 'Maret',
|
||||
4 => 'April',
|
||||
5 => 'Mei',
|
||||
6 => 'Juni',
|
||||
7 => 'Juli',
|
||||
8 => 'Agustus',
|
||||
9 => 'September',
|
||||
10 => 'Oktober',
|
||||
11 => 'November',
|
||||
12 => 'Desember',
|
||||
DatePicker::make('specific_date')
|
||||
->label('Tanggal')
|
||||
->visible(fn (Get $get) => $get('date_type') === 'date')
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y'),
|
||||
|
||||
Select::make('month')
|
||||
->label('Bulan')
|
||||
->options([
|
||||
1 => 'Januari',
|
||||
2 => 'Februari',
|
||||
3 => 'Maret',
|
||||
4 => 'April',
|
||||
5 => 'Mei',
|
||||
6 => 'Juni',
|
||||
7 => 'Juli',
|
||||
8 => 'Agustus',
|
||||
9 => 'September',
|
||||
10 => 'Oktober',
|
||||
11 => 'November',
|
||||
12 => 'Desember',
|
||||
])
|
||||
->visible(fn (Get $get) => $get('date_type') === 'month')
|
||||
->native(false),
|
||||
|
||||
Select::make('year')
|
||||
->label('Tahun')
|
||||
->options(function () {
|
||||
$years = range(date('Y'), 2020);
|
||||
|
||||
return array_combine($years, $years);
|
||||
})
|
||||
->visible(fn (Get $get) => in_array($get('date_type'), ['month', 'year']))
|
||||
->native(false),
|
||||
|
||||
DatePicker::make('start_date')
|
||||
->label('Mulai Tanggal')
|
||||
->visible(fn (Get $get) => $get('date_type') === 'range')
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y'),
|
||||
|
||||
DatePicker::make('end_date')
|
||||
->label('Sampai Tanggal')
|
||||
->visible(fn (Get $get) => $get('date_type') === 'range')
|
||||
->native(false)
|
||||
->displayFormat('l, d F Y'),
|
||||
])
|
||||
->visible(fn (Get $get) => $get('date_type') === 'month'),
|
||||
->query(function (Builder $query, array $data): Builder {
|
||||
$type = $data['date_type'] ?? null;
|
||||
$column = 'initial_submission_date';
|
||||
|
||||
Select::make('year')
|
||||
->label('Tahun')
|
||||
->options(function () {
|
||||
$years = range(date('Y'), 2020);
|
||||
if ($type === 'date' && ! empty($data['specific_date'])) {
|
||||
return $query->whereDate($column, $data['specific_date']);
|
||||
}
|
||||
if ($type === 'month' && ! empty($data['month']) && ! empty($data['year'])) {
|
||||
return $query->whereMonth($column, $data['month'])
|
||||
->whereYear($column, $data['year']);
|
||||
}
|
||||
if ($type === 'year' && ! empty($data['year'])) {
|
||||
return $query->whereYear($column, $data['year']);
|
||||
}
|
||||
if ($type === 'range' && ! empty($data['start_date']) && ! empty($data['end_date'])) {
|
||||
return $query->whereBetween($column, [$data['start_date'], $data['end_date']]);
|
||||
}
|
||||
|
||||
return array_combine($years, $years);
|
||||
})
|
||||
->visible(fn (Get $get) => in_array($get('date_type'), ['month', 'year'])),
|
||||
|
||||
DatePicker::make('start_date')
|
||||
->label('Mulai Tanggal')
|
||||
->visible(fn (Get $get) => $get('date_type') === 'range'),
|
||||
|
||||
DatePicker::make('end_date')
|
||||
->label('Sampai Tanggal')
|
||||
->visible(fn (Get $get) => $get('date_type') === 'range'),
|
||||
])
|
||||
->query(function (Builder $query, array $data): Builder {
|
||||
$type = $data['date_type'] ?? null;
|
||||
$column = 'initial_submission_date';
|
||||
|
||||
if ($type === 'date' && ! empty($data['specific_date'])) {
|
||||
return $query->whereDate($column, $data['specific_date']);
|
||||
}
|
||||
if ($type === 'month' && ! empty($data['month']) && ! empty($data['year'])) {
|
||||
return $query->whereMonth($column, $data['month'])
|
||||
->whereYear($column, $data['year']);
|
||||
}
|
||||
if ($type === 'year' && ! empty($data['year'])) {
|
||||
return $query->whereYear($column, $data['year']);
|
||||
}
|
||||
if ($type === 'range' && ! empty($data['start_date']) && ! empty($data['end_date'])) {
|
||||
return $query->whereBetween($column, [$data['start_date'], $data['end_date']]);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}),
|
||||
])
|
||||
return $query;
|
||||
}),
|
||||
] : [],
|
||||
FiltersLayout::AboveContentCollapsible
|
||||
)
|
||||
->filtersFormColumns(3)
|
||||
->recordActions([
|
||||
ViewAction::make(),
|
||||
|
||||
@ -254,18 +278,17 @@ public static function configure(Table $table): Table
|
||||
|
||||
CompleteCooperationAction::make('completeCooperation'),
|
||||
|
||||
EditAction::make()
|
||||
->visible(fn (): bool => ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
||||
EditAction::make(),
|
||||
|
||||
DeleteAction::make()
|
||||
->visible(fn (): bool => ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
||||
DeleteAction::make(),
|
||||
])
|
||||
->headerActions([
|
||||
ExportAction::make()
|
||||
->exports([
|
||||
CooperationExcelExport::make(),
|
||||
])
|
||||
->color('success'),
|
||||
->color('success')
|
||||
->visible(fn (): bool => auth()->user()->hasRole(RoleEnum::DEVELOPER->value) || auth()->user()->hasRole(RoleEnum::ADMINISTRATOR->value)),
|
||||
|
||||
])
|
||||
->toolbarActions([
|
||||
|
||||
@ -56,7 +56,7 @@ protected function setUp(): void
|
||||
// Notify User
|
||||
$record->user?->notify(new BroadcastNotification([
|
||||
'title' => 'Permohonan Perubahan Ditolak 🛑',
|
||||
'body' => "Halo! Mohon maaf, permohonan perubahan data Anda ({$record->change_reason}) ditolak oleh admin. Alasan: {$data['rejection_reason']} 😔",
|
||||
'body' => "Halo! Mohon maaf, permohonan perubahan data Anda untuk {$record->change_reason} ditolak oleh admin. Alasan: {$data['rejection_reason']} 😔",
|
||||
]));
|
||||
})
|
||||
->visible(fn (DataChangeRequest $record): bool => $record->status === DataChangeStatus::PENDING && ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value))
|
||||
|
||||
@ -44,13 +44,13 @@ class DataChangesResource extends Resource
|
||||
|
||||
protected static ?string $slug = 'manage/data-changes';
|
||||
|
||||
public static function getNavigationBadge(): string
|
||||
public static function getNavigationBadge(): ?string
|
||||
{
|
||||
return static::getModel()::pending()
|
||||
->when(auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value), function (Builder $query): void {
|
||||
$query->where('user_id', auth()->id());
|
||||
})
|
||||
->count();
|
||||
if (auth()->user()->hasRole(RoleEnum::PERUSAHAAN)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return static::getModel()::pending()->count();
|
||||
}
|
||||
|
||||
public static function infolist(Schema $schema): Schema
|
||||
@ -249,7 +249,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
ViewAction::make(),
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Filament\Resources\Manage\Journalists\Actions;
|
||||
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Filament\Actions\Cheerful\CreateAction;
|
||||
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
@ -32,7 +31,9 @@ protected function setUp(): void
|
||||
])
|
||||
->modalWidth(Width::Large)
|
||||
->using(function (array $data, string $model): Model {
|
||||
$data['partner_media_id'] = auth()->user()->company?->partnerMedia?->id;
|
||||
$user = auth()->user();
|
||||
|
||||
$data['partner_media_id'] = $user->company?->partnerMedia?->id;
|
||||
|
||||
$journalist = $model::create($data);
|
||||
|
||||
@ -68,7 +69,7 @@ protected function setUp(): void
|
||||
}
|
||||
|
||||
// If company is already approved, addition of new journalist needs permohonan/review
|
||||
if (auth()->user()->company?->status === VerificationStatus::APPROVED) {
|
||||
if ($user->company?->verificationRequest !== null) {
|
||||
$fieldLabels = Journalist::dataChangeEntryLabels();
|
||||
$newFields = [];
|
||||
|
||||
@ -98,10 +99,10 @@ protected function setUp(): void
|
||||
|
||||
User::superAdmin()
|
||||
->get()
|
||||
->each(function ($admin) use ($dataChangeRequest): void {
|
||||
->each(function ($admin) use ($dataChangeRequest, $user): void {
|
||||
$admin->notify(new BroadcastNotification([
|
||||
'title' => 'Ada Penambahan Jurnalis Baru ✨',
|
||||
'body' => 'Halooo Admin! 👋 '.auth()->user()->name.' baru saja menambahkan jurnalis baru. Yuk, cek detailnya! 🚀',
|
||||
'body' => 'Halooo Admin! 👋 '.$user->name.' baru saja menambahkan jurnalis baru. Yuk, cek detailnya! 🚀',
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
|
||||
@ -23,9 +23,9 @@ protected function setUp(): void
|
||||
|
||||
$this->successNotification(null);
|
||||
|
||||
$this->modalHeading(fn () => auth()->user()->company?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value) ? 'Ajukan Penghapusan Jurnalis' : 'Hapus Jurnalis');
|
||||
$this->modalHeading(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? 'Ajukan Penghapusan Jurnalis' : 'Hapus Jurnalis');
|
||||
|
||||
$this->schema(fn () => auth()->user()->company?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value) ? [
|
||||
$this->schema(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? [
|
||||
Textarea::make('deletion_reason')
|
||||
->label('Alasan Penghapusan')
|
||||
->placeholder('Jelaskan alasan mengapa jurnalis ini dihapus...')
|
||||
@ -34,10 +34,8 @@ protected function setUp(): void
|
||||
|
||||
$this->action(function (Journalist $record, array $data): void {
|
||||
$user = auth()->user();
|
||||
$needsReview = $user->company?->status === VerificationStatus::APPROVED &&
|
||||
$user->hasRole(RoleEnum::PERUSAHAAN->value);
|
||||
|
||||
if ($needsReview) {
|
||||
if ($user->company?->verificationRequest !== null) {
|
||||
$existingRequest = DataChangeRequest::where('entity_type', Journalist::class)
|
||||
->where('entity_id', $record->id)
|
||||
->where('status', DataChangeStatus::PENDING)
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
use App\Enums\DataChangeStatus;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
||||
use App\Filament\Support\CheerfulNotification;
|
||||
use App\Models\DataChangeRequest;
|
||||
@ -50,10 +49,9 @@ protected function setUp(): void
|
||||
return $data;
|
||||
})
|
||||
->using(function (Journalist $record, array $data): Journalist {
|
||||
$needsReview = auth()->user()->company?->status === VerificationStatus::APPROVED &&
|
||||
auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value);
|
||||
$user = auth()->user();
|
||||
|
||||
if ($needsReview) {
|
||||
if ($user->company?->verificationRequest !== null) {
|
||||
$existingRequest = DataChangeRequest::where('entity_type', Journalist::class)
|
||||
->where('entity_id', $record->id)
|
||||
->where('status', DataChangeStatus::PENDING)
|
||||
@ -67,69 +65,67 @@ protected function setUp(): void
|
||||
|
||||
return $record;
|
||||
}
|
||||
}
|
||||
|
||||
$fieldLabels = Journalist::dataChangeEntryLabels();
|
||||
$editableFields = ['name', 'email', 'phone_number', 'press_card', 'ukw_certificate'];
|
||||
$fieldLabels = Journalist::dataChangeEntryLabels();
|
||||
$editableFields = ['name', 'email', 'phone_number', 'press_card', 'ukw_certificate'];
|
||||
|
||||
$changedFields = [];
|
||||
$oldDataArr = [];
|
||||
$changedFields = [];
|
||||
$oldDataArr = [];
|
||||
|
||||
$casts = $record->getCasts();
|
||||
foreach ($editableFields as $field) {
|
||||
$val = $data[$field] ?? null;
|
||||
$oldVal = $record->{$field};
|
||||
$casts = $record->getCasts();
|
||||
foreach ($editableFields as $field) {
|
||||
$val = $data[$field] ?? null;
|
||||
$oldVal = $record->{$field};
|
||||
|
||||
// If value is a raw scalar but should be an enum, resolve it for display
|
||||
if (isset($casts[$field]) && ! ($val instanceof \BackedEnum) && enum_exists($casts[$field])) {
|
||||
$enumClass = $casts[$field];
|
||||
$val = $enumClass::tryFrom($val) ?? $val;
|
||||
// If value is a raw scalar but should be an enum, resolve it for display
|
||||
if (isset($casts[$field]) && ! ($val instanceof \BackedEnum) && enum_exists($casts[$field])) {
|
||||
$enumClass = $casts[$field];
|
||||
$val = $enumClass::tryFrom($val) ?? $val;
|
||||
}
|
||||
|
||||
$displayVal = ($val instanceof HasLabel) ? $val->getLabel() : ($val instanceof \BackedEnum ? $val->value : $val);
|
||||
$displayOldVal = ($oldVal instanceof HasLabel) ? $oldVal->getLabel() : ($oldVal instanceof \BackedEnum ? $oldVal->value : $oldVal);
|
||||
|
||||
if ($displayOldVal !== $displayVal) {
|
||||
$label = $fieldLabels[$field] ?? $field;
|
||||
$changedFields[$label] = $displayVal;
|
||||
$oldDataArr[$label] = $displayOldVal;
|
||||
}
|
||||
}
|
||||
|
||||
$displayVal = ($val instanceof HasLabel) ? $val->getLabel() : ($val instanceof \BackedEnum ? $val->value : $val);
|
||||
$displayOldVal = ($oldVal instanceof HasLabel) ? $oldVal->getLabel() : ($oldVal instanceof \BackedEnum ? $oldVal->value : $oldVal);
|
||||
$documentFields = ['press_card_docs', 'ukw_certificate_docs'];
|
||||
$mediaItems = $record->getMedia('journalists');
|
||||
|
||||
if ($displayOldVal !== $displayVal) {
|
||||
$label = $fieldLabels[$field] ?? $field;
|
||||
$changedFields[$label] = $displayVal;
|
||||
$oldDataArr[$label] = $displayOldVal;
|
||||
foreach ($documentFields as $field) {
|
||||
$newDocs = array_values((array) ($data[$field] ?? []));
|
||||
sort($newDocs);
|
||||
|
||||
$docType = str($field)->replace('_docs', '')->slug('-');
|
||||
$currentMedia = $mediaItems
|
||||
->where('custom_properties.doc_type', $docType)
|
||||
->sortByDesc('created_at')
|
||||
->first();
|
||||
|
||||
$oldDocs = $currentMedia ? [$currentMedia->getPathRelativeToRoot()] : [];
|
||||
$oldDocs = array_values($oldDocs);
|
||||
sort($oldDocs);
|
||||
|
||||
if (json_encode($newDocs) !== json_encode($oldDocs)) {
|
||||
$label = $fieldLabels[$field] ?? $field;
|
||||
$changedFields[$label] = $newDocs;
|
||||
$oldDataArr[$label] = $oldDocs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$documentFields = ['press_card_docs', 'ukw_certificate_docs'];
|
||||
$mediaItems = $record->getMedia('journalists');
|
||||
if (empty($changedFields)) {
|
||||
CheerfulNotification::info(
|
||||
'Belum ada yang berubah ✨',
|
||||
'Ubah data terlebih dulu lalu simpan kembali 💪'
|
||||
)->send();
|
||||
|
||||
foreach ($documentFields as $field) {
|
||||
$newDocs = array_values((array) ($data[$field] ?? []));
|
||||
sort($newDocs);
|
||||
|
||||
$docType = str($field)->replace('_docs', '')->slug('-');
|
||||
$currentMedia = $mediaItems
|
||||
->where('custom_properties.doc_type', $docType)
|
||||
->sortByDesc('created_at')
|
||||
->first();
|
||||
|
||||
$oldDocs = $currentMedia ? [$currentMedia->getPathRelativeToRoot()] : [];
|
||||
$oldDocs = array_values($oldDocs);
|
||||
sort($oldDocs);
|
||||
|
||||
if (json_encode($newDocs) !== json_encode($oldDocs)) {
|
||||
$label = $fieldLabels[$field] ?? $field;
|
||||
$changedFields[$label] = $newDocs;
|
||||
$oldDataArr[$label] = $oldDocs;
|
||||
return $record;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($changedFields)) {
|
||||
CheerfulNotification::info(
|
||||
'Belum ada yang berubah ✨',
|
||||
'Ubah data terlebih dulu lalu simpan kembali 💪'
|
||||
)->send();
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
if ($needsReview) {
|
||||
$dataChangeRequest = DataChangeRequest::create([
|
||||
'user_id' => auth()->id(),
|
||||
'entity_type' => Journalist::class,
|
||||
@ -146,10 +142,10 @@ protected function setUp(): void
|
||||
|
||||
User::superAdmin()
|
||||
->get()
|
||||
->each(function ($admin) use ($dataChangeRequest): void {
|
||||
->each(function ($admin) use ($dataChangeRequest, $user): void {
|
||||
$admin->notify(new BroadcastNotification([
|
||||
'title' => 'Ada Pengajuan Perubahan Jurnalis ✨',
|
||||
'body' => 'Halooo Admin! 👋 '.auth()->user()->name.' baru saja mengajukan perubahan data jurnalis. Yuk, cek detailnya! 🚀',
|
||||
'body' => 'Halooo Admin! 👋 '.$user->name.' baru saja mengajukan perubahan data jurnalis. Yuk, cek detailnya! 🚀',
|
||||
'action' => [
|
||||
Action::make('view')
|
||||
->label('Lihat')
|
||||
@ -163,7 +159,7 @@ protected function setUp(): void
|
||||
|
||||
$this->performSave($record, $data);
|
||||
|
||||
CheerfulNotification::update()->send(); // Manual success notification
|
||||
CheerfulNotification::update()->send();
|
||||
|
||||
return $record;
|
||||
})
|
||||
|
||||
@ -49,17 +49,6 @@ class JournalistResource extends Resource
|
||||
|
||||
protected static ?string $slug = 'manage/journalists';
|
||||
|
||||
public static function getNavigationBadge(): ?string
|
||||
{
|
||||
return static::getModel()::pending()
|
||||
->when(auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value), function (Builder $query): void {
|
||||
$query->whereHas('partnerMedia.company', function (Builder $q): void {
|
||||
$q->where('user_id', auth()->id());
|
||||
});
|
||||
})
|
||||
->count() ?: null;
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
$documents = [
|
||||
@ -145,7 +134,7 @@ public static function form(Schema $schema): Schema
|
||||
->rows(3)
|
||||
->required(),
|
||||
])
|
||||
->visible(fn () => auth()->user()->company?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
||||
->visible(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
||||
])
|
||||
->columns(1);
|
||||
}
|
||||
@ -186,16 +175,26 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->checkIfRecordIsSelectableUsing(
|
||||
fn () => ! (
|
||||
in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) ||
|
||||
auth()->user()->company?->verificationRequest()->pending()->exists()
|
||||
)
|
||||
)
|
||||
->recordActions([
|
||||
EditJournalistAction::make('edit'),
|
||||
EditJournalistAction::make('edit')
|
||||
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||
|
||||
DeleteJournalistAction::make('delete'),
|
||||
DeleteJournalistAction::make('delete')
|
||||
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||
|
||||
ForceDeleteAction::make(),
|
||||
ForceDeleteAction::make()
|
||||
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||
|
||||
RestoreAction::make(),
|
||||
RestoreAction::make()
|
||||
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
@ -204,7 +203,7 @@ public static function table(Table $table): Table
|
||||
ForceDeleteBulkAction::make(),
|
||||
|
||||
RestoreBulkAction::make(),
|
||||
]),
|
||||
])->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||
])
|
||||
->emptyStateIcon(Heroicon::Identification)
|
||||
->emptyStateDescription('Setelah Anda membubat data pertama, maka akan muncul disini.')
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Manage\Journalists\Pages;
|
||||
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Filament\Resources\Manage\Journalists\Actions\CreateJournalistAction;
|
||||
use App\Filament\Resources\Manage\Journalists\JournalistResource;
|
||||
use Filament\Resources\Pages\ManageRecords;
|
||||
@ -20,7 +21,8 @@ protected function getHeaderActions(): array
|
||||
}
|
||||
|
||||
return [
|
||||
CreateJournalistAction::make(),
|
||||
CreateJournalistAction::make()
|
||||
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Filament\Resources\Manage\Partners;
|
||||
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\DefaultBulkActions;
|
||||
use App\Filament\Resources\Manage\Partners\Pages\ManagePartners;
|
||||
use App\Filament\Resources\Manage\Partners\Pages\ViewPartner;
|
||||
@ -112,7 +113,7 @@ public static function infolist(Schema $schema): Schema
|
||||
->first();
|
||||
|
||||
if (! $media) {
|
||||
return 'Tidak ada dokumen';
|
||||
return '';
|
||||
}
|
||||
|
||||
$url = $media->getUrl();
|
||||
@ -298,9 +299,19 @@ public static function table(Table $table): Table
|
||||
->sortable()
|
||||
->badge(),
|
||||
|
||||
TextColumn::make('company.status')
|
||||
TextColumn::make('status')
|
||||
->label('Status')
|
||||
->badge(),
|
||||
->badge()
|
||||
->getStateUsing(function ($record) {
|
||||
return $record->company->verificationRequest
|
||||
? $record->company->verificationRequest->status->getLabel()
|
||||
: 'Belum Mengajukan';
|
||||
})
|
||||
->color(function ($record) {
|
||||
return $record->company->verificationRequest
|
||||
? $record->company->verificationRequest->status->getColor()
|
||||
: 'gray';
|
||||
}),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label('Tgl Daftar')
|
||||
@ -313,7 +324,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
ViewAction::make(),
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\Categories;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -83,7 +84,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\Classifications;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -83,7 +84,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\Departments;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -93,7 +94,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\Locations;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -83,7 +84,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\SubClassifications;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -102,7 +103,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\SubLocations;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -98,7 +99,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Master\Themes;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -83,7 +84,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -88,7 +88,8 @@ public static function form(Schema $schema): Schema
|
||||
->searchable(),
|
||||
|
||||
Hidden::make('password')
|
||||
->default(fn (?User $record): ?string => $record ? null : config('auth.password_default')),
|
||||
->default(fn (): string => config('auth.password_default'))
|
||||
->visibleOn('create'),
|
||||
])
|
||||
->columns(1);
|
||||
}
|
||||
@ -146,7 +147,7 @@ public static function table(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
use App\Enums\Channel;
|
||||
use App\Enums\ContentType;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Enums\SocialMedia;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
@ -72,7 +73,9 @@ public static function configure(Table $table): Table
|
||||
...TimestampColumns::make(),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make()->native(false),
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
|
||||
SelectFilter::make('social_media')
|
||||
->label('Media Sosial')
|
||||
@ -106,7 +109,6 @@ public static function configure(Table $table): Table
|
||||
'year' => 'Tahun',
|
||||
'range' => 'Rentang Tanggal',
|
||||
])
|
||||
->default('date')
|
||||
->live()
|
||||
->native(false),
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ public static function configure(Schema $schema): Schema
|
||||
->schema([
|
||||
Select::make('location_id')
|
||||
->label('Lokus')
|
||||
->relationship('location', 'name')
|
||||
->relationship('location', 'name', fn (Builder $query): Builder => $query->active())
|
||||
->searchable()
|
||||
->preload()
|
||||
->live()
|
||||
@ -46,7 +46,7 @@ public static function configure(Schema $schema): Schema
|
||||
|
||||
Select::make('sub_location_id')
|
||||
->label('Sub Lokus')
|
||||
->relationship('subLocation', 'name', fn (Builder $query, Get $get): Builder => $query->where('location_id', $get('location_id')))
|
||||
->relationship('subLocation', 'name', fn (Builder $query, Get $get): Builder => $query->active()->where('location_id', $get('location_id')))
|
||||
->searchable()
|
||||
->preload()
|
||||
->required(),
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Monitoring\IssueManagements\Tables;
|
||||
|
||||
use App\Enums\IssueSentiment;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -73,7 +74,7 @@ public static function configure(Table $table): Table
|
||||
->filters([
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
|
||||
SelectFilter::make('issue')
|
||||
->label('Filter Isu')
|
||||
@ -123,7 +124,6 @@ public static function configure(Table $table): Table
|
||||
'year' => 'Tahun',
|
||||
'range' => 'Rentang Tanggal',
|
||||
])
|
||||
->default('date')
|
||||
->live()
|
||||
->native(false),
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Monitoring\MediaMonitorings\Tables;
|
||||
|
||||
use App\Enums\Channel;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -96,7 +97,9 @@ public static function configure(Table $table): Table
|
||||
...TimestampColumns::make(),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make()->native(false),
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
|
||||
SelectFilter::make('themes')
|
||||
->label('Tema')
|
||||
@ -133,7 +136,6 @@ public static function configure(Table $table): Table
|
||||
'year' => 'Tahun',
|
||||
'range' => 'Rentang Tanggal',
|
||||
])
|
||||
->default('date')
|
||||
->live()
|
||||
->native(false),
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Publication\Announcements;
|
||||
|
||||
use App\Enums\AnnouncementType;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -116,17 +117,25 @@ public static function table(Table $table): Table
|
||||
->badge()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('partnerMedia.name')
|
||||
TextColumn::make('partnerMedia')
|
||||
->label('Penerima')
|
||||
->getStateUsing(
|
||||
fn ($record) => $record->partnerMedia->pluck('name')->toArray()
|
||||
)
|
||||
->listWithLineBreaks()
|
||||
->limitList(3)
|
||||
->expandableLimitedList()
|
||||
->placeholder(fn (Announcement $record): string => $record->type === AnnouncementType::PUBLIC ? 'Publik' : 'Tidak ada penerima'),
|
||||
->badge()
|
||||
->placeholder(
|
||||
fn (Announcement $record) => $record->type === AnnouncementType::PUBLIC ? 'Publik' : 'Tidak ada penerima'
|
||||
),
|
||||
|
||||
...TimestampColumns::make(),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make()->native(false),
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\Publication\News\Tables;
|
||||
|
||||
use App\Enums\NewsStatus;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Actions\Cheerful\DeleteAction;
|
||||
use App\Filament\Actions\Cheerful\EditAction;
|
||||
use App\Filament\Actions\Cheerful\ForceDeleteAction;
|
||||
@ -81,7 +82,9 @@ public static function configure(Table $table): Table
|
||||
...TimestampColumns::make(),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make()->native(false),
|
||||
TrashedFilter::make()
|
||||
->native(false)
|
||||
->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
|
||||
@ -45,7 +45,9 @@ protected function getStats(): array
|
||||
->descriptionIcon(Heroicon::BuildingOffice2)
|
||||
->color('primary'),
|
||||
|
||||
Stat::make('Media Terverifikasi', PartnerMedia::approved()
|
||||
Stat::make('Media Terverifikasi', PartnerMedia::whereHas('company.verificationRequest', function ($q) {
|
||||
$q->approved();
|
||||
})
|
||||
->when($startDate, fn ($q) => $q->whereDate('created_at', '>=', $startDate))
|
||||
->when($endDate, fn ($q) => $q->whereDate('created_at', '<=', $endDate))
|
||||
->count())
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\VerificationStatus;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -19,13 +18,6 @@ class Company extends Model implements HasMedia
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'status' => VerificationStatus::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function journalists(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Journalist::class, PartnerMedia::class);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@ -28,6 +29,7 @@ protected function casts(): array
|
||||
'final_submission_date' => 'date',
|
||||
'payment_amount' => 'integer',
|
||||
'payment_date' => 'date',
|
||||
'completed_at' => 'date',
|
||||
'status' => CooperationStatus::class,
|
||||
];
|
||||
}
|
||||
@ -62,30 +64,46 @@ protected function completed(Builder $query): void
|
||||
$query->where('status', CooperationStatus::COMPLETED);
|
||||
}
|
||||
|
||||
public function cooperationMedia(): HasOne
|
||||
public function cooperationMedia(): HasMany
|
||||
{
|
||||
return $this->hasOne(CooperationMedia::class);
|
||||
return $this->hasMany(CooperationMedia::class);
|
||||
}
|
||||
|
||||
public function partnerMedia(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(PartnerMedia::class, 'cooperation_media')
|
||||
->using(CooperationMedia::class)
|
||||
->withPivot(['status'])
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
public function proposal(): HasOne
|
||||
public function proposal(): HasMany
|
||||
{
|
||||
return $this->hasOne(CooperationProposal::class);
|
||||
return $this->hasMany(CooperationProposal::class);
|
||||
}
|
||||
|
||||
public function reports(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Report::class, TaskAssignment::class);
|
||||
return $this->hasManyThrough(
|
||||
Report::class,
|
||||
MediaTaskAssignment::class,
|
||||
'task_assignment_id',
|
||||
'media_task_assignment_id'
|
||||
);
|
||||
}
|
||||
|
||||
public function taskAssignment(): HasOne
|
||||
{
|
||||
return $this->hasOne(TaskAssignment::class);
|
||||
}
|
||||
|
||||
public function payments(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(
|
||||
CooperationPayment::class,
|
||||
CooperationMedia::class,
|
||||
'cooperation_id',
|
||||
'cooperation_media_id'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
@ -57,9 +57,9 @@ public function partnerMedia(): BelongsTo
|
||||
return $this->belongsTo(PartnerMedia::class);
|
||||
}
|
||||
|
||||
public function payments(): HasMany
|
||||
public function payment(): HasOne
|
||||
{
|
||||
return $this->hasMany(CooperationPayment::class, 'cooperation_media_id');
|
||||
return $this->hasOne(CooperationPayment::class, 'cooperation_media_id');
|
||||
}
|
||||
|
||||
public function rejectionReasons(): MorphMany
|
||||
|
||||
@ -17,13 +17,6 @@ class Journalist extends Model implements HasMedia
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'status' => VerificationStatus::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function partnerMedia(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PartnerMedia::class);
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
@ -23,6 +25,12 @@ protected function casts(): array
|
||||
];
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function active(Builder $query): void
|
||||
{
|
||||
$query->where('is_active', IsActive::ACTIVE);
|
||||
}
|
||||
|
||||
public function issueManagements(): HasMany
|
||||
{
|
||||
return $this->hasMany(IssueManagement::class);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
use App\Enums\ApprovalStatus;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
use Swindon\FilamentHashids\Traits\HasHashid;
|
||||
@ -38,4 +39,9 @@ public function rejectionReasons(): MorphMany
|
||||
{
|
||||
return $this->morphMany(RejectionReason::class, 'rejectable');
|
||||
}
|
||||
|
||||
public function reports(): HasMany
|
||||
{
|
||||
return $this->hasMany(Report::class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
use App\Enums\ApprovalStatus;
|
||||
use App\Enums\MediaClassification;
|
||||
use App\Enums\MediaType;
|
||||
use App\Enums\VerificationStatus;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@ -29,34 +28,9 @@ protected function casts(): array
|
||||
return [
|
||||
'type' => MediaType::class,
|
||||
'classification' => MediaClassification::class,
|
||||
'status' => VerificationStatus::class,
|
||||
];
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function pending(Builder $query): void
|
||||
{
|
||||
$query->where('status', VerificationStatus::PENDING);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function approved(Builder $query): void
|
||||
{
|
||||
$query->where('status', VerificationStatus::APPROVED);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function needRevision(Builder $query): void
|
||||
{
|
||||
$query->where('status', VerificationStatus::NEED_REVISION);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function rejected(Builder $query): void
|
||||
{
|
||||
$query->where('status', VerificationStatus::REJECTED);
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function verified(Builder $query): void
|
||||
{
|
||||
@ -111,6 +85,7 @@ public function cooperationProposals(): HasMany
|
||||
public function cooperations(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Cooperation::class, 'cooperation_media')
|
||||
->using(CooperationMedia::class)
|
||||
->withPivot(['status'])
|
||||
->withTimestamps();
|
||||
}
|
||||
@ -128,6 +103,7 @@ public function mediaTaskAssignments(): HasMany
|
||||
public function taskAssignments(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(TaskAssignment::class, 'media_task_assignment')
|
||||
->using(MediaTaskAssignment::class)
|
||||
->withPivot(['status'])
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
@ -26,9 +26,9 @@ protected function casts(): array
|
||||
];
|
||||
}
|
||||
|
||||
public function taskAssignment(): BelongsTo
|
||||
public function mediaTaskAssignment(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TaskAssignment::class);
|
||||
return $this->belongsTo(MediaTaskAssignment::class);
|
||||
}
|
||||
|
||||
public function rejectionReasons(): MorphMany
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -24,6 +26,12 @@ protected function casts(): array
|
||||
];
|
||||
}
|
||||
|
||||
#[Scope]
|
||||
protected function active(Builder $query): void
|
||||
{
|
||||
$query->where('is_active', IsActive::ACTIVE);
|
||||
}
|
||||
|
||||
public function issueManagements(): HasMany
|
||||
{
|
||||
return $this->hasMany(IssueManagement::class);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Swindon\FilamentHashids\Traits\HasHashid;
|
||||
|
||||
@ -29,9 +30,16 @@ public function cooperation(): BelongsTo
|
||||
return $this->belongsTo(Cooperation::class);
|
||||
}
|
||||
|
||||
public function reports(): HasMany
|
||||
public function reports(): HasManyThrough
|
||||
{
|
||||
return $this->hasMany(Report::class);
|
||||
return $this->hasManyThrough(
|
||||
Report::class,
|
||||
MediaTaskAssignment::class,
|
||||
'task_assignment_id', // Foreign key di tabel media_task_assignment
|
||||
'media_task_assignment_id', // Foreign key di tabel reports
|
||||
'id', // Local key di tabel task_assignments
|
||||
'id' // Local key di tabel media_task_assignment
|
||||
);
|
||||
}
|
||||
|
||||
public function rejectionReasons(): MorphMany
|
||||
@ -44,9 +52,10 @@ public function mediaTaskAssignments(): HasMany
|
||||
return $this->hasMany(MediaTaskAssignment::class);
|
||||
}
|
||||
|
||||
public function partnerMedias(): BelongsToMany
|
||||
public function partnerMedia(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(PartnerMedia::class, 'media_task_assignment')
|
||||
->using(MediaTaskAssignment::class)
|
||||
->withPivot(['status'])
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Enums\VerificationStatus;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Panel;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
@ -37,6 +38,10 @@ protected function casts(): array
|
||||
|
||||
public function canAccessPanel(Panel $panel): bool
|
||||
{
|
||||
if ($this->company?->verificationRequest?->status === VerificationStatus::REJECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->is_active === IsActive::ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
@ -4,11 +4,13 @@
|
||||
|
||||
use Filament\Notifications\Notification as FilamentNotification;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class BroadcastNotification extends Notification
|
||||
class BroadcastNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public function __construct(
|
||||
protected array $payload
|
||||
|
||||
@ -1,401 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Enums\DecisionAdmin;
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Filament\Pages\Company as PagesCompany;
|
||||
use App\Filament\Pages\Media;
|
||||
use App\Filament\Resources\Manage\Journalists\Pages\ManageJournalists;
|
||||
use App\Models\Company;
|
||||
use App\Models\VerificationRequest;
|
||||
use App\Models\VerificationReview;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class VerificationService
|
||||
{
|
||||
/**
|
||||
* Check if all required data is complete for verification
|
||||
*/
|
||||
public function isDataComplete(?Company $company): bool
|
||||
{
|
||||
return $company !== null
|
||||
&& $company->partnerMedia !== null
|
||||
&& $company->partnerMedia?->journalists !== null
|
||||
&& $company->partnerMedia->journalists->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get missing data items for verification
|
||||
*/
|
||||
public function getMissingData(?Company $company): array
|
||||
{
|
||||
$missing = [];
|
||||
|
||||
if (! $company) {
|
||||
$missing[] = 'Data Perusahaan';
|
||||
}
|
||||
|
||||
if ($company && ! $company->partnerMedia) {
|
||||
$missing[] = 'Data Media';
|
||||
}
|
||||
|
||||
if ($company && $company->partnerMedia && ($company->partnerMedia?->journalists === null || $company->partnerMedia?->journalists?->count() === 0)) {
|
||||
$missing[] = 'Data Jurnalis (minimal 1)';
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can submit verification
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the current step based on status
|
||||
*/
|
||||
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, // Draft / not submitted yet
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest review notes
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all reviews history
|
||||
*/
|
||||
public function getReviewHistory(?VerificationRequest $verificationRequest): Collection
|
||||
{
|
||||
if (! $verificationRequest) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return $verificationRequest->reviews()
|
||||
->with('reviewer')
|
||||
->latest()
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unified verification progress data
|
||||
*/
|
||||
public function getVerificationProgress(?Company $company, ?VerificationRequest $verificationRequest): array
|
||||
{
|
||||
$currentStep = $this->resolveStep($company, $verificationRequest);
|
||||
$isComplete = $this->isDataComplete($company);
|
||||
$missingData = $this->getMissingData($company);
|
||||
|
||||
$status = $verificationRequest?->status;
|
||||
|
||||
return [
|
||||
'currentStep' => $currentStep,
|
||||
'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($verificationRequest, $isComplete, $missingData),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get steps array for stepper
|
||||
*/
|
||||
protected function getSteps(?VerificationRequest $verificationRequest, bool $isComplete, array $missingData): 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',
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit unified verification
|
||||
*/
|
||||
public function submitVerification(Company $company, ?VerificationRequest $existingRequest): VerificationRequest
|
||||
{
|
||||
if ($existingRequest && $existingRequest->status === VerificationStatus::NEED_REVISION) {
|
||||
// Resubmit - update existing request
|
||||
$existingRequest->update([
|
||||
'status' => VerificationStatus::PENDING,
|
||||
]);
|
||||
|
||||
return $existingRequest->fresh(['reviews.reviewer']);
|
||||
}
|
||||
|
||||
// New submission
|
||||
return VerificationRequest::create([
|
||||
'company_id' => $company->id,
|
||||
'submitted_by' => auth()->id(),
|
||||
'status' => VerificationStatus::PENDING,
|
||||
])->load(['reviews.reviewer']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process review decision - unified for Company, Media, and Journalists
|
||||
*/
|
||||
public function processReview(VerificationRequest $verificationRequest, DecisionAdmin $decision, ?string $note): void
|
||||
{
|
||||
$verificationRequest->load(['company.partnerMedia.journalists']);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Create review record
|
||||
VerificationReview::create([
|
||||
'verification_request_id' => $verificationRequest->id,
|
||||
'reviewer_id' => auth()->id(),
|
||||
'decision' => $decision,
|
||||
'note' => $note,
|
||||
]);
|
||||
|
||||
// Update verification request status
|
||||
$newStatus = match ($decision) {
|
||||
DecisionAdmin::APPROVED => VerificationStatus::APPROVED,
|
||||
DecisionAdmin::NEED_REVISION => VerificationStatus::NEED_REVISION,
|
||||
DecisionAdmin::REJECTED => VerificationStatus::REJECTED,
|
||||
};
|
||||
|
||||
$verificationRequest->update([
|
||||
'status' => $newStatus,
|
||||
]);
|
||||
|
||||
// Update Company status
|
||||
$company = $verificationRequest->company;
|
||||
if ($company) {
|
||||
$company->update(['status' => $newStatus]);
|
||||
|
||||
// Update Media status
|
||||
$media = $company->partnerMedia;
|
||||
if ($media) {
|
||||
$media->update(['status' => $newStatus]);
|
||||
|
||||
// Update all Journalists status
|
||||
$media->journalists()->update(['status' => $newStatus]);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Verification review processing failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'request_id' => $verificationRequest->id,
|
||||
'decision' => $decision->value,
|
||||
]);
|
||||
|
||||
DB::rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get company name from verification request
|
||||
*/
|
||||
public function getCompanyName(VerificationRequest $request): string
|
||||
{
|
||||
return $request->company?->name ?? 'Data tidak ditemukan';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get verification summary data for admin
|
||||
*/
|
||||
public function getVerificationSummary(VerificationRequest $request): array
|
||||
{
|
||||
$company = $request->company;
|
||||
$media = $company?->partnerMedia;
|
||||
$journalists = $media?->journalists ?? collect();
|
||||
|
||||
return [
|
||||
'company' => [
|
||||
'name' => $company?->name ?? 'Belum diisi',
|
||||
'email' => $company?->email ?? '-',
|
||||
'exists' => $company !== null,
|
||||
],
|
||||
'media' => [
|
||||
'name' => $media?->name ?? 'Belum diisi',
|
||||
'type' => $media?->type?->getLabel() ?? '-',
|
||||
'exists' => $media !== null,
|
||||
],
|
||||
'journalists' => [
|
||||
'count' => $journalists->count(),
|
||||
'names' => $journalists->pluck('name')->take(3)->toArray(),
|
||||
'exists' => $journalists->count() > 0,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alert data for verification status
|
||||
*/
|
||||
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' => 'Verifikasi Anda telah diterima dan disetujui oleh admin. Sekarang Anda sudah resmi terverifikasi dan bekerja sama dengan kami!',
|
||||
'color' => 'success',
|
||||
];
|
||||
}
|
||||
|
||||
if ($status === VerificationStatus::PENDING) {
|
||||
return [
|
||||
'type' => 'pending',
|
||||
'icon' => 'clock',
|
||||
'title' => 'Menunggu Verifikasi',
|
||||
'message' => 'Data Anda sedang dalam proses verifikasi oleh admin. Mohon tunggu.',
|
||||
'color' => 'info',
|
||||
'animate' => true,
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get missing data buttons configuration
|
||||
*/
|
||||
public function getMissingDataButtons(?Company $company): array
|
||||
{
|
||||
$buttons = [];
|
||||
|
||||
if (! $company) {
|
||||
$buttons[] = [
|
||||
'label' => 'Lengkapi Data Perusahaan',
|
||||
'url' => PagesCompany::getUrl(),
|
||||
'icon' => 'building-office-2',
|
||||
'color' => 'warning',
|
||||
];
|
||||
}
|
||||
|
||||
if ($company && ! $company->partnerMedia) {
|
||||
$buttons[] = [
|
||||
'label' => 'Lengkapi Data Media',
|
||||
'url' => Media::getUrl(),
|
||||
'icon' => 'newspaper',
|
||||
'color' => 'warning',
|
||||
];
|
||||
}
|
||||
|
||||
if ($company && $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;
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@ public function definition(): array
|
||||
'domicile_certificate' => $this->faker->numerify('###/###/DOMISILI/####'),
|
||||
'profile' => $this->faker->numerify('PROFILE-####-########'),
|
||||
'profile' => $this->faker->numerify('PROFILE-####-########'),
|
||||
'status' => VerificationStatus::PENDING,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
@ -28,7 +27,6 @@ public function up(): void
|
||||
$table->string('annual_tax_return', 100);
|
||||
$table->string('domicile_certificate', 100);
|
||||
$table->string('profile', 100);
|
||||
$table->enum('status', VerificationStatus::cases())->default(VerificationStatus::PENDING)->comment(VerificationStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
use App\Enums\MediaClassification;
|
||||
use App\Enums\MediaType;
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
@ -25,7 +24,6 @@ public function up(): void
|
||||
$table->enum('classification', [MediaClassification::values()])->comment(MediaClassification::comment());
|
||||
$table->string('journalism_organization')->nullable();
|
||||
$table->string('press_council_certificate')->nullable();
|
||||
$table->enum('status', VerificationStatus::cases())->default(VerificationStatus::PENDING)->comment(VerificationStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\VerificationStatus;
|
||||
use App\Models\PartnerMedia;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
@ -21,7 +20,6 @@ public function up(): void
|
||||
$table->string('phone_number', 20);
|
||||
$table->string('press_card', 100)->nullable();
|
||||
$table->string('ukw_certificate', 100)->nullable();
|
||||
$table->enum('status', VerificationStatus::cases())->default(VerificationStatus::PENDING)->comment(VerificationStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
|
||||
@ -20,7 +20,8 @@ public function up(): void
|
||||
$table->text('description');
|
||||
$table->unsignedInteger('payment_amount')->nullable();
|
||||
$table->date('payment_date')->nullable();
|
||||
$table->enum('status', [CooperationStatus::values()])->default(CooperationStatus::PENDING)->comment(CooperationStatus::comment());
|
||||
$table->date('completed_at')->nullable();
|
||||
$table->enum('status', CooperationStatus::values())->default(CooperationStatus::PENDING)->comment(CooperationStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
|
||||
@ -18,7 +18,7 @@ public function up(): void
|
||||
$table->id();
|
||||
$table->foreignIdFor(Cooperation::class)->constrained()->cascadeOnDelete();
|
||||
$table->foreignIdFor(PartnerMedia::class)->constrained()->cascadeOnDelete();
|
||||
$table->enum('status', [ApprovalStatus::values()])->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->enum('status', ApprovalStatus::values())->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
});
|
||||
|
||||
@ -19,8 +19,8 @@ public function up(): void
|
||||
$table->foreignIdFor(Cooperation::class)->constrained()->cascadeOnDelete();
|
||||
$table->foreignIdFor(PartnerMedia::class)->constrained()->cascadeOnDelete();
|
||||
$table->text('description')->nullable();
|
||||
$table->string('e_catalog', 50)->nullable();
|
||||
$table->enum('status', [ApprovalStatus::values()])->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->string('e_catalog', 200)->nullable();
|
||||
$table->enum('status', ApprovalStatus::values())->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->timestamp('submitted_at')->useCurrent();
|
||||
$table->timestamp('responded_at')->nullable();
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
|
||||
@ -18,7 +18,7 @@ public function up(): void
|
||||
$table->id();
|
||||
$table->foreignIdFor(TaskAssignment::class)->constrained()->cascadeOnDelete();
|
||||
$table->foreignIdFor(PartnerMedia::class)->constrained()->cascadeOnDelete();
|
||||
$table->enum('status', [ApprovalStatus::values()])->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->enum('status', ApprovalStatus::values())->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\ApprovalStatus;
|
||||
use App\Models\TaskAssignment;
|
||||
use App\Models\MediaTaskAssignment;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
@ -15,12 +15,12 @@ public function up(): void
|
||||
{
|
||||
Schema::create('reports', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignIdFor(TaskAssignment::class)->constrained()->cascadeOnDelete();
|
||||
$table->foreignIdFor(MediaTaskAssignment::class)->constrained()->cascadeOnDelete();
|
||||
$table->string('title', 200);
|
||||
$table->date('publication_date');
|
||||
$table->string('link', 50);
|
||||
$table->text('description');
|
||||
$table->enum('status', [ApprovalStatus::values()])->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->enum('status', ApprovalStatus::values())->default(ApprovalStatus::PENDING)->comment(ApprovalStatus::comment());
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
|
||||
@ -522,6 +522,18 @@ public function run(): void
|
||||
"name": "Admin Monitoring",
|
||||
"guard_name": "web",
|
||||
"permissions": [
|
||||
"ViewAny:Classification",
|
||||
"View:Classification",
|
||||
"Create:Classification",
|
||||
"Update:Classification",
|
||||
"Delete:Classification",
|
||||
"Restore:Classification",
|
||||
"ForceDelete:Classification",
|
||||
"ForceDeleteAny:Classification",
|
||||
"RestoreAny:Classification",
|
||||
"Replicate:Classification",
|
||||
"Reorder:Classification",
|
||||
|
||||
"View:Dashboard",
|
||||
|
||||
"ViewAny:IssueManagement",
|
||||
@ -535,6 +547,18 @@ public function run(): void
|
||||
"RestoreAny:IssueManagement",
|
||||
"Replicate:IssueManagement",
|
||||
"Reorder:IssueManagement",
|
||||
|
||||
"ViewAny:Location",
|
||||
"View:Location",
|
||||
"Create:Location",
|
||||
"Update:Location",
|
||||
"Delete:Location",
|
||||
"Restore:Location",
|
||||
"ForceDelete:Location",
|
||||
"ForceDeleteAny:Location",
|
||||
"RestoreAny:Location",
|
||||
"Replicate:Location",
|
||||
"Reorder:Location",
|
||||
|
||||
"ViewAny:MediaMonitoring",
|
||||
"View:MediaMonitoring",
|
||||
@ -659,15 +683,6 @@ public function run(): void
|
||||
"permissions": [
|
||||
"ViewAny:Cooperation",
|
||||
"View:Cooperation",
|
||||
"Create:Cooperation",
|
||||
"Update:Cooperation",
|
||||
"Delete:Cooperation",
|
||||
"Restore:Cooperation",
|
||||
"ForceDelete:Cooperation",
|
||||
"ForceDeleteAny:Cooperation",
|
||||
"RestoreAny:Cooperation",
|
||||
"Replicate:Cooperation",
|
||||
"Reorder:Cooperation",
|
||||
|
||||
"View:Dashboard"
|
||||
]
|
||||
@ -676,29 +691,8 @@ public function run(): void
|
||||
"name": "Perusahaan",
|
||||
"guard_name": "web",
|
||||
"permissions": [
|
||||
"ViewAny:Announcement",
|
||||
"View:Announcement",
|
||||
"Create:Announcement",
|
||||
"Update:Announcement",
|
||||
"Delete:Announcement",
|
||||
"Restore:Announcement",
|
||||
"ForceDelete:Announcement",
|
||||
"ForceDeleteAny:Announcement",
|
||||
"RestoreAny:Announcement",
|
||||
"Replicate:Announcement",
|
||||
"Reorder:Announcement",
|
||||
|
||||
"ViewAny:Cooperation",
|
||||
"View:Cooperation",
|
||||
"Create:Cooperation",
|
||||
"Update:Cooperation",
|
||||
"Delete:Cooperation",
|
||||
"Restore:Cooperation",
|
||||
"ForceDelete:Cooperation",
|
||||
"ForceDeleteAny:Cooperation",
|
||||
"RestoreAny:Cooperation",
|
||||
"Replicate:Cooperation",
|
||||
"Reorder:Cooperation",
|
||||
|
||||
"View:Company",
|
||||
|
||||
@ -706,21 +700,12 @@ public function run(): void
|
||||
|
||||
"ViewAny:DataChangeRequest",
|
||||
"View:DataChangeRequest",
|
||||
"Create:DataChangeRequest",
|
||||
"Update:DataChangeRequest",
|
||||
"Delete:DataChangeRequest",
|
||||
"Restore:DataChangeRequest",
|
||||
"ForceDelete:DataChangeRequest",
|
||||
"ForceDeleteAny:DataChangeRequest",
|
||||
"RestoreAny:DataChangeRequest",
|
||||
"Replicate:DataChangeRequest",
|
||||
"Reorder:DataChangeRequest",
|
||||
|
||||
"ViewAny:Journalits",
|
||||
"View:Journalits",
|
||||
"Create:Journalits",
|
||||
"Update:Journalits",
|
||||
"Delete:Journalits",
|
||||
"ViewAny:Journalist",
|
||||
"View:Journalist",
|
||||
"Create:Journalist",
|
||||
"Update:Journalist",
|
||||
"Delete:Journalist",
|
||||
|
||||
"View:Media",
|
||||
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
<form wire:submit.prevent="save">
|
||||
{{ $this->form }}
|
||||
|
||||
<div class="mt-6">
|
||||
{{ $this->saveAction() }}
|
||||
</div>
|
||||
@if (!$this->isVerificationStage)
|
||||
<div class="mt-6">
|
||||
{{ $this->saveAction() }}
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</x-filament-panels::page>
|
||||
|
||||
@ -32,9 +32,11 @@ class="dark:text-gray-400">
|
||||
<form wire:submit.prevent="save">
|
||||
{{ $this->form }}
|
||||
|
||||
<div class="mt-6">
|
||||
{{ $this->saveAction() }}
|
||||
</div>
|
||||
@if (!$this->isVerificationStage)
|
||||
<div class="mt-6">
|
||||
{{ $this->saveAction() }}
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
@endif
|
||||
</x-filament-panels::page>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user