feat: update notification system to use key-based messages and improve user feedback across various components

This commit is contained in:
Yoga Pangestu 2026-04-01 20:18:54 +07:00
parent a1068bc1ed
commit b001c6bfbf
18 changed files with 597 additions and 381 deletions

View File

@ -93,12 +93,8 @@ 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. 😴',
'Akses Akun Terbatas',
'Akun Anda saat ini dalam status tidak aktif. Mohon hubungi pihak Administrator untuk klarifikasi lebih lanjut.'
)->send();
SystemNotification::send('access_suspended', type: 'danger')
->send();
throw ValidationException::withMessages([
'login' => 'Akun Anda sedang dinonaktifkan.',
@ -145,24 +141,16 @@ public function authenticate(): ?LoginResponse
session()->regenerate();
SystemNotification::success(
'Berhasil Masuk ✨',
'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();
SystemNotification::send('login_success', ['name' => $user->name])
->send();
return app(LoginResponse::class);
}
protected function throwFailureValidationException(): never
{
SystemNotification::danger(
'Gagal Masuk 🚫',
'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();
SystemNotification::send('login_failed', type: 'danger')
->send();
throw ValidationException::withMessages([]);
}

View File

@ -49,19 +49,19 @@ class Index extends Page implements HasActions, HasForms
#[Computed]
public function instructions(): string
{
return SystemNotification::getMessage('Geser ke samping buat intip hari lainnya ya! 📅✨', 'Geser ke samping untuk melihat hari lainnya.');
return SystemNotification::getByKey('labels.course_schedule_hint');
}
#[Computed]
public function emptyHeading(): string
{
return SystemNotification::getMessage('Yah, Belum Ada Jadwal Nih! 📄💤', 'Tidak ada data yang ditemukan');
return SystemNotification::getByKey('labels.empty_course_schedule.title');
}
#[Computed]
public function emptyDescription(): string
{
return SystemNotification::getMessage('Belum ada jadwal perkuliahan yang terdaftar. Mungkin hari ini kamu bisa istirahat dulu? 😉💤', 'Belum ada jadwal perkuliahan yang terdaftar untuk kriteria ini. Hubungi administrator jika jadwal Anda belum muncul.');
return SystemNotification::getByKey('labels.empty_course_schedule.description');
}
public ?string $search = '';

View File

@ -56,25 +56,25 @@ public static function getPagePermission(): string
#[Computed]
public function heading(): string
{
return SystemNotification::getMessage('Daftar Grup Seru! 💃🕺', 'Kelompok Belajar');
return SystemNotification::getByKey('labels.study_group_list.title');
}
#[Computed]
public function description(): string
{
return SystemNotification::getMessage('Lihat semua kelompok belajarmu di sini. Makin kompak makin asik! 🤝📚', 'Daftar kelompok belajar Anda dan teman-teman sekelas.');
return SystemNotification::getByKey('labels.study_group_list.description');
}
#[Computed]
public function emptyHeading(): string
{
return SystemNotification::getMessage('Wah, Belum Ada Grup! 👯‍♂️🌀', 'Tidak ada data yang ditemukan');
return SystemNotification::getByKey('labels.empty_study_group.title');
}
#[Computed]
public function emptyDescription(): string
{
return SystemNotification::getMessage('Belum ada kelompok belajar yang terdaftar. Ayo ajak teman-temanmu bikin kelompok biar makin seru belajarnya! 🤝📄', 'Belum ada kelompok belajar yang terdaftar untuk kriteria ini. Klik tombol tambah untuk memulai pembuatan kelompok.');
return SystemNotification::getByKey('labels.empty_study_group.description');
}
public ?int $course_id = null;

View File

@ -37,9 +37,9 @@ public function form(Schema $schema): Schema
{
return $schema
->components([
Section::make(SystemNotification::getMessage('Akun Pengguna 👤✨', 'Akun'))
->description(SystemNotification::getMessage('Kelola informasi detail akun Anda di sini ya biar nggak kudet! 😉🚀', 'Kelola informasi detail akun Anda agar selalu terkini.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-face-smile' : 'heroicon-o-user')
Section::make(SystemNotification::getByKey('labels.user_account.title'))
->description(SystemNotification::getByKey('labels.user_account.description'))
->icon(SystemNotification::getByKey('icons.user_account'))
->schema([
Grid::make(2)
->schema([
@ -67,9 +67,9 @@ public function form(Schema $schema): Schema
]),
]),
Section::make(SystemNotification::getMessage('Data Mahasiswa 🎓📚', 'Informasi Mahasiswa'))
->description(SystemNotification::getMessage('Pastikan data akademikmu sesuai dengan yang di sistem, jangan sampai salah loh! 🤓📝', 'Pastikan data akademik Anda sesuai dengan record sistem.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-academic-cap' : 'heroicon-o-identification')
Section::make(SystemNotification::getByKey('labels.student_data.title'))
->description(SystemNotification::getByKey('labels.student_data.description_profile'))
->icon(SystemNotification::getByKey('icons.student_data'))
->statePath('student')
->schema([
TextInput::make('full_name')
@ -135,9 +135,9 @@ public function form(Schema $schema): Schema
->columns(2)
->visible(fn () => auth()->user()?->student()->exists()),
Section::make(SystemNotification::getMessage('Keamanan Akun 🔐⚡', 'Keamanan Akun'))
->description(SystemNotification::getMessage('Rajin-rajin ganti password ya, biar akunmu aman dan nggak dibobol orang! 🕵️‍♂️🛡️', 'Perbarui kata sandi Anda secara berkala untuk menjaga keamanan akun.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-shield-check' : 'heroicon-o-lock-closed')
Section::make(SystemNotification::getByKey('labels.account_security.title'))
->description(SystemNotification::getByKey('labels.account_security.description'))
->icon(SystemNotification::getByKey('icons.account_security'))
->schema([
Grid::make(2)
->schema([
@ -164,9 +164,9 @@ public function form(Schema $schema): Schema
]),
]),
Section::make(SystemNotification::getMessage('Pengaturan Tampilan & UX 🎨✨', 'Preferensi Tampilan'))
->description(SystemNotification::getMessage('Personalisasi pengalaman aplikasi Anda agar lebih nyaman dan sesuai selera! 🌈🚀', 'Sesuaikan gaya bahasa, warna tema, dan jenis huruf aplikasi Anda.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-swatch' : 'heroicon-o-paint-brush')
Section::make(SystemNotification::getByKey('labels.appearance_settings.title'))
->description(SystemNotification::getByKey('labels.appearance_settings.description'))
->icon(SystemNotification::getByKey('icons.appearance_settings'))
->schema([
Grid::make(2)
->schema([
@ -327,24 +327,16 @@ protected function handleRecordUpdate(Model $record, array $data): Model
protected function afterSave(): void
{
SystemNotification::success(
'Profil Berhasil Diperbarui ✅✨',
'Data profil Anda telah berhasil disimpan dan diperbarui. Makin keren deh! 😎🌈',
'Pembaharuan Profil Berhasil',
'Seluruh data profil Anda telah berhasil sinkronisasi dan disimpan dalam database.'
)->send();
SystemNotification::send('profile_updated')
->send();
if (filled($this->form->getState()['password'] ?? null)) {
filament()->auth()->logout();
session()->invalidate();
session()->regenerateToken();
SystemNotification::info(
'Keamanan Akun Diperbarui 🔐',
'Anda telah mengubah kata sandi. Demi keamanan, silakan masuk kembali ya! 🚪🔑',
'Pembaruan Kredensial',
'Kata sandi Anda telah berhasil diubah. Harap lakukan otentikasi ulang untuk melanjutkan sesi.'
)->send();
SystemNotification::send('account_security_updated', type: 'info')
->send();
$this->redirect(filament()->getLoginUrl());
} else {

View File

@ -36,12 +36,8 @@ 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. 📋',
'Penyalinan Tautan Berhasil',
'Tautan URL telah berhasil disalin ke papan klip sistem.'
)->send();
SystemNotification::send('link_copied')
->send();
});
}
}

View File

@ -41,24 +41,16 @@ protected function setUp(): void
if ($existing) {
$existing->delete();
SystemNotification::success(
'Pin Dilepas! Bye 📌',
'Pin pada tugas ini sukses dilepas dari daftar prioritas kamu. Semangat! 👋',
'Pembatalan Prioritas Berhasil',
'Penanda prioritas pada tugas ini telah berhasil dihapus dari daftar akun Anda.'
)->send();
SystemNotification::send('assignment_unpinned')
->send();
} else {
AssignmentPin::create([
'student_id' => $studentProfile->id,
'assignment_id' => $assignmentId,
]);
SystemNotification::success(
'Keren! Tugas Jadi Utama 📍',
'Tugas ini sekarang nangkring di posisi teratas daftar prioritas kamu. Sikat! 🚀',
'Penandaan Prioritas Berhasil',
'Tugas ini telah berhasil ditandai sebagai prioritas utama dalam daftar tugas Anda.'
)->send();
SystemNotification::send('assignment_pinned')
->send();
}
unset($livewire->assignments, $livewire->pinnedIds);

View File

@ -93,13 +93,13 @@ protected function getHeaderActions(): array
#[Computed]
public function heading(): string
{
return SystemNotification::getMessage('Daftar Tugas Bikin Lemes! 🤣📒', 'Tugas Saya');
return SystemNotification::getByKey('labels.assignment_list.title');
}
#[Computed]
public function description(): string
{
return SystemNotification::getMessage('Yuk, cek dan kumpulin tugasmu biar tenang hidupnya! Klik aja di tugasnya ya. 🚀👨‍💻', 'Klik pada tugas untuk melihat detail dan mengumpulkan file.');
return SystemNotification::getByKey('labels.assignment_list.description');
}
public function pinAction(): Action

View File

@ -157,23 +157,15 @@ public function submit(): void
$assignment = $this->record;
if ($assignment->type === AssignmentType::Group && ! $this->currentGroup) {
SystemNotification::danger(
'Gagal Mengumpulkan 🚫',
'Anda tidak terdaftar dalam kelompok manapun yang ditugaskan untuk tugas ini. 😟',
'Kesalahan Pengumpulan Tugas',
'Data akun Anda tidak ditemukan dalam daftar kelompok yang ditugaskan untuk tugas ini.'
)->send();
SystemNotification::send('submission_no_group', type: 'danger')
->send();
return;
}
if (! $this->canSubmit) {
SystemNotification::danger(
'Akses Ditolak 🚫',
'Hanya ketua kelompok yang diizinkan untuk mengumpulkan atau memperbarui tugas kelompok. 👑',
'Batasan Otoritas Pengumpulan',
'Hanya ketua kelompok yang memiliki otoritas untuk memperbarui atau mengumpulkan tugas kelompok.'
)->send();
SystemNotification::send('submission_not_leader', type: 'danger')
->send();
return;
}
@ -181,12 +173,8 @@ public function submit(): void
$existingSubmission = $this->existingSubmission;
if (! $existingSubmission && ! $this->file) {
SystemNotification::warning(
'Pilih File Dulu Dong! 📁',
'Silakan pilih file untuk dikumpulkan agar sistem bisa menyimpannya ya! 😊',
'Kelengkapan Berkas Diperlukan',
'Mohon sertakan lampiran berkas sebelum melanjutkan proses pengumpulan tugas.'
)->send();
SystemNotification::send('submission_file_missing', type: 'warning')
->send();
return;
}
@ -216,12 +204,8 @@ public function submit(): void
'submitted_at' => now(),
]);
SystemNotification::success(
'Keren! Tugas Sudah Update ✨',
'File tugas Anda telah berhasil diunggah ulang dan diperbarui di sistem. 📤',
'Pembaruan Berkas Berhasil',
'Berkas tugas telah berhasil diunggah ulang dan divalidasi oleh sistem.'
)->send();
SystemNotification::send('submission_updated')
->send();
} else {
$submission = AssignmentSubmission::create([
'assignment_id' => $assignment->id,
@ -235,12 +219,8 @@ public function submit(): void
->usingFileName($this->file->getClientOriginalName())
->toMediaCollection('submission');
SystemNotification::success(
'Yeay! Tugas Terkumpul! 🎉',
'Berhasil! Tugas Anda telah tercatat dengan aman di sistem. Semangat! 🎈',
'Konfirmasi Pengumpulan Berhasil',
'Seluruh berkas tugas Anda telah berhasil diverifikasi dan disimpan oleh sistem.'
)->send();
SystemNotification::send('submission_success')
->send();
}
$this->file = null;

View File

@ -3,7 +3,6 @@
namespace App\Filament\Resources\Learning\Assignments\Schemas;
use App\Enums\AssignmentType;
use App\Enums\NotifStyle;
use App\Filament\Resources\Learning\Assignments\Actions\SelectAllStudentsAction;
use App\Filament\Support\SystemNotification;
use App\Models\Assignment;
@ -30,9 +29,9 @@ public static function configure(Schema $schema): Schema
{
return $schema
->components([
Section::make(SystemNotification::getMessage('Informasi Tugas 📝✨', 'Informasi Tugas'))
->description(SystemNotification::getMessage('Jelaskan tugasnya apa, kapan deadline-nya, dan buat sesi berapa. Semangat! 💪', 'Lengkapi informasi detail penugasan.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-document-text' : 'heroicon-o-information-circle')
Section::make(SystemNotification::getByKey('labels.assignment_info.title'))
->description(SystemNotification::getByKey('labels.assignment_info.description'))
->icon(SystemNotification::getByKey('icons.assignment_info'))
->schema([
TextInput::make('title')
@ -128,9 +127,9 @@ public static function configure(Schema $schema): Schema
])
->columns(2),
Section::make(SystemNotification::getMessage('Target Penugasan 🎯🧑‍🎓', 'Target Penugasan'))
->description(SystemNotification::getMessage('Pilih siapa saja yang bakal ngerjain tugas ini. Jangan sampai salah sasaran ya! 🏹', 'Tentukan sasaran penerima penugasan ini.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-users' : 'heroicon-o-user-group')
Section::make(SystemNotification::getByKey('labels.assignment_target.title'))
->description(SystemNotification::getByKey('labels.assignment_target.description'))
->icon(SystemNotification::getByKey('icons.assignment_target'))
->schema([
Select::make('student_ids')
->label('Mahasiswa')

View File

@ -38,37 +38,37 @@ class ManageAttendances extends Page implements HasForms, HasTable
#[Computed]
public function heading(): string
{
return SystemNotification::getMessage('Ayo Presensi Dulu! 🙋‍♂️✨', 'Sesi Kuliah');
return SystemNotification::getByKey('labels.attendance_section.title');
}
#[Computed]
public function description(): string
{
return SystemNotification::getMessage('Jangan lupa absen ya kalau kelasnya udah mulai! Biar tercatat hadir. 💪', 'Silakan melakukan presensi sesuai dengan waktu kelas.');
return SystemNotification::getByKey('labels.attendance_section.description');
}
#[Computed]
public function historyHeading(): string
{
return SystemNotification::getMessage('Jejak Presensimu 🕰️📜', 'Riwayat Presensi');
return SystemNotification::getByKey('labels.attendance_history.title');
}
#[Computed]
public function historyDescription(): string
{
return SystemNotification::getMessage('Di sini kamu bisa ngecek semua histori kehadiranmu sebelumnya. Rajin-rajin ya! 🎓', 'Berikut adalah riwayat kehadiran Anda pada sesi perkuliahan.');
return SystemNotification::getByKey('labels.attendance_history.description');
}
#[Computed]
public function emptyHeading(): string
{
return SystemNotification::getMessage('Yah, Absensi Belum Muncul! 💁‍♂️🌀', 'Tidak ada data yang ditemukan');
return SystemNotification::getByKey('labels.empty_attendance.title');
}
#[Computed]
public function emptyDescription(): string
{
return SystemNotification::getMessage('Sabar ya, setelah jadwal perkuliahan kamu muncul baru bisa diabsen di sini. Pantau terus jam kuliahnya! 🕒💪', 'Setelah jadwal Anda muncul, Anda dapat melakukan presensi di sini. Pastikan Anda mengecek kembali pada jam perkuliahan.');
return SystemNotification::getByKey('labels.empty_attendance.description');
}
public function getSchedules()
@ -187,12 +187,8 @@ public function attend(int $sessionId): void
->first();
if ($existing) {
SystemNotification::warning(
'Presensi Sudah Tercatat ⚠️',
'Anda telah melakukan presensi untuk sesi perkuliahan ini. Jangan lupa belajar yang rajin ya! 📚✨',
'Pemberitahuan Presensi',
'Status kehadiran Anda untuk sesi perkuliahan ini telah tercatat sebelumnya dalam sistem.'
)->send();
SystemNotification::send('attendance_already_recorded', type: 'warning')
->send();
return;
}
@ -200,12 +196,8 @@ public function attend(int $sessionId): void
// Check time
$startTime = $session->start_time;
if (now()->lessThan($startTime)) {
SystemNotification::warning(
'Sabar Yaa! Belum Dibuka ⏳',
'Waktu presensi untuk sesi perkuliahan ini belum dimulai nih. Tunggu sebentar lagi, ya! ☕😊',
'Sesi Presensi Belum Dimulai',
'Akses pengisian presensi untuk sesi ini belum diaktifkan sesuai dengan jadwal yang ditentukan.'
)->send();
SystemNotification::send('attendance_not_started', type: 'warning')
->send();
return;
}
@ -223,12 +215,8 @@ public function attend(int $sessionId): void
'attended_at' => now(),
]);
SystemNotification::success(
'Mantap! Presensi Berhasil ✨🚀',
'Kehadiran Anda telah berhasil direkam. Semangat belajarnya hari ini! 💪✅',
'Konfirmasi Presensi Berhasil',
'Informasi kehadiran Anda telah berhasil diverifikasi dan disimpan secara resmi ke dalam sistem.'
)->send();
SystemNotification::send('attendance_success')
->send();
}
public function table(Table $table): Table

View File

@ -30,12 +30,8 @@ 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. 📋',
'Penyalinan Tautan Berhasil',
'Tautan URL telah berhasil disalin ke papan klip sistem.'
)->send();
SystemNotification::send('link_copied')
->send();
});
}
}

View File

@ -67,12 +67,8 @@ protected function setUp(): void
$totalNewSessions = (int) ($data['total_sessions'] ?? 1);
if (! $schedule) {
SystemNotification::danger(
'Oops! Gagal Generate 🚫',
'Jadwal belum ditentukan untuk mata kuliah ini, jadi sistem bingung mau buat sesi kapan. 😟',
'Eksekusi Dibatalkan',
'Penjadwalan resmi belum dikonfigurasi untuk mata kuliah ini. Proses pembuatan sesi otomatis tidak dapat dilanjutkan.'
)->send();
SystemNotification::send('sessions_generated_failed', type: 'danger')
->send();
return;
}
@ -98,12 +94,11 @@ protected function setUp(): void
);
}
SystemNotification::success(
'Hore! Sesi Siap ✨🚀',
$totalNewSessions.' Sesi baru (No. '.$nextNumber.' sampai '.$maxNumber.') berhasil digenerate. 🎉',
'Verifikasi Sesi Berhasil',
'Seluruh '.$totalNewSessions.' sesi pembelajaran tambahan telah berhasil dikonfigurasi secara otomatis.'
)->send();
SystemNotification::send('sessions_generated_success', [
'count' => $totalNewSessions,
'start' => $nextNumber,
'end' => $maxNumber,
])->send();
});
}
}

View File

@ -33,12 +33,8 @@ protected function setUp(): void
'password' => Hash::make($data['password']),
]);
SystemNotification::success(
'Aha! Kata Sandi Baru Berhasil 🔑✨',
"Kata sandi untuk {$record->full_name} sudah update nih. Jangan lupa ingatkan mereka ya! 😉",
'Perubahan Kata Sandi Berhasil',
"Kredensial keamanan untuk mahasiswa {$record->full_name} telah diperbarui sesuai dengan entri sistem."
)->send();
SystemNotification::send('password_changed', ['name' => $record->full_name])
->send();
});
}
}

