user(); // $approverId = $get('characteristic_approver_master_id'); // if (!$approverId) return true; // disable if no approver selected // $approver = CharacteristicApproverMaster::find($approverId); // if (!$approver) return true; // // Enable if Super Admin // if ($currentUser && $currentUser->hasRole('Super Admin')) { // return false; // not disabled // } // // Enable only if current user is one of the approvers // $userName = $currentUser?->name; // return !in_array($userName, [ // $approver->name1, // $approver->name2, // $approver->name3, // ]); // }; return $form ->schema([ Section::make('') ->schema([ Forms\Components\Select::make('plant_id') ->label('Plant') ->reactive() ->relationship('plant', 'name') ->required() ->default(function () { return optional(RequestCharacteristic::latest()->first())->plant_id; }) ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant_id'); $updRec = $get('id'); $set('machine_id', null); $set('item_id', null); $set('aufnr', null); $set('machine_name', null); $set('characteristic_approver_master_id', null); if (! $updRec && $plantId) { $set('work_flow_id', self::isNewWorkFlow($get)); } $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(fn ($get) => self::isFieldDisabled($get)), Forms\Components\Select::make('machine_id') ->label('Work Center') // ->relationship('machine', 'name') ->reactive() ->searchable() ->options(function (callable $get) { $plantId = $get('plant_id'); if (! $plantId) { return []; } return Machine::where('plant_id', $plantId)->pluck('work_center', 'id'); }) ->required() ->default(function () { return optional(RequestCharacteristic::latest()->first())->machine_id ?? []; }) ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('item_id', null); $set('aufnr', null); $set('machine_name', null); $set('characteristic_approver_master_id', null); $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(fn ($get) => self::isFieldDisabled($get)), Forms\Components\TextInput::make('work_flow_id') ->label('Work Flow ID') ->readOnly() ->reactive() ->default(function ($state, callable $set, callable $get) { $updRec = $get('id'); if (! $updRec) { return self::isNewWorkFlow($get); } $set('updated_by', Filament::auth()->user()?->name); }), // ->rule(function (callable $get) { // return Rule::unique('request_characteristics', 'work_flow_id') // ->where('plant_id', $get('plant_id')) // ->ignore($get('id')); // }), Forms\Components\Select::make('item_id') ->label('Item') // ->relationship('item', 'id') ->reactive() ->searchable() ->options(function (callable $get) { $plantId = $get('plant_id'); if (! $plantId) { return []; } return Item::where('plant_id', $plantId)->pluck('code', 'id'); }) ->required() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('aufnr', null); $set('updated_by', Filament::auth()->user()?->name); }) ->default(function () { return optional(RequestCharacteristic::latest()->first())->item_id ?? []; }) ->disabled(fn ($get) => self::isFieldDisabled($get)), Forms\Components\TextInput::make('aufnr') ->label('Aufnr') ->reactive() ->required() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->default(function () { return optional(RequestCharacteristic::latest()->first())->aufnr ?? ''; }) ->disabled(fn ($get) => self::isFieldDisabled($get)), Forms\Components\Select::make('machine_name') ->label('Machines') ->reactive() ->nullable() ->searchable() ->options(function (callable $get) { $plantId = $get('plant_id'); $machineId = $get('machine_id'); if (! $plantId || ! $machineId) { return []; } return CharacteristicApproverMaster::where('plant_id', $plantId)->where('machine_id', $machineId)->pluck('machine_name', 'machine_name')->unique(); }) ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('characteristic_approver_master_id', null); // dd($get('characteristic_approver_master_id')); $set('updated_by', Filament::auth()->user()?->name); }) ->default(function () { $machineName = ''; $reqId = RequestCharacteristic::latest()->first()?->characteristic_approver_master_id; if ($reqId) { $reqMac = CharacteristicApproverMaster::where('id', $reqId)->first()?->machine_name; if ($reqMac) { $machineName = $reqMac; } else { $machineName = null; } } else { $machineName = null; } // return optional(RequestCharacteristic::latest()->first())->characteristic_approver_master_id ?? []; return $machineName ?? []; }) ->afterStateHydrated(function ($component, $state, Get $get, Set $set) { if ($get('id')) { $reqId = RequestCharacteristic::where('id', $get('id'))->first()?->characteristic_approver_master_id; if ($reqId) { $reqMac = CharacteristicApproverMaster::where('id', $reqId)->first()?->machine_name; if ($reqMac) { $set('machine_name', $reqMac); } else { $set('machine_name', null); } } else { $set('machine_name', null); } } }) ->required(), Forms\Components\Select::make('characteristic_approver_master_id') ->label('Master Characteristic Field') // ->relationship('characteristicApproverMaster', 'characteristic_field') ->reactive() ->nullable() ->searchable() ->options(function (callable $get) { $plantId = $get('plant_id'); $machineId = $get('machine_id'); $machineName = $get('machine_name'); if (! $plantId || ! $machineId || ! $machineName) { return []; } return CharacteristicApproverMaster::where('plant_id', $plantId)->where('machine_id', $machineId)->where('machine_name', $machineName)->pluck('characteristic_field', 'id'); }) ->default(function () { return optional(RequestCharacteristic::latest()->first())->characteristic_approver_master_id ?? []; }) ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->required(), // ->disabled(fn ($get) => self::isFieldDisabled($get)) Section::make('Request Characteristic') // ->columnSpan(['default' => 2, 'sm' => 4]) ->reactive() ->schema([ Forms\Components\TextInput::make('characteristic_name') ->label('Characteristic Name') ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->required() ->disabled(fn ($get) => self::isFieldDisabled($get)), Forms\Components\TextInput::make('current_value') ->label('Current Value') ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(fn ($get) => self::isFieldDisabled(get: $get)), Forms\Components\TextInput::make('update_value') ->label('Update Value') ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(fn ($get) => self::isFieldDisabled($get)), ]) ->collapsible() ->columns(['default' => 1, 'sm' => 3]), Section::make(function ($get): string { $approverId = $get('characteristic_approver_master_id'); $approverName = $approverId ? CharacteristicApproverMaster::find($approverId)?->name1 : null; return 'Approver - 1'.($approverName ? " ( {$approverName} )" : ''); }) ->reactive() // ->description(fn (Get $get) => CharacteristicApproverMaster::find($get('characteristic_approver_master_id'))?->name1 ?? 'Select approver above' // ) ->schema([ Forms\Components\Select::make('approver_status1') ->label('Approver Status') ->reactive() ->live() ->options([ 'Approved' => 'Approved', 'Hold' => 'Hold', 'Rejected' => 'Rejected', ]) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($state && empty($get('approved1_at'))) { $set('approved1_at', now()); } $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return true; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return true; } // Super Admin can edit any if ($currentUser && $currentUser->hasRole('Super Admin')) { return false; // field enabled } // Otherwise, enable only if the user's name matches return $approver->name1 != $currentUser?->name; }), Forms\Components\TextInput::make('approver_remark1') ->label('Approver Remark') ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); $updId = $get('id'); if (! $updId) { return true; } elseif ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } else { return true; } }), Forms\Components\DateTimePicker::make('approved1_at') // ->label('Approved At') ->label(fn (callable $get): string => match ($get('approver_status1')) { 'Approved' => 'Approved At', 'Hold' => 'Hold At', 'Rejected' => 'Rejected At', default => 'Updated At', }) ->reactive() ->live() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); // logged-in user $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return true; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return true; } if ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } return $approver->name1 != $currentUser?->name; }), ]) ->collapsed()// collapsible() ->columns(['default' => 1, 'sm' => 3]), Section::make(function ($get): string { $approverId = $get('characteristic_approver_master_id'); $approverName = $approverId ? CharacteristicApproverMaster::find($approverId)?->name2 : null; return 'Approver - 2'.($approverName ? " ( {$approverName} )" : ''); }) ->reactive() ->schema([ Forms\Components\Select::make('approver_status2') ->label('Approver Status') ->reactive() ->options([ 'Approved' => 'Approved', 'Hold' => 'Hold', 'Rejected' => 'Rejected', ]) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($state && empty($get('approved2_at'))) { $set('approved2_at', now()); } $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); // get the User object $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return true; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return true; } // Super Admin can always edit if ($currentUser && $currentUser->hasRole('Super Admin')) { return false; // ENABLE field } // Otherwise, enable only if the user's name matches return $approver->name2 != $currentUser?->name; }), Forms\Components\TextInput::make('approver_remark2') ->label('Approver Remark') ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); $updId = $get('id'); if (! $updId) { return true; } elseif ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } else { return true; } }), Forms\Components\DateTimePicker::make('approved2_at') ->label(fn (callable $get): string => match ($get('approver_status2')) { 'Approved' => 'Approved At', 'Hold' => 'Hold At', 'Rejected' => 'Rejected At', default => 'Updated At', }) ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); // logged-in user $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return true; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return true; } if ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } return $approver->name2 != $currentUser?->name; }), // ->dehydrated(true), ]) ->collapsed()// collapsible() ->columns(['default' => 1, 'sm' => 3]), Section::make(function ($get): string { $approverId = $get('characteristic_approver_master_id'); $approverName = $approverId ? CharacteristicApproverMaster::find($approverId)?->name3 : null; return 'Approver - 3'.($approverName ? " ( {$approverName} )" : ''); }) ->reactive() ->schema([ Forms\Components\Select::make('approver_status3') ->label('Approver Status') ->reactive() ->options([ 'Approved' => 'Approved', 'Hold' => 'Hold', 'Rejected' => 'Rejected', ]) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($state && empty($get('approved3_at'))) { $set('approved3_at', now()); } $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return true; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return true; } if ($currentUser->hasRole('Super Admin')) { return false; } else { return $approver->name3 != $currentUser?->name; } }), Forms\Components\TextInput::make('approver_remark3') ->label('Approver Remark') ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); $updId = $get('id'); if (! $updId) { return true; } elseif ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } else { return true; } }), Forms\Components\DateTimePicker::make('approved3_at') ->label(fn (callable $get): string => match ($get('approver_status3')) { 'Approved' => 'Approved At', 'Hold' => 'Hold At', 'Rejected' => 'Rejected At', default => 'Updated At', }) ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('updated_by', Filament::auth()->user()?->name); }) ->disabled(function ($get) { $currentUser = Filament::auth()->user(); // logged-in user $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return true; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return true; } if ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } return $approver->name3 != $currentUser?->name; }), ]) ->collapsed()// collapsible() ->columns(['default' => 1, 'sm' => 3]), Forms\Components\Hidden::make('created_by') ->label('Created By') ->default(Filament::auth()->user()?->name), Forms\Components\Hidden::make('updated_by') ->label('Updated By') ->default(Filament::auth()->user()?->name), Forms\Components\TextInput::make('id') ->hidden() ->readOnly(), ]) ->columns(['default' => 1, 'sm' => 3]), ]); } protected static function isFieldDisabled($get): bool { $currentUser = Filament::auth()->user(); $approverId = $get('characteristic_approver_master_id'); if (! $approverId) { return false; } if (str_contains($approverId, '_')) { [$approverId, $level] = explode('_', $approverId); } $approver = CharacteristicApproverMaster::find($approverId); if (! $approver) { return false; } if ($currentUser && $currentUser->hasRole('Super Admin')) { return false; } $userName = $currentUser?->name; return in_array($userName, [ $approver->name1, $approver->name2, $approver->name3, ]); } protected static function isNewWorkFlow($get): string { $year = now()->format('y'); $month = now()->format('m'); $date = now()->format('d'); $prefix = "WF-{$year}{$month}{$date}-"; $lastWorkflow = RequestCharacteristic::where('work_flow_id', 'like', "{$prefix}%") // ->where('machine_id', $MachineId) ->where('work_flow_id', 'like', "{$prefix}%") ->orderByDesc('work_flow_id') ->first(); if ($lastWorkflow) { $lastSerial = substr($lastWorkflow->work_flow_id, strlen($prefix)); $nextSerial = str_pad( intval($lastSerial) + 1, 3, '0', STR_PAD_LEFT ); } else { $nextSerial = '001'; } $workFlowId = "{$prefix}{$nextSerial}"; return $workFlowId; } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('No.') ->label('No.') ->getStateUsing(function ($record, $livewire, $column, $rowLoop) { $paginator = $livewire->getTableRecords(); $perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10; $currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1; return ($currentPage - 1) * $perPage + $rowLoop->iteration; }), Tables\Columns\TextColumn::make('work_flow_id') ->label('Work Flow ID') ->alignCenter() ->searchable(), // isIndividual: true Tables\Columns\TextColumn::make('plant.name') ->label('Plant') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('machine.work_center') ->label('Work Center') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('item.code') ->label('Item Code') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('aufnr') ->label('Aufnr') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('characteristicApproverMaster.machine_name') ->label('Machine') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('characteristicApproverMaster.characteristic_field') ->label('Master Characteristic') ->alignCenter() ->searchable() ->formatStateUsing(fn (string $state): string => strtoupper(__($state))) ->extraAttributes(['class' => 'uppercase']) ->sortable(), Tables\Columns\TextColumn::make('characteristic_name') ->label('Characteristic Name') ->alignCenter() ->searchable() ->formatStateUsing(fn (string $state): string => strtoupper(__($state))) ->extraAttributes(['class' => 'uppercase']) ->sortable(), Tables\Columns\TextColumn::make('current_value') ->label('Current Value') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('update_value') ->label('Update Value') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('characteristicApproverMaster.name1') ->label('Approver Name 1') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approver_status1') ->label('Approver Status 1') ->color(fn (string $state): string => match ($state) { 'Approved' => 'success', 'Hold' => 'warning', 'Rejected' => 'danger', default => 'gray', }) ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approver_remark1') ->label('Approver Remark 1') // ->color('success') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approved1_at') ->label('Approver At 1') ->alignCenter() ->dateTime() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('characteristicApproverMaster.name2') ->label('Approver Name 2') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approver_status2') ->label('Approver Status 2') ->color(fn (string $state): string => match ($state) { 'Approved' => 'success', 'Hold' => 'warning', 'Rejected' => 'danger', default => 'gray', }) ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approver_remark2') ->label('Approver Remark 2') // ->color('success') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approved2_at') ->label('Approver At 2') ->alignCenter() ->dateTime() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('characteristicApproverMaster.name3') ->label('Approver Name 3') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approver_status3') ->label('Approver Status 3') ->color(fn (string $state): string => match ($state) { 'Approved' => 'success', 'Hold' => 'warning', 'Rejected' => 'danger', default => 'gray', }) ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approver_remark3') ->label('Approver Remark 3') // ->color('success') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('approved3_at') ->label('Approver At 3') ->alignCenter() ->dateTime() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('created_at') ->label('Created At') ->dateTime() ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('created_by') ->label('Created By') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('updated_at') ->label('Updated At') ->dateTime() ->alignCenter() ->searchable() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('updated_by') ->label('Updated By') ->alignCenter() ->searchable() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('deleted_at') ->label('Deleted At') ->dateTime() ->alignCenter() ->searchable() ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->searchPlaceholder('Search Work Flow ID') ->filters([ Tables\Filters\TrashedFilter::make(), ]) ->actions([ Tables\Actions\ViewAction::make(), Tables\Actions\EditAction::make(), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make(), Tables\Actions\ForceDeleteBulkAction::make(), Tables\Actions\RestoreBulkAction::make(), ]), ]) ->headerActions([ // ImportAction::make() // ->label('Import Request Characteristics') // ->color('warning') // ->importer(RequestCharacteristicImporter::class) // ->visible(function () { // return Filament::auth()->user()->can('view import request characteristic'); // }), ExportAction::make() ->label('Export Request Characteristics') ->color('warning') ->exporter(RequestCharacteristicExporter::class) ->visible(function () { return Filament::auth()->user()->can('view export request characteristic'); }), ]); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListRequestCharacteristics::route('/'), 'create' => Pages\CreateRequestCharacteristic::route('/create'), 'view' => Pages\ViewRequestCharacteristic::route('/{record}'), 'edit' => Pages\EditRequestCharacteristic::route('/{record}/edit'), ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() ->withoutGlobalScopes([ SoftDeletingScope::class, ]); } }