diff --git a/README.md b/README.md index 67e9df0..7661d05 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,8 @@

## Built with -- [Laravel 11](https://github.com/laravel/framework) +- [Laravel 12](https://github.com/laravel/framework) - [spatie/laravel-permission](https://github.com/spatie/laravel-permission) -- [Laravel Breeze](https://github.com/laravel/breeze) - [balajidharma/laravel-menu](https://github.com/balajidharma/laravel-menu) - [Vue 3](https://vuejs.org/) - [Tailwind CSS](https://tailwindcss.com/) diff --git a/app/Models/User.php b/app/Models/User.php index 7576d0d..8837b48 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Illuminate\Support\Str; use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable @@ -20,6 +21,7 @@ class User extends Authenticatable protected $fillable = [ 'name', 'email', + 'username', 'password', ]; @@ -41,4 +43,60 @@ class User extends Authenticatable protected $casts = [ 'email_verified_at' => 'datetime', ]; + + public static function boot() + { + parent::boot(); + + static::saving(function ($model) { + $model->setUsername(); + }); + } + + protected function usernameExists(string $username): bool + { + return self::where('username', $username)->exists(); + } + + public function setUsername(): void + { + // Early return if username is already set + if ($this->username) { + return; + } + + $baseUsername = $this->generateBaseUsername(); + $this->username = $this->generateUniqueUsername($baseUsername); + } + + private function generateBaseUsername(): string + { + return Str::of($this->name) + ->ascii() + ->lower() + ->replaceMatches('/[\s._-]+/', '') // Replace multiple special characters at once + ->trim(); + } + + private function generateUniqueUsername(string $baseUsername): string + { + $username = $baseUsername; + + // If base username is already unique, return it + if (! $this->usernameExists($username)) { + return $username; + } + + // Generate a random suffix between 100000 and 999999 + $suffix = random_int(100000, 999999); + $username = $baseUsername.$suffix; + + // In the unlikely case of collision, increment until unique + while ($this->usernameExists($username)) { + $suffix++; + $username = $baseUsername.$suffix; + } + + return $username; + } } diff --git a/composer.json b/composer.json index 05bfc98..9e376fd 100644 --- a/composer.json +++ b/composer.json @@ -6,23 +6,22 @@ "license": "MIT", "require": { "php": "^8.2", - "balajidharma/laravel-admin-core": "^2.0", - "inertiajs/inertia-laravel": "^1.0", - "laravel/framework": "^11.0", + "balajidharma/laravel-admin-core": "^3.0", + "inertiajs/inertia-laravel": "^2.0", + "laravel/framework": "^12.0", "laravel/sanctum": "^4.0", - "laravel/tinker": "^2.9", - "tightenco/ziggy": "^2.0" + "laravel/tinker": "^2.10.1", + "tightenco/ziggy": "^2.4" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.7", "fakerphp/faker": "^1.23", - "laravel/breeze": "^2.0", - "laravel/pint": "^1.13", - "laravel/sail": "^1.26", + "laravel/pail": "^1.2.2", + "laravel/pint": "^1.18", + "laravel/sail": "^1.41", "mockery/mockery": "^1.6", - "nunomaduro/collision": "^8.1", - "phpunit/phpunit": "^10.5", - "spatie/laravel-ignition": "^2.4" + "nunomaduro/collision": "^8.6", + "phpunit/phpunit": "^11.5.3" }, "autoload": { "psr-4": { diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 27ee603..b7947a6 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -15,6 +15,7 @@ public function up(): void $table->id(); $table->string('name'); $table->string('email')->unique(); + $table->string('username')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); diff --git a/resources/js/Pages/Admin/Category/Item/Create.vue b/resources/js/Pages/Admin/Category/Item/Create.vue index d8dc1a9..198d46b 100644 --- a/resources/js/Pages/Admin/Category/Item/Create.vue +++ b/resources/js/Pages/Admin/Category/Item/Create.vue @@ -93,6 +93,7 @@ const form = useForm({ :options="{ enabled: 'Enabled' }" /> diff --git a/resources/js/Pages/Admin/Category/Item/Edit.vue b/resources/js/Pages/Admin/Category/Item/Edit.vue index 4e5cff6..7c01458 100644 --- a/resources/js/Pages/Admin/Category/Item/Edit.vue +++ b/resources/js/Pages/Admin/Category/Item/Edit.vue @@ -98,6 +98,7 @@ const form = useForm({ :options="{ enabled: 'Enabled' }" />