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:
2025-07-28 18:56:17 +05:00
parent 189cb53856
commit 74fc3b5e6a
22 changed files with 513 additions and 58 deletions

View File

@@ -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.';
}
}
}

View 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'),
]);
}
}

View 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'),
];
}
}

View File

@@ -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;
}

View 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(),
];
}
}

View File

@@ -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(),
];
}
}

View File

@@ -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,
];
}

View File

@@ -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(),
]),
]);
}
}

View File

@@ -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'));
}
}

View File

@@ -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
View 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);
}
}

View File

@@ -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);
}
}

View File

@@ -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([

View 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';
}
}