Add HR resource labels and helper methods for various resources; update locale handling in user model and department factory

This commit is contained in:
Mekan1206
2026-07-31 23:40:35 +05:00
parent 581cb8241c
commit 20d032c4cc
83 changed files with 4386 additions and 39 deletions

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Filament\Concerns;
trait HasHrResourceLabels
{
/**
* @return array{model: string, plural: string, navigation?: string}
*/
abstract protected static function hrLabelKeys(): array;
public static function getModelLabel(): string
{
return __('hr.resources.'.static::hrLabelKeys()['model']);
}
public static function getPluralModelLabel(): string
{
return __('hr.resources.'.static::hrLabelKeys()['plural']);
}
public static function getNavigationLabel(): string
{
$keys = static::hrLabelKeys();
return __('hr.resources.'.($keys['navigation'] ?? $keys['plural']));
}
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\ActivityLogs;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\ActivityLogs\Pages\ListActivityLogs;
use App\Filament\Resources\ActivityLogs\Pages\ViewActivityLog;
use App\Filament\Resources\ActivityLogs\Schemas\ActivityLogInfolist;
@@ -19,8 +20,19 @@ use UnitEnum;
class ActivityLogResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Activity::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'activity_log',
'plural' => 'activity_logs',
'navigation' => 'audit_log',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedClipboardDocumentList;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::System;
@@ -29,21 +41,6 @@ class ActivityLogResource extends Resource
protected static ?string $slug = 'activity-logs';
public static function getNavigationLabel(): string
{
return __('hr.resources.audit_log');
}
public static function getModelLabel(): string
{
return __('hr.resources.activity_log');
}
public static function getPluralModelLabel(): string
{
return __('hr.resources.activity_logs');
}
public static function form(Schema $schema): Schema
{
return $schema;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Bonuses;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Bonuses\Pages\CreateBonus;
use App\Filament\Resources\Bonuses\Pages\EditBonus;
use App\Filament\Resources\Bonuses\Pages\ListBonuses;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Bonuses\Schemas\BonusInfolist;
use App\Filament\Resources\Bonuses\Tables\BonusesTable;
use App\Models\Bonus;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class BonusResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Bonus::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'bonus',
'plural' => 'bonuses',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCurrencyDollar;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Records;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Departments;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Departments\Pages\CreateDepartment;
use App\Filament\Resources\Departments\Pages\EditDepartment;
use App\Filament\Resources\Departments\Pages\ListDepartments;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Departments\Schemas\DepartmentInfolist;
use App\Filament\Resources\Departments\Tables\DepartmentsTable;
use App\Models\Department;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class DepartmentResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Department::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'department',
'plural' => 'departments',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedBuildingOffice2;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Organization;

View File

@@ -2,8 +2,8 @@
namespace App\Filament\Resources\Departments\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Schemas\Schema;
@@ -16,10 +16,6 @@ class DepartmentForm
TextInput::make('name')
->required()
->maxLength(255),
TextInput::make('code')
->required()
->maxLength(50)
->unique(ignoreRecord: true),
Textarea::make('description')
->rows(3)
->columnSpanFull(),

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\DisciplinaryReports;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\DisciplinaryReports\Pages\CreateDisciplinaryReport;
use App\Filament\Resources\DisciplinaryReports\Pages\EditDisciplinaryReport;
use App\Filament\Resources\DisciplinaryReports\Pages\ListDisciplinaryReports;
@@ -14,18 +15,28 @@ use App\Filament\Resources\DisciplinaryReports\Schemas\DisciplinaryReportInfolis
use App\Filament\Resources\DisciplinaryReports\Tables\DisciplinaryReportsTable;
use App\Models\DisciplinaryReport;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class DisciplinaryReportResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = DisciplinaryReport::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'disciplinary_report',
'plural' => 'disciplinary_reports',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedExclamationTriangle;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Records;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\EmployeeDocuments;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\EmployeeDocuments\Pages\CreateEmployeeDocument;
use App\Filament\Resources\EmployeeDocuments\Pages\EditEmployeeDocument;
use App\Filament\Resources\EmployeeDocuments\Pages\ListEmployeeDocuments;
@@ -14,18 +15,28 @@ use App\Filament\Resources\EmployeeDocuments\Schemas\EmployeeDocumentInfolist;
use App\Filament\Resources\EmployeeDocuments\Tables\EmployeeDocumentsTable;
use App\Models\EmployeeDocument;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class EmployeeDocumentResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = EmployeeDocument::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'employee_document',
'plural' => 'employee_documents',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedDocument;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Records;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Employees;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Employees\Pages\CreateEmployee;
use App\Filament\Resources\Employees\Pages\EditEmployee;
use App\Filament\Resources\Employees\Pages\ListEmployees;
@@ -22,7 +23,6 @@ use App\Filament\Resources\Employees\Schemas\EmployeeInfolist;
use App\Filament\Resources\Employees\Tables\EmployeesTable;
use App\Models\Employee;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
@@ -30,11 +30,22 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class EmployeeResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Employee::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'employee',
'plural' => 'employees',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedUsers;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Employees;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Explanations;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Explanations\Pages\CreateExplanation;
use App\Filament\Resources\Explanations\Pages\EditExplanation;
use App\Filament\Resources\Explanations\Pages\ListExplanations;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Explanations\Schemas\ExplanationInfolist;
use App\Filament\Resources\Explanations\Tables\ExplanationsTable;
use App\Models\Explanation;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class ExplanationResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Explanation::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'explanation',
'plural' => 'explanations',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedDocumentText;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Records;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Gifts;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Gifts\Pages\CreateGift;
use App\Filament\Resources\Gifts\Pages\EditGift;
use App\Filament\Resources\Gifts\Pages\ListGifts;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Gifts\Schemas\GiftInfolist;
use App\Filament\Resources\Gifts\Tables\GiftsTable;
use App\Models\Gift;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class GiftResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Gift::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'gift',
'plural' => 'gifts',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedGift;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Records;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Positions;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Positions\Pages\CreatePosition;
use App\Filament\Resources\Positions\Pages\EditPosition;
use App\Filament\Resources\Positions\Pages\ListPositions;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Positions\Schemas\PositionInfolist;
use App\Filament\Resources\Positions\Tables\PositionsTable;
use App\Models\Position;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class PositionResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Position::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'position',
'plural' => 'positions',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedBriefcase;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Organization;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Shifts;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Shifts\Pages\CreateShift;
use App\Filament\Resources\Shifts\Pages\EditShift;
use App\Filament\Resources\Shifts\Pages\ListShifts;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Shifts\Schemas\ShiftInfolist;
use App\Filament\Resources\Shifts\Tables\ShiftsTable;
use App\Models\Shift;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class ShiftResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Shift::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'shift',
'plural' => 'shifts',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedClock;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::Organization;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\SickLeaves;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\SickLeaves\Pages\CreateSickLeave;
use App\Filament\Resources\SickLeaves\Pages\EditSickLeave;
use App\Filament\Resources\SickLeaves\Pages\ListSickLeaves;
@@ -14,18 +15,28 @@ use App\Filament\Resources\SickLeaves\Schemas\SickLeaveInfolist;
use App\Filament\Resources\SickLeaves\Tables\SickLeavesTable;
use App\Models\SickLeave;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class SickLeaveResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = SickLeave::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'sick_leave',
'plural' => 'sick_leaves',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedHeart;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::LeaveManagement;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\UnpaidLeaves;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\UnpaidLeaves\Pages\CreateUnpaidLeave;
use App\Filament\Resources\UnpaidLeaves\Pages\EditUnpaidLeave;
use App\Filament\Resources\UnpaidLeaves\Pages\ListUnpaidLeaves;
@@ -14,18 +15,28 @@ use App\Filament\Resources\UnpaidLeaves\Schemas\UnpaidLeaveInfolist;
use App\Filament\Resources\UnpaidLeaves\Tables\UnpaidLeavesTable;
use App\Models\UnpaidLeave;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class UnpaidLeaveResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = UnpaidLeave::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'unpaid_leave',
'plural' => 'unpaid_leaves',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCalendarDays;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::LeaveManagement;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Users;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Users\Pages\CreateUser;
use App\Filament\Resources\Users\Pages\EditUser;
use App\Filament\Resources\Users\Pages\ListUsers;
@@ -22,8 +23,18 @@ use UnitEnum;
class UserResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = User::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'user',
'plural' => 'users',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedUsers;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::System;

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Filament\Resources\Vacations;
use App\Enums\NavigationGroup;
use App\Filament\Concerns\HasHrResourceLabels;
use App\Filament\Resources\Vacations\Pages\CreateVacation;
use App\Filament\Resources\Vacations\Pages\EditVacation;
use App\Filament\Resources\Vacations\Pages\ListVacations;
@@ -14,18 +15,28 @@ use App\Filament\Resources\Vacations\Schemas\VacationInfolist;
use App\Filament\Resources\Vacations\Tables\VacationsTable;
use App\Models\Vacation;
use BackedEnum;
use UnitEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use UnitEnum;
class VacationResource extends Resource
{
use HasHrResourceLabels;
protected static ?string $model = Vacation::class;
protected static function hrLabelKeys(): array
{
return [
'model' => 'vacation',
'plural' => 'vacations',
];
}
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedSun;
protected static string|UnitEnum|null $navigationGroup = NavigationGroup::LeaveManagement;

25
app/Helpers/helpers.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* User function, returns user, if there is no user, returns empty User class
*/
function user(): User|null
{
return Auth::user() ?? new User([
'locale' => config('hr.default_locale'),
'name' => 'Guest',
'email' => 'guest@example.com',
'password' => Hash::make('password'),
'email_verified_at' => now(),
'remember_token' => Str::random(10),
'created_at' => now(),
'updated_at' => now(),
]);
}

View File

@@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
class Department extends Model
{
@@ -30,6 +31,38 @@ class Department extends Model
];
}
protected static function booted(): void
{
static::saving(function (Department $department): void {
if (blank($department->code) && filled($department->name)) {
$department->code = static::generateUniqueCodeFromName(
$department->name,
$department->id,
);
}
});
}
public static function generateUniqueCodeFromName(string $name, ?int $ignoreId = null): string
{
$base = Str::upper(Str::slug($name));
$query = static::query()
->when($ignoreId, fn ($query) => $query->where('id', '!=', $ignoreId));
if (! $query->clone()->where('code', $base)->exists()) {
return $base;
}
$maxSuffix = $query->clone()
->where('code', 'like', "{$base}-%")
->pluck('code')
->map(fn (string $code): int => (int) Str::after($code, "{$base}-"))
->max();
return "{$base}-".(($maxSuffix ?? 0) + 1);
}
public function employees(): HasMany
{
return $this->hasMany(Employee::class);

View File

@@ -37,6 +37,7 @@ use App\Policies\UserPolicy;
use App\Policies\VacationPolicy;
use BezhanSalleh\LanguageSwitch\Events\LocaleChanged;
use BezhanSalleh\LanguageSwitch\LanguageSwitch;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
@@ -81,11 +82,11 @@ class AppServiceProvider extends ServiceProvider
->locales(config('hr.supported_locales'))
->labels(config('hr.locale_labels'))
->displayLocale('native')
->userPreferredLocale(fn () => auth()->user()?->locale);
->userPreferredLocale(fn () => user()->locale);
});
Event::listen(function (LocaleChanged $event): void {
auth()->user()?->update(['locale' => $event->locale]);
user()->update(['locale' => $event->locale]);
});
}
}