feat: implement Company History module with CRUD functionality, localization support, and timeline display for enhanced user experience

This commit is contained in:
Ümit Tunç
2026-05-21 19:33:38 +03:00
parent a9d6f17e3c
commit c82dd5c6b6
17 changed files with 1271 additions and 2 deletions
@@ -0,0 +1,77 @@
<?php
namespace App\Filament\Admin\Resources\CompanyHistoryItems;
use App\Filament\Admin\Resources\CompanyHistoryItems\Pages\CreateCompanyHistoryItem;
use App\Filament\Admin\Resources\CompanyHistoryItems\Pages\EditCompanyHistoryItem;
use App\Filament\Admin\Resources\CompanyHistoryItems\Pages\ListCompanyHistoryItems;
use App\Filament\Admin\Resources\CompanyHistoryItems\Schemas\CompanyHistoryItemForm;
use App\Filament\Admin\Resources\CompanyHistoryItems\Tables\CompanyHistoryItemsTable;
use App\Models\CompanyHistoryItem;
use BackedEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class CompanyHistoryItemResource extends Resource
{
protected static ?string $model = CompanyHistoryItem::class;
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-clock';
protected static ?int $navigationSort = 45;
public static function getNavigationGroup(): ?string
{
return __('company_history.navigation_group');
}
public static function getNavigationLabel(): string
{
return __('company_history.navigation_label');
}
public static function getModelLabel(): string
{
return __('company_history.model_label');
}
public static function getPluralModelLabel(): string
{
return __('company_history.plural_model_label');
}
public static function form(Schema $schema): Schema
{
return CompanyHistoryItemForm::configure($schema);
}
public static function table(Table $table): Table
{
return CompanyHistoryItemsTable::configure($table);
}
public static function getRelations(): array
{
return [];
}
public static function getPages(): array
{
return [
'index' => ListCompanyHistoryItems::route('/'),
'create' => CreateCompanyHistoryItem::route('/create'),
'edit' => EditCompanyHistoryItem::route('/{record}/edit'),
];
}
public static function getRecordRouteBindingEloquentQuery(): Builder
{
return parent::getRecordRouteBindingEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Filament\Admin\Resources\CompanyHistoryItems\Pages;
use App\Filament\Admin\Resources\CompanyHistoryItems\CompanyHistoryItemResource;
use App\Filament\Admin\Resources\Components\TranslationTabs;
use Filament\Resources\Pages\CreateRecord;
class CreateCompanyHistoryItem extends CreateRecord
{
protected static string $resource = CompanyHistoryItemResource::class;
public function getTitle(): string
{
return __('company_history.create');
}
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
protected function getCreatedNotificationTitle(): ?string
{
return __('company_history.created_successfully');
}
protected function mutateFormDataBeforeCreate(array $data): array
{
if (empty($data['position'])) {
$data['position'] = null;
}
unset($data['color_custom']);
return $data;
}
protected function afterCreate(): void
{
TranslationTabs::saveTranslations($this->record, $this->form->getState());
}
}
@@ -0,0 +1,65 @@
<?php
namespace App\Filament\Admin\Resources\CompanyHistoryItems\Pages;
use App\Filament\Admin\Resources\CompanyHistoryItems\CompanyHistoryItemResource;
use App\Filament\Admin\Resources\Components\TranslationTabs;
use Filament\Actions\DeleteAction;
use Filament\Actions\ForceDeleteAction;
use Filament\Actions\RestoreAction;
use Filament\Resources\Pages\EditRecord;
class EditCompanyHistoryItem extends EditRecord
{
protected static string $resource = CompanyHistoryItemResource::class;
public function getTitle(): string
{
return __('company_history.edit');
}
protected function getHeaderActions(): array
{
return [
DeleteAction::make()
->label(__('company_history.delete')),
ForceDeleteAction::make()
->label(__('company_history.force_delete')),
RestoreAction::make()
->label(__('company_history.restore')),
];
}
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
protected function getSavedNotificationTitle(): ?string
{
return __('company_history.updated_successfully');
}
protected function mutateFormDataBeforeFill(array $data): array
{
$data['translations'] = TranslationTabs::loadTranslations($this->record);
return $data;
}
protected function mutateFormDataBeforeSave(array $data): array
{
if (empty($data['position'])) {
$data['position'] = null;
}
unset($data['color_custom']);
return $data;
}
protected function afterSave(): void
{
TranslationTabs::saveTranslations($this->record, $this->form->getState());
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Filament\Admin\Resources\CompanyHistoryItems\Pages;
use App\Filament\Admin\Resources\CompanyHistoryItems\CompanyHistoryItemResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;
class ListCompanyHistoryItems extends ListRecords
{
protected static string $resource = CompanyHistoryItemResource::class;
public function getTitle(): string
{
return __('company_history.title');
}
protected function getHeaderActions(): array
{
return [
CreateAction::make()
->label(__('company_history.create')),
];
}
}
@@ -0,0 +1,124 @@
<?php
namespace App\Filament\Admin\Resources\CompanyHistoryItems\Schemas;
use App\Filament\Admin\Resources\Components\TranslationTabs;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
class CompanyHistoryItemForm
{
public static function iconOptions(): array
{
return [
'heroicon-o-building-office-2' => __('company_history.icon_building'),
'heroicon-o-academic-cap' => __('company_history.icon_academic'),
'heroicon-o-globe-alt' => __('company_history.icon_globe'),
'heroicon-o-users' => __('company_history.icon_users'),
'heroicon-o-trophy' => __('company_history.icon_trophy'),
'heroicon-o-map' => __('company_history.icon_map'),
'heroicon-o-light-bulb' => __('company_history.icon_light_bulb'),
'heroicon-o-rocket-launch' => __('company_history.icon_rocket'),
];
}
public static function colorPresets(): array
{
return [
'#17a2b8' => __('company_history.color_teal'),
'#f5a623' => __('company_history.color_orange'),
'#e91e63' => __('company_history.color_pink'),
'#2c3e50' => __('company_history.color_navy'),
'#5dade2' => __('company_history.color_blue'),
'#27ae60' => __('company_history.color_green'),
];
}
public static function configure(Schema $schema): Schema
{
return $schema
->columns(3)
->schema([
Section::make(__('company_history.content_section'))
->schema([
TextInput::make('year')
->label(__('company_history.year_field'))
->required()
->numeric()
->minValue(1900)
->maxValue(2100),
TextInput::make('title')
->label(__('company_history.title_field'))
->required()
->maxLength(255),
Textarea::make('content')
->label(__('company_history.content_field'))
->required()
->rows(5)
->columnSpanFull(),
TranslationTabs::make([
'title' => [
'type' => 'text',
'label' => __('company_history.title_field'),
'required' => false,
'maxLength' => 255,
],
'content' => [
'type' => 'textarea',
'label' => __('company_history.content_field'),
'required' => false,
'rows' => 5,
],
]),
])
->columnSpan(2)
->collapsible(false),
Section::make(__('company_history.settings_section'))
->schema([
Select::make('color')
->label(__('company_history.color_field'))
->options(self::colorPresets())
->default('#17a2b8')
->required()
->native(false)
->searchable(),
Select::make('icon')
->label(__('company_history.icon_field'))
->options(self::iconOptions())
->default('heroicon-o-building-office-2')
->required()
->native(false)
->searchable(),
Select::make('position')
->label(__('company_history.position_field'))
->options([
'' => __('company_history.position_auto'),
'left' => __('company_history.position_left'),
'right' => __('company_history.position_right'),
])
->default(null),
TextInput::make('sort_order')
->label(__('company_history.sort_order_field'))
->numeric()
->default(0)
->minValue(0),
Checkbox::make('is_active')
->label(__('company_history.is_active_field'))
->default(true),
])
->columnSpan(1),
]);
}
}
@@ -0,0 +1,94 @@
<?php
namespace App\Filament\Admin\Resources\CompanyHistoryItems\Tables;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ForceDeleteBulkAction;
use Filament\Actions\RestoreBulkAction;
use Filament\Tables\Columns\ColorColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Columns\ToggleColumn;
use Filament\Tables\Filters\TernaryFilter;
use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
class CompanyHistoryItemsTable
{
public static function configure(Table $table): Table
{
return $table
->columns([
TextColumn::make('year')
->label(__('company_history.table_year'))
->sortable()
->alignCenter(),
ColorColumn::make('color')
->label(__('company_history.color_field')),
TextColumn::make('title')
->label(__('company_history.table_title'))
->searchable()
->sortable()
->limit(40),
TextColumn::make('content')
->label(__('company_history.content_field'))
->limit(60)
->toggleable(),
TextColumn::make('position')
->label(__('company_history.position_field'))
->formatStateUsing(fn (?string $state): string => match ($state) {
'left' => __('company_history.position_left'),
'right' => __('company_history.position_right'),
default => __('company_history.position_auto'),
})
->toggleable(),
ToggleColumn::make('is_active')
->label(__('company_history.table_is_active'))
->alignCenter(),
TextColumn::make('sort_order')
->label(__('company_history.sort_order_field'))
->sortable()
->alignCenter(),
TextColumn::make('created_at')
->label(__('company_history.table_created_at'))
->dateTime('d.m.Y H:i')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')
->label(__('company_history.table_updated_at'))
->dateTime('d.m.Y H:i')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
TernaryFilter::make('is_active')
->label(__('company_history.is_active_field')),
TrashedFilter::make(),
])
->recordActions([
EditAction::make()
->label(__('company_history.edit')),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make()
->label(__('company_history.delete')),
RestoreBulkAction::make()
->label(__('company_history.restore')),
ForceDeleteBulkAction::make()
->label(__('company_history.force_delete')),
]),
])
->defaultSort('sort_order', 'asc')
->reorderable('sort_order');
}
}