Skip to content

Commit 06ef77d

Browse files
feat:[lar-145] complete preference page (#267)
Co-authored-by: Arthur Monney <[email protected]>
1 parent dc57dcf commit 06ef77d

File tree

7 files changed

+135
-15
lines changed

7 files changed

+135
-15
lines changed

app/Livewire/Components/User/Preferences.php

+51-7
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,78 @@
55
namespace App\Livewire\Components\User;
66

77
use App\Models\User;
8+
use Filament\Forms;
9+
use Filament\Forms\Concerns\InteractsWithForms;
10+
use Filament\Forms\Contracts\HasForms;
11+
use Filament\Forms\Form;
12+
use Filament\Notifications\Notification;
813
use Illuminate\Contracts\View\View;
914
use Illuminate\Support\Facades\Auth;
1015
use Livewire\Attributes\Computed;
1116
use Livewire\Component;
1217

1318
/**
19+
* @property Form $form
1420
* @property User $user
1521
*/
16-
final class Preferences extends Component
22+
final class Preferences extends Component implements HasForms
1723
{
18-
public string $theme = 'light';
24+
use InteractsWithForms;
25+
26+
public ?array $data = [];
27+
28+
public function mount(): void
29+
{
30+
$this->form->fill([
31+
'theme' => $this->user->setting('theme', 'light'),
32+
'locale' => $this->user->setting('locale', config('app.locale')),
33+
]);
34+
}
1935

2036
#[Computed]
2137
public function user(): User
2238
{
2339
return Auth::user(); // @phpstan-ignore-line
2440
}
2541

26-
public function mount(): void
42+
public function form(Form $form): Form
2743
{
28-
$this->theme = get_current_theme();
44+
return $form
45+
->schema([
46+
Forms\Components\ToggleButtons::make('theme')
47+
->label('Theme')
48+
->options([
49+
'light' => 'Light',
50+
'dark' => 'Dark',
51+
])
52+
->icons([
53+
'light' => 'phosphor-sun-duotone',
54+
'dark' => 'phosphor-moon-duotone',
55+
])
56+
->grouped(),
57+
Forms\Components\Select::make('locale')
58+
->label(__('global.language'))
59+
->options([
60+
'fr' => __('global.french'),
61+
'en' => __('global.english'),
62+
]),
63+
])
64+
->statePath('data');
2965
}
3066

31-
public function updatedTheme(string $value): void
67+
public function save(): void
3268
{
33-
$this->user->settings(['theme' => $value]);
69+
$this->validate();
70+
71+
$this->user->settings($this->form->getState());
72+
73+
$this->dispatch('theme-changed', get_current_theme());
3474

35-
$this->redirectRoute('settings', navigate: true);
75+
Notification::make()
76+
->success()
77+
->title(__('notifications.user.profile_updated'))
78+
->duration(3500)
79+
->send();
3680
}
3781

3882
public function render(): View

lang/en/global.php

+3
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,8 @@
104104
'locale_help' => 'The language in which your content will be available on the site.',
105105
'community_oss_description' => 'The community is also developing open source packages to contribute to the Laravel ecosystem.',
106106
'holidays' => 'Happy Holidays',
107+
'language' => 'Language',
108+
'french' => 'French',
109+
'english' => 'English',
107110

108111
];

lang/fr/global.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,7 @@
104104
'locale_help' => 'La langue dans laquelle votre contenu sera accessible sur le site.',
105105
'holidays' => 'Joyeuses fêtes',
106106
'community_oss_description' => 'La communauté développe aussi des packages open source pour contribuer à l\'ecosystème de Laravel.',
107-
107+
'language' => 'Langue',
108+
'french' => 'Français',
109+
'english' => 'Anglais',
108110
];

resources/js/app.js

+47
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,51 @@ Alpine.plugin(collapse)
1919

2020
window.Alpine = Alpine
2121

