Implement news management features: add author field and comments functionality in NewsResource, enhance HomePageController to fetch latest news, and create dedicated views for news display and commenting. Update routes for comment submission and adjust homepage to showcase recent news articles.
This commit is contained in:
@@ -15,8 +15,6 @@ use Illuminate\Contracts\Support\Htmlable;
|
||||
|
||||
class HomePageSettings extends SettingsPage
|
||||
{
|
||||
protected static ?string $navigationIcon = 'heroicon-o-home';
|
||||
|
||||
protected static string $settings = HomeSettings::class;
|
||||
|
||||
public function form(Form $form): Form
|
||||
@@ -291,4 +289,4 @@ class HomePageSettings extends SettingsPage
|
||||
{
|
||||
return 'Manage the homepage hero section, background video, and call-to-action content.';
|
||||
}
|
||||
}
|
||||
}
|
||||
40
app/Filament/Pages/ManageCtaSettings.php
Normal file
40
app/Filament/Pages/ManageCtaSettings.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Settings\CtaSettings;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Pages\SettingsPage;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
class ManageCtaSettings extends SettingsPage
|
||||
{
|
||||
protected static ?string $navigationGroup = 'CMS';
|
||||
protected static ?string $navigationLabel = 'Call To Action';
|
||||
protected static ?string $navigationIcon = 'heroicon-o-megaphone';
|
||||
|
||||
protected static string $settings = CtaSettings::class;
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('title')
|
||||
->label('Call To Action Title')
|
||||
->required(),
|
||||
Forms\Components\TextInput::make('button_text')
|
||||
->label('Button Text')
|
||||
->required(),
|
||||
Forms\Components\TextInput::make('button_url')
|
||||
->label('Button URL')
|
||||
->required()
|
||||
->url(),
|
||||
FileUpload::make('background_image')
|
||||
->label('Background Image 1320x408')
|
||||
->directory('settings')
|
||||
->image()
|
||||
->columnSpan('full'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
99
app/Filament/Resources/CommentResource.php
Normal file
99
app/Filament/Resources/CommentResource.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\CommentResource\Pages;
|
||||
use App\Filament\Resources\CommentResource\RelationManagers;
|
||||
use App\Models\Comment;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
|
||||
class CommentResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Comment::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-chat-bubble-bottom-center-text';
|
||||
|
||||
protected static ?string $navigationGroup = 'CMS';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Card::make()
|
||||
->schema([
|
||||
Select::make('news_id')
|
||||
->relationship('news', 'title')
|
||||
->required(),
|
||||
TextInput::make('title')
|
||||
->required()
|
||||
->maxLength(255),
|
||||
RichEditor::make('message')
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
TextInput::make('author_name')
|
||||
->label('Author Name (Optional)')
|
||||
->maxLength(255),
|
||||
])
|
||||
->columns(2),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('news.title')
|
||||
->label('News Article')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('title')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('author_name')
|
||||
->label('Author')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListComments::route('/'),
|
||||
'create' => Pages\CreateComment::route('/create'),
|
||||
'edit' => Pages\EditComment::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\CommentResource\Pages;
|
||||
|
||||
use App\Filament\Resources\CommentResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateComment extends CreateRecord
|
||||
{
|
||||
protected static string $resource = CommentResource::class;
|
||||
}
|
||||
19
app/Filament/Resources/CommentResource/Pages/EditComment.php
Normal file
19
app/Filament/Resources/CommentResource/Pages/EditComment.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\CommentResource\Pages;
|
||||
|
||||
use App\Filament\Resources\CommentResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditComment extends EditRecord
|
||||
{
|
||||
protected static string $resource = CommentResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\CommentResource\Pages;
|
||||
|
||||
use App\Filament\Resources\CommentResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListComments extends ListRecords
|
||||
{
|
||||
protected static string $resource = CommentResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ use Filament\Tables;
|
||||
use Filament\Tables\Columns\ImageColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Filament\Resources\NewsResource\RelationManagers\CommentsRelationManager;
|
||||
|
||||
class NewsResource extends Resource
|
||||
{
|
||||
@@ -42,10 +43,14 @@ class NewsResource extends Resource
|
||||
->dehydrated()
|
||||
->unique(News::class, 'slug', ignoreRecord: true),
|
||||
FileUpload::make('image')
|
||||
->label('Image 1100x660')
|
||||
->image()
|
||||
->directory('news')
|
||||
->nullable()
|
||||
->columnSpanFull(),
|
||||
TextInput::make('author')
|
||||
->required()
|
||||
->maxLength(255),
|
||||
RichEditor::make('content')
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
@@ -70,6 +75,9 @@ class NewsResource extends Resource
|
||||
Tables\Columns\TextColumn::make('slug')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('author')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('published_at')
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
@@ -99,7 +107,7 @@ class NewsResource extends Resource
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
CommentsRelationManager::class,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\NewsResource\RelationManagers;
|
||||
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class CommentsRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'comments';
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
TextInput::make('title')
|
||||
->required()
|
||||
->maxLength(255),
|
||||
RichEditor::make('message')
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
TextInput::make('author_name')
|
||||
->label('Author Name (Optional)')
|
||||
->maxLength(255),
|
||||
]);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->recordTitleAttribute('title')
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('title')
|
||||
->searchable(),
|
||||
Tables\Columns\TextColumn::make('author_name')
|
||||
->label('Author')
|
||||
->searchable(),
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->headerActions([
|
||||
Tables\Actions\CreateAction::make(),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Brand;
|
||||
use App\Models\News;
|
||||
use App\Settings\HomeSettings;
|
||||
|
||||
class HomePageController extends Controller
|
||||
@@ -11,7 +12,8 @@ class HomePageController extends Controller
|
||||
{
|
||||
$brands = Brand::query()->get(['id', 'image']);
|
||||
$homeSettings = app(HomeSettings::class);
|
||||
$allNews = News::query()->latest()->take(3)->get();
|
||||
|
||||
return view('web.pages.home.index', compact('homeSettings', 'brands'));
|
||||
return view('web.pages.home.index', compact('homeSettings', 'brands', 'allNews'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\News;
|
||||
use App\Models\Comment;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class NewsPageController extends Controller
|
||||
{
|
||||
@@ -17,4 +19,17 @@ class NewsPageController extends Controller
|
||||
{
|
||||
return view('web.pages.news.show', compact('news'));
|
||||
}
|
||||
|
||||
public function storeComment(Request $request, News $news)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'message' => 'required|string',
|
||||
'author_name' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
$news->comments()->create($validated);
|
||||
|
||||
return back()->with('success', 'Comment added successfully!');
|
||||
}
|
||||
}
|
||||
|
||||
24
app/Models/Comment.php
Normal file
24
app/Models/Comment.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class Comment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'message',
|
||||
'author_name',
|
||||
'news_id',
|
||||
];
|
||||
|
||||
public function news(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(News::class);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class News extends Model
|
||||
{
|
||||
@@ -15,5 +16,11 @@ class News extends Model
|
||||
'content',
|
||||
'image',
|
||||
'published_at',
|
||||
'author',
|
||||
];
|
||||
|
||||
public function comments(): HasMany
|
||||
{
|
||||
return $this->hasMany(Comment::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Providers\Filament;
|
||||
|
||||
use Filament\Http\Middleware\Authenticate;
|
||||
use Filament\Http\Middleware\AuthenticateSession;
|
||||
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||
use Filament\Pages;
|
||||
@@ -15,8 +14,11 @@ use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||
use Illuminate\Session\Middleware\AuthenticateSession;
|
||||
use Illuminate\Session\Middleware\StartSession;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
use App\Filament\Pages\HomePageSettings;
|
||||
use App\Filament\Pages\ManageCtaSettings;
|
||||
|
||||
class PanelPanelProvider extends PanelProvider
|
||||
{
|
||||
@@ -34,6 +36,8 @@ class PanelPanelProvider extends PanelProvider
|
||||
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
|
||||
->pages([
|
||||
Pages\Dashboard::class,
|
||||
HomePageSettings::class,
|
||||
ManageCtaSettings::class,
|
||||
])
|
||||
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
|
||||
->widgets([
|
||||
|
||||
18
app/Settings/CtaSettings.php
Normal file
18
app/Settings/CtaSettings.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Settings;
|
||||
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
|
||||
class CtaSettings extends Settings
|
||||
{
|
||||
public string $title;
|
||||
public string $button_text;
|
||||
public string $button_url;
|
||||
public string $background_image;
|
||||
|
||||
public static function group(): string
|
||||
{
|
||||
return 'cta';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user