Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andreiio committed Aug 19, 2024
1 parent e98f788 commit ee5b48c
Show file tree
Hide file tree
Showing 22 changed files with 960 additions and 95 deletions.
31 changes: 31 additions & 0 deletions app/Concerns/Enums/Arrayable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\Concerns\Enums;

trait Arrayable
{
public static function names(): array
{
return collect(self::cases())
->pluck('name')
->all();
}

public static function values(): array
{
return collect(self::cases())
->pluck('value')
->all();
}

public static function options(): array
{
return collect(self::cases())
->mapWithKeys(fn (self $case) => [
$case->value => $case->getLabel(),
])
->all();
}
}
43 changes: 43 additions & 0 deletions app/Concerns/Enums/Comparable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace App\Concerns\Enums;

use BackedEnum;

trait Comparable
{
/**
* Check if this enum matches the given enum instance or value.
*/
public function is(BackedEnum | string | int | null $enum): bool
{
if ($enum instanceof static) {
return $this->value === $enum->value;
}

return $this->value === $enum;
}

/**
* Check if this enum doesn't match the given enum instance or value.
*/
public function isNot(BackedEnum | string | int | null $enum): bool
{
return ! $this->is($enum);
}

public static function isValue(BackedEnum | string | int | null $subject, BackedEnum $enum): bool
{
if ($subject === null) {
return false;
}

if (! $subject instanceof self) {
$subject = self::tryFrom(\is_int($enum->value) ? (int) $subject : (string) $subject);
}

return $subject?->is($enum) ?? false;
}
}
37 changes: 37 additions & 0 deletions app/Concerns/HasRole.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace App\Concerns;

use App\Enums\User\Role;

trait HasRole
{
public function initializeHasRole(): void
{
$this->casts['role'] = Role::class;

$this->fillable[] = 'role';
}

public function hasRole(Role | string $role): bool
{
return $this->role->is($role);
}

public function isAdmin(): bool
{
return $this->hasRole(Role::ADMIN);
}

public function isContributor(): bool
{
return $this->hasRole(Role::CONTRIBUTOR);
}

public function isViewer(): bool
{
return $this->hasRole(Role::VIEWER);
}
}
28 changes: 28 additions & 0 deletions app/Enums/User/Role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace App\Enums\User;

use App\Concerns\Enums\Arrayable;
use App\Concerns\Enums\Comparable;
use Filament\Support\Contracts\HasLabel;

enum Role: string implements HasLabel
{
use Arrayable;
use Comparable;

case ADMIN = 'admin';
case CONTRIBUTOR = 'contributor';
case VIEWER = 'viewer';

public function getLabel(): ?string
{
return match ($this) {
self::ADMIN => __('app.user.role.admin'),
self::CONTRIBUTOR => __('app.user.role.contributor'),
self::VIEWER => __('app.user.role.viewer'),
};
}
}
154 changes: 154 additions & 0 deletions app/Filament/Resources/UserResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Enums\User\Role;
use App\Filament\Resources\UserResource\Pages;
use App\Models\User;
use Filament\Forms;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Infolists;
use Filament\Infolists\Components\SpatieMediaLibraryImageEntry;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Infolist;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\SpatieMediaLibraryImageColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;

class UserResource extends Resource
{
protected static ?string $model = User::class;

protected static ?string $navigationIcon = 'heroicon-o-users';

protected static ?int $navigationSort = 31;

public static function getNavigationGroup(): ?string
{
return __('admin.navigation.admin');
}

public static function getModelLabel(): string
{
return __('app.user.label.singular');
}

public static function getPluralModelLabel(): string
{
return __('app.user.label.plural');
}

public static function form(Form $form): Form
{
return $form
->columns(1)
->schema([
Forms\Components\Split::make([
SpatieMediaLibraryFileUpload::make('avatar')
->collection('avatar')
->avatar()
->grow(false),

Group::make()
->schema([
TextInput::make('name')
->label(__('admin.field.name'))
->required(),

TextInput::make('email')
->label(__('admin.field.email'))
->required()
->unique(ignoreRecord: true),

Select::make('role')
->label(__('admin.field.role'))
->options(Role::options())
->enum(Role::class)
->reactive()
->required(),
]),
])->from('md'),
]);
}

public static function infolist(Infolist $infolist): Infolist
{
return $infolist
->columns(1)
->schema([
Infolists\Components\Split::make([
SpatieMediaLibraryImageEntry::make('avatar')
->collection('avatar')
->circular()
->grow(false),

Infolists\Components\Group::make()
->schema([
TextEntry::make('name')
->label(__('admin.field.name')),

TextEntry::make('email')
->label(__('admin.field.email')),

TextEntry::make('role')
->label(__('admin.field.role')),
]),
]),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
SpatieMediaLibraryImageColumn::make('avatar')
->collection('avatar')
->conversion('thumb')
->shrink(),

TextColumn::make('name')
->label(__('admin.field.name'))
->searchable(),

TextColumn::make('email')
->label(__('admin.field.email'))
->searchable(),

TextColumn::make('role')
->label(__('admin.field.role')),
])
->filters([
//
])
->actions([
Tables\Actions\ViewAction::make()
->iconButton(),

Tables\Actions\EditAction::make()
->iconButton(),
]);
}

public static function getRelations(): array
{
return [
//
];
}

public static function getPages(): array
{
return [
'index' => Pages\ManageUsers::route('/'),

];
}
}
12 changes: 12 additions & 0 deletions app/Models/Media.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace App\Models;

use Spatie\MediaLibrary\MediaCollections\Models\Media as Model;

class Media extends Model
{
//
}
9 changes: 8 additions & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Concerns\HasRole;
use Database\Factories\UserFactory;
use Filament\Models\Contracts\FilamentUser;
use Filament\Models\Contracts\HasName;
use Filament\Panel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Jeffgreco13\FilamentBreezy\Traits\TwoFactorAuthenticatable;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

class User extends Authenticatable implements FilamentUser, HasName
class User extends Authenticatable implements FilamentUser, HasName, HasMedia
{
use HasRole;
/** @use HasFactory<UserFactory> */
use HasFactory;
use InteractsWithMedia;
use Notifiable;
use TwoFactorAuthenticatable;

protected static string $factory = UserFactory::class;

Expand Down
Loading

0 comments on commit ee5b48c

Please sign in to comment.