From ae52c75bd3185e19ab3b64d59fc0e69d2462789d Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Mon, 30 Mar 2026 18:33:45 +0700 Subject: [PATCH] refactor: implement configurable notification styles with formal and cheerful modes based on user preferences --- app/Filament/Pages/Auth/Login.php | 12 +- app/Filament/Pages/Profile.php | 1 - .../Actions/CopyAssignmentLinkAction.php | 6 +- .../Actions/CopyAttendanceLinkAction.php | 6 +- app/Filament/Support/SystemNotification.php | 192 ++++++++++++------ app/Providers/Filament/AdminPanelProvider.php | 1 - 6 files changed, 149 insertions(+), 69 deletions(-) diff --git a/app/Filament/Pages/Auth/Login.php b/app/Filament/Pages/Auth/Login.php index 1033496..600da88 100644 --- a/app/Filament/Pages/Auth/Login.php +++ b/app/Filament/Pages/Auth/Login.php @@ -96,7 +96,9 @@ public function authenticate(): ?LoginResponse if ($user->is_active === IsActive::Inactive) { SystemNotification::danger( 'Akses Ditangguhkan โ›”', - 'Maaf, Anda tidak dapat masuk karena status akun saat ini sedang tidak aktif. Silakan hubungi Administrator untuk informasi lebih lanjut. ๐Ÿ˜ด' + 'Maaf, Anda tidak dapat masuk karena status akun saat ini sedang tidak aktif. Silakan hubungi Administrator untuk informasi lebih lanjut. ๐Ÿ˜ด', + 'Akses Akun Terbatas', + 'Akun Anda saat ini dalam status tidak aktif. Mohon hubungi pihak Administrator untuk klarifikasi lebih lanjut.' )->send(); throw ValidationException::withMessages([ @@ -146,7 +148,9 @@ public function authenticate(): ?LoginResponse SystemNotification::success( 'Berhasil Masuk โœจ', - 'Selamat datang kembali, '.$user->name.'. Sesi Anda telah berhasil diaktifkan dengan aman.' + 'Selamat datang kembali, '.$user->name.'. Sesi Anda telah berhasil diaktifkan dengan aman. ๐Ÿ‘‹', + 'Otentikasi Berhasil', + 'Selamat datang, '.$user->name.'. Sesi autentikasi Anda telah berhasil dikonfirmasi oleh sistem.' )->send(); return app(LoginResponse::class); @@ -156,7 +160,9 @@ protected function throwFailureValidationException(): never { SystemNotification::danger( 'Gagal Masuk ๐Ÿšซ', - 'Terjadi kendala saat proses masuk. Mohon periksa kembali alamat surel atau kata sandi Anda.' + 'Terjadi kendala saat proses masuk. Mohon periksa kembali alamat surel atau kata sandi Anda. ๐Ÿ˜Ÿ', + 'Otentikasi Gagal', + 'Upaya masuk gagal dilakukan. Mohon lakukan verifikasi kembali pada kredensial yang Anda masukkan.' )->send(); throw ValidationException::withMessages([]); diff --git a/app/Filament/Pages/Profile.php b/app/Filament/Pages/Profile.php index b86e53c..9e82475 100644 --- a/app/Filament/Pages/Profile.php +++ b/app/Filament/Pages/Profile.php @@ -7,7 +7,6 @@ use App\Filament\Support\SystemNotification; use Carbon\Carbon; use Filament\Auth\Pages\EditProfile; -use Filament\Forms\Components\ColorPicker; use Filament\Forms\Components\DatePicker; use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; diff --git a/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAssignmentLinkAction.php b/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAssignmentLinkAction.php index 4f0c9f5..d4b8a95 100644 --- a/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAssignmentLinkAction.php +++ b/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAssignmentLinkAction.php @@ -33,8 +33,10 @@ protected function setUp(): void $livewire->js("if (navigator.clipboard) { navigator.clipboard.writeText('{$url}').catch(() => {}); }"); SystemNotification::success( - 'Tautan Berhasil Disalin โœจ', - 'Tautan telah disalin ke clipboard dan siap untuk dibagikan.' + 'Tautan Berhasil Disalin โœจ๐Ÿš€', + 'Tautan telah disalin ke clipboard dan siap untuk dibagikan. ๐Ÿ“‹', + 'Penyalinan Tautan Berhasil', + 'Tautan URL telah berhasil disalin ke papan klip sistem.' )->send(); }); } diff --git a/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAttendanceLinkAction.php b/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAttendanceLinkAction.php index 155055d..8b05678 100644 --- a/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAttendanceLinkAction.php +++ b/app/Filament/Resources/Learning/ClassSessions/Actions/CopyAttendanceLinkAction.php @@ -31,8 +31,10 @@ protected function setUp(): void $livewire->js("if (navigator.clipboard) { navigator.clipboard.writeText('{$url}').catch(() => {}); }"); SystemNotification::success( - 'Tautan Berhasil Disalin โœจ', - 'Tautan telah disalin ke clipboard dan siap untuk dibagikan.' + 'Tautan Berhasil Disalin โœจ๐Ÿš€', + 'Tautan telah disalin ke clipboard dan siap untuk dibagikan. ๐Ÿ“‹', + 'Penyalinan Tautan Berhasil', + 'Tautan URL telah berhasil disalin ke papan klip sistem.' )->send(); }); } diff --git a/app/Filament/Support/SystemNotification.php b/app/Filament/Support/SystemNotification.php index 5645c83..a90d49f 100644 --- a/app/Filament/Support/SystemNotification.php +++ b/app/Filament/Support/SystemNotification.php @@ -2,7 +2,9 @@ namespace App\Filament\Support; +use App\Enums\NotifStyle; use Filament\Notifications\Notification; +use Illuminate\Support\Facades\Auth; class SystemNotification { @@ -19,10 +21,10 @@ public static function make(): Notification */ public static function create(): Notification { - return self::make() - ->title('Data Berhasil Disimpan โœจ') - ->body('Data baru telah berhasil ditambahkan ke dalam sistem.') - ->success(); + return self::success( + self::getMessage('Hore! Data Tersimpan ๐ŸŽ‰โœจ', 'Data Berhasil Disimpan'), + self::getMessage('Data baru berhasil ditambahkan! Sistem sudah menyimpannya dengan aman. ๐Ÿš€๐Ÿ’ช', 'Data baru telah berhasil ditambahkan ke dalam sistem.') + ); } /** @@ -30,10 +32,10 @@ public static function create(): Notification */ public static function update(): Notification { - return self::make() - ->title('Perubahan Berhasil Disimpan โœ…') - ->body('Pembaruan data telah berhasil disimpan dengan aman.') - ->success(); + return self::success( + self::getMessage('Mantap! Data Diperbarui โœ…๐Ÿ”ฅ', 'Perubahan Tersimpan'), + self::getMessage('Perubahan berhasil disimpan! Data sekarang sudah up-to-date dan segar lagi. โœจ๐Ÿ‘Œ', 'Perubahan pada data telah berhasil diperbarui dan disimpan.') + ); } /** @@ -41,10 +43,10 @@ public static function update(): Notification */ public static function delete(): Notification { - return self::make() - ->title('Data Berhasil Dihapus ๐Ÿ—‘๏ธ') - ->body('Data yang dipilih telah berhasil dihapus dari sistem.') - ->success(); + return self::success( + self::getMessage('Oke, Data Dihapus ๐Ÿ—‘๏ธ๐Ÿ‘‹', 'Data Dihapus'), + self::getMessage('Data tersebut sudah berhasil dihapus dari sistem. Semuanya bersih dan rapi sekarang! ๐Ÿ˜Š๐Ÿšฎ', 'Data tersebut telah berhasil dihapus dari sistem aplikasi.') + ); } /** @@ -52,10 +54,10 @@ public static function delete(): Notification */ public static function forceDelete(): Notification { - return self::make() - ->title('Data Dihapus Secara Permanen ๐Ÿ›ก๏ธ') - ->body('Data telah dihapus secara permanen dan tidak dapat dipulihkan kembali.') - ->success(); + return self::success( + self::getMessage('Selamat Tinggal Selamanya ๐Ÿ‘‹๐Ÿ˜ข', 'Data Dihapus Permanen'), + self::getMessage('Data telah dihapus permanen dan tidak bisa kembali. Semoga ini keputusan yang tepat! ๐Ÿšฎ๐Ÿ’จ', 'Data tersebut telah dihapus secara permanen dari sistem.') + ); } /** @@ -63,10 +65,10 @@ public static function forceDelete(): Notification */ public static function restore(): Notification { - return self::make() - ->title('Data Berhasil Dipulihkan ๐Ÿ”„') - ->body('Data telah berhasil dikembalikan dan diaktifkan kembali di sistem.') - ->success(); + return self::success( + self::getMessage('Welcome Back! Data Pulih โ™ป๏ธโœจ', 'Data Berhasil Dipulihkan'), + self::getMessage('Data berhasil dikembalikan! Hati-hati ya, jangan sampai terhapus lagi. ๐Ÿ˜‰๐Ÿ‘', 'Data yang dihapus sebelumnya telah berhasil dipulihkan ke dalam sistem.') + ); } /** @@ -74,10 +76,10 @@ public static function restore(): Notification */ public static function statusUpdated(?string $title = null, ?string $body = null): Notification { - return self::make() - ->title($title ?? 'Status Berhasil Diperbarui โšก') - ->body($body ?? 'Status data telah berhasil diperbarui dan sudah aktif kembali.') - ->success(); + return self::success( + $title ?? self::getMessage('Status Berubah! ๐Ÿ”„โœจ', 'Status Diperbarui'), + $body ?? self::getMessage('Status data berhasil diperbarui. Perubahan langsung aktif ya! ๐Ÿ‘', 'Status data telah berhasil diperbarui dan telah diterapkan.') + ); } /** @@ -85,10 +87,10 @@ public static function statusUpdated(?string $title = null, ?string $body = null */ public static function bulkDelete(): Notification { - return self::make() - ->title('Data Massal Berhasil Dihapus ๐Ÿ“') - ->body('Seluruh data yang dipilih telah berhasil dihapus dari sistem.') - ->success(); + return self::success( + self::getMessage('Oke, Banyak Data Dihapus ๐Ÿ—‘๏ธ๐Ÿ‘‹', 'Data Berhasil Dihapus'), + self::getMessage('Semua data yang dipilih berhasil dihapus. Sistem makin lega deh! ๐Ÿ˜Š', 'Seluruh data yang dipilih telah berhasil dihapus dari sistem.') + ); } /** @@ -96,10 +98,10 @@ public static function bulkDelete(): Notification */ public static function bulkForceDelete(): Notification { - return self::make() - ->title('Penghapusan Massal Permanen Berhasil โš™๏ธ') - ->body('Seluruh data terpilih telah dihapus secara permanen dari sistem.') - ->success(); + return self::success( + self::getMessage('Bye Bye Semua! ๐Ÿ‘‹๐Ÿ”ฅ', 'Data Dihapus Permanen'), + self::getMessage('Data yang dipilih sudah dihapus permanen. Bersih total! ๐Ÿงน๐Ÿ’จ', 'Data yang dipilih telah berhasil dihapus secara permanen.') + ); } /** @@ -107,53 +109,123 @@ public static function bulkForceDelete(): Notification */ public static function bulkRestore(): Notification { - return self::make() - ->title('Pemulihan Massal Berhasil โœจ') - ->body('Seluruh data yang dipilih telah berhasil dipulihkan kembali ke sistem.') - ->success(); + return self::success( + self::getMessage('Hore! Banyak Data Pulih โ™ป๏ธ๐ŸŽ‰', 'Data Berhasil Dipulihkan'), + self::getMessage('Data-data tersebut sudah kembali aktif. Selamat bekerja kembali! ๐Ÿ’ชโœจ', 'Seluruh data yang dipilih telah berhasil dikembalikan ke posisi semula.') + ); } /** - * Custom cheerful success notification. + * Success notification wrapper. */ - public static function success(string $title, string $body): Notification + public static function success(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification { - return self::make() - ->title($title) - ->body($body) - ->success(); + $finalTitle = self::getMessage($title, $formalTitle ?? $title); + $finalBody = self::getMessage($body, $formalBody ?? $body); + + return self::applyStyle( + self::make() + ->title(self::clean($finalTitle)) + ->body(self::clean($finalBody)) + ->success() + ); } /** - * Custom cheerful info notification. + * Custom info notification. */ - public static function info(string $title, string $body): Notification + public static function info(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification { - return self::make() - ->title($title) - ->body($body) - ->info(); + $finalTitle = self::getMessage($title, $formalTitle ?? $title); + $finalBody = self::getMessage($body, $formalBody ?? $body); + + return self::applyStyle( + self::make() + ->title(self::clean($finalTitle)) + ->body(self::clean($finalBody)) + ->info() + ); } /** - * Custom cheerful warning notification. + * Custom warning notification. */ - public static function warning(string $title, string $body): Notification + public static function warning(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification { - return self::make() - ->title($title) - ->body($body) - ->warning(); + $finalTitle = self::getMessage($title, $formalTitle ?? $title); + $finalBody = self::getMessage($body, $formalBody ?? $body); + + return self::applyStyle( + self::make() + ->title(self::clean($finalTitle)) + ->body(self::clean($finalBody)) + ->warning() + ); } /** - * Custom cheerful danger notification. + * Custom danger notification. */ - public static function danger(string $title, string $body): Notification + public static function danger(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification { - return self::make() - ->title($title) - ->body($body) - ->danger(); + $finalTitle = self::getMessage($title, $formalTitle ?? $title); + $finalBody = self::getMessage($body, $formalBody ?? $body); + + return self::applyStyle( + self::make() + ->title(self::clean($finalTitle)) + ->body(self::clean($finalBody)) + ->danger() + ); + } + + /** + * Apply the user's selected style to the notification. + */ + protected static function applyStyle(Notification $notification): Notification + { + if (self::getNotifStyle() === NotifStyle::Formal) { + $notification->icon(null); + } + + return $notification; + } + + /** + * Get the current user's notification style preference. + */ + public static function getNotifStyle(): NotifStyle + { + try { + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return $user?->settings?->notif_style ?? NotifStyle::Cheerful; + } catch (\Throwable $e) { + return NotifStyle::Cheerful; + } + } + + /** + * Get message based on the user's notification style preference. + */ + public static function getMessage(string $cheerful, string $formal): string + { + return self::getNotifStyle() === NotifStyle::Cheerful ? $cheerful : $formal; + } + + /** + * Strip emojis if the notification style is formal. + */ + public static function clean(string $text): string + { + if (self::getNotifStyle() === NotifStyle::Formal) { + // Comprehensive regex to remove emojis and symbols + $regex = '/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{1F900}-\x{1F9FF}\x{1F1E0}-\x{1F1FF}]/u'; + + return trim(preg_replace($regex, '', $text)); + } + + return $text; } } diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index e3716a3..a9d0560 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -6,7 +6,6 @@ use App\Filament\Pages\Auth\Login; use App\Filament\Pages\Profile; use App\Http\Middleware\DynamicFilamentTheme; -use App\Models\User; use BezhanSalleh\FilamentShield\FilamentShieldPlugin; use DiogoGPinto\AuthUIEnhancer\AuthUIEnhancerPlugin; use Filament\Http\Middleware\Authenticate;