22+
document.addEventListener('alpine:init', () => {
23+
const theme =
24+
localStorage.getItem('theme') ??
25+
getComputedStyle(document.documentElement).getPropertyValue(
26+
'--default-theme-mode',
27+
)
28+
29+
window.Alpine.store(
30+
'theme',
31+
theme === 'dark' ||
32+
(theme === 'system' &&
33+
window.matchMedia('(prefers-color-scheme: dark)').matches)
34+
? 'dark'
35+
: 'light',
36+
)
37+
38+
window.addEventListener('theme-changed', (event) => {
39+
let theme = event.detail
40+
41+
localStorage.setItem('theme', theme)
42+
43+
if (theme === 'system') {
44+
theme = window.matchMedia('(prefers-color-scheme: dark)').matches
45+
? 'dark'
46+
: 'light'
47+
}
48+
49+
window.Alpine.store('theme', theme)
50+
})
51+
52+
window
53+
.matchMedia('(prefers-color-scheme: dark)')
54+
.addEventListener('change', (event) => {
55+
if (localStorage.getItem('theme') === 'system') {
56+
window.Alpine.store('theme', event.matches ? 'dark' : 'light')
57+
}
58+
})
59+
60+
window.Alpine.effect(() => {
61+
const theme = window.Alpine.store('theme')
62+
63+
theme === 'dark'
64+
? document.documentElement.classList.add('dark')
65+
: document.documentElement.classList.remove('dark')
66+
})
67+
})
68+
2269
Livewire.start()

resources/views/layouts/app.blade.php

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@props(['title' => null, 'canonical' => null])
22

33
<!DOCTYPE html>
4-
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="h-full scroll-smooth {{ get_current_theme() }}">
4+
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="h-full scroll-smooth">
55
<head>
66
<meta charset="utf-8" />
77
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
@@ -29,6 +29,25 @@
2929
@filamentStyles
3030
@vite(['resources/css/app.css', 'resources/js/app.js'])
3131
@include('partials._analytics')
32+
33+
@if (! auth()->check())
34+
<script>
35+
localStorage.setItem('theme', 'light')
36+
</script>
37+
@else
38+
<script>
39+
const theme = localStorage.getItem('theme') ?? @js(auth()->user()->setting('theme', 'light'))
40+
41+
if (
42+
theme === 'dark' ||
43+
(theme === 'system' &&
44+
window.matchMedia('(prefers-color-scheme: dark)')
45+
.matches)
46+
) {
47+
document.documentElement.classList.add('dark')
48+
}
49+
</script>
50+
@endif
3251
</head>
3352
<body class="h-full bg-gray-50 font-sans text-gray-500 antialiased dark:text-gray-400 dark:bg-gray-900">
3453
<div class="flex min-h-screen flex-col justify-between">

resources/views/livewire/components/user/preferences.blade.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,12 @@
44
:description="__('pages/account.settings.preferences_description')"
55
/>
66

7-
<div class="mt-10"></div>
7+
<form wire:submit="save" class="mt-10 max-w-xs space-y-10">
8+
{{ $this->form }}
9+
10+
<x-buttons.submit
11+
:title="__('actions.save')"
12+
wire:loading.attr="data-loading"
13+
/>
14+
</form>
815
</div>

resources/views/livewire/pages/account/settings.blade.php

+3-5
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@
4444
{{ __('global.navigation.notifications') }}
4545
</x-filament::tabs.item>
4646

47-
<x-filament::tabs.item
47+
{{--<x-filament::tabs.item
4848
alpine-active="activeTab === 'subscription'"
4949
x-on:click="activeTab = 'subscription'"
5050
icon="untitledui-credit-card-02"
5151
>
5252
{{ __('global.navigation.subscription') }}
53-
</x-filament::tabs.item>
53+
</x-filament::tabs.item>--}}
5454
</x-filament::tabs>
5555
</div>
5656
<div class="mt-10 lg:mt-0 lg:flex-1">
@@ -66,9 +66,7 @@
6666
<div x-cloak x-show="activeTab === 'notifications'">
6767
<livewire:components.user.notifications />
6868
</div>
69-
<div x-cloak x-show="activeTab === 'subscription'">
70-
<h4>Subscription</h4>
71-
</div>
69+
<div x-cloak x-show="activeTab === 'subscription'"></div>
7270
</div>
7371
</section>
7472
</x-container>

0 commit comments

Comments
 (0)