schema([ Section::make('') ->schema([ Forms\Components\Select::make('plant_id') ->relationship('plant', 'name') ->required() // ->nullable() ->reactive() // ->afterStateUpdated(fn ($set) => $set('block_name', null)) ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant_id'); $set('block_name', null); if (!$plantId) { $set('pqPlantError', 'Please select a plant first.'); return; } else { $set('validationError', null); $set('pqPlantError', null); } }) ->extraAttributes(fn ($get) => [ 'class' => $get('pqPlantError') ? 'border-red-500' : '', ]) ->hint(fn ($get) => $get('pqPlantError') ? $get('pqPlantError') : null) ->hintColor('danger'), Forms\Components\Select::make('block_name') ->required() // ->nullable() ->options(function (callable $get) { if (!$get('plant_id')) { return []; } return \App\Models\Block::where('plant_id', $get('plant_id')) ->pluck('name', 'id') ->toArray(); }) ->reactive() // ->afterStateUpdated(fn ($set) => $set('shift_id', null)) ->afterStateUpdated(function ($state, callable $set, callable $get) { $blockId = $get('block_name'); $set('shift_id', null); if (!$blockId) { $set('pqBlockError', 'Please select a block first.'); return; } else { $set('validationError', null); $set('pqBlockError', null); } }) ->extraAttributes(fn ($get) => [ 'class' => $get('pqBlockError') ? 'border-red-500' : '', ]) ->hint(fn ($get) => $get('pqBlockError') ? $get('pqBlockError') : null) ->hintColor('danger'), Forms\Components\Select::make('shift_id') ->relationship('shift', 'name') ->required() // ->nullable() ->options(function (callable $get) { if (!$get('plant_id') || !$get('block_name')) { return []; } return \App\Models\Shift::where('plant_id', $get('plant_id')) ->where('block_id', $get('block_name')) ->pluck('name', 'id') ->toArray(); }) ->reactive() ->afterStateUpdated(fn ($set) => $set('line_id', null)) ->afterStateUpdated(function ($state, callable $set, callable $get) { $shiftId = $get('shift_id'); $set('line_id', null); if (!$shiftId) { $set('pqShiftError', 'Please select a shift first.'); return; } else { $set('validationError', null); $set('pqShiftError', null); } }) ->extraAttributes(fn ($get) => [ 'class' => $get('pqShiftError') ? 'border-red-500' : '', ]) ->hint(fn ($get) => $get('pqShiftError') ? $get('pqShiftError') : null) ->hintColor('danger'), Forms\Components\Select::make('line_id') ->relationship('line', 'name') ->required() // ->nullable() // ->options(fn (callable $get) => // \App\Models\Line::where('plant_id', $get('plant_id')) // ->pluck('name', 'id') // ->toArray() // Convert collection to array // ) ->options(function (callable $get) { if (!$get('plant_id') || !$get('block_name') || !$get('shift_id')) { return []; } return \App\Models\Line::where('plant_id', $get('plant_id')) ->pluck('name', 'id') ->toArray(); }) ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $lineId = $get('line_id'); if (!$lineId) { $set('ppLineError', 'Please select a line first.'); return; } else { $set('validationError', null); $set('ppLineError', null); } }) ->extraAttributes(fn ($get) => [ 'class' => $get('ppLineError') ? 'border-red-500' : '', ]) ->hint(fn ($get) => $get('ppLineError') ? $get('ppLineError') : null) ->hintColor('danger'), // Forms\Components\Select::make('item_id') // ->label('Item Code') // ->relationship('item', 'code') // ->required(), // // Forms\Components\TextInput::make('item_code') // // ->required() // // ->autocapitalize('item_code'), // // //->columnSpanFull(), // Virtual field for code input (not stored in DB) Forms\Components\TextInput::make('item_code') ->label('Item Code') // ->required() ->reactive() ->afterStateUpdated(function ($state, callable $get, callable $set) { // **Check if input is empty before processing** if (empty($state)) { $set('item_id', null); $set('item_description', null); $set('serial_number', null); $set('validationError', null); return; } else { if (!$get('plant_id')) { $set('item_code', null); $set('item_id', null); $set('item_description', null); $set('serial_number', null); $set('validationError', 'Please select a plant first.'); return; } else if (!$get('block_name')) { $set('item_code', null); $set('item_id', null); $set('item_description', null); $set('serial_number', null); $set('validationError', 'Please select a block first.'); return; } else if (!$get('shift_id')) { $set('item_code', null); $set('item_id', null); $set('item_description', null); $set('serial_number', null); $set('validationError', 'Please select a shift first.'); return; } else if (!$get('line_id')) { $set('item_code', null); $set('item_id', null); $set('item_description', null); $set('serial_number', null); $set('validationError', 'Please select a line first.'); return; } $set('validationError', null); } if (!preg_match('/^[a-zA-Z0-9]+\|[a-zA-Z0-9]+(\|)?$/', $state)) { $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } // Only search when all parent IDs are selected $parts = explode('|', $state); $itemCode = trim($parts[0]); // Extract item code // 123456|123456789 $serialNumber = isset($parts[1]) ? trim($parts[1]) : null; if (strlen($itemCode) < 6) { $set('validationError', 'Item code must be at least 6 digits.'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } else if (!ctype_alnum($itemCode)) { $set('validationError', 'Item code should contain alpha-numeric values.'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } else if ($serialNumber === '') { $set('validationError', 'Waiting for full QR scan...'); $set('item_description', null); $set('serial_number', null); return; // Do not clear item_id, just wait for full input } else if (strlen($serialNumber) < 9) { $set('validationError', 'Serial Number must be at least 9 digits.'); $set('item_description', null); $set('serial_number', null); return; } else if (!ctype_alnum($serialNumber)) { $set('validationError', 'Serial Number should contain alpha-numeric values.'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } else { $set('validationError', null); } // Fetch item using item code and plant_id $item = \App\Models\Item::where('code', $itemCode) ->where('plant_id', $get('plant_id')) ->first(); if ($item) { $sNo = ProductionQuantity::where('serial_number', $serialNumber) // ->where('plant_id', $get('plant_id')) ->exists(); if (!$sNo) { $set('serial_number', $serialNumber); $set('item_id', $item->id); $set('item_code', $itemCode); //$itemCode $set('item_description', $item->description); } else { $set('validationError', 'Serial number already exist in database.'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } } else { $set('validationError', 'Item code does not exist in master data.'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } }) ->extraAttributes(fn ($get) => [ 'class' => $get('validationError') ? 'border-red-500' : '', ]) ->hint(fn ($get) => $get('validationError') ? $get('validationError') : null) ->hintColor('danger'), Forms\Components\Hidden::make('item_id') ->required(), Forms\Components\TextInput::make('item_description') ->label('Description') ->reactive() ->readOnly(true) ->required(), // Forms\Components\Select::make('item_id') // ->label('Description') // ->relationship('item', 'description') // ->required(), Forms\Components\TextInput::make('serial_number') ->required() ->unique(ignoreRecord: true) ->readOnly(true) ->autocapitalize('serial_number'), //->columnSpanFull(), ]) ->columns(2), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('id') ->label('ID') ->numeric() ->sortable(), Tables\Columns\TextColumn::make('item.code') ->sortable(), Tables\Columns\TextColumn::make('serial_number') ->sortable(), Tables\Columns\TextColumn::make('line.name') ->sortable(), Tables\Columns\TextColumn::make('shift.name') ->sortable(), Tables\Columns\TextColumn::make('plant.name') ->sortable(), Tables\Columns\TextColumn::make('created_at') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('updated_at') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('deleted_at') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->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() ->importer(ProductionQuantityImporter::class), ]); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListProductionQuantities::route('/'), 'create' => Pages\CreateProductionQuantity::route('/create'), 'view' => Pages\ViewProductionQuantity::route('/{record}'), 'edit' => Pages\EditProductionQuantity::route('/{record}/edit'), ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() ->withoutGlobalScopes([ SoftDeletingScope::class, ]); } }