View File

@ -2,7 +2,6 @@
namespace App\Filament\Resources\Master\Students\Schemas;
use App\Enums\NotifStyle;
use App\Enums\Sex;
use App\Filament\Support\SystemNotification;
use Carbon\Carbon;
@ -21,12 +20,9 @@ public static function configure(Schema $schema): Schema
{
return $schema
->components([
Section::make(SystemNotification::getMessage('Kredensial Akun 🔑✨', 'Akun'))
->description(new HtmlString(SystemNotification::getMessage(
'Pake email dan username ini buat login ya. Oh iya, password awalnya <code class="text-sm bg-gray-100 text-red-400 px-1.5 py-0.5 rounded font-mono">Minimal8@</code> 🥳',
'Alamat Surel dan Nama Pengguna akan digunakan untuk masuk ke dalam sistem. Kata sandi bawaan adalah <code class="text-sm bg-gray-100 text-red-400 px-1.5 py-0.5 rounded font-mono">Minimal8@</code>'
)))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-key' : 'heroicon-o-user')
Section::make(SystemNotification::getByKey('labels.account_credentials.title'))
->description(new HtmlString(SystemNotification::getByKey('labels.account_credentials.description')))
->icon(SystemNotification::getByKey('icons.account_credentials'))
->schema([
TextInput::make('email')
->label('Alamat Surel')
@ -50,9 +46,9 @@ public static function configure(Schema $schema): Schema
->columns(2)
->hiddenOn('edit'),
Section::make(SystemNotification::getMessage('Data Mahasiswa 🎓📚', 'Informasi Mahasiswa'))
->description(SystemNotification::getMessage('Lengkapi data mahasiswa di bawah ini dengan benar ya! 🤓📝', 'Masukkan seluruh informasi akademik dan personal mahasiswa dengan benar.'))
->icon(SystemNotification::getNotifStyle() === NotifStyle::Cheerful ? 'heroicon-o-academic-cap' : 'heroicon-o-identification')
Section::make(SystemNotification::getByKey('labels.student_data.title'))
->description(SystemNotification::getByKey('labels.student_data.description'))
->icon(SystemNotification::getByKey('icons.student_data'))
->schema([
TextInput::make('full_name')
->label('Nama Lengkap')

View File

@ -104,12 +104,8 @@ public static function configure(Table $table): Table
->delete();
}
SystemNotification::success(
$state ? 'Pengguna Diaktifkan! ✅✨' : 'Pengguna Dinonaktifkan ⛔👋',
$state ? 'Status akun pengguna berhasil diaktifkan kembali. Siap beraksi! 🚀' : 'Status akun pengguna telah berhasil dinonaktifkan. Istirahat dulu ya... 😴',
$state ? 'Aktivasi Akun Berhasil' : 'Penonaktifan Akun Berhasil',
$state ? 'Status akun pengguna terpilih telah diubah menjadi aktif.' : 'Status akun pengguna terpilih telah diubah menjadi tidak aktif.'
)->send();
SystemNotification::send($state ? 'user_activated' : 'user_deactivated')
->send();
})
->visible(fn () => auth()->user()->hasRole([RoleEnum::Kosma, RoleEnum::Developer])),

308
app/Filament/Support/SystemNotification.php Normal file → Executable file
View File

@ -3,9 +3,7 @@
namespace App\Filament\Support;
use App\Enums\NotifStyle;
use App\Models\User;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Auth;
class SystemNotification
{
@ -18,215 +16,110 @@ public static function make(): Notification
}
/**
* Notification for successful record creation.
*/
public static function create(): Notification
{
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.')
);
}
/**
* Notification for successful record update.
*/
public static function update(): Notification
{
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.')
);
}
/**
* Notification for successful record deletion (soft delete).
*/
public static function delete(): Notification
{
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.')
);
}
/**
* Notification for successful permanent deletion.
*/
public static function forceDelete(): Notification
{
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.')
);
}
/**
* Notification for successful record restoration.
*/
public static function restore(): Notification
{
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.')
);
}
/**
* Notification for successful status change/toggle.
*/
public static function statusUpdated(?string $title = null, ?string $body = null): Notification
{
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.')
);
}
/**
* Notification for successful bulk deletion.
*/
public static function bulkDelete(): Notification
{
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.')
);
}
/**
* Notification for successful bulk permanent deletion.
*/
public static function bulkForceDelete(): Notification
{
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.')
);
}
/**
* Notification for successful bulk restoration.
*/
public static function bulkRestore(): Notification
{
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.')
);
}
/**
* Success notification wrapper.
*/
public static function success(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification
{
$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(),
'success'
);
}
/**
* Custom info notification.
*/
public static function info(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification
{
$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(),
'info'
);
}
/**
* Custom warning notification.
*/
public static function warning(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification
{
$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(),
'warning'
);
}
/**
* Custom danger notification.
*/
public static function danger(string $title, string $body, ?string $formalTitle = null, ?string $formalBody = null): Notification
{
$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(),
'danger'
);
}
/**
* Apply the user's selected style to the notification.
*/
protected static function applyStyle(Notification $notification, string $status): Notification
{
$isCheerful = self::getNotifStyle() === NotifStyle::Cheerful;
if ($isCheerful) {
$notification
->duration(6000)
->icon(match ($status) {
'success' => 'heroicon-o-sparkles',
'danger' => 'heroicon-o-fire',
'warning' => 'heroicon-o-bolt',
'info' => 'heroicon-o-megaphone',
default => null,
});
} else {
$notification
->icon(null)
->duration(4000);
}
return $notification;
}
/**
* Get the current user's notification style preference.
* Get the current user's Notification style preference.
*/
public static function getNotifStyle(): NotifStyle
{
try {
/** @var User|null $user */
$user = Auth::user();
return $user?->settings?->notif_style ?? NotifStyle::Cheerful;
return auth()->user()?->settings?->notif_style ?? NotifStyle::Cheerful;
} catch (\Throwable $e) {
return NotifStyle::Cheerful;
}
}
public static function create(): Notification
{
return self::make()
->title(self::getByKey('create.title'))
->body(self::getByKey('create.body'))
->success();
}
public static function update(): Notification
{
return self::make()
->title(self::getByKey('update.title'))
->body(self::getByKey('update.body'))
->success();
}
public static function delete(): Notification
{
return self::make()
->title(self::getByKey('delete.title'))
->body(self::getByKey('delete.body'))
->success();
}
public static function forceDelete(): Notification
{
return self::make()
->title(self::getByKey('force_delete.title'))
->body(self::getByKey('force_delete.body'))
->success();
}
public static function restore(): Notification
{
return self::make()
->title(self::getByKey('restore.title'))
->body(self::getByKey('restore.body'))
->success();
}
public static function statusUpdated(?string $title = null, ?string $body = null): Notification
{
return self::make()
->title($title ?? self::getByKey('status_updated.title'))
->body($body ?? self::getByKey('status_updated.body'))
->success();
}
public static function bulkDelete(): Notification
{
return self::make()
->title(self::getByKey('bulk_delete.title'))
->body(self::getByKey('bulk_delete.body'))
->success();
}
public static function bulkForceDelete(): Notification
{
return self::make()
->title(self::getByKey('bulk_force_delete.title'))
->body(self::getByKey('bulk_force_delete.body'))
->success();
}
public static function bulkRestore(): Notification
{
return self::make()
->title(self::getByKey('bulk_restore.title'))
->body(self::getByKey('bulk_restore.body'))
->success();
}
/**
* Get message based on the user's notification style preference.
* Send a notification by key.
*/
public static function send(string $key, array $replace = [], string $type = 'success'): Notification
{
$notification = self::make()
->title(self::getByKey("$key.title", $replace))
->body(self::getByKey("$key.body", $replace));
return match ($type) {
'info' => $notification->info(),
'warning' => $notification->warning(),
'danger' => $notification->danger(),
default => $notification->success(),
};
}
/**
* Get dynamic message based on UX style.
*
* @deprecated Use getByKey('key') for centralized messages.
*/
public static function getMessage(string $cheerful, string $formal): string
{
@ -234,17 +127,12 @@ public static function getMessage(string $cheerful, string $formal): string
}
/**
* Strip emojis if the notification style is formal.
* Get translation by key and current user notification style.
*/
public static function clean(string $text): string
public static function getByKey(string $key, array $replace = []): 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';
$style = self::getNotifStyle()->value;
return trim(preg_replace($regex, '', $text));
}
return $text;
return __("notif.{$style}.{$key}", $replace);
}
}

