Display custom infolist dynamically in laravel filament

In this article, we are going to explore how can we show infolist dynamically in laravel filament.

Click here to check the visual representation of what we are going to create.

Create a custom page

So, the first step is to create a custom page using the following command:

php artisan make:filament-page FeePaymentPage

Implement HasForms, Hastables

Since, we are having a filter on our page , so we will implement HasForms and HasTables and use their traits.

class FeePaymentPage extends Page implements HasForms, HasActions
{
    use InteractsWithForms, InteractsWithActions;
    protected static string $view = 'filament.admin.pages.fee-payment-page';
    public $learner_id = null;


}

Learn more about filament.

Add your form and tables

If you want to add form and table on your custom page, you can add the required methods and implement the functionality. You can checkout the youtube playlist or our articles for that.

Form Code:

public function form(Form $form): Form
    {
        return $form
            ->schema([
                Section::make()
                    ->schema([
                        Grid::make(3)
                            ->schema([
                                Select::make('class_id')
                                    ->label('Class')
                                    ->options(Classes::all()->pluck('name', 'id'))
                                    ->searchable()
                                    ->required()
                                    ->reactive()
                                    ->afterStateUpdated(function ($state) {
                                        $this->class_id = $state;
                                        $this->stream_id = null;
                                        $this->learner_id = null;
                                        $this->learnerData = null;
                                        $this->resetTable();
                                    }),
                                
                                Select::make('stream_id')
                                    ->label('Stream')
                                    ->options(function (callable $get) {
                                        if (!$get('class_id')) {
                                            return [];
                                        }
                                        
                                        return Stream::where('class_id', $get('class_id'))
                                            ->pluck('name', 'id');
                                    })
                                    ->searchable()
                                    ->visible(fn (callable $get) => $get('class_id'))
                                    ->reactive()
                                    ->afterStateUpdated(function ($state) {
                                        $this->stream_id = $state;
                                        $this->learner_id = null;
                                        $this->learnerData = null;
                                        $this->resetTable();
                                    }),
                                
                                Select::make('learner_id')
                                    ->label('Student')
                                    ->options(function (callable $get) {
                                        if (!$get('stream_id')) {
                                            return [];
                                        }
                                        
                                        return Learner::where('stream_id', $get('stream_id'))
                                            ->get()
                                            ->pluck('name', 'id');
                                    })
                                    ->searchable()
                                    ->visible(fn (callable $get) => $get('stream_id'))
                                    ->reactive()
                                    ->afterStateUpdated(function ($state) {
                                        $this->learner_id = $state;
                                        $this->loadLearnerData();
                                        $this->resetTable();
                                    }),
                            ]),
                    ])
                    ->columnSpan('full'),
            ]);
    }

   public function loadLearnerData(): void
    {
        if (!$this->learner_id) {
            return;
        }

        $this->learnerData = Learner::with(['stream', 'stream.class',"financialProfile"])->find($this->learner_id);
    }

Table

    public function table(Table $table): Table
    {
        return $table
            ->query(function () {
                if (!$this->learner_id) {
                    return Transaction::query()->whereNull('id'); // Empty query if no learner selected
                }
                
                $query = Transaction::query()
                    ->where('learner_id', $this->learner_id)
                    ->where('transaction_type',Transaction::DEBIT);
                
                return $query;
            })
            ->columns([
                TextColumn::make('transaction_date')
                    ->label('Date')
                    ->date('d/m/Y')
                    ->sortable(),

                TextColumn::make('feeStructure.name')
                    ->label('Fee Structure')
                    ->searchable(),

                TextColumn::make('feeCategory.name')
                    ->label('Fee Category')
                    ->searchable(),

                TextColumn::make('amount')
                    ->label('Amount')
                    ->sortable()
                    ->badge(),

                BadgeColumn::make('status')
                    ->colors([
                        'warning' => 'Pending',
                        'success' => 'Completed',
                        'danger' => 'Failed',
                    ]),
                TextColumn::make('payment_method')
                    ->label('Payment Method'),
                TextColumn::make('remarks')
                    ->label('Remarks')
                    ->limit(20),
            ])
            ->filters([
                SelectFilter::make('status')
                    ->default(Transaction::PENDING_STATUS)
                    ->options([
                        'Pending' => 'Pending',
                        'Completed' => 'Completed',
                        'Failed' => 'Failed',
                    ]),
                SelectFilter::make('transaction_type')
                    ->options([
                        'Debit' => 'Debit',
                        'Credit' => 'Credit',
                    ]),
            ])
            ->actions([
               
            ])
            ->bulkActions([])
            ->emptyStateHeading('No transactions found')
            ->emptyStateDescription('Select a student to view their transactions.')
            ->poll('60s');
    }

Modify your blade component to use form, table and your dynamic custom infolist

<x-filament-panels::page>
    <div>
        {{ $this->form }}
    </div>

    @if($learnerData)
        <div class="mt-8 rounded-xl shadow p-6">
            <h2 class="text-xl font-bold mb-4">Student Information</h2>
            <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
                <div>
                    <h3 class="text-gray-500 font-medium">Name</h3>
                    <p class="text-lg">{{ $learnerData->name }}</p>
                </div>
                <div>
                    <h3 class="text-gray-500 font-medium">Class</h3>
                    <p class="text-lg">{{ $learnerData->stream?->class?->name }}</p>
                </div>
                <div>
                    <h3 class="text-gray-500 font-medium">Stream</h3>
                    <p class="text-lg">{{ $learnerData->stream?->name }}</p>
                </div>
                <div>
                    <h3 class="text-gray-500 font-medium">Total Outstandings</h3>
                    <p class="text-lg">{{ $learnerData->financialProfile?->current_outstanding_balance }}</p>
                </div>
            </div>
        </div>
    @endif
    <div class="mt-8">
        {{ $this->table }}
    </div>
    </x-filament:pages>

So , in this way you can create a dynamic infolist page on your custom page.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top