Files
thrillwiki_laravel/memory-bank/features/FilamentIntegration.md
2025-02-25 21:28:57 -05:00

336 lines
11 KiB
Markdown

# Filament PHP Integration
## Overview
This document outlines the integration of [Filament PHP](https://filamentphp.com/) into the ThrillWiki Laravel project. Filament PHP is a collection of tools for rapidly building beautiful CRUD interfaces for Laravel applications, with a focus on developer experience and end-user usability.
## Purpose
Filament PHP will be used to implement administrative interfaces and CRUD operations in the ThrillWiki Laravel project, while maintaining feature parity with the original Django implementation. This approach leverages Filament's powerful features to enhance the admin experience while ensuring all functionality from the Django implementation is preserved.
## Django Admin Analysis
After examining the original Django project, we've identified several key admin interfaces that need to be replicated using Filament PHP:
1. **Review System Admin**
- Review management with moderation capabilities
- ReviewImage management
- ReviewLike tracking
- ReviewReport handling
2. **Ride Management Admin**
- Ride CRUD with complex relationships
- RollerCoasterStats as nested forms
- Status management actions
- Rating display and calculations
3. **Moderation System**
- Custom moderation admin site with permission controls
- EditSubmission workflow (pending, approved, rejected, escalated)
- PhotoSubmission workflow
- History event tracking
## Implementation Strategy
### 1. Admin Panel Structure
Filament PHP will be used to create two separate admin panels:
1. **Main Admin Panel**
- For administrators and superusers
- Complete access to all resources
- Full CRUD capabilities
- Equivalent to Django's default admin
2. **Moderation Panel**
- For moderators
- Limited to moderation-specific resources
- Custom actions for approval workflows
- Equivalent to Django's custom ModerationAdminSite
### 2. Resource Mapping
Each Django admin model will be mapped to a Filament resource:
| Django Admin Model | Filament Resource |
|-------------------|-------------------|
| ReviewAdmin | ReviewResource |
| ReviewImageAdmin | ReviewImageResource |
| ReviewLikeAdmin | ReviewLikeResource |
| ReviewReportAdmin | ReviewReportResource |
| RideAdmin | RideResource |
| RollerCoasterStatsAdmin | RollerCoasterStatsResource |
| EditSubmissionAdmin | EditSubmissionResource |
| PhotoSubmissionAdmin | PhotoSubmissionResource |
| HistoryEventAdmin | HistoryEventResource |
### 3. Feature Parity Requirements
For each Filament resource, we must ensure:
1. **List View Parity**
- Match all columns from Django's list_display
- Implement equivalent filters from list_filter
- Support same search fields from search_fields
- Include bulk actions matching Django actions
2. **Form Layout Parity**
- Match Django's fieldsets structure
- Implement same field grouping and organization
- Support inline forms (equivalent to Django's inlines)
- Maintain field validation rules
3. **Custom Functionality**
- Implement computed columns (like get_status, get_avg_rating)
- Create custom actions for workflows (approve, reject, etc.)
- Support relationship management
- Maintain permission controls
## Implementation Details
### 1. Review System Implementation
The Review system will be implemented using Filament's resource management capabilities:
1. **ReviewResource**
```php
class ReviewResource extends Resource
{
protected static ?string $model = Review::class;
public static function form(Form $form): Form
{
return $form->schema([
// Match Django's review fieldset structure
Forms\Components\Section::make('Review Details')
->schema([
Forms\Components\TextInput::make('title'),
Forms\Components\RichEditor::make('content'),
Forms\Components\Select::make('status')
->options(ReviewStatus::class),
Forms\Components\BelongsTo::make('ride'),
Forms\Components\BelongsTo::make('user'),
]),
Forms\Components\Section::make('Moderation')
->schema([
Forms\Components\Toggle::make('is_featured'),
Forms\Components\Toggle::make('is_verified'),
Forms\Components\DateTimePicker::make('moderated_at'),
Forms\Components\TextInput::make('moderation_notes'),
]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
// Match Django's list_display
Tables\Columns\TextColumn::make('title'),
Tables\Columns\TextColumn::make('user.name'),
Tables\Columns\TextColumn::make('ride.name'),
Tables\Columns\BadgeColumn::make('status')
->colors([
'success' => 'published',
'warning' => 'pending',
'danger' => 'rejected',
]),
Tables\Columns\TextColumn::make('created_at')
->dateTime(),
])
->filters([
// Match Django's list_filter
Tables\Filters\SelectFilter::make('status')
->options(ReviewStatus::class),
Tables\Filters\BooleanFilter::make('is_featured'),
Tables\Filters\BooleanFilter::make('is_verified'),
])
->actions([
// Match Django's actions
Tables\Actions\EditAction::make(),
Tables\Actions\Action::make('approve')
->action(fn (Review $record) => $record->approve())
->requiresConfirmation(),
Tables\Actions\Action::make('reject')
->action(fn (Review $record) => $record->reject())
->requiresConfirmation(),
])
->bulkActions([
Tables\Actions\BulkAction::make('approve')
->action(fn (Collection $records) => $records->each->approve())
->requiresConfirmation(),
Tables\Actions\BulkAction::make('reject')
->action(fn (Collection $records) => $records->each->reject())
->requiresConfirmation(),
]);
}
}
```
2. **ReviewImageResource**
```php
class ReviewImageResource extends Resource
{
protected static ?string $model = ReviewImage::class;
public static function form(Form $form): Form
{
return $form->schema([
Forms\Components\FileUpload::make('image')
->image()
->required(),
Forms\Components\BelongsTo::make('review'),
Forms\Components\TextInput::make('caption'),
Forms\Components\Toggle::make('is_featured'),
]);
}
}
```
3. **Custom Actions**
```php
class ReviewResource extends Resource
{
public static function getActions(): array
{
return [
Actions\Action::make('moderate')
->form([
Forms\Components\Select::make('status')
->options(ReviewStatus::class)
->required(),
Forms\Components\Textarea::make('notes'),
])
->action(function (array $data, Review $record) {
$record->update([
'status' => $data['status'],
'moderation_notes' => $data['notes'],
'moderated_at' => now(),
]);
}),
];
}
}
```
### 2. Moderation Panel Configuration
The moderation panel will be configured as a separate Filament panel:
```php
use Filament\Panel;
class ModerationPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->id('moderation')
->path('moderation')
->login()
->registration(false)
->passwordReset()
->resources([
ReviewResource::class,
ReviewImageResource::class,
ReviewReportResource::class,
PhotoSubmissionResource::class,
EditSubmissionResource::class,
])
->middleware([
'auth',
'verified',
'can:access-moderation-panel',
]);
}
}
```
### 3. Permission Integration
Filament's authorization will be integrated with Laravel's permission system:
```php
use Filament\Support\Authorization\Permissions;
class ReviewResource extends Resource
{
protected static function getNavigationGroup(): ?string
{
return 'Content Moderation';
}
public static function canViewAny(): bool
{
return auth()->user()->can('view-any-reviews');
}
public static function canCreate(): bool
{
return auth()->user()->can('create-reviews');
}
public static function canEdit(Model $record): bool
{
return auth()->user()->can('edit-reviews');
}
public static function canDelete(Model $record): bool
{
return auth()->user()->can('delete-reviews');
}
}
```
### 4. Validation Rules
Form validation will match Django's validation rules:
```php
class ReviewResource extends Resource
{
public static function form(Form $form): Form
{
return $form->schema([
Forms\Components\TextInput::make('title')
->required()
->minLength(10)
->maxLength(200),
Forms\Components\RichEditor::make('content')
->required()
->minLength(100)
->maxLength(10000),
Forms\Components\Select::make('rating')
->options(range(1, 5))
->required(),
]);
}
}
```
### 5. Computed Properties
Implementing computed properties to match Django's property methods:
```php
class Review extends Model
{
protected $appends = ['status_label', 'avg_rating'];
public function getStatusLabelAttribute(): string
{
return match($this->status) {
ReviewStatus::Published => 'Published',
ReviewStatus::Pending => 'Pending Moderation',
ReviewStatus::Rejected => 'Rejected',
default => 'Unknown',
};
}
public function getAvgRatingAttribute(): float
{
return $this->ratings()->avg('value') ?? 0.0;
}
}
```
These implementations ensure feature parity with the Django admin while leveraging Filament's powerful features for an enhanced administrative experience.