154 lines
5.3 KiB
PHP
154 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace Modules\Core\Review\Pages;
|
|
|
|
use Filament\Forms\Components\Group;
|
|
use Filament\Forms\Components\Placeholder;
|
|
use Filament\Forms\Components\Textarea;
|
|
use Filament\Forms\Components\TextInput;
|
|
use Filament\Forms\Form;
|
|
use Filament\Tables\Actions\Action;
|
|
use Filament\Tables\Actions\DeleteAction;
|
|
use Filament\Tables\Actions\DeleteBulkAction;
|
|
use Filament\Tables\Actions\ViewAction;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Table;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\HtmlString;
|
|
use Lunar\Admin\Filament\Resources\ProductResource;
|
|
use Lunar\Admin\Support\Pages\BaseManageRelatedRecords;
|
|
use Modules\Core\Review\Models\ProductReview;
|
|
|
|
class ManageProductReviews extends BaseManageRelatedRecords
|
|
{
|
|
protected static string $resource = ProductResource::class;
|
|
|
|
protected static string $relationship = 'reviews';
|
|
|
|
public static function getNavigationIcon(): ?string
|
|
{
|
|
return 'heroicon-o-star';
|
|
}
|
|
|
|
public function getTitle(): string
|
|
{
|
|
return 'Reviews';
|
|
}
|
|
|
|
public static function getNavigationLabel(): string
|
|
{
|
|
return 'Reviews';
|
|
}
|
|
|
|
public function form(Form $form): Form
|
|
{
|
|
return $form
|
|
->schema([
|
|
TextInput::make('rating')
|
|
->label('Rating')
|
|
->disabled(),
|
|
TextInput::make('title')
|
|
->label('Title')
|
|
->disabled(),
|
|
Textarea::make('body')
|
|
->label('Body')
|
|
->disabled()
|
|
->columnSpanFull(),
|
|
Group::make([
|
|
TextInput::make('reviewer_name')
|
|
->label('Reviewer name')
|
|
->disabled(),
|
|
TextInput::make('reviewer_email')
|
|
->label('Reviewer email')
|
|
->disabled(),
|
|
])->columns(2),
|
|
Group::make([
|
|
TextInput::make('location')
|
|
->label('Location')
|
|
->disabled(),
|
|
TextInput::make('source')
|
|
->label('Source')
|
|
->disabled(),
|
|
])->columns(2),
|
|
Group::make([
|
|
TextInput::make('reviewed_at')
|
|
->label('Reviewed at')
|
|
->disabled(),
|
|
TextInput::make('replied_at')
|
|
->label('Replied at')
|
|
->disabled(),
|
|
])->columns(2),
|
|
Textarea::make('reply')
|
|
->label('Reply')
|
|
->disabled()
|
|
->columnSpanFull(),
|
|
Placeholder::make('images')
|
|
->label('Images')
|
|
->content(function (?ProductReview $record) {
|
|
if (! $record) {
|
|
return null;
|
|
}
|
|
|
|
$media = $record->getMedia(ProductReview::IMAGES_COLLECTION);
|
|
|
|
if ($media->isEmpty()) {
|
|
return 'No images';
|
|
}
|
|
|
|
$tags = $media->map(fn ($item) => sprintf(
|
|
'<a href="%1$s" target="_blank"><img src="%1$s" style="height:6rem;width:6rem;object-fit:cover;border-radius:0.5rem;display:inline-block;margin:0.25rem" /></a>',
|
|
$item->getUrl(),
|
|
))->implode('');
|
|
|
|
return new HtmlString($tags);
|
|
})
|
|
->columnSpanFull(),
|
|
]);
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->recordTitleAttribute('title')
|
|
->columns([
|
|
TextColumn::make('rating')
|
|
->label('Rating')
|
|
->formatStateUsing(fn (int $state) => str_repeat('★', $state).str_repeat('☆', 5 - $state))
|
|
->sortable(),
|
|
TextColumn::make('title')
|
|
->label('Title')
|
|
->limit(40)
|
|
->searchable(),
|
|
TextColumn::make('reviewer_name')
|
|
->label('Reviewer')
|
|
->searchable(),
|
|
])
|
|
->defaultSort('reviewed_at', 'desc')
|
|
->filters([
|
|
//
|
|
])
|
|
->actions([
|
|
ViewAction::make(),
|
|
Action::make('reply')
|
|
->label(fn (ProductReview $record) => $record->reply ? 'Edit reply' : 'Reply')
|
|
->icon('heroicon-o-chat-bubble-left-right')
|
|
->form([
|
|
Textarea::make('reply')
|
|
->label('Reply')
|
|
->required(),
|
|
])
|
|
->fillForm(fn (ProductReview $record) => ['reply' => $record->reply])
|
|
->action(function (ProductReview $record, array $data) {
|
|
$record->update([
|
|
'reply' => $data['reply'],
|
|
'replied_at' => Carbon::now(),
|
|
]);
|
|
}),
|
|
DeleteAction::make(),
|
|
])
|
|
->bulkActions([
|
|
DeleteBulkAction::make(),
|
|
]);
|
|
}
|
|
}
|