Initial commit
This commit is contained in:
188
resources/views/profile/delete-user-form.blade.php
Normal file
188
resources/views/profile/delete-user-form.blade.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<x-jetstream.action-section>
|
||||
<x-slot name="title">
|
||||
{{ trans_with_platform( __('Delete your @PLATFORM_NAME@ profile')) }}
|
||||
</x-slot>
|
||||
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Permanently erase your digital footprint.') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<div class="font-medium text-theme-text-primary">
|
||||
{{ __('Ready to close your account?')}}
|
||||
</div>
|
||||
<div class="max-w-xl text-sm text-theme-secondary my-3">
|
||||
{{ __('Before deleting your account, please download all your personal data, transactions and messages that you wish to retain.') }}
|
||||
</div>
|
||||
<div class="my-6">
|
||||
<x-jetstream.button wire:click="confirmUserDeletion" wire:loading.attr="disabled">
|
||||
<x-icon class="mr-3 h-5 w-5" name="exclamation-triangle" />
|
||||
{{ __('Delete profile') }}
|
||||
</x-jetstream.button>
|
||||
</div>
|
||||
|
||||
<!-- Delete User Confirmation Modal -->
|
||||
<x-jetstream.dialog-modal wire:model.live="confirmingUserDeletion">
|
||||
<x-slot name="title">
|
||||
{{ trans_with_platform( __('Delete your @PLATFORM_NAME@ profile')) }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<div class="font-semibold text-red-600">
|
||||
{{ __('Are you sure you want to delete your profile? This step is irriversable.') }}
|
||||
</div>
|
||||
<div class="my-3">
|
||||
{{ __('Once your profile is deleted, all of its balance totals and data will be permanently deleted. All your transactions will be anonymized, also in the online transaction overviews and statements of other ' . platform_name() . ' users.')}}
|
||||
</div>
|
||||
<div>
|
||||
{{ __('Before deleting your account, please download all your personal data, transactions and messages that you wish to retain.') }}
|
||||
</div>
|
||||
{{-- Account Balances Overview --}}
|
||||
@if($accounts && $accounts->count() > 0)
|
||||
<div class="mt-6 p-4 bg-gray-50 rounded-lg border border-gray-200">
|
||||
<h4 class="text-sm font-semibold text-gray-700 mb-3">{{ __('Your accounts') }}</h4>
|
||||
|
||||
<div class="space-y-2">
|
||||
@foreach($accounts as $account)
|
||||
<div class="flex justify-between items-center text-sm">
|
||||
<span class="text-gray-600">{{ $account['name'] }}</span>
|
||||
<span class="font-medium {{ $account['balance'] < 0 ? 'text-red-600' : 'text-gray-900' }}">
|
||||
{{ $account['balanceFormatted'] }}
|
||||
</span>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<div class="pt-2 mt-2 border-t border-gray-300 flex justify-between items-center">
|
||||
<span class="text-sm font-semibold text-gray-700">{{ __('Total balance') }}</span>
|
||||
<span class="text-base font-bold {{ $totalBalance < 0 ? 'text-red-600' : 'text-gray-900' }}">
|
||||
{{ tbFormat($totalBalance) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Central Bank Warning --}}
|
||||
@if($isCentralBank)
|
||||
<div class="mt-4 p-4 bg-red-50 border border-red-200 rounded-lg">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-red-600 mt-0.5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-red-800">{{ __('Central bank cannot be deleted') }}</div>
|
||||
<p class="mt-1 text-sm text-red-700">{{ __('This is the central bank (level 0) and cannot be removed from the system. Central banks are essential for currency creation and management.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Final Admin Warning --}}
|
||||
@if($isFinalAdmin)
|
||||
<div class="mt-4 p-4 bg-red-50 border border-red-200 rounded-lg">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-red-600 mt-0.5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-red-800">{{ __('Final administrator cannot be deleted') }}</div>
|
||||
<p class="mt-1 text-sm text-red-700">{{ __('At least one administrator account must remain active in the system.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Negative Balance Warning --}}
|
||||
@if($hasNegativeBalance)
|
||||
<div class="mt-4 p-4 bg-red-50 border border-red-200 rounded-lg">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-red-600 mt-0.5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-red-800">{{ __('Cannot delete profile with negative balance') }}</div>
|
||||
<p class="mt-1 text-sm text-red-700">{{ __('You must settle all debts before you can delete your profile. Please ensure all your account balances are zero or positive.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Balance Handling Options --}}
|
||||
@if($showBalanceOptions && $totalBalance != 0 && !$hasNegativeBalance && !$isCentralBank && !$isFinalAdmin)
|
||||
<div class="mt-6">
|
||||
<x-jetstream.label for="balanceHandlingOption" value="{{ __('What would you like to do with your remaining balance?') }}" />
|
||||
|
||||
<div class="mt-3 space-y-3">
|
||||
<label class="flex items-start">
|
||||
<input type="radio" wire:model.live="balanceHandlingOption" value="donate" class="mt-1 text-theme-brand focus:border-theme-accent focus:ring-1 focus:ring-theme-accent">
|
||||
<span class="ml-3">
|
||||
<span class="block text-sm font-medium text-theme-primary">{{ __('Donate to an organization') }}</span>
|
||||
<span class="block text-sm text-theme-muted">{{ __('Transfer your remaining balance to an organization of your choice') }}</span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label class="flex items-start">
|
||||
<input type="radio" wire:model.live="balanceHandlingOption" value="delete" class="mt-1 text-theme-brand focus:border-theme-accent focus:ring-1 focus:ring-theme-accent">
|
||||
<span class="ml-3">
|
||||
<span class="block text-sm font-medium text-theme-primary">{{ __('Delete balance') }}</span>
|
||||
<span class="block text-sm text-theme-muted">{{ __('Permanently delete your balance total') }}</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@if($balanceHandlingOption === 'donate')
|
||||
<div class="mt-4">
|
||||
<livewire:to-account-organization-only :label="__('Select organization account')" />
|
||||
<x-jetstream.input-error for="donationAccountId" class="mt-2" />
|
||||
|
||||
@if($donationExceedsLimit && $donationLimitError)
|
||||
<div class="mt-4 p-4 bg-red-50 border border-red-200 rounded-lg">
|
||||
<div class="flex items-start">
|
||||
<svg class="w-5 h-5 text-red-600 mt-0.5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-red-800">{{ __('Donation exceeds account limits') }}</div>
|
||||
<p class="mt-1 text-sm text-red-700">{{ $donationLimitError }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(!$isCentralBank && !$hasNegativeBalance && !$isFinalAdmin)
|
||||
<div class="mt-4" x-data="{}" x-on:confirming-delete-user.window="setTimeout(() => $refs.password.focus(), 250)">
|
||||
<x-jetstream.input type="password" class="mt-1 block w-3/4"
|
||||
placeholder="{{ getActiveProfileType() == 'Organization' ?
|
||||
__('Password of') . ' ' . auth()->guard('web')->user()->name :
|
||||
__('Password of') . ' ' . getActiveProfile()->name }}"
|
||||
x-ref="password"
|
||||
wire:model="password"
|
||||
wire:keydown.enter="deleteUser" />
|
||||
|
||||
<x-jetstream.input-error for="password" class="mt-2" />
|
||||
</div>
|
||||
@endif
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="footer">
|
||||
<x-jetstream.secondary-button wire:click="$toggle('confirmingUserDeletion')" wire:loading.attr="disabled">
|
||||
{{ __('Cancel') }}
|
||||
</x-jetstream.secondary-button>
|
||||
|
||||
<x-jetstream.danger-button
|
||||
class="ml-3"
|
||||
wire:click="deleteUser"
|
||||
wire:loading.attr="disabled"
|
||||
:disabled="$hasNegativeBalance || $isCentralBank || $isFinalAdmin || $donationExceedsLimit">
|
||||
<x-icon class="mr-3 h-5 w-5" name="exclamation-triangle" />
|
||||
{{ __('Delete profile') }}
|
||||
</x-jetstream.danger-button>
|
||||
</x-slot>
|
||||
</x-jetstream.dialog-modal>
|
||||
</x-slot>
|
||||
</x-jetstream.action-section>
|
||||
@@ -0,0 +1,97 @@
|
||||
<x-jetstream.action-section>
|
||||
<x-slot name="title">
|
||||
{{ __('Browser Sessions') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Manage and log out your active sessions on other browsers and devices.') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<div class="max-w-xl text-sm text-gray-600">
|
||||
{{ __('If necessary, you may log out of all of your other browser sessions across all of your devices. Some of your recent sessions are listed below; however, this list may not be exhaustive. If you feel your account has been compromised, you should also update your password.') }}
|
||||
</div>
|
||||
|
||||
@if (count($this->sessions) > 0)
|
||||
<div class="mt-5 space-y-6">
|
||||
<!-- Other Browser Sessions -->
|
||||
@foreach ($this->sessions as $session)
|
||||
<div class="flex items-center">
|
||||
<div>
|
||||
@if ($session->agent->isDesktop())
|
||||
<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor" class="w-8 h-8 text-gray-500">
|
||||
<path d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
@else
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" class="w-8 h-8 text-gray-500">
|
||||
<path d="M0 0h24v24H0z" stroke="none"></path><rect x="7" y="4" width="10" height="16" rx="1"></rect><path d="M11 5h2M12 17v.01"></path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="ml-3">
|
||||
<div class="text-sm text-gray-600">
|
||||
{{ $session->agent->platform() ? $session->agent->platform() : 'Unknown' }} - {{ $session->agent->browser() ? $session->agent->browser() : 'Unknown' }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-xs text-gray-500">
|
||||
{{ $session->ip_address }},
|
||||
|
||||
@if ($session->is_current_device)
|
||||
<span class="text-green-500 font-semibold">{{ __('This device') }}</span>
|
||||
@else
|
||||
{{ __('Last active') }} {{ $session->last_active }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="flex items-center mt-5">
|
||||
<x-jetstream.button wire:click="confirmLogout" wire:loading.attr="disabled">
|
||||
{{ __('Log out other browser sessions') }}
|
||||
</x-jetstream.button>
|
||||
|
||||
<x-jetstream.action-message class="ml-3" on="loggedOut">
|
||||
{{ __('Done.') }}
|
||||
</x-jetstream.action-message>
|
||||
</div>
|
||||
|
||||
<!-- Log out Other Devices Confirmation Modal -->
|
||||
<x-jetstream.dialog-modal wire:model.live="confirmingLogout">
|
||||
<x-slot name="title">
|
||||
{{ __('Log out other browser sessions') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
{{ __('Please enter your password to confirm you would like to log out of your other browser sessions across all of your devices.') }}
|
||||
|
||||
<div class="mt-4" x-data="{}" x-on:confirming-logout-other-browser-sessions.window="setTimeout(() => $refs.password.focus(), 250)">
|
||||
<x-jetstream.input type="password" class="mt-1 block w-3/4"
|
||||
placeholder="{{ __('Password') }}"
|
||||
x-ref="password"
|
||||
wire:model="password"
|
||||
wire:keydown.enter="logoutOtherBrowserSessions" />
|
||||
|
||||
<x-jetstream.input-error for="password" class="mt-2" />
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="footer">
|
||||
<x-jetstream.secondary-button wire:click="$toggle('confirmingLogout')" wire:loading.attr="disabled">
|
||||
{{ __('Cancel') }}
|
||||
</x-jetstream.secondary-button>
|
||||
|
||||
<x-jetstream.button class="ml-3"
|
||||
wire:click="logoutOtherBrowserSessions"
|
||||
wire:loading.attr="disabled">
|
||||
{{ __('Log out other browser sessions') }}
|
||||
</x-jetstream.button>
|
||||
</x-slot>
|
||||
</x-jetstream.dialog-modal>
|
||||
</x-slot>
|
||||
</x-jetstream.action-section>
|
||||
27
resources/views/profile/not_found.blade.php
Normal file
27
resources/views/profile/not_found.blade.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
{{ __('Profile not found') }}
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8 justify-between">
|
||||
<div class="overflow-hidden bg-white shadow-xl sm:rounded-lg">
|
||||
<div class="border-b border-gray-200 mx-auto bg-white p-6 sm:px-20">
|
||||
|
||||
<div class="mt-12">
|
||||
<!-- TODO: insert not found image here -->
|
||||
|
||||
<div class="mt-8 text-5xl font-bold text-gray-900">
|
||||
{{ __('Sorry, we can not find this profile.') }}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="mb-12 mt-6">
|
||||
<span class="text-xl font-bold text-gray-900">{{ __('This profile might be inactive, incomplete, or it may have been removed.') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
53
resources/views/profile/settings.blade.php
Normal file
53
resources/views/profile/settings.blade.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
{{ __('Settings') }}
|
||||
</x-slot>
|
||||
|
||||
<div>
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||
@if (Laravel\Fortify\Features::canUpdateProfileInformation())
|
||||
@livewire('profile.update-settings-form')
|
||||
<x-jetstream.section-border />
|
||||
@livewire('profile.update-profile-phone-form')
|
||||
<x-jetstream.section-border />
|
||||
@endif
|
||||
|
||||
@if (Laravel\Fortify\Features::enabled(Laravel\Fortify\Features::updatePasswords()))
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('profile.update-password-form')
|
||||
</div>
|
||||
<x-jetstream.section-border />
|
||||
@endif
|
||||
{{-- Anchor used in email footer--}}
|
||||
<div id="message_settings"/>
|
||||
@if (Laravel\Fortify\Features::canManageTwoFactorAuthentication())
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('profile.two-factor-authentication-form')
|
||||
</div>
|
||||
<x-jetstream.section-border />
|
||||
@endif
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('profile.update-message-settings-form')
|
||||
</div>
|
||||
<x-jetstream.section-border />
|
||||
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('profile.export-profile-data')
|
||||
</div>
|
||||
<x-jetstream.section-border />
|
||||
|
||||
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('profile.logout-other-browser-sessions-form')
|
||||
</div>
|
||||
<x-jetstream.section-border />
|
||||
|
||||
|
||||
@if (Laravel\Jetstream\Jetstream::hasAccountDeletionFeatures())
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('profile.delete-user-form')
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
95
resources/views/profile/show.blade.php
Normal file
95
resources/views/profile/show.blade.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
{{ $header }}
|
||||
</x-slot>
|
||||
|
||||
<div class="py-6">
|
||||
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
|
||||
@livewire('profile.show', [
|
||||
'profile' => $profile,
|
||||
'inactive' => $inactive ?? false,
|
||||
'hidden' => $hidden ?? false,
|
||||
'inactiveLabel' => $inactiveLabel ?? false,
|
||||
'inactiveSince' => $inactiveSince ?? null,
|
||||
'registerDate' => $registerDate ?? null,
|
||||
'lastLoginDate' => $lastLoginDate ?? null,
|
||||
'emailUnverifiedLabel' => $emailUnverifiedLabel ?? false,
|
||||
'isIncomplete' => $isIncomplete ?? false,
|
||||
'incompleteLabel' => $incompleteLabel ?? false,
|
||||
'noExchangesYetLabel' => $noExchangesYetLabel ?? false,
|
||||
'removedSince' => $removedSince ?? null,
|
||||
])
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($showIncompleteWarning ?? false)
|
||||
<!-- Incomplete Profile Warning Modal -->
|
||||
<div x-data="{ show: true }"
|
||||
x-show="show"
|
||||
x-init="$watch('show', value => { if (value) { document.body.classList.add('overflow-y-hidden'); } else { document.body.classList.remove('overflow-y-hidden'); } })"
|
||||
x-on:keydown.escape.window="show = false"
|
||||
class="jetstream-modal fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50"
|
||||
style="display: none;">
|
||||
|
||||
<!-- Backdrop -->
|
||||
<div x-show="show"
|
||||
x-on:click="show = false"
|
||||
class="fixed inset-0 bg-black opacity-50"
|
||||
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>
|
||||
|
||||
<!-- Modal Content -->
|
||||
<div x-show="show"
|
||||
class="mb-6 bg-theme-background rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full sm:max-w-2xl 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">
|
||||
|
||||
<div class="px-6 py-6">
|
||||
<!-- Header with Close Button -->
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-8 h-8 text-theme-text-primary" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<div class="text-xl font-medium text-theme-primary">
|
||||
{{ __('Your profile is currently hidden') }}
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" @click="show = false" class="text-theme-primary hover:text-theme-secondary transition-colors">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Content from side-post -->
|
||||
<div class="text-theme-primary">
|
||||
@livewire('side-post', [
|
||||
'type' => 'SiteContents\\ProfileIncomplete',
|
||||
'sticky' => true,
|
||||
'fallbackTitle' => __('Your profile is currently hidden'),
|
||||
'fallbackDescription' => __('Your profile is currently not visible to other users and organizations because it is incomplete.')
|
||||
])
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="flex justify-end mt-6 pt-6">
|
||||
<x-jetstream.secondary-button @click="show = false" type="button">
|
||||
{{ __('Close') }}
|
||||
</x-jetstream.secondary-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</x-app-layout>
|
||||
126
resources/views/profile/two-factor-authentication-form.blade.php
Normal file
126
resources/views/profile/two-factor-authentication-form.blade.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<div id="two-factor-authentication-form" class="scroll-mt-[100px]">
|
||||
<x-jetstream.action-section>
|
||||
<x-slot name="title">
|
||||
{{ __('Two Factor Authentication') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Add additional security to your account using two factor authentication.') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<div class="font-medium text-theme-text-primary">
|
||||
@if ($this->enabled)
|
||||
@if ($showingConfirmation)
|
||||
{{ __('Finish enabling two factor authentication') }}
|
||||
@else
|
||||
{{ __('You have enabled two factor authentication') }}
|
||||
@endif
|
||||
@else
|
||||
{{ __('You have not enabled two factor authentication') }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-3 max-w-xl text-sm text-gray-600">
|
||||
<p>
|
||||
{{ __('When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone\'s Two Factor Authenticator application.') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@if ($this->enabled)
|
||||
@if ($showingQrCode)
|
||||
<div class="mt-4 max-w-xl text-sm text-gray-600">
|
||||
<p class="font-semibold">
|
||||
@if ($showingConfirmation)
|
||||
{{ __('To finish enabling two factor authentication, scan the following QR code using your phone\'s authenticator application or enter the setup key and provide the generated OTP code.') }}
|
||||
@else
|
||||
{{ __('Two factor authentication is now enabled. Scan the following QR code using your phone\'s authenticator application or enter the setup key.') }}
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{!! $this->user->twoFactorQrCodeSvg() !!}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 max-w-xl text-sm text-gray-600">
|
||||
<p class="font-semibold">
|
||||
{{ __('Setup Key') }}: {{ decrypt($this->user->two_factor_secret) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@if ($showingConfirmation)
|
||||
<div class="mt-4">
|
||||
<x-jetstream.label for="code" value="{{ __('Code') }}" />
|
||||
|
||||
<x-jetstream.input id="code" type="text" name="code" class="block mt-1 w-1/2" inputmode="numeric" autofocus autocomplete="one-time-code"
|
||||
wire:model="code"
|
||||
wire:keydown.enter="confirmTwoFactorAuthentication" />
|
||||
|
||||
<x-jetstream.input-error for="code" class="mt-2" />
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@if ($showingRecoveryCodes)
|
||||
<div class="mt-4 max-w-xl text-sm text-gray-600">
|
||||
<p class="font-semibold">
|
||||
{{ __('Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-1 max-w-xl mt-4 px-4 py-4 font-mono text-sm bg-gray-100 rounded-lg">
|
||||
@foreach (json_decode(decrypt($this->user->two_factor_recovery_codes), true) as $code)
|
||||
<div>{{ $code }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
<div class="my-6">
|
||||
@if (! $this->enabled)
|
||||
<x-jetstream.confirms-password wire:then="enableTwoFactorAuthentication">
|
||||
<x-jetstream.button type="button" wire:loading.attr="disabled">
|
||||
{{ __('Enable') }}
|
||||
</x-jetstream.button>
|
||||
</x-jetstream.confirms-password>
|
||||
@else
|
||||
@if ($showingRecoveryCodes)
|
||||
<x-jetstream.confirms-password wire:then="regenerateRecoveryCodes">
|
||||
<x-jetstream.secondary-button class="mr-3">
|
||||
{{ __('Regenerate Recovery Codes') }}
|
||||
</x-jetstream.secondary-button>
|
||||
</x-jetstream.confirms-password>
|
||||
@elseif ($showingConfirmation)
|
||||
<x-jetstream.confirms-password wire:then="confirmTwoFactorAuthentication">
|
||||
<x-jetstream.button type="button" class="mr-3" wire:loading.attr="disabled">
|
||||
{{ __('Confirm') }}
|
||||
</x-jetstream.button>
|
||||
</x-jetstream.confirms-password>
|
||||
@else
|
||||
<x-jetstream.confirms-password wire:then="showRecoveryCodes">
|
||||
<x-jetstream.secondary-button class="mr-3">
|
||||
{{ __('Show Recovery Codes') }}
|
||||
</x-jetstream.secondary-button>
|
||||
</x-jetstream.confirms-password>
|
||||
@endif
|
||||
|
||||
@if ($showingConfirmation)
|
||||
<x-jetstream.confirms-password wire:then="disableTwoFactorAuthentication">
|
||||
<x-jetstream.secondary-button wire:loading.attr="disabled">
|
||||
{{ __('Cancel') }}
|
||||
</x-jetstream.secondary-button>
|
||||
</x-jetstream.confirms-password>
|
||||
@else
|
||||
<x-jetstream.confirms-password wire:then="disableTwoFactorAuthentication">
|
||||
<x-jetstream.danger-button wire:loading.attr="disabled">
|
||||
{{ __('Disable') }}
|
||||
</x-jetstream.danger-button>
|
||||
</x-jetstream.confirms-password>
|
||||
@endif
|
||||
|
||||
@endif
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-jetstream.action-section>
|
||||
</div>
|
||||
75
resources/views/profile/update-password-form.blade.php
Normal file
75
resources/views/profile/update-password-form.blade.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<x-jetstream.form-section submit="updatePassword">
|
||||
<x-slot name="title">
|
||||
{{ __('Update Password') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Ensure your profile is using a long, random password to stay secure.') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<div class="col-span-6 sm:col-span-4" x-data="{ showPassword: false }">
|
||||
<x-jetstream.label for="current_password" value="{{ __('Current Password') }}" />
|
||||
<div class="relative">
|
||||
<x-jetstream.input id="current_password" ::type="showPassword ? 'text' : 'password'" class="mt-1 block w-full pr-10" wire:model.defer="state.current_password" autocomplete="current-password" />
|
||||
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
|
||||
<button type="button" @click="showPassword = !showPassword" class="text-gray-500 hover:text-gray-700 focus:outline-none focus:text-gray-700">
|
||||
<template x-if="!showPassword">
|
||||
<x-icon name="eye" class="h-5 w-5" />
|
||||
</template>
|
||||
<template x-if="showPassword">
|
||||
<x-icon name="eye-slash" class="h-5 w-5" />
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<x-jetstream.input-error for="current_password" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="col-span-6 sm:col-span-4" x-data="{ showPassword: false }">
|
||||
<x-jetstream.label for="password" value="{{ __('New Password') }}" />
|
||||
<div class="relative">
|
||||
<x-jetstream.input id="password" ::type="showPassword ? 'text' : 'password'" class="mt-1 block w-full pr-10" wire:model.defer="state.password" autocomplete="new-password" />
|
||||
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
|
||||
<button type="button" @click="showPassword = !showPassword" class="text-gray-500 hover:text-gray-700 focus:outline-none focus:text-gray-700">
|
||||
<template x-if="!showPassword">
|
||||
<x-icon name="eye" class="h-5 w-5" />
|
||||
</template>
|
||||
<template x-if="showPassword">
|
||||
<x-icon name="eye-slash" class="h-5 w-5" />
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<x-jetstream.input-error for="password" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="col-span-6 sm:col-span-4" x-data="{ showPassword: false }">
|
||||
<x-jetstream.label for="password_confirmation" value="{{ __('Confirm Password') }}" />
|
||||
<div class="relative">
|
||||
<x-jetstream.input id="password_confirmation" ::type="showPassword ? 'text' : 'password'" class="mt-1 block w-full pr-10" wire:model.defer="state.password_confirmation" autocomplete="new-password" />
|
||||
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
|
||||
<button type="button" @click="showPassword = !showPassword" class="text-gray-500 hover:text-gray-700 focus:outline-none focus:text-gray-700">
|
||||
<template x-if="!showPassword">
|
||||
<x-icon name="eye" class="h-5 w-5" />
|
||||
</template>
|
||||
<template x-if="showPassword">
|
||||
<x-icon name="eye-slash" class="h-5 w-5" />
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<x-jetstream.input-error for="password_confirmation" class="mt-2" />
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="actions">
|
||||
<x-jetstream.action-message class="mr-3" on="saved">
|
||||
{{ __('Saved') }}
|
||||
</x-jetstream.action-message>
|
||||
|
||||
<x-jetstream.button>
|
||||
{{ __('Save') }}
|
||||
</x-jetstream.button>
|
||||
</x-slot>
|
||||
</x-jetstream.form-section>
|
||||
Reference in New Issue
Block a user