Skip to content

Commit 0adffa9

Browse files
cybersoldattechChri$
and
Chri$
authored
feat:[LAR-32] Add article list with action in cpanel (#160)
Co-authored-by: Chri$ <[email protected]>
1 parent bef79c0 commit 0adffa9

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed
+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Filament\Resources;
6+
7+
use App\Filament\Resources\ArticleResource\Pages;
8+
use App\Models\Article;
9+
use Filament\Resources\Resource;
10+
use Filament\Tables;
11+
use Filament\Tables\Actions\Action;
12+
use Filament\Tables\Actions\ActionGroup;
13+
use Filament\Tables\Actions\BulkAction;
14+
use Filament\Tables\Columns\TextColumn;
15+
use Filament\Tables\Filters\Filter;
16+
use Filament\Tables\Table;
17+
use Illuminate\Database\Eloquent\Builder;
18+
use Illuminate\Database\Eloquent\Collection;
19+
20+
final class ArticleResource extends Resource
21+
{
22+
protected static ?string $model = Article::class;
23+
24+
protected static ?string $navigationIcon = 'heroicon-o-newspaper';
25+
26+
public static function table(Table $table): Table
27+
{
28+
return $table
29+
->columns([
30+
TextColumn::make('title')
31+
->label('Titre')
32+
->sortable(),
33+
TextColumn::make('status')
34+
->getStateUsing(function ($record) {
35+
if ($record->approved_at) {
36+
return 'Approuver';
37+
} elseif ($record->declined_at) {
38+
return 'Décliner';
39+
} elseif ($record->submitted_at) {
40+
return 'Soumis';
41+
} else {
42+
return 'Brouillon';
43+
}
44+
})
45+
->colors([
46+
'success' => 'Approuver',
47+
'danger' => 'Décliner',
48+
'warning' => 'Soumis',
49+
'default' => 'Brouillon',
50+
])
51+
->badge(),
52+
TextColumn::make('submitted_at')
53+
->label('Date de soumission')
54+
->dateTime(),
55+
TextColumn::make('user.name')
56+
->label('Auteur')
57+
->sortable(),
58+
])
59+
->filters([
60+
Filter::make('submitted_at')->query(fn (Builder $query) => $query->whereNotNull('submitted_at'))->label('Soumis'),
61+
Filter::make('declined_at')->query(fn (Builder $query) => $query->whereNotNull('declined_at'))->label('Décliner'),
62+
Filter::make('approved_at')->query(fn (Builder $query) => $query->whereNotNull('approved_at'))->label('Approuver'),
63+
])
64+
65+
->actions([
66+
ActionGroup::make([
67+
Action::make('approved')
68+
->visible(fn (Article $record) => $record->isAwaitingApproval())
69+
->label('Approuver')
70+
->icon('heroicon-s-check')
71+
->color('success')
72+
->modalHeading(__('Voulez vous approuver cet article'))
73+
->successNotificationTitle(__('Opération effectuée avec succès'))
74+
->requiresConfirmation()
75+
->modalIcon('heroicon-s-check')
76+
->action(function ($record): void {
77+
$record->approved_at = now();
78+
$record->save();
79+
}),
80+
Action::make('declined')
81+
->visible(fn (Article $record) => $record->isAwaitingApproval())
82+
->label('Décliner')
83+
->icon('heroicon-s-x-mark')
84+
->color('warning')
85+
->modalHeading(__('Voulez vous décliner cet article'))
86+
->successNotificationTitle(__('Opération effectuée avec succès'))
87+
->requiresConfirmation()
88+
->modalIcon('heroicon-s-x-mark')
89+
->action(function ($record): void {
90+
$record->declined_at = now();
91+
$record->save();
92+
}),
93+
Tables\Actions\DeleteAction::make('delete'),
94+
]),
95+
96+
])
97+
->bulkActions([
98+
Tables\Actions\BulkActionGroup::make([
99+
BulkAction::make('approved')
100+
->label('Approuver la sélection')
101+
->icon('heroicon-s-check')
102+
->color('success')
103+
->action(fn (Collection $records) => $records->each->update(['approved_at' => now()]))
104+
->deselectRecordsAfterCompletion()
105+
->requiresConfirmation()
106+
->modalIcon('heroicon-s-check')
107+
->modalHeading('Approuver')
108+
->modalSubheading('Voulez-vous vraiment approuver ces articles ?')
109+
->modalButton('Confirmer'),
110+
BulkAction::make('declined')
111+
->label('Décliner la sélection')
112+
->icon('heroicon-s-x-mark')
113+
->color('warning')
114+
->action(fn (Collection $records) => $records->each->update(['declined_at' => now()]))
115+
->deselectRecordsAfterCompletion()
116+
->requiresConfirmation()
117+
->modalIcon('heroicon-s-x-mark')
118+
->modalHeading('Décliner')
119+
->modalSubheading('Voulez-vous vraiment décliner ces articles ?')
120+
->modalButton('Confirmer'),
121+
122+
Tables\Actions\DeleteBulkAction::make(),
123+
]),
124+
]);
125+
}
126+
127+
public static function getPages(): array
128+
{
129+
return [
130+
'index' => Pages\ListArticles::route('/'),
131+
];
132+
}
133+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Filament\Resources\ArticleResource\Pages;
6+
7+
use App\Filament\Resources\ArticleResource;
8+
use Filament\Resources\Pages\ListRecords;
9+
10+
final class ListArticles extends ListRecords
11+
{
12+
protected static string $resource = ArticleResource::class;
13+
}
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use App\Filament\Resources\ArticleResource;
6+
use App\Models\Article;
7+
use Livewire\Livewire;
8+
9+
beforeEach(function (): void {
10+
$this->user = $this->login();
11+
$this->articles = Article::factory()->count(10)->create([
12+
'submitted_at' => now(),
13+
]);
14+
});
15+
16+
describe(ArticleResource::class, function (): void {
17+
18+
it('page can display table with records', function (): void {
19+
Livewire::test(ArticleResource\Pages\ListArticles::class)
20+
->assertCanSeeTableRecords($this->articles);
21+
});
22+
23+
it('admin user can approved article', function (): void {
24+
$article = $this->articles->first();
25+
26+
Livewire::test(ArticleResource\Pages\ListArticles::class)
27+
->callTableAction('approved', $article);
28+
29+
$article->refresh();
30+
31+
expect($article->approved_at)
32+
->not
33+
->toBe(null)
34+
->and($article->declined_at)
35+
->toBe(null);
36+
37+
Livewire::test(ArticleResource\Pages\ListArticles::class)
38+
->assertTableActionHidden('approved', $article)
39+
->assertTableActionHidden('declined', $article);
40+
});
41+
42+
it('admin user can declined article', function (): void {
43+
$article = $this->articles->first();
44+
45+
Livewire::test(ArticleResource\Pages\ListArticles::class)
46+
->callTableAction('declined', $article);
47+
48+
$article->refresh();
49+
50+
expect($article->declined_at)
51+
->not
52+
->toBe(null)
53+
->and($article->approved_at)
54+
->toBe(null);
55+
56+
Livewire::test(ArticleResource\Pages\ListArticles::class)
57+
->assertTableActionHidden('approved', $article)
58+
->assertTableActionHidden('declined', $article);
59+
60+
});
61+
})->group('articles');

0 commit comments

Comments
 (0)