-
-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
1,949 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
@props(['status']) | ||
|
||
@if ($status) | ||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-gray-400']) }}> | ||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}> | ||
{{ $status }} | ||
</div> | ||
@endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
@props([ | ||
'name', | ||
'show' => false, | ||
'maxWidth' => '2xl' | ||
]) | ||
|
||
@php | ||
$maxWidth = [ | ||
'sm' => 'sm:max-w-sm', | ||
'md' => 'sm:max-w-md', | ||
'lg' => 'sm:max-w-lg', | ||
'xl' => 'sm:max-w-xl', | ||
'2xl' => 'sm:max-w-2xl', | ||
][$maxWidth]; | ||
@endphp | ||
|
||
<div | ||
x-data="{ | ||
show: @js($show), | ||
focusables() { | ||
// All focusable element types... | ||
let selector = 'a, button, input:not([type=\'hidden\']), textarea, select, details, [tabindex]:not([tabindex=\'-1\'])' | ||
return [...$el.querySelectorAll(selector)] | ||
// All non-disabled elements... | ||
.filter(el => ! el.hasAttribute('disabled')) | ||
}, | ||
firstFocusable() { return this.focusables()[0] }, | ||
lastFocusable() { return this.focusables().slice(-1)[0] }, | ||
nextFocusable() { return this.focusables()[this.nextFocusableIndex()] || this.firstFocusable() }, | ||
prevFocusable() { return this.focusables()[this.prevFocusableIndex()] || this.lastFocusable() }, | ||
nextFocusableIndex() { return (this.focusables().indexOf(document.activeElement) + 1) % (this.focusables().length + 1) }, | ||
prevFocusableIndex() { return Math.max(0, this.focusables().indexOf(document.activeElement)) -1 }, | ||
}" | ||
x-init="$watch('show', value => { | ||
if (value) { | ||
document.body.classList.add('overflow-y-hidden'); | ||
{{ $attributes->has('focusable') ? 'setTimeout(() => firstFocusable().focus(), 100)' : '' }} | ||
} else { | ||
document.body.classList.remove('overflow-y-hidden'); | ||
} | ||
})" | ||
x-on:open-modal.window="$event.detail == '{{ $name }}' ? show = true : null" | ||
x-on:close.stop="show = false" | ||
x-on:keydown.escape.window="show = false" | ||
x-on:keydown.tab.prevent="$event.shiftKey || nextFocusable().focus()" | ||
x-on:keydown.shift.tab.prevent="prevFocusable().focus()" | ||
x-show="show" | ||
class="fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50" | ||
style="display: {{ $show ? 'block' : 'none' }};" | ||
> | ||
<div | ||
x-show="show" | ||
class="fixed inset-0 transform transition-all" | ||
x-on:click="show = false" | ||
x-transition:enter="ease-out duration-300" | ||
x-transition:enter-start="opacity-0" | ||
x-transition:enter-end="opacity-100" | ||
x-transition:leave="ease-in duration-200" | ||
x-transition:leave-start="opacity-100" | ||
x-transition:leave-end="opacity-0" | ||
> | ||
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div> | ||
</div> | ||
|
||
<div | ||
x-show="show" | ||
class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto" | ||
x-transition:enter="ease-out duration-300" | ||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" | ||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100" | ||
x-transition:leave="ease-in duration-200" | ||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100" | ||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" | ||
> | ||
{{ $slot }} | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<x-app-layout> | ||
<x-slot name="header"> | ||
<h2 class="font-semibold text-xl leading-tight"> | ||
{{ __('Profile') }} | ||
</h2> | ||
</x-slot> | ||
|
||
<div class="space-y-6"> | ||
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg dark:bg-gray-800"> | ||
<div class="max-w-xl"> | ||
@include('profile.partials.update-profile-information-form') | ||
</div> | ||
</div> | ||
|
||
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg dark:bg-gray-800"> | ||
<div class="max-w-xl"> | ||
@include('profile.partials.update-password-form') | ||
</div> | ||
</div> | ||
|
||
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg dark:bg-gray-800"> | ||
<div class="max-w-xl"> | ||
@include('profile.partials.delete-user-form') | ||
</div> | ||
</div> | ||
</div> | ||
</x-app-layout> |
77 changes: 77 additions & 0 deletions
77
stubs/blade/views/profile/partials/delete-user-form.blade.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<section class="space-y-6"> | ||
<header> | ||
<h2 class="text-lg font-medium"> | ||
{{ __('Delete Account') }} | ||
</h2> | ||
|
||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400"> | ||
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }} | ||
</p> | ||
</header> | ||
|
||
<x-button | ||
variant="danger" | ||
x-data="" | ||
x-on:click.prevent="$dispatch('open-modal', 'confirm-user-deletion')" | ||
> | ||
{{ __('Delete Account') }} | ||
</x-button> | ||
|
||
<x-modal | ||
name="confirm-user-deletion" | ||
:show="$errors->userDeletion->isNotEmpty()" | ||
focusable | ||
> | ||
<form | ||
method="post" | ||
action="{{ route('profile.destroy') }}" | ||
class="p-6" | ||
> | ||
@csrf | ||
@method('delete') | ||
|
||
<h2 class="text-lg font-medium"> | ||
{{ __('Are you sure you want to delete your account?') }} | ||
</h2> | ||
|
||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400"> | ||
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }} | ||
</p> | ||
|
||
<div class="mt-6 space-y-6"> | ||
<x-form.label | ||
for="delete-user-password" | ||
value="Password" | ||
class="sr-only" | ||
/> | ||
|
||
<x-form.input | ||
id="delete-user-password" | ||
name="password" | ||
type="password" | ||
class="block w-3/4" | ||
placeholder="Password" | ||
/> | ||
|
||
<x-form.error :messages="$errors->userDeletion->get('password')" /> | ||
</div> | ||
|
||
<div class="mt-6 flex justify-end"> | ||
<x-button | ||
type="button" | ||
variant="secondary" | ||
x-on:click="$dispatch('close')" | ||
> | ||
{{ __('Cancel') }} | ||
</x-button> | ||
|
||
<x-button | ||
variant="danger" | ||
class="ml-3" | ||
> | ||
{{ __('Delete Account') }} | ||
</x-button> | ||
</div> | ||
</form> | ||
</x-modal> | ||
</section> |
89 changes: 89 additions & 0 deletions
89
stubs/blade/views/profile/partials/update-password-form.blade.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<section> | ||
<header> | ||
<h2 class="text-lg font-medium"> | ||
{{ __('Update Password') }} | ||
</h2> | ||
|
||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400"> | ||
{{ __('Ensure your account is using a long, random password to stay secure.') }} | ||
</p> | ||
</header> | ||
|
||
<form | ||
method="post" | ||
action="{{ route('password.update') }}" | ||
class="mt-6 space-y-6" | ||
> | ||
@csrf | ||
@method('put') | ||
|
||
<div class="space-y-2"> | ||
<x-form.label | ||
for="current_password" | ||
:value="__('Current Password')" | ||
/> | ||
|
||
<x-form.input | ||
id="current_password" | ||
name="current_password" | ||
type="password" | ||
class="block w-full" | ||
autocomplete="current-password" | ||
/> | ||
|
||
<x-form.error :messages="$errors->updatePassword->get('current_password')" /> | ||
</div> | ||
|
||
<div class="space-y-2"> | ||
<x-form.label | ||
for="password" | ||
:value="__('New Password')" | ||
/> | ||
|
||
<x-form.input | ||
id="password" | ||
name="password" | ||
type="password" | ||
class="block w-full" | ||
autocomplete="new-password" | ||
/> | ||
|
||
<x-form.error :messages="$errors->updatePassword->get('password')" /> | ||
</div> | ||
|
||
<div class="space-y-2"> | ||
<x-form.label | ||
for="password_confirmation" | ||
:value="__('Confirm Password')" | ||
/> | ||
|
||
<x-form.input | ||
id="password_confirmation" | ||
name="password_confirmation" | ||
type="password" | ||
class="block w-full" | ||
autocomplete="new-password" | ||
/> | ||
|
||
<x-form.error :messages="$errors->updatePassword->get('password_confirmation')" /> | ||
</div> | ||
|
||
<div class="flex items-center gap-4"> | ||
<x-button> | ||
{{ __('Save') }} | ||
</x-button> | ||
|
||
@if (session('status') === 'password-updated') | ||
<p | ||
x-data="{ show: true }" | ||
x-show="show" | ||
x-transition | ||
x-init="setTimeout(() => show = false, 2000)" | ||
class="text-sm text-gray-600 dark:text-gray-400" | ||
> | ||
{{ __('Saved.') }} | ||
</p> | ||
@endif | ||
</div> | ||
</form> | ||
</section> |
Oops, something went wrong.