View File

@ -15,6 +15,6 @@ class SupportWidget extends Widget
public function getHeading(): string
{
return SystemNotification::getMessage('Butuh Bantuan? Tanya Saja! 💬✨', 'Informasi & Bantuan');
return SystemNotification::getByKey('labels.help_center.title');
}
}

414
lang/id/notif.php Normal file
View File

@ -0,0 +1,414 @@
<?php
return [
'cheerful' => [
// Standard Actions
'create' => [
'title' => 'Hore! Data Tersimpan 🎉✨',
'body' => 'Data baru berhasil ditambahkan! Sistem sudah menyimpannya dengan aman. 🚀💪',
],
'update' => [
'title' => 'Mantap! Data Diperbarui ✅🔥',
'body' => 'Perubahan berhasil disimpan! Data sekarang sudah up-to-date dan segar lagi. ✨👌',
],
'delete' => [
'title' => 'Oke, Data Dihapus 🗑️👋',
'body' => 'Data tersebut sudah berhasil dihapus dari sistem. Semuanya bersih dan rapi sekarang! 😊🚮',
],
'force_delete' => [
'title' => 'Selamat Tinggal Selamanya 👋😢',
'body' => 'Data telah dihapus permanen dan tidak bisa kembali. Semoga ini keputusan yang tepat! 🚮💨',
],
'restore' => [
'title' => 'Welcome Back! Data Pulih ♻️✨',
'body' => 'Data berhasil dikembalikan! Hati-hati ya, jangan sampai terhapus lagi. 😉👍',
],
'status_updated' => [
'title' => 'Status Berubah! 🔄✨',
'body' => 'Status data berhasil diperbarui. Perubahan langsung aktif ya! 👍',
],
'bulk_delete' => [
'title' => 'Oke, Banyak Data Dihapus 🗑️👋',
'body' => 'Semua data yang dipilih berhasil dihapus. Sistem makin lega deh! 😊',
],
'bulk_force_delete' => [
'title' => 'Bye Bye Semua! 👋🔥',
'body' => 'Data yang dipilih sudah dihapus permanen. Bersih total! 🧹💨',
],
'bulk_restore' => [
'title' => 'Hore! Banyak Data Pulih ♻️🎉',
'body' => 'Data-data tersebut sudah kembali aktif. Selamat bekerja kembali! 💪✨',
],
// Custom Messages
'password_changed' => [
'title' => 'Password Berhasil Diganti 🔑✨',
'body' => 'Password untuk :name sudah diperbarui. Jangan sampai lupa lagi ya! 😉🔐',
],
'profile_updated' => [
'title' => 'Profil Kece Diperbarui! 👤🌈',
'body' => 'Data profil kamu sudah berhasil disimpan. Tampil makin oke deh! 🚀✨',
],
'account_security_updated' => [
'title' => 'Keamanan Akun Diperbarui 🔐',
'body' => 'Anda telah mengubah kata sandi. Demi keamanan, silakan masuk kembali ya! 🚪🔑',
],
'login_success' => [
'title' => 'Selamat Datang Kembali! 👋✨',
'body' => 'Senang melihatmu lagi, :name! Ayo lanjut belajar dan berkarya hari ini. 💪🚀',
],
'login_failed' => [
'title' => 'Ups! Ada yang Salah 🙅‍♂️❌',
'body' => 'Email atau password kamu nggak pas nih. Coba dicek lagi ya, pelan-pelan saja! 😉🔍',
],
'access_suspended' => [
'title' => 'Akses Ditangguhkan ⛔',
'body' => 'Maaf, Anda tidak dapat masuk karena status akun saat ini sedang tidak aktif. Silakan hubungi Administrator ya! 😴',
],
'login_invalid' => [
'title' => 'Waduh! Gagal Masuk 🛑⚠️',
'body' => 'Ada masalah saat memproses login kamu. Coba lagi sebentar lagi ya! 🙏🌀',
],
'assignment_pinned' => [
'title' => 'Tugas Disematkan! 📌✨',
'body' => 'Tugas ini sekarang ada di paling atas biar gampang kamu pantau! 🚀',
],
'assignment_unpinned' => [
'title' => 'Sematkan Dilepas 📍👋',
'body' => 'Tugas sudah kembali ke posisi semula di daftar. 👌',
],
'link_copied' => [
'title' => 'Link Berhasil Disalin! 🔗✨',
'body' => 'Link tugas sudah tersimpan di clipboard kamu. Tinggal share deh! 🚀👌',
],
'attendance_already_recorded' => [
'title' => 'Presensi Sudah Tercatat ⚠️',
'body' => 'Anda telah melakukan presensi untuk sesi perkuliahan ini. Jangan lupa belajar yang rajin ya! 📚✨',
],
'attendance_not_started' => [
'title' => 'Sabar Yaa! Belum Dibuka ⏳',
'body' => 'Waktu presensi untuk sesi perkuliahan ini belum dimulai nih. Tunggu sebentar lagi, ya! ☕😊',
],
'attendance_success' => [
'title' => 'Mantap! Presensi Berhasil ✨🚀',
'body' => 'Kehadiran Anda telah berhasil direkam. Semangat belajarnya hari ini! 💪✅',
],
'sessions_generated_failed' => [
'title' => 'Oops! Gagal Generate 🚫',
'body' => 'Jadwal belum ditentukan untuk mata kuliah ini, jadi sistem bingung mau buat sesi kapan. 😟',
],
'sessions_generated_success' => [
'title' => 'Hore! Sesi Siap ✨🚀',
'body' => ':count Sesi baru (No. :start sampai :end) berhasil dibuat otomatis. 🎉',
],
'submission_no_group' => [
'title' => 'Gagal Mengumpulkan 🚫',
'body' => 'Anda tidak terdaftar dalam kelompok manapun yang ditugaskan untuk tugas ini. 😟',
],
'submission_not_leader' => [
'title' => 'Akses Ditolak 🚫',
'body' => 'Hanya ketua kelompok yang diizinkan untuk mengumpulkan atau memperbarui tugas kelompok. 👑',
],
'submission_file_missing' => [
'title' => 'Pilih File Dulu Dong! 📁',
'body' => 'Silakan pilih file untuk dikumpulkan agar sistem bisa menyimpannya ya! 😊',
],
'submission_updated' => [
'title' => 'Keren! Tugas Sudah Update ✨',
'body' => 'File tugas Anda telah berhasil diunggah ulang dan diperbarui di sistem. 📤',
],
'submission_success' => [
'title' => 'Yeay! Tugas Terkumpul! 🎉',
'body' => 'Berhasil! Tugas Anda telah tercatat dengan aman di sistem. Semangat! 🎈',
],
'user_activated' => [
'title' => 'Pengguna Diaktifkan! ✅✨',
'body' => 'Status akun pengguna berhasil diaktifkan kembali. Siap beraksi! 🚀',
],
'user_deactivated' => [
'title' => 'Pengguna Dinonaktifkan ⛔👋',
'body' => 'Status akun pengguna telah berhasil dinonaktifkan. Istirahat dulu ya... 😴',
],
// UI Labels & Descriptions
'labels' => [
'assignment_info' => [
'title' => 'Informasi Tugas 📝✨',
'description' => 'Jelaskan tugasnya apa, kapan deadline-nya, dan buat sesi berapa. Semangat! 💪',
],
'assignment_target' => [
'title' => 'Target Penugasan 🎯🧑‍🎓',
'description' => 'Pilih siapa saja yang bakal ngerjain tugas ini. Jangan sampai salah sasaran ya! 🏹',
],
'account_credentials' => [
'title' => 'Kredensial Akun 🔑✨',
'description' => 'Pake email dan username ini buat login ya. Oh iya, password awalnya <code class="text-sm bg-gray-100 text-red-400 px-1.5 py-0.5 rounded font-mono">Minimal8@</code> 🥳',
],
'student_data' => [
'title' => 'Data Mahasiswa 🎓📚',
'description' => 'Lengkapi data mahasiswa di bawah ini dengan benar ya! 🤓📝',
'description_profile' => 'Pastikan data akademikmu sesuai dengan yang di sistem, jangan sampai salah loh! 🤓📝',
],
'user_account' => [
'title' => 'Akun Pengguna 👤✨',
'description' => 'Kelola informasi detail akun Anda di sini ya biar nggak kudet! 😉🚀',
],
'account_security' => [
'title' => 'Keamanan Akun 🔐⚡',
'description' => 'Rajin-rajin ganti password ya, biar akunmu aman dan nggak dibobol orang! 🕵️‍♂️🛡️',
],
'appearance_settings' => [
'title' => 'Pengaturan Tampilan & UX 🎨✨',
'description' => 'Personalisasi pengalaman aplikasi Anda agar lebih nyaman dan sesuai selera! 🌈🚀',
],
'help_center' => [
'title' => 'Butuh Bantuan? Tanya Saja! 💬✨',
],
'study_group_list' => [
'title' => 'Daftar Grup Seru! 💃🕺',
'description' => 'Lihat semua kelompok belajarmu di sini. Makin kompak makin asik! 🤝📚',
],
'empty_study_group' => [
'title' => 'Wah, Belum Ada Grup! 👯‍♂️🌀',
'description' => 'Belum ada kelompok belajar yang terdaftar. Ayo ajak teman-temanmu bikin kelompok biar makin seru belajarnya! 🤝📄',
],
'course_schedule_hint' => 'Geser ke samping buat intip hari lainnya ya! 📅✨',
'empty_course_schedule' => [
'title' => 'Yah, Belum Ada Jadwal Nih! 📄💤',
'description' => 'Belum ada jadwal perkuliahan yang terdaftar. Mungkin hari ini kamu bisa istirahat dulu? 😉💤',
],
'attendance_section' => [
'title' => 'Ayo Presensi Dulu! 🙋‍♂️✨',
'description' => 'Jangan lupa absen ya kalau kelasnya udah mulai! Biar tercatat hadir. 💪',
],
'attendance_history' => [
'title' => 'Jejak Presensimu 🕰️📜',
'description' => 'Di sini kamu bisa ngecek semua histori kehadiranmu sebelumnya. Rajin-rajin ya! 🎓',
],
'empty_attendance' => [
'title' => 'Yah, Absensi Belum Muncul! 💁‍♂️🌀',
'description' => 'Sabar ya, setelah jadwal perkuliahan kamu muncul baru bisa diabsen di sini. Pantau terus jam kuliahnya! 🕒💪',
],
'assignment_list' => [
'title' => 'Daftar Tugas Bikin Lemes! 🤣📒',
'description' => 'Yuk, cek dan kumpulin tugasmu biar tenang hidupnya! Klik aja di tugasnya ya. 🚀👨‍💻',
],
],
// Icons
'icons' => [
'assignment_info' => 'heroicon-o-document-text',
'assignment_target' => 'heroicon-o-users',
'account_credentials' => 'heroicon-o-key',
'student_data' => 'heroicon-o-academic-cap',
'user_account' => 'heroicon-o-face-smile',
'account_security' => 'heroicon-o-shield-check',
'appearance_settings' => 'heroicon-o-swatch',
],
],
'formal' => [
// Standard Actions
'create' => [
'title' => 'Data Berhasil Disimpan',
'body' => 'Data baru telah berhasil ditambahkan ke dalam sistem.',
],
'update' => [
'title' => 'Perubahan Tersimpan',
'body' => 'Perubahan pada data telah berhasil diperbarui dan disimpan.',
],
'delete' => [
'title' => 'Data Dihapus',
'body' => 'Data tersebut telah berhasil dihapus dari sistem aplikasi.',
],
'force_delete' => [
'title' => 'Data Dihapus Permanen',
'body' => 'Data tersebut telah dihapus secara permanen dari sistem.',
],
'restore' => [
'title' => 'Data Berhasil Dipulihkan',
'body' => 'Data yang dihapus sebelumnya telah berhasil dipulihkan ke dalam sistem.',
],
'status_updated' => [
'title' => 'Status Diperbarui',
'body' => 'Status data telah berhasil diperbarui dan telah diterapkan.',
],
'bulk_delete' => [
'title' => 'Data Berhasil Dihapus',
'body' => 'Seluruh data yang dipilih telah berhasil dihapus dari sistem.',
],
'bulk_force_delete' => [
'title' => 'Data Dihapus Permanen',
'body' => 'Data yang dipilih telah berhasil dihapus secara permanen.',
],
'bulk_restore' => [
'title' => 'Data Berhasil Dipulihkan',
'body' => 'Seluruh data yang dipilih telah berhasil dikembalikan ke posisi semula.',
],
// Custom Messages
'password_changed' => [
'title' => 'Kata Sandi Berhasil Diperbarui',
'body' => 'Kata sandi untuk :name telah berhasil diperbarui di dalam sistem.',
],
'profile_updated' => [
'title' => 'Profil Berhasil Diperbarui',
'body' => 'Perubahan pada informasi profil Anda telah berhasil disimpan.',
],
'account_security_updated' => [
'title' => 'Pembaruan Kredensial',
'body' => 'Kata sandi Anda telah berhasil diubah. Harap lakukan otentikasi ulang untuk melanjutkan sesi.',
],
'login_success' => [
'title' => 'Otentikasi Berhasil',
'body' => 'Selamat datang kembali, :name. Anda telah berhasil masuk ke dalam sistem.',
],
'login_failed' => [
'title' => 'Otentikasi Gagal',
'body' => 'Email atau kata sandi yang Anda masukkan tidak sesuai dengan record kami.',
],
'access_suspended' => [
'title' => 'Akses Akun Terbatas',
'body' => 'Akun Anda saat ini dalam status tidak aktif. Mohon hubungi pihak Administrator untuk klarifikasi lebih lanjut.',
],
'login_invalid' => [
'title' => 'Kesalahan Sistem',
'body' => 'Terjadi kesalahan saat memproses permintaan masuk Anda. Silakan coba lagi.',
],
'assignment_pinned' => [
'title' => 'Tugas Disematkan',
'body' => 'Tugas telah berhasil disematkan ke bagian atas daftar penugasan.',
],
'assignment_unpinned' => [
'title' => 'Sematkan Dilepas',
'body' => 'Status sematan pada tugas ini telah berhasil dilepaskan.',
],
'link_copied' => [
'title' => 'Tautan Berhasil Disalin',
'body' => 'Tautan tugas telah disalin ke papan klip perangkat Anda.',
],
'attendance_already_recorded' => [
'title' => 'Pemberitahuan Presensi',
'body' => 'Status kehadiran Anda untuk sesi perkuliahan ini telah tercatat sebelumnya dalam sistem.',
],
'attendance_not_started' => [
'title' => 'Sesi Presensi Belum Dimulai',
'body' => 'Akses pengisian presensi untuk sesi ini belum diaktifkan sesuai dengan jadwal yang ditentukan.',
],
'attendance_success' => [
'title' => 'Konfirmasi Presensi Berhasil',
'body' => 'Informasi kehadiran Anda telah berhasil diverifikasi dan disimpan secara resmi ke dalam sistem.',
],
'sessions_generated_failed' => [
'title' => 'Eksekusi Dibatalkan',
'body' => 'Penjadwalan resmi belum dikonfigurasi untuk mata kuliah ini. Proses pembuatan sesi otomatis tidak dapat dilanjutkan.',
],
'sessions_generated_success' => [
'title' => 'Verifikasi Sesi Berhasil',
'body' => 'Seluruh :count sesi pembelajaran tambahan (No. :start sampai :end) telah berhasil dikonfigurasi secara otomatis.',
],
'submission_no_group' => [
'title' => 'Kesalahan Pengumpulan Tugas',
'body' => 'Data akun Anda tidak ditemukan dalam daftar kelompok yang ditugaskan untuk tugas ini.',
],
'submission_not_leader' => [
'title' => 'Batasan Otoritas Pengumpulan',
'body' => 'Hanya ketua kelompok yang memiliki otoritas untuk memperbarui atau mengumpulkan tugas kelompok.',
],
'submission_file_missing' => [
'title' => 'Kelengkapan Berkas Diperlukan',
'body' => 'Mohon sertakan lampiran berkas sebelum melanjutkan proses pengumpulan tugas.',
],
'submission_updated' => [
'title' => 'Pembaruan Berkas Berhasil',
'body' => 'Berkas tugas telah berhasil diunggah ulang dan divalidasi oleh sistem.',
],
'submission_success' => [
'title' => 'Konfirmasi Pengumpulan Berhasil',
'body' => 'Seluruh berkas tugas Anda telah berhasil diverifikasi dan disimpan oleh sistem.',
],
'user_activated' => [
'title' => 'Aktivasi Akun Berhasil',
'body' => 'Status akun pengguna terpilih telah diubah menjadi aktif.',
],
'user_deactivated' => [
'title' => 'Penonaktifan Akun Berhasil',
'body' => 'Status akun pengguna terpilih telah diubah menjadi tidak aktif.',
],
// UI Labels & Descriptions
'labels' => [
'assignment_info' => [
'title' => 'Informasi Tugas',
'description' => 'Lengkapi informasi detail penugasan.',
],
'assignment_target' => [
'title' => 'Target Penugasan',
'description' => 'Tentukan sasaran penerima penugasan ini.',
],
'account_credentials' => [
'title' => 'Akun',
'description' => 'Alamat Surel dan Nama Pengguna akan digunakan untuk masuk ke dalam sistem. Kata sandi bawaan adalah <code class="text-sm bg-gray-100 text-red-400 px-1.5 py-0.5 rounded font-mono">Minimal8@</code>',
],
'student_data' => [
'title' => 'Informasi Mahasiswa',
'description' => 'Masukkan seluruh informasi akademik dan personal mahasiswa dengan benar.',
'description_profile' => 'Pastikan data akademik Anda sesuai dengan record sistem.',
],
'user_account' => [
'title' => 'Akun',
'description' => 'Kelola informasi detail akun Anda agar selalu terkini.',
],
'account_security' => [
'title' => 'Keamanan Akun',
'description' => 'Perbarui kata sandi Anda secara berkala untuk menjaga keamanan akun.',
],
'appearance_settings' => [
'title' => 'Preferensi Tampilan',
'description' => 'Sesuaikan gaya bahasa, warna tema, dan jenis huruf aplikasi Anda.',
],
'help_center' => [
'title' => 'Informasi & Bantuan',
],
'study_group_list' => [
'title' => 'Kelompok Belajar',
'description' => 'Daftar kelompok belajar Anda dan teman-teman sekelas.',
],
'empty_study_group' => [
'title' => 'Tidak ada data yang ditemukan',
'description' => 'Belum ada kelompok belajar yang terdaftar untuk kriteria ini. Klik tombol tambah untuk memulai pembuatan kelompok.',
],
'course_schedule_hint' => 'Geser ke samping untuk melihat hari lainnya.',
'empty_course_schedule' => [
'title' => 'Tidak ada data yang ditemukan',
'description' => 'Belum ada jadwal perkuliahan yang terdaftar untuk kriteria ini. Hubungi administrator jika jadwal Anda belum muncul.',
],
'attendance_section' => [
'title' => 'Sesi Kuliah',
'description' => 'Silakan melakukan presensi sesuai dengan waktu kelas.',
],
'attendance_history' => [
'title' => 'Riwayat Presensi',
'description' => 'Berikut adalah riwayat kehadiran Anda pada sesi perkuliahan.',
],
'empty_attendance' => [
'title' => 'Tidak ada data yang ditemukan',
'description' => 'Setelah jadwal Anda muncul, Anda dapat melakukan presensi di sini. Pastikan Anda mengecek kembali pada jam perkuliahan.',
],
'assignment_list' => [
'title' => 'Tugas Saya',
'description' => 'Klik pada tugas untuk melihat detail dan mengumpulkan file.',
],
],
// Icons
'icons' => [
'assignment_info' => 'heroicon-o-information-circle',
'assignment_target' => 'heroicon-o-user-group',
'account_credentials' => 'heroicon-o-user',
'student_data' => 'heroicon-o-identification',
'user_account' => 'heroicon-o-user',
'account_security' => 'heroicon-o-lock-closed',
'appearance_settings' => 'heroicon-o-paint-brush',
],
],
];