components([ Section::make('Feedback Information') ->schema([ Select::make('customer_id') ->relationship('customer', 'name') ->searchable() ->required() ->live(), Toggle::make('is_general') ->label('General feedback (not related to a product)') ->default(false) ->live(), Select::make('customer_product_id') ->label('Product') ->searchable() ->getSearchResultsUsing(function (string $search, $get): array { $customerId = $get('customer_id'); if (! $customerId) { return []; } $keyword = mb_strtolower($search); return CustomerProduct::where('customer_id', $customerId) ->whereHas('product', fn ($q) => $q->whereRaw('LOWER(name) LIKE ?', ["%{$keyword}%"])) ->with('product') ->limit(50) ->get() ->pluck('product.name', 'id') ->toArray(); }) ->getOptionLabelUsing(fn ($value): ?string => CustomerProduct::find($value)?->product?->name ) ->visible(fn ($get): bool => ! $get('is_general')) ->nullable() ->live(), Select::make('contract_id') ->label('Hợp đồng') ->visible(fn ($get): bool => ! $get('is_general') && filled($get('customer_product_id'))) ->options(function ($get): array { $customerProductId = $get('customer_product_id'); if (! $customerProductId) { return []; } $cp = \App\Models\CustomerProduct::find($customerProductId); if (! $cp) { return []; } return \App\Models\Contract::where('product_id', $cp->product_id) ->where('status', 'active') ->with('customer') ->get() ->mapWithKeys(fn ($c) => [ $c->id => sprintf('%s (%s) - %s', \App\Enums\ContractType::from($c->type)->label(), $c->customer->name, $c->start_date?->format('d/m/Y') ?? 'N/A', ), ]) ->toArray(); }) ->afterStateHydrated(function ($component, $state, $get): void { if (filled($state)) { return; } $customerProductId = $get('customer_product_id'); if (! $customerProductId) { return; } $cp = \App\Models\CustomerProduct::find($customerProductId); if (! $cp) { return; } $activeContract = \App\Models\Contract::where('product_id', $cp->product_id) ->where('status', 'active') ->first(); if ($activeContract) { $component->state($activeContract->id); } }) ->nullable() ->searchable(), Select::make('feedback_channel_id') ->relationship('feedbackChannel', 'name') ->required() ->preload(), TextInput::make('title') ->required() ->maxLength(255), Textarea::make('content') ->required() ->rows(6) ->columnSpanFull(), Select::make('attachment_collection') ->label('Attachment Collection') ->options([ 'general' => 'General', 'proof_of_resolution' => 'Proof of Resolution', 'customer_evidence' => 'Customer Evidence', ]) ->default('general'), FileUpload::make('attachments') ->label('Attachments') ->multiple() ->disk('local') ->directory('feedback-attachments') ->columnSpanFull() ->dehydrated(false), Select::make('tags') ->relationship('tags', 'name') ->multiple() ->preload() ->createOptionForm([ TextInput::make('name')->required(), TextInput::make('slug')->required(), ColorPicker::make('color')->default('#3b82f6'), ]), Select::make('status') ->options([ 'pending' => 'Pending', 'processing' => 'Processing', 'resolved' => 'Resolved', 'closed' => 'Closed', ]) ->default('pending') ->required(), Select::make('assigned_to') ->relationship('assignedTo', 'name') ->searchable() ->nullable(), Select::make('current_department_id') ->label('Department') ->options(Department::pluck('name', 'id')->toArray()) ->searchable() ->nullable(), Toggle::make('is_escalated') ->label('Escalated') ->visible(fn (): bool => auth()->user()?->hasRole(['admin', 'manager']) ?? false), ]) ->columns(2), ]); } }