From d720934533b9e66c82ba54f6d7b43e33af7acf75 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sun, 4 Jan 2026 22:24:55 +0700 Subject: [PATCH] feat: implement member account settings page for profile and password updates --- .../Forms/Member/Setting/ProfileForm.php | 58 +++++++ app/Livewire/Member/Setting/Account.php | 90 +++++++++++ app/Livewire/Studio/Setting/Account.php | 4 +- .../sections/ui/member/_header.blade.php | 4 +- .../livewire/member/setting/account.blade.php | 144 ++++++++++++++++++ .../livewire/studio/setting/account.blade.php | 2 +- routes/pages/member.php | 2 + tests/Feature/Member/Setting/AccountTest.php | 71 +++++++++ 8 files changed, 370 insertions(+), 5 deletions(-) create mode 100644 app/Livewire/Forms/Member/Setting/ProfileForm.php create mode 100644 app/Livewire/Member/Setting/Account.php create mode 100644 resources/views/livewire/member/setting/account.blade.php create mode 100644 tests/Feature/Member/Setting/AccountTest.php diff --git a/app/Livewire/Forms/Member/Setting/ProfileForm.php b/app/Livewire/Forms/Member/Setting/ProfileForm.php new file mode 100644 index 0000000..9284cd3 --- /dev/null +++ b/app/Livewire/Forms/Member/Setting/ProfileForm.php @@ -0,0 +1,58 @@ + ['required', 'string', 'max:100'], + 'phone_number' => ['required', 'string', new PhoneNumber], + 'gender' => ['required', Rule::in(Gender::cases())], + ]; + } + + public function validationAttributes(): array + { + return [ + 'name' => 'nama lengkap', + 'phone_number' => 'nomor telepon', + 'gender' => 'jenis kelamin', + ]; + } + + public function setProfile(Customer $customer): void + { + $this->customer = $customer; + + $this->name = $customer->name; + $this->phone_number = $customer->phone_number; + $this->gender = $customer->gender->value; + } + + public function update(): void + { + $this->validate(); + + $this->customer->update([ + 'name' => $this->name, + 'phone_number' => $this->phone_number, + 'gender' => $this->gender, + ]); + } +} diff --git a/app/Livewire/Member/Setting/Account.php b/app/Livewire/Member/Setting/Account.php new file mode 100644 index 0000000..2253653 --- /dev/null +++ b/app/Livewire/Member/Setting/Account.php @@ -0,0 +1,90 @@ +user(); + + $this->accountForm->setAccount($user); + + $customer = $user->customer; + $this->hasMemberData = (bool) $customer; + + if ($this->hasMemberData) { + $this->profileForm->setProfile($customer); + } + + $this->passwordForm->setUser($user); + } + + public function updateAccount(): void + { + $this->accountForm->update(); + + $this->toast('Akun berhasil diperbarui.'); + } + + public function updateProfile(): void + { + if (! $this->hasMemberData) { + return; + } + + $this->profileForm->update(); + + $this->toast('Profil member berhasil diperbarui.'); + } + + public function updatePassword(): void + { + if (! Hash::check($this->passwordForm->current_password, auth()->user()->password)) { + $this->toast('Kata sandi yang Anda masukkan tidak sesuai dengan kata sandi saat ini.', 'Gagal', 'danger'); + + return; + } + + auth()->logoutOtherDevices($this->passwordForm->current_password); + + $this->passwordForm->update(); + + auth()->logout(); + session()->invalidate(); + session()->regenerateToken(); + + $this->toast('Kata sandi berhasil diperbarui. Silakan masuk kembali.'); + + $this->redirectRoute('login', navigate: true); + } + + public function render(): View + { + return view('livewire.member.setting.account', [ + 'pageTitle' => 'Pengaturan Akun', + ]); + } +} diff --git a/app/Livewire/Studio/Setting/Account.php b/app/Livewire/Studio/Setting/Account.php index 93f21ee..c6dec61 100644 --- a/app/Livewire/Studio/Setting/Account.php +++ b/app/Livewire/Studio/Setting/Account.php @@ -66,10 +66,10 @@ public function updatePassword(): void return; } - $this->passwordForm->update(); - auth()->logoutOtherDevices($this->passwordForm->current_password); + $this->passwordForm->update(); + auth()->logout(); session()->invalidate(); session()->regenerateToken(); diff --git a/resources/views/components/sections/ui/member/_header.blade.php b/resources/views/components/sections/ui/member/_header.blade.php index dc4236e..4db5601 100644 --- a/resources/views/components/sections/ui/member/_header.blade.php +++ b/resources/views/components/sections/ui/member/_header.blade.php @@ -1,4 +1,4 @@ @include('components.sections.ui.shared._header', [ - 'profileName' => auth()->user()?->customer?->name, - 'settingsRoute' => route('studio.setting.account', auth()->id()) + 'profileName' => auth()->user()?->customer?->name ?? auth()->user()->username, + 'settingsRoute' => route('member.setting'), ]) diff --git a/resources/views/livewire/member/setting/account.blade.php b/resources/views/livewire/member/setting/account.blade.php new file mode 100644 index 0000000..e64b0fb --- /dev/null +++ b/resources/views/livewire/member/setting/account.blade.php @@ -0,0 +1,144 @@ + +
+
+ {{ $pageTitle }} +
+
+ +
+ + +
+
+ Akun + Pengaturan untuk kredensial masuk Anda. +
+ +
+
+
+
+ + Nama Pengguna * + + + + + + Email * + + + + + + + + +
+
+
+ +
+ + Simpan + +
+
+
+
+ + @if ($hasMemberData) + + +
+
+ Profil Member + Informasi mengenai data keanggotaan Anda. +
+ +
+
+
+
+
+ + Nama Lengkap * + + + + +
+ + + Nomor Telepon * + + + + + + Jenis Kelamin * + + @foreach (\App\Enums\Gender::cases() as $gender) + + {{ $gender->label() }} + + @endforeach + + + +
+
+
+ +
+ + Simpan + +
+
+
+ @endif + + + +
+
+ Kata Sandi + Atur ulang kata sandi Anda. +
+ +
+ + Kata Sandi Saat Ini * + + + + + + Kata Sandi Baru * + + + + + + Konfirmasi Kata Sandi Baru* + + + + +
+ + Simpan + +
+
+
+
diff --git a/resources/views/livewire/studio/setting/account.blade.php b/resources/views/livewire/studio/setting/account.blade.php index b313a59..32c7ad6 100644 --- a/resources/views/livewire/studio/setting/account.blade.php +++ b/resources/views/livewire/studio/setting/account.blade.php @@ -156,7 +156,7 @@ class="w-full *:flex-1"> - Konfirmasi Kata Sandi * + Konfirmasi Kata Sandi Baru* diff --git a/routes/pages/member.php b/routes/pages/member.php index 5f66438..b5c629c 100644 --- a/routes/pages/member.php +++ b/routes/pages/member.php @@ -3,6 +3,7 @@ use App\Livewire\Member\Membership; use App\Livewire\Member\Overview; use App\Livewire\Member\RedeemPoint; +use App\Livewire\Member\Setting\Account; use App\Livewire\Member\Voucher; use Illuminate\Support\Facades\Route; @@ -14,4 +15,5 @@ Route::get('vouchers', Voucher::class)->name('voucher'); Route::get('memberships', Membership::class)->name('membership'); Route::get('redeem-points', RedeemPoint::class)->name('redeem_point'); + Route::get('settings', Account::class)->name('setting'); }); diff --git a/tests/Feature/Member/Setting/AccountTest.php b/tests/Feature/Member/Setting/AccountTest.php new file mode 100644 index 0000000..a301fa1 --- /dev/null +++ b/tests/Feature/Member/Setting/AccountTest.php @@ -0,0 +1,71 @@ +setupUser(); +}); + +it('renders member setting account page', function () { + $this->actingAs($this->user); + + Livewire::test(Account::class) + ->assertStatus(200) + ->assertSee('Pengaturan Akun'); +}); + +it('can update account information', function () { + $this->actingAs($this->user); + + Livewire::test(Account::class) + ->set('accountForm.username', 'newusername') + ->set('accountForm.email', 'new@example.com') + ->call('updateAccount') + ->assertHasNoErrors(); + + $this->assertDatabaseHas('users', [ + 'id' => $this->user->id, + 'username' => 'newusername', + 'email' => 'new@example.com', + ]); +}); + +it('can update member profile when customer exists', function () { + $this->actingAs($this->user); + $customer = Customer::factory()->for($this->user)->create([ + 'name' => 'Old Name', + 'phone_number' => '0812 3456 7890', + 'gender' => Gender::MALE, + ]); + + Livewire::test(Account::class) + ->set('profileForm.name', 'New Name') + ->set('profileForm.phone_number', '0812 3456 7891') + ->set('profileForm.gender', Gender::FEMALE->value) + ->call('updateProfile') + ->assertHasNoErrors(); + + $this->assertDatabaseHas('customers', [ + 'id' => $customer->id, + 'name' => 'New Name', + 'phone_number' => '0812 3456 7891', + 'gender' => Gender::FEMALE->value, + ]); +}); + +it('can change password', function () { + $this->actingAs($this->user); + $this->user->update(['password' => Hash::make('OldPassword123!')]); + + Livewire::test(Account::class) + ->set('passwordForm.current_password', 'OldPassword123!') + ->set('passwordForm.new_password', '@Member#2026_Settings!') + ->set('passwordForm.new_confirm_password', '@Member#2026_Settings!') + ->call('updatePassword') + ->assertHasNoErrors() + ->assertRedirect(route('login')); +});