diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 9cf74b3..1091ec2 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -3,6 +3,7 @@ namespace Eclipse\Core\Database\Factories; use Eclipse\Core\Models\User; +use Eclipse\World\Models\Country; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; @@ -35,8 +36,11 @@ public function definition(): array 'first_name' => fake()->firstName(), 'last_name' => fake()->lastName(), 'email' => fake()->unique()->safeEmail(), + 'phone_number' => fake()->phoneNumber(), 'email_verified_at' => now(), 'password' => static::$password ??= Hash::make('password'), + 'country_id' => Country::inRandomOrder()->first()?->id ?? Country::factory()->create()->id, + 'date_of_birth' => now()->subYears(rand(20, 40)), 'remember_token' => Str::random(10), 'login_count' => 0, ]; diff --git a/database/migrations/2025_06_24_000000_add_dob_phone_country_columns_to_users_tables.php b/database/migrations/2025_06_24_000000_add_dob_phone_country_columns_to_users_tables.php new file mode 100644 index 0000000..93b6929 --- /dev/null +++ b/database/migrations/2025_06_24_000000_add_dob_phone_country_columns_to_users_tables.php @@ -0,0 +1,49 @@ +string('phone_number', 20) + ->after('email') + ->nullable(); + $table->string('country_id', 2) + ->after('password') + ->nullable(); + $table->date('date_of_birth') + ->after('country_id') + ->nullable(); + + $table->index('phone_number'); + $table->index('country_id'); + $table->index('date_of_birth'); + + $table->foreign('country_id') + ->references('id') + ->on('world_countries') + ->onDelete('set null'); + }); + } + + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropForeign(['country_id']); + + $table->dropIndex(['phone_number']); + $table->dropIndex(['country_id']); + $table->dropIndex(['date_of_birth']); + + $table->dropColumn([ + 'date_of_birth', + 'phone_number', + 'country_id', + ]); + }); + } +}; diff --git a/src/Filament/Resources/UserResource.php b/src/Filament/Resources/UserResource.php index 2839797..10d5055 100644 --- a/src/Filament/Resources/UserResource.php +++ b/src/Filament/Resources/UserResource.php @@ -50,6 +50,9 @@ public static function form(Form $form): Form self::getFirstNameFormComponent(), self::getLastNameFormComponent(), self::getEmailFormComponent(), + Forms\Components\TextInput::make('phone_number') + ->label('Phone') + ->tel(), Forms\Components\DateTimePicker::make('email_verified_at') ->visible(config('eclipse.email_verification')) ->disabled(), @@ -69,6 +72,15 @@ public static function form(Form $form): Form fn (Set $set) => $set('password', Str::password(16)) ) ), + Forms\Components\Select::make('country_id') + ->relationship('country', 'name') + ->preload() + ->optionsLimit(20) + ->searchable(), + Forms\Components\DatePicker::make('date_of_birth') + ->native(false) + ->minDate(now()->subYears(80)) + ->maxDate(now()), Forms\Components\Select::make('roles') ->relationship('roles', 'name') ->saveRelationshipsUsing(function (User $record, $state) { @@ -129,6 +141,9 @@ public static function table(Table $table): Table ->width(150); } + $columns[] = Tables\Columns\TextColumn::make('phone_number') + ->label('Phone'); + $columns[] = Tables\Columns\TextColumn::make('email_verified_at') ->label('Verified email') ->placeholder('Not verified') @@ -138,6 +153,12 @@ public static function table(Table $table): Table ->visible(config('eclipse.email_verification')) ->width(150); + $columns[] = Tables\Columns\TextColumn::make('country.name') + ->badge(); + + $columns[] = Tables\Columns\TextColumn::make('date_of_birth') + ->date('M d, Y'); + $columns[] = Tables\Columns\TextColumn::make('created_at') ->dateTime() ->sortable() @@ -163,6 +184,12 @@ public static function table(Table $table): Table blank: fn (Builder $query) => $query, ) ->visible(config('eclipse.email_verification')), + Tables\Filters\SelectFilter::make('country_id') + ->label('Country') + ->multiple() + ->relationship('country', 'name', fn (Builder $query): Builder => $query->distinct()) + ->preload() + ->optionsLimit(20), Tables\Filters\QueryBuilder::make() ->constraints([ TextConstraint::make('first_name') @@ -231,7 +258,7 @@ public static function infolist(Infolist $infolist): Infolist ->dateTime(), ]), Section::make('Personal information') - ->columns(3) + ->columns(4) ->schema([ SpatieMediaLibraryImageEntry::make('avatar') ->collection('avatars') @@ -245,6 +272,14 @@ public static function infolist(Infolist $infolist): Infolist ->icon(config('eclipse.email_verification') ? fn (User $user) => $user->email_verified_at ? 'heroicon-s-check-circle' : 'heroicon-s-x-circle' : null) ->iconColor(fn (User $user) => $user->email_verified_at ? Color::Green : Color::Red), ]), + Group::make() + ->schema([ + TextEntry::make('phone_number')->placeholder('-'), + TextEntry::make('country.name') + ->badge() + ->placeholder('-'), + ]), + TextEntry::make('date_of_birth')->date('M d, Y')->placeholder('-'), ]), ]); } diff --git a/src/Models/User.php b/src/Models/User.php index 18b2df9..d7b3d56 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -3,6 +3,7 @@ namespace Eclipse\Core\Models; use Eclipse\Core\Database\Factories\UserFactory; +use Eclipse\World\Models\Country; use Eclipse\Core\Settings\UserSettings; use Exception; use Filament\Models\Contracts\FilamentUser; @@ -11,6 +12,7 @@ use Filament\Panel; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; @@ -50,7 +52,10 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasMedia, 'first_name', 'last_name', 'email', + 'phone_number', 'password', + 'country_id', + 'date_of_birth', 'last_login_at', 'login_count', ]; @@ -75,6 +80,7 @@ protected function casts(): array return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', + 'date_of_birth' => 'date', 'last_login_at' => 'datetime', ]; } @@ -89,6 +95,11 @@ public function sites() return $this->belongsToMany(Site::class, 'site_has_user'); } + public function country(): BelongsTo + { + return $this->belongsTo(Country::class); + } + public function getFilamentAvatarUrl(): ?string { return $this->getMedia('avatars')->first()?->getUrl();