Vamos conhecer o Filament, um conjunto de modulos com muitos componentes que irão acelerar o desenvolvimento de nossas aplicações web. O Filament se baseia na
TallStack (TailWindCSS,AlpineJS,Laravel,Livewire) e neste projeto vamos desenvolver um projeto de clinica de exemplo da documentação e adicionar novas funcionalidades.
⭐ Este sistema de exemplo irá abordar o primeiro exemplo que a próprio documentação do
Filamentdemosntra e também irei adicionar novas funcionalidades para melhor aprendizado e melhorar o sistema. Obs.: Toda codificação e exeplicações do exemplo que a documentação apresenta, não irei descrever.
Exemplo | Filament: 🌟 Sera a construção de um sistema simples de clínica veterinária e com novas funcionalidades descritas abaixo, terá gerenciamento de pacientes para uma clínica veterinária usando o Filament. Apoiará a adição de novospacientes(gatos, cães ou coelhos), atribuindo-os a umproprietárioe registrando quaistratamentoseles receberam. O sistema terá um painel com estatísticas sobre os tipos de pacientes e um gráfico com a quantidade de tratamentos administrados no último ano.
🌟 Continuando a construção do sistema da clínica, vamos adicionar novas funcionalidades, com um blog, que terá uma lista de
posts(notícias) com seus devidos autores, onde teremos associações decategorias,comentáriose replicas de comentários dosusuários. E por fim também terá a adição lista deprodutosque a clínica terá em seu estoque com associação a categorias.
🔔 No sistema da clínica, vamos poder verificar em cada view, suas associações conforme o Filament disponibiliza com o gerenciamento das categorias, comentários, posts, pacientes, etc.
php artisan make:model Inventory -m
php artisan make:model Poost -m
php artisan make:model Category -m
💬 Propriedades das Migrations documentação laravel migrations table
Vou demonstrar duas formas de relacionamento na migration, com os
exemplosem Inventories e Post e suas associações com Categoria.
    Schema::create('inventories', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('description');
`        $table->string('image');
        $table->integer('quantity');
        $table->foreignIdFor(\App\Models\Category::class);
        $table->timestamps();
    });
    Schema::create('categories', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('slug')->unique();
        $table->timestamps();
    });
- 🔔 Se não tem certeza com a chave, 
category_idou qualquer outra chave, podemos usar a funçãoforeignIdFore passar a classe Eloquent, que automaticamente irá criar a coluna com onome da classee_id. 
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('thumbnail')->nullable();
        $table->string('title');
        $table->string('color');
        $table->string('slug')->unique();
        $table->foreignId('category_id')->constrained()->cascadeOnDelete();
        $table->text('content')->nullable();
        $table->json('tags')->nullable();
        $table->boolean('published')->default(false);
        $table->timestamps();
    });
php artisan make:migration alter_inventory_table_add_active_column --table=inventories
    Schema::table('inventories', function (Blueprint $table) {
        $table->boolean('active')->default(true);
    });
Estes são os metodos de relacionamento que iremos utilizar na relação HasMany (1-1 & 1-M)
    //Inventory and Post
    public function category()
    {
        return $this->belongsTo(Category::class);
    }
    //Category
    public function products()
    {
        return $this->hasMany(Inventory::class);
    }
Para que a imagem do produto apareça de forma correta, temos que ativa o
storage linke modificar logo apos no arquivo.ENVa linha deAPP_URLpara receber a base do app=http://127.0.0.1:8000.
    php artisan storage:link
    FileUpload::make('thumbnail')
        ->disk('public')
        ->directory('thumbnails')->columnSpanFull(),
Vamos utilizar dois dos vários comandos que o Filament disponibiliza filament-resource e filament-relation-manager.
- 💥 make:filament-relation-manager  ✔️ O Filament permite que possamos gerenciar relacionamentos em nosso app. | documentation
- Os relacionamentos que podem ser gerenciados são 
HasMany,HasManyThrough,BelongsToMany,MorphManyeMorphToMany. 
✔️ Os gerenciadores de relacionamento são tabelas interativas que permitem aos administradores listar, criar, anexar, associar, editar, desanexar, dissociar e excluir registros relacionados sem sair da página Editar ou Visualizar do recurso.
 - Os relacionamentos que podem ser gerenciados são 
 - 💥 make:filament-resource          ✔️ Cria o arquivo de 
resourcesdo seu modelo em App/Filament e cria toda estrutura das classes padrão.- Qualquer 
modelque você criar em seu projeto laravel, podemos criar os Filaments em nosso projeto e ter páginas ou modais. 
 - Qualquer 
 
Criando as classes views completas| O generate irá add todas propriedades da sua migrate, criando páginas para seu projeto.
php artisan make:filament-resource Inventory --generate
php artisan make:filament-resource Post --generate
php artisan make:filament-resource User --generate
Opção: Você pode criar de forma simples, views
simplificadas com MODAIsno lugar de um página, como editar ou criar.
php artisan make:filament-resource Inventory --simple --generate
Com os metodos de relacionamento criados nos models BelongsTo e HasMany, vamos add na view de InventoryResource,
o relacionamento relationship e ele tem dois argumentos.
O primeiro argumento é o nome do metodo no modelo e segundo a proriedade que mostra.
   Select::make('category_id')->relationship('category', 'name')
Para adiconar este gerenciador, utilizamos o comando abaixo e mais agluns argumentos como qual resource você quer gerenciar,
(Ex.: CategoryResource), segundo é o nome do relacionamento em sua model (Ex.: posts) e por último qual propriedade da model quer usar (title).
php artisan make:filament-relation-manager CategoryResource posts title
O filament irá criar um outro diretorio em App/Filament/Resources/CategoryResource/RelaionManagers. chamado de PostsRelationManager.php. Esta mesma é o complemento da categoria, mostrando os relacionamentos que a categoria tem com seus posts, mas antes disso, como a propria documentação do Filament informa, precisamos dizer qual seu relacionament no metodo getRelations da CategoryResource.
    public static function getRelations(): array
    {
        return [
            RelationManagers\PostsRelationManager::class
        ];
    }
🔔 Validation | documentation
Abaixo um exemplo dos diversos metodos de validação dedicados que o Filament inclui, mas você também pode usar
quaisquer outras regras de validação do Laravel, incluindo regras de validação personalizadas.
    TextInput::make('title')->required()
        ->alpha()
        ->doesntStartWith(['admin'])
        ->rules(['min:3|max:30', 'alpha'])
        ->in(['test', 'hello'])
Algo interessante que o Filament nos proporciona, é poder adiconar outras regras de validação proprias ou usar as validações que o proprio laravel disponibiliza | documentation.
Nesta relação vamos ter uma tabela pivo que irá guardar os IDs de relação entre User e Post, assim vamos poder
visualizar e gerenciar quais autores temos em cada postagem. E aqui vamos criar a relação, que terá como ser definida no
formulário de criação do post, mas também vamos criar o gerenciamento que o Filament permite criar.
    Schema::create('post__users', function (Blueprint $table) {
        $table->id();
        $table->foreignIdFor(\App\Models\Post::class);
        $table->foreignIdFor(\App\Models\User::class);
        $table->timestamps();
    });
    //USER
    public function posts()
    {
        return $this->belongsToMany(Post::class, 'post__users')->withTimestamps();
    }
    //POST
    public function authors()
    {
        return $this->belongsToMany(User::class, 'post__users')->withTimestamps();
    }
💬 Em PostResource teremos duas formas de mostrar, multiple com multiplos autores (Array) e CheckboxList autores.
        Select::make('authors casa')
            ->label('Autores')
            ->multiple()
            ->preload()
            ->relationship('authors', 'name'),
        Forms\Components\CheckboxList::make('authors casa')
            ->label('Autores')
            ->searchable()
            ->relationship('authors', 'name'),
Agora vamos ao filament-relation-manager onde vamos criar o gerenciamento dos autores dos post, onde
vamos poder adicionar novos autores ou vincular autores já cadastrados.
    php artisan make:filament-relation-manager PostResource authors name
    public static function getRelations(): array
    {
        return [
            RelationManagers\AuthorsRelationManager::class
        ];
    }
Coluna adicionada na migrate pivo post
    $table->integer('nota')->default(0);
- php artisan migrate:refresh --step=1
 
    //Post e User add.
    public function authors()
    {
        return $this->belongsToMany(User::class, 'post__users')->withPivot('nota')->withTimestamps();
    }
->headerActions([
    Tables\Actions\AttachAction::make()
        ->form(fn (AttachAction $action): array => [
        $action->getRecordSelect(),
        Forms\Components\TextInput::make('nota')->required(),
    ]),
])
💬 No relacionamentos polimórficos vamos lidar com o relacionamento de 1 para 1 e 1 para muitos e o gerenciador de relacionamento.
Alguns links de estudo que utilizei para aprendizado e desenvolvimento.
    //Add migrate
    php artisan make:model Comment -m
    //Property in migrate comments
    Schema::create('comments', function (Blueprint $table) {
        $table->id();
        $table->foreignIdFor(\App\Models\User::class);
        $table->morphs('comentable');
        $table->string('comment');
        $table->timestamps();
    });
    php artisan make:filament-resource Comment
🔔 Aqui, criaremos um modelo de tabela de Comment, User e Post. também usaremos "morphMany()" e "morphTo()" para relacionamento de ambos os modelos.
    //Comment
    public $guarded = ['id'];
    
    /**
    * Comment
    * Obtenha todos os modelos comentáveis.
    */
    public function commentable()
    {
        return $this->morphTo();
    }
    public function user()
    {
        return $this->belongsTo(User::class);
    }
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
    /**
    * User e Post
    * Obtenha todos os comentários.
    */
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
💬 No form passamos o relationship, comment e o MorphToSelect.
💬 MorphToSelect: Passamos em make o nome definido na migrate comment $table->morphs('commentable').
:speech_balloon: types: Definimos um array, com quais recursos ou modelos podemos usar no relacionamento.
No types teremos comentários em Postagens, usuários e em outros comentários.
    //FORM
    Select::make('user_id')->relationship('user', 'name')->searchable()->preload(),
    TextInput::make('comment'),
    MorphToSelect::make('commentable')
        ->label('Tipo de comentários')
        ->types([
            Type::make(Post::class)->titleAttribute('title'),
            Type::make(User::class)->titleAttribute('email'),
            Type::make(Comment::class)->titleAttribute('id'),
        ])
        ->searchable()->preload()
    //TABLE
    ->columns([
        Tables\Columns\TextColumn::make('commentable_id'),
        Tables\Columns\TextColumn::make('commentable_type'),
        Tables\Columns\TextColumn::make('comment'),
    ])
💬 Depois de filament-relation-manager, primeiro argumento a classe que terá o gerenciador Post e
segundo o nome do metodo que faz o relacionamento mophMany e último é o identificador dos comentários commentable.
    php artisan make:filament-relation-manager Post comments commentable
💬 Depois, basta definir o gerenciamento a relação em getRelations do PostResource e CommentResource.
💬 Aqui alguns recursos do Filament que achei interessante demonstrar, mas você pode verificar melhor na
documentação do Filament.
Alguns detalhes/Dicas de GRIDs Groups, Sections com columns e columnSpans.
    
    return $form->schema([
        RichEditor::make('content')->columnSpan(3) //ou 'full' ou ->columnSpanFull()
    ])->columns(3),
    Forms\Components\Grid::make()->schema([
        //...
    ])->columns(2),
    
    //Forms
    return $form
            ->schema([
                Section::make('Dados básicos da postagem')
                    ->description('Criação de postagem')
                    ->collapsible()
                    ->schema([
                    //..
                ])->columnSpan(1)->columns(2),
                Section::make('description')
                    ->schema([
                    //...
                ])->columnSpan(1)->columns(2),
    ])->columns([
          'default'   => 1,
          'md'        => 2,
          'lg'        => 2,
          'xl'        => 2,
      ]);
Com o
collapsible()podemos fazer com que uma seção seja recolhida, usando o collapsed atributo. Omake("...")edescription("...")são titulo e subtitulo easide()se adicionado, podemos alinha a div a esquerda.
As Guias ou "Tabs", ajuda muito no front, por oferecer uma exibição de diversas telas em uma única guia.
    Forms\Components\Tabs::make('Criar novo post')->tabs([
        Forms\Components\Tabs\Tab::make('Image data')->icon('heroicon-m-inbox')->schema([
            //...
        ]),
    
        Forms\Components\Tabs\Tab::make('Conteudo')->icon('heroicon-m-inbox')->schema([
            //...
        ])
    ])->columnSpanFull()->activeTab(1)->persistTabInQueryString(),
💬 Link docs. Guias em tabelas de listas personalizadas. Ex. Em Filament\Resources\PostResource\Pages\ListPosts
    public function getTabs(): array
    {
        return [
            'Todos'     => Tab::make(),
            'Ativos'    => Tab::make()->modifyQueryUsing(function (Builder $query){
                $query->where('published', true);
            }),
            'inativos'  => Tab::make()->modifyQueryUsing(function (Builder $query){
                $query->where('published', false);
            })
        ];
    }
Na tabela podemos adicionar filtros para todos tipos de propriedades que temos em nosso projeto e aqui vai dois exemplos.
Filteraborda a propriedade booleana para ativos e não e aTernaryFilteraborda da mesma forma, mas simplificada. E aSelectFiltertemos o filtro por categoria utilizando o relacionamento.
    ->filters([
        Filter::make('Posts ativos')->query(
            function (Builder $query): Builder {
                return $query->where('published', true);
            }
        ),
        TernaryFilter::make('published')->label('Filtro por publicados ou não')->default(true),
        SelectFilter::make('category_id')->label('Categorias')
            ->relationship('category', 'name')->preload()
            ->multiple()
    ])
php artisan make:filament-widget PatientTypeOverview --stats-overview
php artisan make:filament-widget TreatmentsChart --chart
composer require flowframe/laravel-trend
💬 Authorization | Policy Filament.
💬 De acordo com a documentação Laravel (10.x), Políticas são classes que organizam a lógica de autorização
em torno de um modelo ou recurso específico. E o Filament se utiliza de todas Polices criada juntamente com os metodos padrões criados no comando abaixo e com outros metodos.
💬 Cria a policy de Post e os metodos (--model=Category) exemplo de CRUD da policy.
    php artisan make:policy CategoryPolicy --model=Category
💬 Se quiser ignorar a autorização de um recurso, você pode definir a $shouldSkipAuthorizationpropriedade como true:
    protected static bool $shouldSkipAuthorization = true;
Contatos 👇🏼 [[email protected]]
