diff --git a/app/Http/Controllers/Admin/RoleController.php b/app/Http/Controllers/Admin/RoleController.php index de3dd5b..9028512 100644 --- a/app/Http/Controllers/Admin/RoleController.php +++ b/app/Http/Controllers/Admin/RoleController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Http\Requests\RoleRequest; +use Spatie\Permission\Models\Permission; use Spatie\Permission\Models\Role; class RoleController extends Controller @@ -18,4 +19,84 @@ class RoleController extends Controller // Kembalikan data ke komponen Inertia 'Admin/Roles/Index' return inertia('Admin/Roles/Index', compact('roles')); } + public function create() +{ + // Ambil semua permission + $permissions = Permission::all(); + + // Kembalikan ke Inertia 'Admin/Roles/Create' dengan data permissions + return inertia('Admin/Roles/Create', [ + 'permissions' => $permissions, + ]); +} + + public function store(RoleRequest $request) + { + // Validasi data input melalui RoleRequest + $validatedData = $request->validated(); + + // Buat role baru dengan data yang telah divalidasi + $role = Role::create($validatedData); + + // Tetapkan permissions pada role yang baru dibuat + $role->syncPermissions($request->input('permissions')); + + // Jika berhasil simpan, arahkan dengan pesan sukses, jika gagal dengan pesan error + if ($role) { + return redirect()->route('admin.roles.index')->with(['success' => 'Data Berhasil Disimpan!']); + } else { + return redirect()->route('admin.roles.index')->with(['error' => 'Data Gagal Disimpan!']); + } + } + + public function edit(Role $role) + { + // Ambil semua permission, diurutkan dari yang terbaru + $permissions = Permission::latest()->get(); + + // Ambil ID dari permissions yang dimiliki oleh role saat ini + $rolePermissions = $role->permissions->pluck('id')->toArray(); + + // Map permissions agar hanya menyertakan 'id' dan 'name' + $permissions = $permissions->map(function ($permission) { + return [ + 'id' => $permission->id, + 'name' => $permission->name, + ]; + }); + + // Kembalikan data ke Inertia 'Admin/Roles/Edit' dengan data role, permissions, dan rolePermissions + return inertia('Admin/Roles/Edit', [ + 'permissions' => $permissions, + 'role' => $role, + 'rolePermissions' => $rolePermissions, + ]); + } + + public function update(RoleRequest $request, Role $role) + { + // Update data role dengan data yang telah divalidasi + $role->name = $request->name; + + // Sync permissions + $role->permissions()->sync($request->permissions); + + // Simpan perubahan + $role->save(); + + // Arahkan kembali ke daftar role + return redirect()->route('admin.roles.index')->with('success', 'Role updated successfully.'); + } + + public function destroy($id) + { + // Cari role berdasarkan ID, error jika tidak ditemukan + $role = Role::findOrFail($id); + + // Hapus role dari database + $role->delete(); + + // Arahkan kembali dengan pesan bahwa role berhasil dihapus + return redirect()->route('admin.roles.index')->with('message', 'Role deleted successfully.'); + } } diff --git a/app/Http/Controllers/HistoryKegiatanController.php b/app/Http/Controllers/HistoryKegiatanController.php new file mode 100644 index 0000000..31a4c77 --- /dev/null +++ b/app/Http/Controllers/HistoryKegiatanController.php @@ -0,0 +1,66 @@ +get(); + return Inertia::render('admin/kegiatan/index_history_kegiatan', ['historykegiatan' => $historykegiatan]); + } catch (\Exception $e) { + Log::error('Error fetching History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function store(HistoryKegiatanRequest $request) + { + try { + $historykegiatan = HistoryKegiatan::withTrashed() + ->where('NamaHistoryKegiatan', $request->NamaHistoryKegiatan) + ->first(); + + if ($historykegiatan) { + $historykegiatan->restore(); + return redirect()->route('admin.historykegiatan.index')->with('success', 'History Kegiatan berhasil dikembalikan.'); + } + + HistoryKegiatan::create($request->validated()); + + return redirect()->route('admin.historykegiatan.index')->with('success', 'History Kegiatan berhasil dibuat.'); + } catch (\Exception $e) { + Log::error('Error creating History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function update(HistoryKegiatanRequest $request, HistoryKegiatan $historykegiatan) + { + try { + $historykegiatan->update($request->validated()); + return redirect()->route('admin.history$historykegiatan.index')->with('success', 'History Kegiatan berhasil diperbarui.'); + } catch (\Exception $e) { + Log::error('Error updating History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function destroy(HistoryKegiatan $historykegiatan) + { + try { + $historykegiatan->delete(); + return redirect()->route('admin.histo$historykegiatan.index')->with('success', 'History Kegiatan berhasil dihapus.'); + } catch (\Exception $e) { + Log::error('Error deleting History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php new file mode 100644 index 0000000..76d16f7 --- /dev/null +++ b/app/Http/Controllers/HomeController.php @@ -0,0 +1,66 @@ +where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->get(); + + // Fetch Pengumuman + $pengumuman = Post::with(['kategori', 'subkategori']) + ->whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Pengumuman'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->take(4) + ->get(); + + // Fetch Undangan + $undangan = Post::with(['kategori', 'subkategori']) + ->whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Undangan'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->take(4) + ->get(); + + // Fetch Peraturan + $peraturan = Post::with(['kategori', 'subkategori']) + ->whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Peraturan'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->take(4) + ->get(); + + // Fetch Sekilas Info + $sekilasInfo = Post::with(['kategori', 'subkategori']) + ->whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Sekilas Info'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->take(3) + ->get(); + + return Inertia::render('welcome', [ + 'posts' => $pengumuman, + 'undangan' => $undangan, + 'peraturan' => $peraturan, + 'sekilasInfo' => $sekilasInfo, + 'runPosts' => $runPosts, + ]); + } +} diff --git a/app/Http/Controllers/HukumController.php b/app/Http/Controllers/HukumController.php new file mode 100644 index 0000000..a2a200d --- /dev/null +++ b/app/Http/Controllers/HukumController.php @@ -0,0 +1,20 @@ +getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/JenisDokILController.php b/app/Http/Controllers/JenisDokILController.php new file mode 100644 index 0000000..97b3fb3 --- /dev/null +++ b/app/Http/Controllers/JenisDokILController.php @@ -0,0 +1,56 @@ +get(); + return Inertia::render('admin/jenisdokil/index_jenisdokil', ['jenisdokil' => $jenisdokil]); + } catch (\Exception $e) { + Log::error('Error fetching Jenis Dokumen Ilmiah: ' . $e->getMessage()); + return back()->with('error', 'Failed to fetch Jenis Dokumen Ilmiah.'); + } + } + + public function store(JenisDokILRequest $request) + { + try { + JenisDokIL::create($request->validated()); + return redirect()->route('admin.jenisdokil.index')->with('success', 'Jenis Dokumen Ilmiah created successfully.'); + } catch (\Exception $e) { + Log::error('Error creating Jenis Dokumen Ilmiah: ' . $e->getMessage()); + return back()->with('error', 'Failed to create Jenis Dokumen Ilmiah.'); + } + } + + public function update(JenisDokILRequest $request, JenisDokIL $jenisdokil) + { + try { + $jenisdokil->update($request->validated()); + return redirect()->route('admin.jenisdokil.index')->with('success', 'Jenis Dokumen Ilmiah updated successfully.'); + } catch (\Exception $e) { + Log::error('Error updating Jenis Dokumen Ilmiah: ' . $e->getMessage()); + return back()->with('error', 'Failed to update Jenis Dokumen Ilmiah.'); + } + } + + public function destroy(JenisDokIL $jenisdokil) + { + try { + $jenisdokil->delete(); + return redirect()->route('admin.jenisdokil.index')->with('success', 'Jenis Dokumen Ilmiah deleted successfully.'); + } catch (\Exception $e) { + Log::error('Error deleting Jenis Dokumen Ilmiah: ' . $e->getMessage()); + return back()->with('error', 'Failed to delete Jenis Dokumen Ilmiah.'); + } + } +} diff --git a/app/Http/Controllers/JenisKegiatanController.php b/app/Http/Controllers/JenisKegiatanController.php new file mode 100644 index 0000000..342acbe --- /dev/null +++ b/app/Http/Controllers/JenisKegiatanController.php @@ -0,0 +1,66 @@ +get(); + return Inertia::render('admin/kegiatan/index_jenis_kegiatan', ['jeniskegiatan' => $jeniskegiatan]); + } catch (\Exception $e) { + Log::error('Error fetching Jenis Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function store(JenisKegiatanRequest $request) + { + try { + $jeniskegiatan = JenisKegiatan::withTrashed() + ->where('NamaJenisKegiatan', $request->NamaJenisKegiatan) + ->first(); + + if ($jeniskegiatan) { + $jeniskegiatan->restore(); + return redirect()->route('admin.jeniskegiatan.index')->with('success', 'Jenis Kegiatan berhasil dikembalikan.'); + } + + JenisKegiatan::create($request->validated()); + + return redirect()->route('admin.jeniskegiatan.index')->with('success', 'Jenis Kegiatan berhasil dibuat.'); + } catch (\Exception $e) { + Log::error('Error creating Jenis Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function update(JenisKegiatanRequest $request, JenisKegiatan $jeniskegiatan) + { + try { + $jeniskegiatan->update($request->validated()); + return redirect()->route('admin.jeniskegiatan.index')->with('success', 'Jenis Kegiatan berhasil diperbarui.'); + } catch (\Exception $e) { + Log::error('Error updating Jenis Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function destroy(JenisKegiatan $jeniskegiatan) + { + try { + $jeniskegiatan->delete(); + return redirect()->route('admin.jeniskegiatan.index')->with('success', 'Jenis Kegiatan berhasil dihapus.'); + } catch (\Exception $e) { + Log::error('Error deleting Jenis Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/JenisSanksiController.php b/app/Http/Controllers/JenisSanksiController.php new file mode 100644 index 0000000..d14057f --- /dev/null +++ b/app/Http/Controllers/JenisSanksiController.php @@ -0,0 +1,55 @@ +get(); + return Inertia::render('admin/jenissanksi/index_jenis_sanksi', ['jenissanksi' => $jenissanksi]); + } catch (\Exception $e) { + Log::error('Error fetching Jenis Sanksi: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function store(Request $request) + { + try { + JenisSanksi::create($request->all()); + return redirect()->route('admin.jenissanksi.index')->with('success', 'Jenis Sanksi berhasil dibuat.'); + } catch (\Exception $e) { + Log::error('Error creating Jenis Sanksi: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function update(Request $request, JenisSanksi $jenissanksi) + { + try { + $jenissanksi->update($request->all()); + return redirect()->route('admin.jenissanksi.index')->with('success', 'Jenis Sanksi berhasil diperbarui.'); + } catch (\Exception $e) { + Log::error('Error updating Jenis Sanksi: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function destroy(JenisSanksi $jenissanksi) + { + try { + $jenissanksi->delete(); + return redirect()->route('admin.jenissanksi.index')->with('success', 'Jenis Sanksi berhasil dihapus.'); + } catch (\Exception $e) { + Log::error('Error deleting Jenis Sanksi: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/PelaporanController.php b/app/Http/Controllers/PelaporanController.php new file mode 100644 index 0000000..08ca839 --- /dev/null +++ b/app/Http/Controllers/PelaporanController.php @@ -0,0 +1,20 @@ +getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/PengumumanController.php b/app/Http/Controllers/PengumumanController.php new file mode 100644 index 0000000..b97d2d1 --- /dev/null +++ b/app/Http/Controllers/PengumumanController.php @@ -0,0 +1,48 @@ +whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Pengumuman'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->get(); + + Log::info('Posts data:', ['posts' => $posts->toArray()]); // Debug log + + return Inertia::render('Pengumuman', [ + 'posts' => $posts + ]); + } + + public function show($slug) + { + $article = Post::with(['kategori', 'subkategori']) + ->where('SlugPost', $slug) + ->firstOrFail(); + + $relatedArticles = Post::with(['kategori', 'subkategori']) + ->where('KategoriId', $article->KategoriId) + ->where('PostId', '!=', $article->PostId) + ->where('IsPublish', true) + ->latest() + ->take(5) + ->get(); + + return Inertia::render('detail/PegumumanDetail', [ + 'article' => $article, + 'relatedArticles' => $relatedArticles + ]); + } +} diff --git a/app/Http/Controllers/PeraturanController.php b/app/Http/Controllers/PeraturanController.php new file mode 100644 index 0000000..4ff037d --- /dev/null +++ b/app/Http/Controllers/PeraturanController.php @@ -0,0 +1,45 @@ +whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Peraturan'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->get(); + + return Inertia::render('Peraturan', [ + 'posts' => $posts + ]); + } + + public function show($slug) + { + $article = Post::with(['kategori', 'subkategori']) + ->where('SlugPost', $slug) + ->firstOrFail(); + + $relatedArticles = Post::with(['kategori', 'subkategori']) + ->where('KategoriId', $article->KategoriId) + ->where('PostId', '!=', $article->PostId) + ->where('IsPublish', true) + ->latest() + ->take(5) + ->get(); + + return Inertia::render('detail/PeraturanDetail', [ + 'article' => $article, + 'relatedArticles' => $relatedArticles + ]); + } +} diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php index ef511e9..12836cb 100644 --- a/app/Http/Controllers/PostController.php +++ b/app/Http/Controllers/PostController.php @@ -10,6 +10,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; use Inertia\Inertia; +use Illuminate\Support\Facades\DB; class PostController extends Controller { @@ -32,34 +33,68 @@ class PostController extends Controller $subkategori = SubKategori::all(); return Inertia::render('admin/post/add_post', [ - 'kategori' => $kategori, - 'subkategori' => $subkategori + 'kategori' => Kategori::all(), + 'subkategori' => SubKategori::all(), + 'existingPosts' => Post::select('JudulPost', 'KategoriId')->get() ]); } public function store(PostRequest $request) { - try { $data = $request->validated(); - $data['IsPublish'] = $request->has('IsPublish'); - if ($request->hasFile('ImagePost')) { - $data['ImagePost'] = $request->file('ImagePost')->store('images/posts'); + DB::beginTransaction(); + + try { + $data['IsPublish'] = $request->boolean('IsPublish'); + + if ($request->hasFile('ImagePost')) { + $file = $request->file('ImagePost'); + + if (!$file->isValid()) { + throw new \Exception('Invalid image file'); + } + + $data['ImagePost'] = $file->store('images/posts', 'public'); + + if ($data['ImagePost'] === false) { + throw new \Exception('Failed to store image'); + } + } + + $post = Post::create($data); + DB::commit(); + + return redirect() + ->route('admin.post.index') + ->with('success', 'Post berhasil ditambahkan'); + + } catch (\Exception $e) { + DB::rollBack(); + + if (isset($data['ImagePost']) && Storage::disk('public')->exists($data['ImagePost'])) { + Storage::disk('public')->delete($data['ImagePost']); + } + + Log::error('Error creating post: ' . $e->getMessage()); + + return redirect() + ->route('admin.post.index') + ->with('error', 'Post gagal ditambahkan: ' . $e->getMessage()); } - Post::create($data); - - return redirect()->route('admin.post.index')->with('success', 'Post berhasil ditambahkan'); } catch (\Exception $e) { - return redirect()->route('admin.post.index')->with('error', 'Post gagal ditambahkan'); - } + Log::error('Validation error: ' . $e->getMessage()); + return redirect() + ->route('admin.post.index') + ->with('error', 'Validasi gagal: ' . $e->getMessage()); + } } public function edit(Post $post) { - return Inertia::render('admin/post/edit_post', [ 'post' => $post, 'kategori' => Kategori::all(), @@ -70,19 +105,30 @@ class PostController extends Controller public function update(PostRequest $request, Post $post) { try { - $data = $request->validated(); + $data = array_filter($request->validated(), function($value) { + return $value !== null; + }); if ($request->hasFile('ImagePost')) { - Storage::disk('public')->delete($post->ImagePost); + if ($post->ImagePost && Storage::disk('public')->exists($post->ImagePost)) { + Storage::disk('public')->delete($post->ImagePost); + } $data['ImagePost'] = $request->file('ImagePost')->store('images/posts', 'public'); } + if (isset($data['IsPublish'])) { + $data['IsPublish'] = (bool) $data['IsPublish']; + } + $post->update($data); - return redirect()->route('admin.post.index')->with('success', 'Post berhasil diperbarui.'); + return redirect() + ->route('admin.post.index') + ->with('success', 'Post berhasil diperbarui.'); + } catch (\Exception $e) { Log::error('Error updating Post: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); + return back()->with('error', 'Terjadi kesalahan saat memperbarui post.'); } } @@ -98,6 +144,4 @@ class PostController extends Controller return back()->with('error', 'Something went wrong.'); } } - - } diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php new file mode 100644 index 0000000..3f05d6f --- /dev/null +++ b/app/Http/Controllers/SearchController.php @@ -0,0 +1,29 @@ +input('q'); + + $searchResults = Post::with(['kategori', 'subkategori']) + ->where('IsPublish', true) + ->where(function($q) use ($query) { + $q->where('JudulPost', 'ILIKE', "%{$query}%") + ->orWhere('DescPost', 'ILIKE', "%{$query}%"); + }) + ->latest() + ->get(); + + return Inertia::render('Search', [ + 'searchResults' => $searchResults, + 'searchQuery' => $query + ]); + } +} diff --git a/app/Http/Controllers/SekilasInfoController.php b/app/Http/Controllers/SekilasInfoController.php new file mode 100644 index 0000000..3da878b --- /dev/null +++ b/app/Http/Controllers/SekilasInfoController.php @@ -0,0 +1,30 @@ +where('SlugPost', $slug) + ->firstOrFail(); + + $relatedArticles = Post::with(['kategori', 'subkategori']) + ->where('KategoriId', $article->KategoriId) + ->where('PostId', '!=', $article->PostId) + ->where('IsPublish', true) + ->latest() + ->take(5) + ->get(); + + return Inertia::render('detail/SekilasInfoDetail', [ + 'article' => $article, + 'relatedArticles' => $relatedArticles + ]); + } +} diff --git a/app/Http/Controllers/TentangController.php b/app/Http/Controllers/TentangController.php new file mode 100644 index 0000000..295d21e --- /dev/null +++ b/app/Http/Controllers/TentangController.php @@ -0,0 +1,20 @@ +getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/UndanganController.php b/app/Http/Controllers/UndanganController.php new file mode 100644 index 0000000..048663c --- /dev/null +++ b/app/Http/Controllers/UndanganController.php @@ -0,0 +1,45 @@ +whereHas('kategori', function($query) { + $query->where('NamaKategori', 'Undangan'); + }) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->get(); + + return Inertia::render('Undangan', [ + 'posts' => $posts + ]); + } + + public function show($slug) + { + $article = Post::with(['kategori', 'subkategori']) + ->where('SlugPost', $slug) + ->firstOrFail(); + + $relatedArticles = Post::with(['kategori', 'subkategori']) + ->where('KategoriId', $article->KategoriId) + ->where('PostId', '!=', $article->PostId) + ->where('IsPublish', true) + ->latest() + ->take(5) + ->get(); + + return Inertia::render('detail/UndanganDetail', [ + 'article' => $article, + 'relatedArticles' => $relatedArticles + ]); + } +} diff --git a/app/Http/Controllers/VerifPelaporanController.php b/app/Http/Controllers/VerifPelaporanController.php new file mode 100644 index 0000000..f0b5c80 --- /dev/null +++ b/app/Http/Controllers/VerifPelaporanController.php @@ -0,0 +1,20 @@ +getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Controllers/VerifikatorController.php b/app/Http/Controllers/VerifikatorController.php new file mode 100644 index 0000000..b062264 --- /dev/null +++ b/app/Http/Controllers/VerifikatorController.php @@ -0,0 +1,56 @@ +get(); + return Inertia::render('admin/verifikator/index_verifikator', ['verifikator' => $verifikator]); + } catch (\Exception $e) { + Log::error('Error fetching Verifikator: ' . $e->getMessage()); + return back()->with('error', 'Failed to fetch verifikator.'); + } + } + + public function store(VerifikatorRequest $request) + { + try { + Verifikator::create($request->validated()); + return redirect()->route('verifikator.index')->with('success', 'Verifikator created successfully.'); + } catch (\Exception $e) { + Log::error('Error creating verifikator: ' . $e->getMessage()); + return back()->with('error', 'Failed to create verifikator.'); + } + } + + public function update(VerifikatorRequest $request, Verifikator $verifikator) + { + try { + $verifikator->update($request->validated()); + return redirect()->route('verifikator.index')->with('success', 'Verifikator updated successfully.'); + } catch (\Exception $e) { + Log::error('Error updating verifikator: ' . $e->getMessage()); + return back()->with('error', 'Failed to update verifikator.'); + } + } + + public function destroy(Verifikator $verifikator) + { + try { + $verifikator->delete(); + return redirect()->route('verifikator.index')->with('success', 'Verifikator deleted successfully.'); + } catch (\Exception $e) { + Log::error('Error deleting verifikator: ' . $e->getMessage()); + return back()->with('error', 'Failed to delete verifikator.'); + } + } +} diff --git a/app/Http/Requests/HistoryKegiatanRequest.php b/app/Http/Requests/HistoryKegiatanRequest.php new file mode 100644 index 0000000..11d72db --- /dev/null +++ b/app/Http/Requests/HistoryKegiatanRequest.php @@ -0,0 +1,35 @@ +|string> + */ + public function rules(): array + { + return [ + 'NamaHistoryKegiatan' => [ + 'required', + 'string', + 'max:255', + Rule::unique('HistoryKegiatan', 'NamaHistoryKegiatan')->whereNull('deleted_at') // Abaikan data yang dihapus (soft delete) + ], + 'IsPublish' => 'boolean', + ]; + } +} diff --git a/app/Http/Requests/HukumRequest.php b/app/Http/Requests/HukumRequest.php new file mode 100644 index 0000000..4f351d2 --- /dev/null +++ b/app/Http/Requests/HukumRequest.php @@ -0,0 +1,58 @@ +|string> + */ + public function rules(): array + { + return [ + 'PerusahaanId' => 'nullable|integer|exists:RefPerusahaan,id', + 'JenisSanksiId' => 'nullable|integer|exists:RefJenisSanksi,id', + 'SanksiNumber' => 'nullable|string|max:100', + 'SanksiDate' => 'nullable|date', + 'SanksiFile' => 'nullable|file|mimes:pdf|max:2048', + 'StatusPenaatan' => 'required|integer|in:1,2,3', + 'PenaatanNumber' => 'nullable|string|max:100', + 'PenaatanDate' => 'nullable|date', + 'PenaatanFile' => 'nullable|file|mimes:pdf,jpg,png|max:2048', + 'IsDeleted' => 'nullable|boolean', + ]; + } + + public function messages(): array + { + return [ + 'PerusahaanId.integer' => 'Perusahaan harus berupa angka.', + 'PerusahaanId.exists' => 'Perusahaan tidak ditemukan.', + 'JenisSanksiId.integer' => 'Jenis Sanksi harus berupa angka.', + 'JenisSanksiId.exists' => 'Jenis Sanksi tidak ditemukan.', + 'SanksiNumber.max' => 'Nomor SK Sanksi maksimal 100 karakter.', + 'SanksiDate.date' => 'Tanggal SK Sanksi harus berupa format tanggal.', + 'SanksiFile.mimes' => 'File Sanksi harus berupa PDF', + 'SanksiFile.max' => 'Ukuran file maksimal 2MB.', + 'StatusPenaatan.required'=> 'Status Penaatan wajib diisi.', + 'StatusPenaatan.in' => 'Status Penaatan hanya boleh 1, 2, atau 3.', + 'PenaatanNumber.max' => 'Nomor SK Penaatan maksimal 100 karakter.', + 'PenaatanDate.date' => 'Tanggal SK Penaatan harus berupa format tanggal.', + 'PenaatanFile.mimes' => 'File Penaatan harus berupa PDF', + 'PenaatanFile.max' => 'Ukuran file maksimal 2MB.', + 'IsDeleted.boolean' => 'IsDeleted hanya boleh bernilai 0 atau 1.', + ]; + } +} diff --git a/app/Http/Requests/JenisDokILRequest.php b/app/Http/Requests/JenisDokILRequest.php new file mode 100644 index 0000000..5579d95 --- /dev/null +++ b/app/Http/Requests/JenisDokILRequest.php @@ -0,0 +1,29 @@ +|string> + */ + public function rules(): array + { + return [ + 'NamaJenisDokIL' => 'required|string|max:255', + 'KodeJenisDokIL' => 'required|string|max:20', + ]; + } +} diff --git a/app/Http/Requests/JenisKegiatanRequest.php b/app/Http/Requests/JenisKegiatanRequest.php new file mode 100644 index 0000000..c27ad5c --- /dev/null +++ b/app/Http/Requests/JenisKegiatanRequest.php @@ -0,0 +1,35 @@ +|string> + */ + public function rules(): array + { + return [ + 'NamaJenisKegiatan' => [ + 'required', + 'string', + 'max:255', + Rule::unique('JenisKegiatan', 'NamaJenisKegiatan')->whereNull('deleted_at') // Abaikan data yang dihapus (soft delete) + ], + 'IsPublish' => 'boolean', + ]; + } +} diff --git a/app/Http/Requests/JenisSanksiRequest.php b/app/Http/Requests/JenisSanksiRequest.php new file mode 100644 index 0000000..72d3267 --- /dev/null +++ b/app/Http/Requests/JenisSanksiRequest.php @@ -0,0 +1,34 @@ +|string> + */ + public function rules(): array + { + return [ + 'NamaJenisSanksi' => [ + 'required', + 'string', + 'max:255', + Rule::unique('JenisSanksi', 'NamaJenisSanksi')->whereNull('deleted_at') // Abaikan data yang dihapus (soft delete) + ], + ]; + } +} diff --git a/app/Http/Requests/PostRequest.php b/app/Http/Requests/PostRequest.php index ef6a44e..142da57 100644 --- a/app/Http/Requests/PostRequest.php +++ b/app/Http/Requests/PostRequest.php @@ -3,7 +3,7 @@ namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Validation\Rule; +use Illuminate\Support\Facades\Log; class PostRequest extends FormRequest { @@ -22,15 +22,53 @@ class PostRequest extends FormRequest */ public function rules(): array { - return [ - 'KategoriId' => 'required|exists:Kategori,KategoriId', - 'SubKategoriId' => [ - 'required', - Rule::exists('SubKategori', 'SubKategoriId')->where('KategoriId', $this->KategoriId), - ], - 'JudulPost' => ['required', 'string', 'max:255'], - 'DescPost' => ['required', 'string'], - 'ImagePost' => ['nullable', 'image', 'mimes:jpg,png,webp', 'max:2048'], - ]; + if ($this->isMethod('POST')) { + return [ + 'KategoriId' => 'required|integer|exists:Kategori,KategoriId', + 'SubKategoriId' => 'required|integer|exists:SubKategori,SubKategoriId', + 'JudulPost' => ['required', 'string', 'max:255'], + 'SlugPost' => ['required', 'string', 'max:255'], + 'DescPost' => ['required', 'string'], + 'ImagePost' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:2048'], + 'IsPublish' => 'boolean', + ]; + } + + if ($this->isMethod('PUT') || $this->isMethod('PATCH')) { + return [ + 'KategoriId' => 'nullable|integer|exists:Kategori,KategoriId', + 'SubKategoriId' => 'nullable|integer|exists:SubKategori,SubKategoriId', + 'JudulPost' => ['nullable', 'string', 'max:255'], + 'SlugPost' => ['nullable', 'string', 'max:255'], + 'DescPost' => ['nullable', 'string'], + 'ImagePost' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:2048'], + 'IsPublish' => 'nullable|boolean', + ]; + } + + return []; + } + + // Add this method to handle validation before rules are applied + protected function prepareForValidation() + { + if ($this->isMethod('PUT') || $this->isMethod('PATCH')) { + // Only set these if they're not provided in the request + if (!$this->has('KategoriId')) { + $this->merge(['KategoriId' => $this->route('post')->KategoriId]); + } + if (!$this->has('SubKategoriId')) { + $this->merge(['SubKategoriId' => $this->route('post')->SubKategoriId]); + } + if (!$this->has('JudulPost')) { + $this->merge(['JudulPost' => $this->route('post')->JudulPost]); + } + if (!$this->has('SlugPost')) { + $this->merge(['SlugPost' => $this->route('post')->SlugPost]); + } + if (!$this->has('DescPost')) { + $this->merge(['DescPost' => $this->route('post')->DescPost]); + } + } } } diff --git a/app/Http/Requests/VerifikatorRequest.php b/app/Http/Requests/VerifikatorRequest.php new file mode 100644 index 0000000..003a6c0 --- /dev/null +++ b/app/Http/Requests/VerifikatorRequest.php @@ -0,0 +1,30 @@ +|string> + */ + public function rules(): array + { + return [ + 'NamaUnitKerja' => 'required|string|max:255', + 'NamaKepala' => 'required|string|max:255', + 'NIP' => 'required|string|max:255', + ]; + } +} diff --git a/app/Models/HistoryKegiatan.php b/app/Models/HistoryKegiatan.php new file mode 100644 index 0000000..4df4d34 --- /dev/null +++ b/app/Models/HistoryKegiatan.php @@ -0,0 +1,24 @@ +belongsTo(Perusahaan::class, 'PerusahaanId'); + } + + /** + * Relasi ke tabel jenis sanksi. + */ + public function jenisSanksi() + { + return $this->belongsTo(JenisSanksi::class, 'JenisSanksiId'); + } +} diff --git a/app/Models/JenisDokIL.php b/app/Models/JenisDokIL.php new file mode 100644 index 0000000..da7bebd --- /dev/null +++ b/app/Models/JenisDokIL.php @@ -0,0 +1,15 @@ +belongsTo(Kabupaten::class, 'KabupatenId', 'KabupatenId'); + } +} diff --git a/app/Models/Kelurahan.php b/app/Models/Kelurahan.php new file mode 100644 index 0000000..500a2ff --- /dev/null +++ b/app/Models/Kelurahan.php @@ -0,0 +1,19 @@ +belongsTo(Kecamatan::class, 'KecamatanId', 'KecamatanId'); + } +} diff --git a/app/Models/Perusahaan.php b/app/Models/Perusahaan.php new file mode 100644 index 0000000..0fbcc96 --- /dev/null +++ b/app/Models/Perusahaan.php @@ -0,0 +1,84 @@ + 'boolean', + 'IsPublish' => 'boolean', + 'ILPdlTanggal' => 'date', + ]; + + // Relationship with JenisKegiatan + public function jenisKegiatan(): BelongsTo + { + return $this->belongsTo(JenisKegiatan::class, 'JenisKegiatanId', 'JenisKegiatanId'); + } + + // Relationship with Kelurahan + public function kelurahan(): BelongsTo + { + return $this->belongsTo(Kelurahan::class, 'KelurahanId', 'KelurahanId'); + } + + // Relationship with JenisDokIL + public function jenisDokIL(): BelongsTo + { + return $this->belongsTo(JenisDokIL::class, 'JenisDokILId', 'JenisDokILId'); + } + + // Relationship with JenisDokIL for PDL + public function jenisDokILPdl(): BelongsTo + { + return $this->belongsTo(JenisDokIL::class, 'ILPdlJenis', 'JenisDokILId'); + } + + // Relationship with Verifikator + public function verifikator(): BelongsTo + { + return $this->belongsTo(Verifikator::class, 'VerifikatorId', 'VerifikatorId'); + } + + // Self-referential relationship for Kawasan + public function kawasan(): BelongsTo + { + return $this->belongsTo(Perusahaan::class, 'Kawasan', 'PerusahaanId'); + } +} diff --git a/app/Models/Post.php b/app/Models/Post.php index 0451a69..419d287 100644 --- a/app/Models/Post.php +++ b/app/Models/Post.php @@ -37,12 +37,12 @@ class Post extends Model return \Carbon\Carbon::parse($this->created_at)->translatedFormat('d F Y'); } - public static function boot() - { - parent::boot(); + // public static function boot() + // { + // parent::boot(); - static::creating(function ($post) { - $post->Slug = Str::slug($post->JudulPost); - }); - } + // static::creating(function ($post) { + // $post->SlugPost = Str::slug($post->JudulPost); + // }); + // } } diff --git a/app/Models/Verifikator.php b/app/Models/Verifikator.php new file mode 100644 index 0000000..1b6dcfc --- /dev/null +++ b/app/Models/Verifikator.php @@ -0,0 +1,17 @@ + fn () => Post::with(['kategori', 'subkategori']) + ->where('IsPublish', true) + ->orderBy('created_at', 'desc') + ->get(), + ]); } } diff --git a/config/filesystems.php b/config/filesystems.php index 44fe9c8..32114d8 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -13,7 +13,7 @@ return [ | */ - 'default' => env('FILESYSTEM_DISK', 'local'), + 'default' => env('FILESYSTEM_DISK', 'public'), /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2024_01_01_create_kelurahans_table.php b/database/migrations/2024_01_01_create_kelurahans_table.php new file mode 100644 index 0000000..e69de29 diff --git a/database/migrations/2025_02_14_142819_create_historykegiatan_table.php b/database/migrations/2025_02_14_142819_create_historykegiatan_table.php new file mode 100644 index 0000000..ac485b3 --- /dev/null +++ b/database/migrations/2025_02_14_142819_create_historykegiatan_table.php @@ -0,0 +1,29 @@ +id('HistoryKegiatanId'); + $table->string('NamaHistoryKegiatan'); + $table->boolean('IsPublish')->default(0); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('historykegiatan'); + } +}; diff --git a/database/migrations/2025_02_14_153943_create_jeniskegiatan_table.php b/database/migrations/2025_02_14_153943_create_jeniskegiatan_table.php new file mode 100644 index 0000000..0f536d4 --- /dev/null +++ b/database/migrations/2025_02_14_153943_create_jeniskegiatan_table.php @@ -0,0 +1,29 @@ +id('JenisKegiatanId'); + $table->string('NamaJenisKegiatan'); + $table->boolean('IsPublish')->default(0); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jeniskegiatan'); + } +}; diff --git a/database/migrations/2025_02_17_083731_add_softdeletes_to_jeniskegiatan_table.php b/database/migrations/2025_02_17_083731_add_softdeletes_to_jeniskegiatan_table.php new file mode 100644 index 0000000..2fced1d --- /dev/null +++ b/database/migrations/2025_02_17_083731_add_softdeletes_to_jeniskegiatan_table.php @@ -0,0 +1,28 @@ +softDeletes()->after('IsPublish'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('JenisKegiatan', function (Blueprint $table) { + $table->dropSoftDeletes(); + }); + } +}; diff --git a/database/migrations/2025_02_17_084617_add_softdeletes_to_historykegiatan_table.php b/database/migrations/2025_02_17_084617_add_softdeletes_to_historykegiatan_table.php new file mode 100644 index 0000000..03bb9b1 --- /dev/null +++ b/database/migrations/2025_02_17_084617_add_softdeletes_to_historykegiatan_table.php @@ -0,0 +1,28 @@ +softDeletes()->after('IsPublish'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HistoryKegiatan', function (Blueprint $table) { + $table->dropSoftDeletes(); + }); + } +}; diff --git a/database/migrations/2025_02_17_100043_modify_nama_kategori_to_non_unique.php b/database/migrations/2025_02_17_100043_modify_nama_kategori_to_non_unique.php new file mode 100644 index 0000000..f8d0695 --- /dev/null +++ b/database/migrations/2025_02_17_100043_modify_nama_kategori_to_non_unique.php @@ -0,0 +1,28 @@ +dropUnique(['NamaKategori']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Kategori', function (Blueprint $table) { + $table->unique('NamaKategori'); + }); + } +}; diff --git a/database/migrations/2025_02_17_111029_create_periodepelaporan_table.php b/database/migrations/2025_02_17_111029_create_periodepelaporan_table.php new file mode 100644 index 0000000..a685da4 --- /dev/null +++ b/database/migrations/2025_02_17_111029_create_periodepelaporan_table.php @@ -0,0 +1,32 @@ +id('PeriodePelaporanId'); + $table->string('NamaPeriodePelaporan'); + $table->date('BulanAwal'); + $table->date('BulanSelesai'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('PeriodePelaporan', function (Blueprint $table) { + // + }); + } +}; diff --git a/database/migrations/2025_02_17_112004_create_perusahaan_table.php b/database/migrations/2025_02_17_112004_create_perusahaan_table.php new file mode 100644 index 0000000..830049b --- /dev/null +++ b/database/migrations/2025_02_17_112004_create_perusahaan_table.php @@ -0,0 +1,64 @@ +id('PerusahaanId'); + $table->string('NomorInduk')->nullable(); + $table->unsignedBigInteger('JenisKegiatanId'); + $table->foreign('JenisKegiatanId')->references('JenisKegiatanId')->on('JenisKegiatan')->onDelete('cascade'); + $table->string('NamaPerusahaan'); + $table->string('Alamat')->nullable(); + $table->unsignedBigInteger('KelurahanId'); + $table->foreign('KelurahanId')->references('KelurahanId')->on('Kelurahan')->onDelete('cascade'); + $table->string('KodePos')->nullable(); + $table->string('Telepon')->nullable(); + $table->string('Fax')->nullable(); + $table->string('Email')->nullable(); + $table->string('Lintang')->nullable(); + $table->string('Bujur')->nullable(); + $table->string('CPNama')->nullable(); + $table->string('CPTelepon')->nullable(); + $table->string('ILNomor')->nullable(); + $table->string('ILTanggal')->nullable(); + $table->unsignedBigInteger('JenisDokILId'); + $table->foreign('JenisDokILId')->references('JenisDokILId')->on('JenisDokIL')->onDelete('cascade'); + $table->unsignedBigInteger('VerifikatorId'); + $table->foreign('VerifikatorId')->references('VerifikatorId')->on('Verifikator')->onDelete('cascade'); + $table->boolean('ReportLocked')->default(1); + $table->boolean('IsPublish')->default(0); + $table->string('ILDokumen')->nullable(); + $table->string('ILPdlNomor')->default('n')->comment('Dok IL versi PDL'); + $table->unsignedInteger('ILPdlJenis')->nullable()->comment('id dari refjenisdokil'); + $table->foreign('ILPdlJenis')->references('JenisDokILId')->on('JenisDokIL')->onDelete('set null'); + $table->string('DocPdlOrig')->nullable()->comment('nama file original'); + $table->string('DocPdlHash')->nullable()->comment('nama file hash'); + $table->string('DocPdlPath')->nullable()->comment('upload path'); + $table->date('ILPdlTanggal')->nullable(); + $table->unsignedInteger('Kawasan')->nullable()->comment('id dari perusahaan, digunakan utk pengelola kawasan'); + $table->foreign('Kawasan')->references('PerusahaanId')->on('Perusahaan')->onDelete('set null'); + + + $table->timestamps(); + $table->index('NomorInduk', 'IndexNomorInduk'); + $table->index('KelurahanId', 'IndexKelurahanId'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Perusahaan'); + } +}; diff --git a/database/migrations/2025_02_17_112206_create_kelurahan_table.php b/database/migrations/2025_02_17_112206_create_kelurahan_table.php new file mode 100644 index 0000000..80fa63a --- /dev/null +++ b/database/migrations/2025_02_17_112206_create_kelurahan_table.php @@ -0,0 +1,30 @@ +id('KelurahanId'); + $table->unsignedBigInteger('KecamatanId'); + $table->foreign('KecamatanId')->references('KecamatanId')->on('Kecamatan')->onDelete('cascade'); + $table->string('NamaKelurahan'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Kelurahan'); + } +}; diff --git a/database/migrations/2025_02_17_112217_create_kecamatan_table.php b/database/migrations/2025_02_17_112217_create_kecamatan_table.php new file mode 100644 index 0000000..3ef994f --- /dev/null +++ b/database/migrations/2025_02_17_112217_create_kecamatan_table.php @@ -0,0 +1,30 @@ +id('KecamatanId'); + $table->unsignedBigInteger('KabupatenId'); + $table->foreign('KabupatenId')->references('KabupatenId')->on('Kabupaten')->onDelete('cascade'); + $table->string('NamaKecamatan'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Kecamatan'); + } +}; diff --git a/database/migrations/2025_02_17_112238_create_kabupaten_table.php b/database/migrations/2025_02_17_112238_create_kabupaten_table.php new file mode 100644 index 0000000..48f5afd --- /dev/null +++ b/database/migrations/2025_02_17_112238_create_kabupaten_table.php @@ -0,0 +1,28 @@ +id('KabupatenId'); + $table->string('NamaKabupaten'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Kabupaten'); + } +}; diff --git a/database/migrations/2025_02_17_124317_create_jenisdokumen__i_l_table.php b/database/migrations/2025_02_17_124317_create_jenisdokumen__i_l_table.php new file mode 100644 index 0000000..f046e02 --- /dev/null +++ b/database/migrations/2025_02_17_124317_create_jenisdokumen__i_l_table.php @@ -0,0 +1,29 @@ +id('JenisDokILId'); + $table->string('KodeJenisDokIL')->unique(); + $table->string('NamaJenisDokIL'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('JenisDokIL'); + } +}; diff --git a/database/migrations/2025_02_17_124903_create_verifikator_table.php b/database/migrations/2025_02_17_124903_create_verifikator_table.php new file mode 100644 index 0000000..3a9016b --- /dev/null +++ b/database/migrations/2025_02_17_124903_create_verifikator_table.php @@ -0,0 +1,30 @@ +id('VerifikatorId'); + $table->string('NamaUnitKerja'); + $table->string('NamaKepala'); + $table->string('NIP'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Verifikator'); + } +}; diff --git a/database/migrations/2025_02_17_150218_create_pelaporan_table.php b/database/migrations/2025_02_17_150218_create_pelaporan_table.php new file mode 100644 index 0000000..e302c3a --- /dev/null +++ b/database/migrations/2025_02_17_150218_create_pelaporan_table.php @@ -0,0 +1,55 @@ +id('PelaporanId'); + $table->unsignedInteger('PeriodePelaporanId'); + $table->foreign('PeriodePelaporanId')->references('PeriodePelaporanId')->on('PeriodePelaporan')->onDelete('cascade'); + $table->year('Tahun'); + $table->unsignedInteger('PerusahaanId'); + $table->foreign('PerusahaanId')->references('PerusahaanId')->on('Perusahaan')->onDelete('cascade'); + $table->float('SKL'); + $table->float('SPL'); + $table->float('SKL_IL'); + $table->float('SKL_AL'); + $table->float('SKL_LB3'); + $table->float('SKL_SB'); + $table->float('SKL_BS'); + $table->float('SKL_STB'); + $table->float('SKL_LP'); + $table->float('SKL_KDM'); + $table->float('SPL_AL'); + $table->float('SPL_LB3'); + $table->float('SPL_SB'); + $table->float('SPL_BS'); + $table->float('SPL_STB'); + $table->float('SPL_LP'); + $table->float('SPL_KDM'); + $table->string('IsChecked', 100)->nullable(); + + $table->timestamps(); + + $table->index('PeriodePelaporanId', 'IndexPeriodePelaporanId'); + $table->index('Tahun', 'IndexTahun'); + $table->index('PerusahaanId', 'IndexPerusahaanId'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Pelaporan'); + } +}; diff --git a/database/migrations/2025_02_18_091634_create_jenis_sanksi_table.php b/database/migrations/2025_02_18_091634_create_jenis_sanksi_table.php new file mode 100644 index 0000000..370d3ec --- /dev/null +++ b/database/migrations/2025_02_18_091634_create_jenis_sanksi_table.php @@ -0,0 +1,29 @@ +id('JenisSanksiId'); + $table->string('NamaJenisSanksi'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('JenisSanksi'); + } +}; diff --git a/database/migrations/2025_02_18_135753_create__hukum_table.php b/database/migrations/2025_02_18_135753_create__hukum_table.php new file mode 100644 index 0000000..5b4e4fc --- /dev/null +++ b/database/migrations/2025_02_18_135753_create__hukum_table.php @@ -0,0 +1,42 @@ +id('HukumId'); + $table->unsignedInteger('PerusahaanId')->nullable()->comment('id dari Perusahaan'); + $table->foreign('PerusahaanId')->references('PerusahaanId')->on('Perusahaan')->onDelete('cascade'); + $table->unsignedInteger('JenisSanksiId')->nullable()->comment('id dari Jenis Sanksi'); + $table->foreign('JenisSanksiId')->references('JenisSanksiId')->on('JenisSanksi')->onDelete('cascade'); + $table->string('SanksiNumber', 100)->nullable()->comment('nomor SK Sanksi'); + $table->date('SanksiDate')->nullable()->comment('tanggal SK Sanksi'); + $table->string('SanksiFile', 255)->nullable()->comment('path + orig filename + id perusahaan + epoch time'); + $table->unsignedTinyInteger('StatusPenaatan')->default(1)->comment('1=pengawasan, 2=peningkatan sanksi, 3=taat'); + $table->string('PenaatanNumber', 100)->nullable()->comment('nomor SK penaatan'); + $table->date('PenaatanDate')->nullable()->comment('tanggal SK penaatan'); + $table->string('PenaatanFile', 255)->nullable()->comment('path + orig filename + id perusahaan + epoch time'); + $table->unsignedTinyInteger('IsDeleted')->default(0)->comment('0=false, 1=true'); + + $table->index('PerusahaanId'); + $table->index('JenisSanksiId'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Hukum'); + } +}; diff --git a/database/seeders/KabupatenTableSeeder.php b/database/seeders/KabupatenTableSeeder.php new file mode 100644 index 0000000..397e4f1 --- /dev/null +++ b/database/seeders/KabupatenTableSeeder.php @@ -0,0 +1,38 @@ +json() as $kabupaten) { + // Convert the id format and map the data + $cleanId = str_replace('.', '', $kabupaten['id']); + + Kabupaten::create([ + 'KabupatenId' => $cleanId, + 'NamaKabupaten' => $kabupaten['data'] + ]); + + // Log data kabupaten yang sedang di-seed + Log::info('Seeding kabupaten: ', [ + 'KabupatenId' => $cleanId, + 'NamaKabupaten' => $kabupaten['data'] + ]); + } + } +} diff --git a/database/seeders/KecamatanTableSeeder.php b/database/seeders/KecamatanTableSeeder.php new file mode 100644 index 0000000..548f80d --- /dev/null +++ b/database/seeders/KecamatanTableSeeder.php @@ -0,0 +1,45 @@ +KabupatenId, 0, 2) . '.' . + substr($kabupaten->KabupatenId, 2, 2); + + $response = Http::get("https://api-wilayah.dinaslhdki.id/api/kecamatan/search?kab={$kabId}"); + + foreach ($response->json() as $kecamatan) { + $cleanId = str_replace('.', '', $kecamatan['id']); + + Kecamatan::create([ + 'KecamatanId' => $cleanId, + 'KabupatenId' => $kabupaten->KabupatenId, + 'NamaKecamatan' => $kecamatan['data'] + ]); + + // Log the seeding process + Log::info('Seeding kecamatan: ', [ + 'KecamatanId' => $cleanId, + 'KabupatenId' => $kabupaten->KabupatenId, + 'NamaKecamatan' => $kecamatan['data'] + ]); + } + } + } +} diff --git a/database/seeders/KelurahanTableSeeder.php b/database/seeders/KelurahanTableSeeder.php new file mode 100644 index 0000000..213b8bc --- /dev/null +++ b/database/seeders/KelurahanTableSeeder.php @@ -0,0 +1,43 @@ +KecamatanId, 0, 2) . '.' . + substr($kecamatan->KecamatanId, 2, 2) . '.' . + substr($kecamatan->KecamatanId, 4, 2); + + $response = Http::get("https://api-wilayah.dinaslhdki.id/api/kelurahan/search?kec={$kecId}"); + + foreach ($response->json() as $kelurahan) { + $cleanId = str_replace('.', '', $kelurahan['id']); + $cleanName = str_replace("\n", ' ', $kelurahan['data']); + + Kelurahan::create([ + 'KelurahanId' => $cleanId, + 'KecamatanId' => $kecamatan->KecamatanId, + 'NamaKelurahan' => $cleanName + ]); + + Log::info('Seeding kelurahan: ', [ + 'KelurahanId' => $cleanId, + 'KecamatanId' => $kecamatan->KecamatanId, + 'NamaKelurahan' => $cleanName + ]); + } + } + } +} diff --git a/package-lock.json b/package-lock.json index da35c5a..9c4fdb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,20 +14,25 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-navigation-menu": "^1.2.4", "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-switch": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-toast": "^1.2.6", "@radix-ui/react-tooltip": "^1.1.3", "@reduxjs/toolkit": "^2.5.1", + "@tanstack/react-table": "^8.21.2", + "@tinymce/tinymce-react": "^5.1.1", "@types/react-redux": "^7.1.34", "apexcharts": "^4.4.0", "ckeditor4-react": "^4.1.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0", + "framer-motion": "^12.4.3", "highlight.js": "^11.11.1", "i18next-browser-languagedetector": "^8.0.2", "i18next-http-backend": "^3.0.2", @@ -43,10 +48,12 @@ "react-redux": "^9.2.0", "react-resizable-panels": "^2.0.19", "react-router-dom": "^7.1.4", + "react-select": "^5.10.0", "react-type-animation": "^3.2.0", "recharts": "^2.15.1", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", + "tinymce": "^7.6.1", "vaul": "^1.1.2", "ziggy-js": "^2.5.0", "zod": "^3.23.8" @@ -101,7 +108,6 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -157,7 +163,6 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.26.5", @@ -191,7 +196,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.9", @@ -233,7 +237,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -243,7 +246,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -277,7 +279,6 @@ "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.26.7" @@ -337,7 +338,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.25.9", @@ -352,7 +352,6 @@ "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", @@ -371,7 +370,6 @@ "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -381,6 +379,126 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -1729,6 +1847,71 @@ } } }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.2.tgz", + "integrity": "sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz", @@ -2125,6 +2308,134 @@ } } }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.3.tgz", + "integrity": "sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-roving-focus": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-collection": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", + "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", + "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-toast": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.6.tgz", @@ -2839,6 +3150,26 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" } }, + "node_modules/@tanstack/react-table": { + "version": "8.21.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz", + "integrity": "sha512-11tNlEDTdIhMJba2RBH+ecJ9l1zgS2kjmexDPAraulc8jeNA4xocSNeyzextT0XJyASil4XsCYlJmf5jEWAtYg==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/@tanstack/react-virtual": { "version": "3.11.3", "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.3.tgz", @@ -2857,6 +3188,19 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@tanstack/table-core": { + "version": "8.21.2", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.2.tgz", + "integrity": "sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/virtual-core": { "version": "3.11.3", "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.3.tgz", @@ -2868,6 +3212,20 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tinymce/tinymce-react": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@tinymce/tinymce-react/-/tinymce-react-5.1.1.tgz", + "integrity": "sha512-DQ0wpvnf/9z8RsOEAmrWZ1DN1PKqcQHfU+DpM3llLze7FHmxVtzuN8O+FYh0oAAF4stzAXwiCIVacfqjMwRieQ==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.6.2", + "tinymce": "^7.0.0 || ^6.0.0 || ^5.5.1" + }, + "peerDependencies": { + "react": "^18.0.0 || ^17.0.1 || ^16.7.0", + "react-dom": "^18.0.0 || ^17.0.1 || ^16.7.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -3016,6 +3374,12 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -3078,6 +3442,15 @@ "@babel/runtime": "^7.9.2" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", @@ -3242,6 +3615,21 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3361,6 +3749,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -3547,6 +3944,31 @@ "node": ">=18" } }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-fetch": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", @@ -3723,7 +4145,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3878,6 +4299,15 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -3957,6 +4387,18 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -4033,6 +4475,12 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -4099,6 +4547,33 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "12.4.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.4.3.tgz", + "integrity": "sha512-rsMeO7w3dKyNG09o3cGwSH49iHU+VgDmfSSfsX+wfkO3zDA6WWkh4sUsMXd155YROjZP+7FTIhDrBYfgZeHjKQ==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.0.0", + "motion-utils": "^12.0.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4223,7 +4698,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -4379,6 +4853,22 @@ "url": "https://opencollective.com/immer" } }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/internmap": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", @@ -4404,6 +4894,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4544,7 +5040,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -4553,6 +5048,12 @@ "node": ">=6" } }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4658,6 +5159,12 @@ "node": ">= 0.4" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4737,11 +5244,25 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/motion-dom": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.0.0.tgz", + "integrity": "sha512-CvYd15OeIR6kHgMdonCc1ihsaUG4MYh/wrkz8gZ3hBX/uamyZCXN9S9qJoYF03GqfTt7thTV/dxnHYX4+55vDg==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.0.0" + } + }, + "node_modules/motion-utils": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.0.0.tgz", + "integrity": "sha512-MNFiBKbbqnmvOjkPyOKgHUp3Q6oiokLkI1bEwm5QA28cxMZrv0CbbBGDNmhF6DIXsi1pCQBSs0dX8xjeER1tmA==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -4904,6 +5425,36 @@ "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==", "license": "BSD-3-Clause" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4941,6 +5492,15 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/perfect-scrollbar": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.6.tgz", @@ -5487,6 +6047,27 @@ "react-dom": ">=18" } }, + "node_modules/react-select": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.0.tgz", + "integrity": "sha512-k96gw+i6N3ExgDwPIg0lUPmexl1ygPe6u5BdQFNBhkpbwroIgCNXdubtIzHfThYXYYTubwOBafoMnn7ruEP1xA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-smooth": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", @@ -5677,6 +6258,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5915,6 +6505,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6020,6 +6619,12 @@ "node": ">=8" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -6137,6 +6742,12 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, + "node_modules/tinymce": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.6.1.tgz", + "integrity": "sha512-5cHhaAoyyTHfAVTInNfoSp0KkUHmeVUbGSu37QKQbOFIPqxYPhqBiaLm1WVLgoNBYOHRProVc3xzxnNTeWHyoQ==", + "license": "GPL-2.0-or-later" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6246,6 +6857,20 @@ } } }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", + "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sidecar": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", diff --git a/package.json b/package.json index f36ec22..4b772e2 100644 --- a/package.json +++ b/package.json @@ -34,20 +34,25 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-navigation-menu": "^1.2.4", "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-switch": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-toast": "^1.2.6", "@radix-ui/react-tooltip": "^1.1.3", "@reduxjs/toolkit": "^2.5.1", + "@tanstack/react-table": "^8.21.2", + "@tinymce/tinymce-react": "^5.1.1", "@types/react-redux": "^7.1.34", "apexcharts": "^4.4.0", "ckeditor4-react": "^4.1.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0", + "framer-motion": "^12.4.3", "highlight.js": "^11.11.1", "i18next-browser-languagedetector": "^8.0.2", "i18next-http-backend": "^3.0.2", @@ -63,10 +68,12 @@ "react-redux": "^9.2.0", "react-resizable-panels": "^2.0.19", "react-router-dom": "^7.1.4", + "react-select": "^5.10.0", "react-type-animation": "^3.2.0", "recharts": "^2.15.1", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", + "tinymce": "^7.6.1", "vaul": "^1.1.2", "ziggy-js": "^2.5.0", "zod": "^3.23.8" diff --git a/public/assets/cover-panduan-skl.png b/public/assets/cover-panduan-skl.png new file mode 100644 index 0000000..812575b Binary files /dev/null and b/public/assets/cover-panduan-skl.png differ diff --git a/public/assets/hero-second.jpg b/public/assets/hero-second.jpg index 7c4bc0c..c4d5f8a 100644 Binary files a/public/assets/hero-second.jpg and b/public/assets/hero-second.jpg differ diff --git a/resources/js/components/Card/CardPengumuman.tsx b/resources/js/components/Card/CardPengumuman.tsx index 439a95d..df77de4 100644 --- a/resources/js/components/Card/CardPengumuman.tsx +++ b/resources/js/components/Card/CardPengumuman.tsx @@ -2,72 +2,10 @@ import React from "react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent } from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { ArrowRight } from "lucide-react"; import { Link } from "@inertiajs/react"; -// const pengumumans = [ -// { -// id: 1, -// title_page: "Pengumuman", -// alt_image: "Pengumuman", -// date: "16 Januari 2025", -// title: "Pelatihan & Sertifikasi Online Bidang Pengendalian Pencemaran Air Dan Udara", -// description: -// "Kegiatan Pelatihan Dan Uji Sertifikasi Tersebut Akan Diselenggarakan Sebagaimana Jadwal Terlampir, Kegiatan Tersebut Bekerjasama Dengan Lembaga P...", -// image: "/assets/img1.jpg", -// }, -// { -// id: 2, -// title_page: "Pengumuman", -// alt_image: "Pengumuman", -// date: "12 Desember 2024", -// title: "Pembinaan Pelaporan secara Online Pengelolaan Lingkungan melalui situs Status Ketaatan Lingkungan (SKL)", -// description: -// "Sukolompok Pengawasan Lingkungan Bidang Pengawasan dan Penataan Hukum Dinas Lingkungan Hidup Prov. DKI Jakarta...", -// image: "/assets/img1.jpg", -// }, -// { -// id: 3, -// title_page: "Pengumuman", -// alt_image: "Pengumuman", -// date: "12 Desember 2024", -// title: "Pembinaan Pelaporan secara Online Pengelolaan Lingkungan melalui situs Status Ketaatan Lingkungan (SKL)", -// description: -// "Sukolompok Pengawasan Lingkungan Bidang Pengawasan dan Penataan Hukum Dinas Lingkungan Hidup Prov. DKI Jakarta...", -// image: "/assets/img1.jpg", -// }, -// { -// id: 4, -// title_page: "Pengumuman", -// alt_image: "Pengumuman", -// date: "12 Desember 2024", -// title: "Pembinaan Pelaporan secara Online Pengelolaan Lingkungan melalui situs Status Ketaatan Lingkungan (SKL)", -// description: -// "Sukolompok Pengawasan Lingkungan Bidang Pengawasan dan Penataan Hukum Dinas Lingkungan Hidup Prov. DKI Jakarta...", -// image: "/assets/img1.jpg", -// }, -// { -// id: 5, -// title_page: "Pengumuman", -// alt_image: "Pengumuman", -// date: "12 Desember 2024", -// title: "Pembinaan Pelaporan secara Online Pengelolaan Lingkungan melalui situs Status Ketaatan Lingkungan (SKL)", -// description: -// "Sukolompok Pengawasan Lingkungan Bidang Pengawasan dan Penataan Hukum Dinas Lingkungan Hidup Prov. DKI Jakarta...", -// image: "/assets/img1.jpg", -// }, -// { -// id: 6, -// title_page: "Pengumuman", -// alt_image: "Pengumuman", -// date: "12 Desember 2024", -// title: "Pembinaan Pelaporan secara Online Pengelolaan Lingkungan melalui situs Status Ketaatan Lingkungan (SKL)", -// description: -// "Sukolompok Pengawasan Lingkungan Bidang Pengawasan dan Penataan Hukum Dinas Lingkungan Hidup Prov. DKI Jakarta...", -// image: "/assets/img1.jpg", -// }, -// ]; - interface SubKategori { SubKategoriId: number; NamaSubKategori: string; @@ -95,55 +33,132 @@ interface CardPengumumanProps { } const CardPengumuman = ({ posts }: CardPengumumanProps) => { + const subcategories = Array.from( + new Set(posts.map((item) => item.subkategori?.NamaSubKategori)) + ).filter(Boolean); + + const filterPosts = (subkategori: string | null) => { + if (!subkategori) return posts; + return posts.filter( + (item) => item.subkategori?.NamaSubKategori === subkategori + ); + }; + + const [visibleItems, setVisibleItems] = React.useState(3); + const [activeTab, setActiveTab] = React.useState("all"); + + const loadMore = () => { + setVisibleItems((prev) => prev + 3); + }; + + const PostGrid = ({ items }: { items: Post[] }) => ( +
+ {new Date(item.created_at).toLocaleDateString( + "id-ID", + { + day: "numeric", + month: "long", + year: "numeric", + } + )} +
++ {item.DescPost.replace(/<[^>]*>/g, "").slice( + 0, + 160 + )} + ... +
+ + + +- {new Date(post.created_at).toLocaleDateString( - "id-ID", - { - day: "numeric", - month: "long", - year: "numeric", - } - )} -
-- {post.DescPost.replace(/<[^>]*>/g, "")} -
- +- {item.date} -
-- {item.description} -
+interface Kategori { + KategoriId: number; + NamaKategori: string; +} + +interface Post { + PostId: number; + JudulPost: string; + DescPost: string; + SlugPost: string; + ImagePost: string; + IsPublish: boolean; + created_at: string; + kategori?: Kategori; + subkategori?: SubKategori; +} + +interface CardPeraturanProps { + posts: Post[]; +} + +const CardPeraturan = ({ posts }: CardPeraturanProps) => { + const subcategories = Array.from( + new Set(posts.map((item) => item.subkategori?.NamaSubKategori)) + ).filter(Boolean); + + const filterPosts = (subkategori: string | null) => { + if (!subkategori) return posts; + return posts.filter( + (item) => item.subkategori?.NamaSubKategori === subkategori + ); + }; + + const [visibleItems, setVisibleItems] = React.useState(3); + const [activeTab, setActiveTab] = React.useState("all"); + + const loadMore = () => { + setVisibleItems((prev) => prev + 3); + }; + + const PostGrid = ({ items }: { items: Post[] }) => ( ++ {new Date(item.created_at).toLocaleDateString( + "id-ID", + { + day: "numeric", + month: "long", + year: "numeric", + } + )} +
++ {item.DescPost.replace(/<[^>]*>/g, "").slice( + 0, + 160 + )} + ... +
+ -- {item.date} -
-- {item.description} -
+interface Kategori { + KategoriId: number; + NamaKategori: string; +} + +interface Post { + PostId: number; + JudulPost: string; + DescPost: string; + SlugPost: string; + ImagePost: string; + IsPublish: boolean; + created_at: string; + kategori?: Kategori; + subkategori?: SubKategori; +} + +interface CardUndanganProps { + posts: Post[]; +} + +const CardUndangan = ({ posts }: CardUndanganProps) => { + const subcategories = Array.from( + new Set(posts.map((item) => item.subkategori?.NamaSubKategori)) + ).filter(Boolean); + + const filterPosts = (subkategori: string | null) => { + if (!subkategori) return posts; + return posts.filter( + (item) => item.subkategori?.NamaSubKategori === subkategori + ); + }; + + const [visibleItems, setVisibleItems] = React.useState(3); + const [activeTab, setActiveTab] = React.useState("all"); + + const loadMore = () => { + setVisibleItems((prev) => prev + 3); + }; + + const PostGrid = ({ items }: { items: Post[] }) => ( ++ {new Date(item.created_at).toLocaleDateString( + "id-ID", + { + day: "numeric", + month: "long", + year: "numeric", + } + )} +
++ {item.DescPost.replace(/<[^>]*>/g, "").slice( + 0, + 160 + )} + ... +
+ -+ {related.JudulPost} +
++ Menampilkan hasil untuk "{searchQuery}" ( + {searchResults.length} hasil) +
++ {result.DescPost.replace(/<[^>]*>/g, "")} +
++ Tidak ada hasil yang ditemukan +
+- {announcements[0].date} -
-- {announcements[0].description} -
- -- {item.date} + {new Date( + posts[0].created_at + ).toLocaleDateString("id-ID", { + day: "numeric", + month: "long", + year: "numeric", + })}
-- {item.description} + {posts[0].DescPost.replace( + /<[^>]*>/g, + "" + ).slice(0, 160)} + ...
- + + ++ {new Date( + post.created_at + ).toLocaleDateString("id-ID", { + day: "numeric", + month: "long", + year: "numeric", + })} +
++ {post.DescPost.replace( + /<[^>]*>/g, + "" + ).slice(0, 160)} + ... +
+ + + +- Kegiatan Pelatihan Dan Uji Sertifikasi Tersebut Akan - Diselenggarakan Sebagaimana Jadwal Terlampir, Kegiatan - Tersebut Bekerjasama Dengan Lembaga P... +
+ Aplikasi Sistem Ketaatan Lingkungan memastikan kepatuhan + terhadap perizinan, pengelolaan limbah, emisi, serta + pengawasan lingkungan.
- + + +- {item.date} + {new Date( + item.created_at + ).toLocaleDateString("id-ID", { + day: "numeric", + month: "long", + year: "numeric", + })}
- {item.description} + {item.DescPost.replace( + /<[^>]*>/g, + "" + ).slice(0, 160)} + ...
- + + +- {slides[currentSlide].description} -
-+ {slides[currentSlide].description} +
+- {messages[currentMessageIndex]} -
++ + { + messages[currentMessageIndex].kategori + ?.NamaKategori + } + + + {" "} + {messages[currentMessageIndex].JudulPost} + +
+- Lorem Ipsum Is Simply Dummy Text Of The Printing - And Typesetting Industry. Lorem Ipsum Has Been - The Industry's Standard Dummy Text Ever Since - The 1500s, When An Unknown Printer Took A Galley - Of Type And Scrambled It To Make A Type Specimen - Book. It Has Survived Not Only Five Centuries, - But Also The Leap Into Electronic Typesetting, - Remaining Essentially Unchanged. It Was - Popularised In The 1960s With The Release Of - Letraset Sheets Containing Lorem Ipsum Passages, - And More Recently With Desktop Publishing - Software Like Aldus PageMaker Including Versions - Of Lorem Ipsum. + SKL adalah Sistem Ketaatan Lingkungan yang + dinaungi oleh Dinas Lingkungan Hidup Provinsi + DKI Jakarta dengan menyediakan sistem yang dapat + memberikan pelayanan dalam pelaporan, analisa + dan evaluasi pengelolaan lingkungan dilakukan + oleh perusahaan atau kegiatan usaha yang berada + di Provinsi DKI Jakarta.
- {item.date} + {new Date(item.created_at).toLocaleDateString( + "id-ID", + { + day: "numeric", + month: "long", + year: "numeric", + } + )}
- {item.description} + {item.DescPost.replace(/<[^>]*>/g, "").slice( + 0, + 160 + )} + ...
- + + ++ Merupakan bagian dari perangkat lunak + CReASINDO yang dikembangkan oleh PT + MANDIRI CReASINDO. +
++ Kegunaan Produk ini adalah menyediakan + sistem yang dapat memberikan pelayanan + dalam pelaporan, analisa dan evaluasi + pengelolaan lingkungan dilakukan oleh + perusahaan atau kegiatan usaha yang + berada di Propinsi DKI Jakarta. +
++ Produk ini diberikan kepada BPLHD DKI + JAKARTA melalui Proyek "SISTEM + PENGAWASAN DAN PENGENDALIAN PENCEMARAN + LINGKUNGAN BPLHD DKI JAKARTA 2015" + Perangkat Lunak ini dilindungi oleh + undang-undang negara Republik Indonesia + dan Perjanjian Internasional yang + berkaitan dengan Hak-Hak Kekayaan + Intelektual. +
++ Silahkan klik gambar cover di samping + untuk membuka buku panduan versi + flipbook +
++ SKL : Status Ketaatan Lingkungan +
++ SPBM : Status Pemenuhan Baku Mutu +
++ IL : Ijin Lingkungan +
+AL : Air Limbah
+LB3 : Limbah B3
++ SB : Sumber Bergerak +
++ BS : Kebisingan & Udara Ambien +
++ STB : Sumber Tidak Bergerak +
+LP : Limbah Padat
++ KDM : Kawasan Dilarang Merokok +
++ STT : Surat Tanda Terima +
++ SE : Surat Evaluasi +
++ Data belum diisi +
++ Data telah diisi dan belum diverifikasi +
++ Data telah siap untuk diverifikasi +
++ Data telah diisi dan diverifikasi +
++ SKL : Status Ketaatan Lingkungan +
++ SPBM : Status Pemenuhan Baku Mutu +
++ IL : Ijin Lingkungan +
+AL : Air Limbah
+LB3 : Limbah B3
++ SB : Sumber Bergerak +
++ BS : Kebisingan & Udara Ambien +
++ STB : Sumber Tidak Bergerak +
+LP : Limbah Padat
++ KDM : Kawasan Dilarang Merokok +
++ STT : Surat Tanda Terima +
++ SE : Surat Evaluasi +
++ Data belum diisi +
++ Data telah diisi dan belum diverifikasi +
++ Data telah siap untuk diverifikasi +
++ Data telah diisi dan diverifikasi +
+