diff --git a/app/Components/User/Manager.php b/app/Components/User/Manager.php
new file mode 100644
index 0000000..baf87e0
--- /dev/null
+++ b/app/Components/User/Manager.php
@@ -0,0 +1,141 @@
+allRoles = Role::all()->toArray();
+ }
+
+ public function updatedPerPage(int $value): void
+ {
+ $this->resetPage();
+ }
+
+ public function updatedSearch(string $value): void
+ {
+ $this->resetPage();
+ }
+
+ #[On('userSaved')]
+ public function showIndex(): void
+ {
+ $this->mode = 'index';
+ $this->resetPage();
+ $this->resetForm();
+ }
+
+ public function showForm(?int $id = null): void
+ {
+ $this->mode = 'form';
+ $this->editingId = $id;
+
+ if ($id) {
+ $user = User::with('roles')->findOrFail($id);
+ $this->fullname = $user->fullname;
+ $this->email = $user->email;
+ $this->roles = $user->roles->pluck('name')->toArray();
+ } else {
+ $this->resetForm();
+ }
+ }
+
+ protected function resetForm(): void
+ {
+ $this->fullname = '';
+ $this->email = '';
+ $this->password = '';
+ $this->password_confirmation = '';
+ $this->roles = [];
+ $this->editingId = null;
+ }
+
+ public function delete(int $id): void
+ {
+ User::findOrFail($id)->delete();
+ session()->flash('message', 'User deleted.');
+ $this->resetPage();
+ }
+
+ public function save(): void
+ {
+ $rules = [
+ 'fullname' => ['required', 'string', 'max:255'],
+ 'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')->ignore($this->editingId)],
+ 'roles' => ['nullable', 'array'],
+ 'roles.*' => ['string', Rule::exists('roles', 'name')],
+ ];
+
+ if (! $this->editingId) {
+ $rules['password'] = ['required', 'string', 'min:6', 'confirmed'];
+ } elseif ($this->password) {
+ $rules['password'] = ['string', 'min:6', 'confirmed'];
+ }
+
+ $this->validate($rules);
+
+ $user = $this->editingId
+ ? User::findOrFail($this->editingId)
+ : new User;
+
+ $user->fullname = $this->fullname;
+ $user->email = $this->email;
+
+ if ($this->password) {
+ $user->password = $this->password;
+ }
+
+ $user->save();
+ $user->syncRoles($this->roles);
+
+ session()->flash('message', 'User saved.');
+ $this->dispatch('userSaved');
+ }
+
+ public function render()
+ {
+ $users = User::with('roles')
+ ->when(
+ $this->search,
+ fn($q) => $q
+ ->where('fullname', 'like', "%{$this->search}%")
+ ->orWhere('email', 'like', "%{$this->search}%")
+ )
+ ->orderByDesc('id')
+ ->paginate($this->perPage);
+
+ return view('components.user.manager', [
+ 'users' => $users,
+ 'allRoles' => collect($this->allRoles),
+ 'title' => $this->mode === 'index'
+ ? 'Users'
+ : ($this->editingId ? 'Edit User' : 'Create User'),
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
new file mode 100644
index 0000000..f8d1206
--- /dev/null
+++ b/app/Http/Controllers/UserController.php
@@ -0,0 +1,13 @@
+ 'hashed',
];
}
+ // Mutator to hash the password using md5 before saving.
+ // Note: Using md5 for passwords is insecure. Consider using bcrypt or Argon2 instead.
+ public function setPasswordAttribute($value)
+ {
+ if ($value !== null && $value !== '') {
+ $this->attributes['password'] = md5($value);
+ }
+ }
}
diff --git a/resources/views/admin/users/manager.blade.php b/resources/views/admin/users/manager.blade.php
new file mode 100644
index 0000000..f257ac2
--- /dev/null
+++ b/resources/views/admin/users/manager.blade.php
@@ -0,0 +1,5 @@
+@extends('layouts.app')
+
+@section('content')
+
ID | +Full Name | +Role | +Phone | +Actions | +|
---|---|---|---|---|---|
{{ $u->id }} | +{{ $u->fullname }} | +{{ $u->email }} | +{{ $u->roles->pluck('name')->join(', ') }} | +{{ $u->phone }} | ++ + + | +
No users found. | +