Skip to content

Commit 6bc39ff

Browse files
committed
wip
1 parent cde56f4 commit 6bc39ff

File tree

5 files changed

+217
-66
lines changed

5 files changed

+217
-66
lines changed

config/fortify.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
|
131131
*/
132132

133-
'views' => false,
133+
'views' => true,
134134

135135
/*
136136
|--------------------------------------------------------------------------
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{{-- Credit: Lucide (https://lucide.dev) --}}
2+
3+
@props([
4+
'variant' => 'outline',
5+
])
6+
7+
@php
8+
if ($variant === 'solid') {
9+
throw new \Exception('The "solid" variant is not supported in Lucide.');
10+
}
11+
12+
$classes = Flux::classes('shrink-0')
13+
->add(match($variant) {
14+
'outline' => '[:where(&)]:size-6',
15+
'solid' => '[:where(&)]:size-6',
16+
'mini' => '[:where(&)]:size-5',
17+
'micro' => '[:where(&)]:size-4',
18+
});
19+
20+
$strokeWidth = match ($variant) {
21+
'outline' => 2,
22+
'mini' => 2.25,
23+
'micro' => 2.5,
24+
};
25+
@endphp
26+
27+
<svg
28+
{{ $attributes->class($classes) }}
29+
data-flux-icon
30+
xmlns="http://www.w3.org/2000/svg"
31+
viewBox="0 0 24 24"
32+
fill="none"
33+
stroke="currentColor"
34+
stroke-width="{{ $strokeWidth }}"
35+
stroke-linecap="round"
36+
stroke-linejoin="round"
37+
aria-hidden="true"
38+
data-slot="icon"
39+
>
40+
<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" />
41+
<circle cx="12" cy="12" r="3" />
42+
</svg>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{{-- Credit: Lucide (https://lucide.dev) --}}
2+
3+
@props([
4+
'variant' => 'outline',
5+
])
6+
7+
@php
8+
if ($variant === 'solid') {
9+
throw new \Exception('The "solid" variant is not supported in Lucide.');
10+
}
11+
12+
$classes = Flux::classes('shrink-0')
13+
->add(match($variant) {
14+
'outline' => '[:where(&)]:size-6',
15+
'solid' => '[:where(&)]:size-6',
16+
'mini' => '[:where(&)]:size-5',
17+
'micro' => '[:where(&)]:size-4',
18+
});
19+
20+
$strokeWidth = match ($variant) {
21+
'outline' => 2,
22+
'mini' => 2.25,
23+
'micro' => 2.5,
24+
};
25+
@endphp
26+
27+
<svg
28+
{{ $attributes->class($classes) }}
29+
data-flux-icon
30+
xmlns="http://www.w3.org/2000/svg"
31+
viewBox="0 0 24 24"
32+
fill="none"
33+
stroke="currentColor"
34+
stroke-width="{{ $strokeWidth }}"
35+
stroke-linecap="round"
36+
stroke-linejoin="round"
37+
aria-hidden="true"
38+
data-slot="icon"
39+
>
40+
<circle cx="12" cy="16" r="1" />
41+
<rect x="3" y="10" width="18" height="12" rx="2" />
42+
<path d="M7 10V7a5 5 0 0 1 10 0v3" />
43+
</svg>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{{-- Credit: Lucide (https://lucide.dev) --}}
2+
3+
@props([
4+
'variant' => 'outline',
5+
])
6+
7+
@php
8+
if ($variant === 'solid') {
9+
throw new \Exception('The "solid" variant is not supported in Lucide.');
10+
}
11+
12+
$classes = Flux::classes('shrink-0')
13+
->add(match($variant) {
14+
'outline' => '[:where(&)]:size-6',
15+
'solid' => '[:where(&)]:size-6',
16+
'mini' => '[:where(&)]:size-5',
17+
'micro' => '[:where(&)]:size-4',
18+
});
19+
20+
$strokeWidth = match ($variant) {
21+
'outline' => 2,
22+
'mini' => 2.25,
23+
'micro' => 2.5,
24+
};
25+
@endphp
26+
27+
<svg
28+
{{ $attributes->class($classes) }}
29+
data-flux-icon
30+
xmlns="http://www.w3.org/2000/svg"
31+
viewBox="0 0 24 24"
32+
fill="none"
33+
stroke="currentColor"
34+
stroke-width="{{ $strokeWidth }}"
35+
stroke-linecap="round"
36+
stroke-linejoin="round"
37+
aria-hidden="true"
38+
data-slot="icon"
39+
>
40+
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" />
41+
<path d="M21 3v5h-5" />
42+
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" />
43+
<path d="M8 16H3v5" />
44+
</svg>

resources/views/livewire/settings/two-factor.blade.php

Lines changed: 87 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ public function backToSetup(): void
102102
103103
public function confirmTwoFactor(ConfirmTwoFactorAuthentication $confirmTwoFactorAuthentication): void
104104
{
105-
dd($this);
106105
$this->validate();
107106
$confirmTwoFactorAuthentication(auth()->user(), $this->authCode);
108107
$this->twoFactorEnabled = true;
@@ -152,6 +151,13 @@ public function toggleRecoveryCodes(): void
152151
$this->showRecoveryCodes = !$this->showRecoveryCodes;
153152
}
154153
154+
public function fetchRecoveryCodes(): void
155+
{
156+
if (!$this->recoveryCodes) {
157+
$this->loadRecoveryCodes();
158+
}
159+
}
160+
155161
private function loadRecoveryCodes(): void
156162
{
157163
$this->recoveryCodes = json_decode(decrypt(auth()->user()->two_factor_recovery_codes), true);
@@ -162,14 +168,15 @@ private function loadRecoveryCodes(): void
162168
@include('partials.settings-heading')
163169
<x-settings.layout :heading="__('Two Factor Authentication')"
164170
:subheading="__('Manage your two-factor authentication settings')">
165-
<div class="flex flex-col w-full mx-auto text-sm space-y-6">
171+
<div class="flex flex-col w-full mx-auto text-sm space-y-6" wire:cloak>
166172
@if(!$twoFactorEnabled)
167173
<div class="relative flex flex-col items-start rounded-xl justify-start space-y-4">
168174
<flux:badge color="red">Disabled</flux:badge>
169-
<p class="text-stone-500 dark:text-stone-400">
175+
<flux:text variant="subtle">
170176
When you enable two-factor authentication, you will be prompted for a secure pin during login.
171177
This pin can be retrieved from a TOTP-supported application on your phone.
172-
</p>
178+
</flux:text>
179+
173180
<div class="w-auto">
174181
<flux:button
175182
variant="primary"
@@ -188,78 +195,93 @@ private function loadRecoveryCodes(): void
188195
<div>
189196
<flux:badge color="green">Enabled</flux:badge>
190197
</div>
191-
<p class="text-stone-500 dark:text-stone-400">
198+
<flux:text>
192199
With two-factor authentication enabled, you will be prompted for a secure, random pin during
193200
login,
194201
which you can retrieve from the TOTP-supported application on your phone.
195-
</p>
196-
197-
<div>
198-
<flux:callout icon="lock-keyhole-open" color="gray" class="rounded-b-none">
199-
<flux:callout.heading>2FA Recovery Codes</flux:callout.heading>
200-
<flux:callout.text>
202+
</flux:text>
203+
204+
<div
205+
class="flex flex-col gap-6 rounded-xl border border-zinc-200 dark:border-white/10 py-6 shadow-sm"
206+
x-data="{ showRecoveryCodes: {{ $showRecoveryCodes ? 'true' : 'false' }} }">
207+
<div class="flex flex-col gap-1.5 px-6">
208+
<div class="flex gap-2">
209+
<flux:icon name="lock-keyhole" class="size-4"/>
210+
<flux:heading>
211+
2FA Recovery Codes
212+
</flux:heading>
213+
</div>
214+
<flux:text variant="subtle">
201215
Recovery codes let you regain access if you lose your 2FA device. Store them in a
202-
secure
203-
password manager.
204-
</flux:callout.text>
205-
</flux:callout>
206-
<div
207-
class="bg-stone-100 dark:bg-stone-800 rounded-b-xl border-t-0 border border-stone-200 dark:border-stone-700 text-sm">
216+
secure password manager.
217+
</flux:text>
218+
</div>
219+
<div class="px-6">
220+
<div class="flex flex-col gap-3 select-none sm:flex-row sm:items-center sm:justify-between">
221+
<flux:button
222+
x-show="!showRecoveryCodes"
223+
icon="eye"
224+
variant="primary"
225+
@click="showRecoveryCodes = true"
226+
aria-expanded="false"
227+
aria-controls="recovery-codes-section"
228+
>
229+
View Recovery Codes
230+
</flux:button>
231+
<flux:button
232+
x-show="showRecoveryCodes"
233+
icon="eye-off"
234+
variant="primary"
235+
@click="showRecoveryCodes = false"
236+
aria-expanded="true"
237+
aria-controls="recovery-codes-section"
238+
>
239+
Hide Recovery Codes
240+
</flux:button>
241+
<flux:button
242+
x-show="showRecoveryCodes"
243+
icon="arrow-path"
244+
variant="filled"
245+
wire:click="regenerateRecoveryCodes"
246+
aria-describedby="regenerate-warning"
247+
>
248+
<span wire:loading.remove
249+
wire:target="regenerateRecoveryCodes">{{ __('Regenerate Codes') }}</span>
250+
<span wire:loading
251+
wire:target="regenerateRecoveryCodes">{{ __('Regenerating...') }}</span>
252+
</flux:button>
253+
</div>
208254
<div
209-
wire:click="toggleRecoveryCodes"
210-
class="h-10 group cursor-pointer flex items-center select-none justify-between px-5 text-xs"
255+
x-show="showRecoveryCodes"
256+
x-transition
257+
id="recovery-codes-section"
258+
class="relative overflow-hidden"
259+
x-bind:aria-hidden="!showRecoveryCodes"
211260
>
212-
<div class="relative transition-opacity duration-200"
213-
@class([
214-
'opacity-40 group-hover:opacity-60' => !$showRecoveryCodes,
215-
'opacity-60' => $showRecoveryCodes
216-
])>
217-
@if(!$showRecoveryCodes)
218-
<span class="flex items-center space-x-1">
219-
<flux:icon.eye class="size-4"/>
220-
<span>View My Recovery Codes</span>
221-
</span>
222-
@else
223-
<span class="flex items-center space-x-1">
224-
<flux:icon.eye-off class="size-4"/>
225-
<span>Hide Recovery Codes</span>
226-
</span>
227-
@endif
228-
</div>
229-
@if($showRecoveryCodes)
230-
<flux:button
231-
size="xs"
232-
variant="filled"
233-
class="text-stone-600"
234-
wire:click.stop="regenerateRecoveryCodes"
235-
wire:loading.attr="disabled"
236-
wire:target="regenerateRecoveryCodes"
237-
>
238-
<span wire:loading.remove
239-
wire:target="regenerateRecoveryCodes">{{ __('Regenerate Codes') }}</span>
240-
<span wire:loading
241-
wire:target="regenerateRecoveryCodes">{{ __('Regenerating...') }}</span>
242-
</flux:button>
243-
@endif
244-
</div>
245-
@if($showRecoveryCodes)
246-
<div class="relative">
261+
<div class="mt-3 space-y-3">
247262
<div
248-
class="grid max-w-xl gap-1 px-4 py-4 font-mono text-sm bg-stone-200 dark:bg-stone-900 dark:text-stone-100">
249-
@forelse($recoveryCodes as $code)
250-
<div>{{ $code }}</div>
251-
@empty
252-
<div class="text-stone-500">No recovery codes available</div>
253-
@endforelse
263+
class="grid gap-1 rounded-lg p-4 bg-zinc-200 dark:bg-white/10 font-mono text-sm selection:bg-accent selection:text-accent-foreground"
264+
role="list" aria-label="Recovery codes">
265+
266+
@foreach($recoveryCodes as $index => $code)
267+
<div role="listitem"
268+
wire:loading
269+
class="animate-pulse h-4 opacity-20 rounded bg-zinc-200/80 dark:bg-white/30"
270+
></div>
271+
<div role="listitem" wire:loading.class="hidden"
272+
class="select-text">{{ $code }}</div>
273+
@endforeach
274+
254275
</div>
255-
<p class="px-4 py-3 text-xs select-none text-stone-500 dark:text-stone-400">
256-
You have {{ count($recoveryCodes) }} recovery codes left.
257-
Each can be used once to access your account and will be removed after use.
276+
<flux:text variant="subtle" class="text-xs">
277+
Each recovery code can be used once to access your account and will be
278+
removed after use.
258279
If you need more, click <span class="font-bold">Regenerate Codes</span>
259280
above.
260-
</p>
281+
</flux:text>
282+
261283
</div>
262-
@endif
284+
</div>
263285
</div>
264286
</div>
265287

0 commit comments

Comments
 (0)