schema([ Forms\Components\Select::make('plant_id') ->relationship('plant', 'name') ->reactive() ->nullable() ->options(function (callable $get) { $userHas = Filament::auth()->user()->plant_id; return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray(); }) ->default(function () { return optional(StickerMaster::latest()->first())->plant_id; }) ->disabled(fn (Get $get) => ! empty($get('id'))) // disable in edit if user try to change ->afterStateUpdated(fn (callable $set) => $set('item_id', null) & // when plant changed remove all the data which is in text input box $set('item_description', null) & $set('item_error', null) & $set('panel_box_code', null) & $set('load_rate', null) & $set('bundle_quantity', null) & $set('material_type', null) & $set('part_validation1', null) & $set('part_validation2', null) & $set('part_validation3', null) & $set('part_validation4', null) & $set('part_validation5', null) & $set('laser_part_validation1', null) & $set('laser_part_validation2', null) & $set('serial_number_motor', false) & $set('serial_number_pump', false) & $set('serial_number_pumpset', false) & $set('pack_slip_motor', false) & $set('pack_slip_pump', false) & $set('pack_slip_pumpset', false) & $set('name_plate_motor', false) & $set('name_plate_pump', false) & $set('name_plate_pumpset', false) & $set('tube_sticker_motor', false) & $set('tube_sticker_pump', false) & $set('tube_sticker_pumpset', false) & $set('warranty_card', false) ) ->required(), Forms\Components\Select::make('item_id') ->label('Item Code') ->options(function (callable $get) { if (! $get('plant_id')) { return []; } return \App\Models\Item::where('plant_id', $get('plant_id')) ->pluck('code', 'id') ->toArray(); }) // ->rule(function (callable $get) { // return Rule::unique('items', 'code') // ->where('plant_id', $get('plant_id')) // ->ignore($get('id')); // Ignore current record during updates // }) ->required() ->nullable() ->searchable() ->reactive() // ->disabled(fn (Get $get) => !empty($get('id'))) ->live(debounce: 500) // Enable live updates ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant_id'); $itemId = $get('item_id'); // If plant_id is changed or empty, reset everything if (blank($plantId)) { $set('item_id', null); $set('item_error', null); $set('item_description', null); return; } if (blank($itemId)) { $set('item_error', null); $set('item_description', null); return; } $availableItems = \App\Models\Item::where('plant_id', $plantId)->exists(); if (! $availableItems) { $set('item_error', null); return; } // Ensure `item_id` is not cleared if (! $plantId || ! $itemId) { $set('item_description', null); return; } // Check if item exists for the selected plant $item = \App\Models\Item::where('plant_id', $plantId) ->where('id', $itemId) ->first(); if ($item) { $set('item_description', $item->description); } else { $set('item_description', null); } $duplicateSticker = StickerMaster::where('plant_id', $plantId) ->where('item_id', $itemId) ->exists(); if (! $get('id')) { $set('item_error', $duplicateSticker ? 'Item Code already exists for the selected plant.' : null); } }) ->extraAttributes(fn ($get) => [ 'class' => $get('item_error') ? 'border-red-500' : '', ]) ->hint(fn ($get) => $get('item_error') ? $get('item_error') : null) ->hintColor('danger'), Forms\Components\TextInput::make('item_description') ->label('Description') ->required() ->afterStateHydrated(function ($component, $state, Get $get, Set $set) { if ($get('id')) { $itemId = StickerMaster::where('id', $get('id'))->first()?->item_id; if ($itemId) { $item = \App\Models\Item::where('id', $itemId)->first()?->description; if ($item) { $set('item_description', $item); } else { $set('item_description', null); } } else { $set('item_description', null); } } }) ->reactive() ->readOnly(true), Forms\Components\TextInput::make('part_validation1') ->label('Part Validation 1') ->nullable(), Forms\Components\TextInput::make('part_validation2') ->label('Part Validation 2') ->nullable(), Forms\Components\TextInput::make('part_validation3') ->label('Part Validation 3') ->nullable(), Forms\Components\TextInput::make('part_validation4') ->label('Part Validation 4') ->nullable(), Forms\Components\TextInput::make('part_validation5') ->label('Part Validation 5 (Capacitor QR)') ->nullable(), Forms\Components\TextInput::make('laser_part_validation1') ->label('Laser Part Validation 1') ->nullable(), Forms\Components\TextInput::make('laser_part_validation2') ->label('Laser Part Validation 2') ->nullable(), Forms\Components\TextInput::make('panel_box_code') ->label('Panel Box Code') ->readOnly(fn (callable $get) => $get('material_type')) ->nullable(), Forms\Components\TextInput::make('load_rate') ->label('Load Rate') ->default(0) ->required() ->disabled(function ($get) { return $get('material_type'); }) ->integer(), Forms\Components\Select::make('material_type') ->label('Material Type') ->options([ '1' => 'Individual', '2' => 'Bundle', '3' => 'Quantity', ]) ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($state) { $set('panel_box_code', null); $set('load_rate', 0); } if ($state !== '2') { $set('bundle_quantity', null); } else { $set('bundle_quantity', 2); } // $plantId = $get('plant_id'); }) ->nullable(), Forms\Components\TextInput::make('bundle_quantity') ->label('Bundle Quantity') ->integer() ->readOnly(fn (callable $get) => $get('material_type') !== '2') ->nullable() ->minValue(2) ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('material_type') !== '2') { $set('bundle_quantity', null); } elseif ($get('bundle_quantity') < 2) { $set('bundle_quantity', 2); } }), Forms\Components\Checkbox::make('serial_number_motor') ->reactive() // ->disabled(function ($get) { // return $get('serial_number_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('serial_number_motor')) { $set('serial_number_pumpset', false); } }) ->dehydrateStateUsing(fn ($state): mixed => $state ? $state : null), Forms\Components\Checkbox::make('serial_number_pump') ->reactive() // ->disabled(function ($get) { // return $get('serial_number_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('serial_number_pump')) { $set('serial_number_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('serial_number_pumpset') ->reactive() // ->disabled(function ($get) { // return $get('serial_number_motor') || $get('serial_number_pump'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('serial_number_pumpset')) { $set('serial_number_motor', false); $set('serial_number_pump', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('pack_slip_motor') ->reactive() // ->disabled(function ($get) { // return $get('pack_slip_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('pack_slip_motor')) { $set('pack_slip_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('pack_slip_pump') ->reactive() // ->disabled(function ($get) { // return $get('pack_slip_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('pack_slip_pump')) { $set('pack_slip_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('pack_slip_pumpset') ->reactive() // ->disabled(function ($get) { // return $get('pack_slip_motor') || $get('pack_slip_pump'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('pack_slip_pumpset')) { $set('pack_slip_motor', false); $set('pack_slip_pump', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('name_plate_motor') ->reactive() // ->disabled(function ($get) { // return $get('name_plate_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('name_plate_motor')) { $set('name_plate_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('name_plate_pump') ->reactive() // ->disabled(function ($get) { // return $get('name_plate_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('name_plate_pump')) { $set('name_plate_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('name_plate_pumpset') ->reactive() // ->disabled(function ($get) { // return $get('name_plate_motor') || $get('name_plate_pump'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('name_plate_pumpset')) { $set('name_plate_motor', false); $set('name_plate_pump', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('tube_sticker_motor') ->reactive() // ->disabled(function ($get) { // return $get('tube_sticker_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('tube_sticker_motor')) { $set('tube_sticker_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('tube_sticker_pump') ->reactive() // ->disabled(function ($get) { // return $get('tube_sticker_pumpset'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('tube_sticker_pump')) { $set('tube_sticker_pumpset', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\Checkbox::make('tube_sticker_pumpset') ->nullable() ->reactive() // ->disabled(function ($get) { // return $get('tube_sticker_motor') || $get('tube_sticker_pump'); // }) ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($get('tube_sticker_pumpset')) { $set('tube_sticker_motor', false); $set('tube_sticker_pump', false); } }) ->dehydrateStateUsing(fn ($state) => $state ? $state : null), // to pass null value Forms\Components\Checkbox::make('warranty_card') ->nullable() ->dehydrateStateUsing(fn ($state) => $state ? $state : null), Forms\Components\TextInput::make('id') ->hidden() ->readOnly(), ]); } public static function table(Table $table): Table { return $table ->columns([ // Tables\Columns\TextColumn::make('id') // ->label('ID') // ->numeric() // ->sortable(), 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('plant.name') ->label('Plant') ->alignCenter() ->sortable() ->searchable(), Tables\Columns\TextColumn::make('item.code') ->label('Item Code') ->alignCenter() ->sortable() ->searchable(), Tables\Columns\CheckboxColumn::make('serial_number_motor') ->label('Serial Number Motor') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('serial_number_pump') ->label('Serial Number Pump') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('serial_number_pumpset') ->label('Serial Number Pumpset') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('pack_slip_motor') ->label('Pack Slip Motor') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('pack_slip_pump') ->label('Pack Slip Pump') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('pack_slip_pumpset') ->label('Pack Slip Pumpset') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('name_plate_motor') ->label('Name Plate Motor') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('name_plate_pump') ->label('Name Plate Pump') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('name_plate_pumpset') ->label('Name Plate Pumpset') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('tube_sticker_motor') ->label('Tube Sticker Motor') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('tube_sticker_pump') ->label('Tube Sticker Pump') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('tube_sticker_pumpset') ->label('Tube Sticker Pumpset') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\CheckboxColumn::make('warranty_card') ->label('Warranty Card') ->disabled(true) ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('part_validation1') ->label('Part Validation 1') ->alignCenter(), Tables\Columns\TextColumn::make('part_validation2') ->label('Part Validation 2') ->alignCenter(), Tables\Columns\TextColumn::make('part_validation3') ->label('Part Validation 3') ->alignCenter(), Tables\Columns\TextColumn::make('part_validation4') ->label('Part Validation 4') ->alignCenter(), Tables\Columns\TextColumn::make('part_validation5') ->label('Part Validation 5') ->alignCenter(), Tables\Columns\TextColumn::make('laser_part_validation1') ->label('Laser Part Validation 1') ->alignCenter(), Tables\Columns\TextColumn::make('laser_part_validation2') ->label('Laser Part Validation 2') ->alignCenter(), Tables\Columns\TextColumn::make('panel_box_code') ->label('Panel Box Code') ->alignCenter(), Tables\Columns\TextColumn::make('load_rate') ->label('Load Rate') ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('bundle_quantity') ->label('Bundle Quantity') ->alignCenter(), Tables\Columns\TextColumn::make('material_type') ->label('Material Type') ->alignCenter() ->formatStateUsing(function ($state) { if (is_null($state) || $state === '') { return ''; } return match ($state) { 1 => 'Individual', 2 => 'Bundle', 3 => 'Quantity', default => '', }; }), Tables\Columns\TextColumn::make('created_at') ->label('Created At') ->dateTime() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('updated_at') ->label('Updated At') ->dateTime() ->alignCenter() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('deleted_at') ->label('Deleted At') ->dateTime() ->alignCenter() ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) // ->filters([ // Tables\Filters\TrashedFilter::make(), // ]) ->filters([ Tables\Filters\TrashedFilter::make(), Filter::make('advanced_filters') ->label('Advanced Filters') ->form([ Select::make('Plant') ->label('Select Plant') ->nullable() ->options(function (callable $get) { $userHas = Filament::auth()->user()->plant_id; return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->orderBy('code')->pluck('name', 'id')->toArray() : Plant::orderBy('code')->pluck('name', 'id')->toArray(); }) ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get): void { $set('item_id', null); $set('operator_id', null); }), Select::make('item_id') ->label('Search by Item Code') ->nullable() // ->options(function (callable $get) { // $plantId = $get('Plant'); // return $plantId // ? Item::where('plant_id', $plantId)->pluck('code', 'id') // : Item::pluck('code', 'id'); // }) ->options(function (callable $get) { $plantId = $get('Plant'); return $plantId ? Item::where('plant_id', $plantId)->pluck('code', 'id') : []; }) ->searchable() ->reactive(), Select::make('material_type') ->label('Material Type') ->options([ 1 => 'Individual', 2 => 'Bundle', 3 => 'Quantity', ]) ->reactive(), TextInput::make('panel_box_code') ->label('Panel Box Code') ->placeholder(placeholder: 'Enter Panel Box Code'), DateTimePicker::make(name: 'created_from') ->label('Created From') ->placeholder(placeholder: 'Select From DateTime') ->reactive() ->native(false), DateTimePicker::make('created_to') ->label('Created To') ->placeholder(placeholder: 'Select To DateTime') ->reactive() ->native(false), ]) ->query(function ($query, array $data) { // Hide all records initially if no filters are applied if ( empty($data['Plant']) && empty($data['item_id']) && empty($data['material_type']) && empty($data['panel_box_code']) && empty($data['created_from']) && empty($data['created_to']) ) { return $query->whereRaw('1 = 0'); } if (! empty($data['Plant'])) { // $plant = $data['Plant'] ?? null $query->where('plant_id', $data['Plant']); } if (! empty($data['item_id'])) { $query->where('item_id', $data['item_id']); } if (! empty($data['material_type'])) { $query->where('material_type', $data['material_type']); } if (! empty($data['panel_box_code'])) { $query->where('panel_box_code', 'like', '%'.$data['panel_box_code'].'%'); } if (! empty($data['created_from'])) { $query->where('created_at', '>=', $data['created_from']); } if (! empty($data['created_to'])) { $query->where('created_at', '<=', $data['created_to']); } }) ->indicateUsing(function (array $data) { $indicators = []; if (! empty($data['Plant'])) { $indicators[] = 'Plant: '.Plant::where('id', $data['Plant'])->value('name'); } if (! empty($data['item_id'])) { $indicators[] = 'Item Code: '.Item::where('id', $data['item_id'])->value('code'); } if (! empty($data['material_type'])) { if ($data['material_type'] == 1) { $indicators[] = 'Material Type: Individual'; } elseif ($data['material_type'] == 2) { $indicators[] = 'Material Type: Bundle'; } elseif ($data['material_type'] == 3) { $indicators[] = 'Material Type: Quantity'; } // $indicators[] = 'Material Type: '.$data['material_type']; } if (! empty($data['panel_box_code'])) { $indicators[] = 'Panel Box Code: '.$data['panel_box_code']; } if (! empty($data['created_from'])) { $indicators[] = 'From: '.$data['created_from']; } if (! empty($data['created_to'])) { $indicators[] = 'To: '.$data['created_to']; } return $indicators; }), ]) ->filtersFormMaxHeight('280px') ->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([ Tables\Actions\Action::make('upload_part_validation_image') ->label('Upload Part Validation Image') ->form([ Select::make('plant_id') ->options(function (callable $get) { $userHas = Filament::auth()->user()->plant_id; return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray(); }) ->label('Select Plant') ->required() ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('item_id', null); $set('part_validation_upload', null); }) ->reactive(), Select::make('item_id') ->options(function (callable $get) { $plantId = $get('plant_id'); if (! $plantId) { return []; } return StickerMaster::where('plant_id', $plantId) ->where(function ($q) { $q->whereNotNull('part_validation1') ->orWhereNotNull('part_validation2') ->orWhereNotNull('part_validation3') ->orWhereNotNull('part_validation4'); }) ->with('item') ->get() ->pluck('item.code', 'item_id') ->toArray(); }) ->label('Item Code') ->required() ->searchable() ->afterStateUpdated(fn ($state, callable $set) => $set('part_validation_upload', null)) ->reactive(), Select::make('validation_type') ->label('Select Validation') ->options(function (callable $get) { $plantId = $get('plant_id'); $itemId = $get('item_id'); if (! $plantId || ! $itemId) { return []; } $sticker = StickerMaster::where('plant_id', $plantId) ->where('item_id', $itemId) ->first(); if (! $sticker) { return []; } $options = []; if (! empty($sticker->part_validation1)) { $options['part_validation1'] = 'Part Validation 1'; } if (! empty($sticker->part_validation2)) { $options['part_validation2'] = 'Part Validation 2'; } if (! empty($sticker->part_validation3)) { $options['part_validation3'] = 'Part Validation 3'; } if (! empty($sticker->part_validation4)) { $options['part_validation4'] = 'Part Validation 4'; } // if (!empty($sticker->part_validation5)) { // $options['part_validation5'] = 'Part Validation 5'; // } return $options; }) ->reactive() ->required(), FileUpload::make('part_validation_upload') ->label('Part Validation Upload') // ->required() ->preserveFilenames() // <- this keeps the original filename ->storeFiles(false) // prevent auto-storing, we will store manually ->reactive() ->required() ->disk('local') // 'local' refers to the local storage disk defined in config/filesystems.php, typically pointing to storage/app. ->visible(fn (Get $get) => ! empty($get('plant_id'))) ->directory('uploads/PartValidation'), ]) ->action(function (array $data) { $uploadedFile = $data['part_validation_upload']; $plantId = $data['plant_id']; $itemId = $data['item_id']; $column = $data['validation_type']; $plant = Plant::find($plantId); $plantCode = $plant->code; $sticker = StickerMaster::where('plant_id', $plantId) ->where('item_id', $itemId) ->first(); if (! $sticker) { Notification::make() ->title('Unknown Sticker Master') ->body('Sticker Master data not found.') ->danger() ->seconds(2) ->send(); } $value = $sticker->{$column}; if (empty($value)) { Notification::make() ->title('Unknown Part validation') ->body("Selected validation '$column' has no value.") ->danger() ->seconds(2) ->send(); } $newFileName = $value.'.png'; $directory = "uploads/PartValidation/{$plantCode}"; $disk = Storage::disk('local'); if (! $disk->exists($directory)) { $disk->makeDirectory($directory, 0755, true); } // $path = $uploadedFile->storeAs( // $directory, // $newFileName, // 'local' // ); try { $path = $uploadedFile->storeAs( $directory, $newFileName, 'local' ); } catch (\Exception $e) { Notification::make() ->title('Upload Failed') ->body('Failed to upload image: '.$e->getMessage()) ->danger() ->seconds(3) ->send(); return; } $fullPath = Storage::disk('local')->path($path); Notification::make() ->title('Success') ->body('Uploaded part validation image successfully') ->success() ->seconds(2) ->send(); }) ->visible(function () { return Filament::auth()->user()->can('view import part validation'); }), ImportAction::make() ->label('Import Sticker Masters') ->color('warning') ->importer(StickerMasterImporter::class) ->visible(function () { return Filament::auth()->user()->can('view import sticker master'); }), ExportAction::make() ->label('Export Sticker Masters') ->color('warning') ->exporter(StickerMasterExporter::class) ->visible(function () { return Filament::auth()->user()->can('view export sticker master'); }), ]); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListStickerMasters::route('/'), 'create' => Pages\CreateStickerMaster::route('/create'), 'view' => Pages\ViewStickerMaster::route('/{record}'), 'edit' => Pages\EditStickerMaster::route('/{record}/edit'), ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() ->withoutGlobalScopes([ SoftDeletingScope::class, ]); } }