diff --git a/app/Livewire/Components/User/Preferences.php b/app/Livewire/Components/User/Preferences.php index 7bb70c5e..8a7a6f63 100644 --- a/app/Livewire/Components/User/Preferences.php +++ b/app/Livewire/Components/User/Preferences.php @@ -5,17 +5,33 @@ namespace App\Livewire\Components\User; use App\Models\User; +use Filament\Forms; +use Filament\Forms\Concerns\InteractsWithForms; +use Filament\Forms\Contracts\HasForms; +use Filament\Forms\Form; +use Filament\Notifications\Notification; use Illuminate\Contracts\View\View; use Illuminate\Support\Facades\Auth; use Livewire\Attributes\Computed; use Livewire\Component; /** + * @property Form $form * @property User $user */ -final class Preferences extends Component +final class Preferences extends Component implements HasForms { - public string $theme = 'light'; + use InteractsWithForms; + + public ?array $data = []; + + public function mount(): void + { + $this->form->fill([ + 'theme' => $this->user->setting('theme', 'light'), + 'locale' => $this->user->setting('locale', config('app.locale')), + ]); + } #[Computed] public function user(): User @@ -23,16 +39,44 @@ public function user(): User return Auth::user(); // @phpstan-ignore-line } - public function mount(): void + public function form(Form $form): Form { - $this->theme = get_current_theme(); + return $form + ->schema([ + Forms\Components\ToggleButtons::make('theme') + ->label('Theme') + ->options([ + 'light' => 'Light', + 'dark' => 'Dark', + ]) + ->icons([ + 'light' => 'phosphor-sun-duotone', + 'dark' => 'phosphor-moon-duotone', + ]) + ->grouped(), + Forms\Components\Select::make('locale') + ->label(__('global.language')) + ->options([ + 'fr' => __('global.french'), + 'en' => __('global.english'), + ]), + ]) + ->statePath('data'); } - public function updatedTheme(string $value): void + public function save(): void { - $this->user->settings(['theme' => $value]); + $this->validate(); + + $this->user->settings($this->form->getState()); + + $this->dispatch('theme-changed', get_current_theme()); - $this->redirectRoute('settings', navigate: true); + Notification::make() + ->success() + ->title(__('notifications.user.profile_updated')) + ->duration(3500) + ->send(); } public function render(): View diff --git a/lang/en/global.php b/lang/en/global.php index aafdf2cb..4f00a59a 100644 --- a/lang/en/global.php +++ b/lang/en/global.php @@ -104,5 +104,8 @@ 'locale_help' => 'The language in which your content will be available on the site.', 'community_oss_description' => 'The community is also developing open source packages to contribute to the Laravel ecosystem.', 'holidays' => 'Happy Holidays', + 'language' => 'Language', + 'french' => 'French', + 'english' => 'English', ]; diff --git a/lang/fr/global.php b/lang/fr/global.php index e355bfc9..f98b8444 100644 --- a/lang/fr/global.php +++ b/lang/fr/global.php @@ -104,5 +104,7 @@ 'locale_help' => 'La langue dans laquelle votre contenu sera accessible sur le site.', 'holidays' => 'Joyeuses fêtes', 'community_oss_description' => 'La communauté développe aussi des packages open source pour contribuer à l\'ecosystème de Laravel.', - + 'language' => 'Langue', + 'french' => 'Français', + 'english' => 'Anglais', ]; diff --git a/resources/js/app.js b/resources/js/app.js index 0feeb03c..c5495184 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -19,4 +19,51 @@ Alpine.plugin(collapse) window.Alpine = Alpine +document.addEventListener('alpine:init', () => { + const theme = + localStorage.getItem('theme') ?? + getComputedStyle(document.documentElement).getPropertyValue( + '--default-theme-mode', + ) + + window.Alpine.store( + 'theme', + theme === 'dark' || + (theme === 'system' && + window.matchMedia('(prefers-color-scheme: dark)').matches) + ? 'dark' + : 'light', + ) + + window.addEventListener('theme-changed', (event) => { + let theme = event.detail + + localStorage.setItem('theme', theme) + + if (theme === 'system') { + theme = window.matchMedia('(prefers-color-scheme: dark)').matches + ? 'dark' + : 'light' + } + + window.Alpine.store('theme', theme) + }) + + window + .matchMedia('(prefers-color-scheme: dark)') + .addEventListener('change', (event) => { + if (localStorage.getItem('theme') === 'system') { + window.Alpine.store('theme', event.matches ? 'dark' : 'light') + } + }) + + window.Alpine.effect(() => { + const theme = window.Alpine.store('theme') + + theme === 'dark' + ? document.documentElement.classList.add('dark') + : document.documentElement.classList.remove('dark') + }) +}) + Livewire.start() diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index d6dde482..f2079e7b 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -1,7 +1,7 @@ @props(['title' => null, 'canonical' => null]) - +
@@ -29,6 +29,25 @@ @filamentStyles @vite(['resources/css/app.css', 'resources/js/app.js']) @include('partials._analytics') + + @if (! auth()->check()) + + @else + + @endif