From ef80dd0e741e81cc04c3c3595970420eede3c3f9 Mon Sep 17 00:00:00 2001 From: myuqinurrohman Date: Sun, 2 Mar 2025 21:37:47 +0700 Subject: [PATCH] feat: media monitoring --- .../Dashboard/DatatableController.php | 59 ++++++ .../Dashboard/MediaMonitoringController.php | 110 +++++++++++ app/Http/Requests/MediaMonitoringRequest.php | 84 +++++++++ app/Models/MediaMonitoring.php | 34 ++++ ..._134617_create_media_monitorings_table.php | 43 +++++ database/seeders/MediaMonitoringSeeder.php | 17 ++ public/assets/dashboard/js/custom.js | 98 +++++++--- .../media-monitorings/create.blade.php | 170 +++++++++++++++++ .../media-monitorings/edit.blade.php | 171 ++++++++++++++++++ .../media-monitorings/index.blade.php | 65 +++++++ .../media-monitorings/show.blade.php | 144 +++++++++++++++ .../views/partials/app/datatable.blade.php | 27 +++ .../views/partials/dashboard/footer.blade.php | 1 + .../partials/dashboard/sidebar.blade.php | 2 +- routes/web.php | 16 ++ 15 files changed, 1017 insertions(+), 24 deletions(-) create mode 100644 app/Http/Controllers/Dashboard/MediaMonitoringController.php create mode 100644 app/Http/Requests/MediaMonitoringRequest.php create mode 100644 app/Models/MediaMonitoring.php create mode 100644 database/migrations/2025_02_28_134617_create_media_monitorings_table.php create mode 100644 database/seeders/MediaMonitoringSeeder.php create mode 100644 resources/views/dashboard/media-monitorings/create.blade.php create mode 100644 resources/views/dashboard/media-monitorings/edit.blade.php create mode 100644 resources/views/dashboard/media-monitorings/index.blade.php create mode 100644 resources/views/dashboard/media-monitorings/show.blade.php diff --git a/app/Http/Controllers/Dashboard/DatatableController.php b/app/Http/Controllers/Dashboard/DatatableController.php index 0a31045..941f083 100644 --- a/app/Http/Controllers/Dashboard/DatatableController.php +++ b/app/Http/Controllers/Dashboard/DatatableController.php @@ -8,6 +8,7 @@ use App\Models\ContentRecap; use App\Models\GovernmentAgency; use App\Models\Location; +use App\Models\MediaMonitoring; use App\Models\News; use App\Models\Role; use App\Models\SubClassification; @@ -481,6 +482,64 @@ public function contentRecap(Request $request){ } + public function mediaMonitoring(Request $request){ + if ($request->ajax()) { + + + + $data = MediaMonitoring::with(['enhancer'])->get(); + + return DataTables::of($data) + ->addIndexColumn() + ->addColumn('enhancer', function ($data) { + return $data->enhancer->name; + }) + ->addColumn('input_date', function ($data) { + return idn_date($data->input_date, 'd F Y'); + }) + ->addColumn('title', function ($data) { + return shorten_text($data->title, 40); + }) + ->addColumn('link', function ($data) { + return ''.$data->link.''; + }) + ->addColumn('action', function ($data) { + $showUrl = route('dashboard.media.monitoring.show', ['id' => encrypt_id($data->id)]); + + $editUrl = route('dashboard.media.monitoring.edit', ['id' => encrypt_id($data->id)]); + + $deleteUrl = route('dashboard.media.monitoring.destroy', ['id' => encrypt_id($data->id)]); + + $dropdown = ''; + + return $dropdown; + }) + + ->rawColumns(['link', 'action']) + ->make(true); + } + + return response()->json(['error' => 'Unauthorized'], 401); + + } + public function user(Request $request){ if ($request->ajax()) { diff --git a/app/Http/Controllers/Dashboard/MediaMonitoringController.php b/app/Http/Controllers/Dashboard/MediaMonitoringController.php new file mode 100644 index 0000000..329b3cb --- /dev/null +++ b/app/Http/Controllers/Dashboard/MediaMonitoringController.php @@ -0,0 +1,110 @@ + 'Monitoring Media' + ]); + } + + public function create(){ + return view('dashboard.media-monitorings.create', [ + 'title' => 'Tambah Monitoring Media' + ]); + } + + public function store(MediaMonitoringRequest $request){ + $validatedData = $request->validated(); + $validatedData['enhancer_id'] = Auth::id(); + + $latestCode = MediaMonitoring::max('code'); + $lastNumber = $latestCode ? intval(substr($latestCode, 3)) : 0; + $newNumber = str_pad($lastNumber + 1, 6, '0', STR_PAD_LEFT); + $code = 'ADN'.$newNumber; + + $validatedData['code'] = $code; + $validatedData['image'] = store_file($validatedData['image'], 'uploads/media-monitorings', 'public')['randomFileName']; + + $createMediaMonitoring = MediaMonitoring::create($validatedData); + + if($createMediaMonitoring){ + return redirect()->back()->with('success-status', 'Berhasil menambahkan monitoring media.'); + }else{ + return redirect()->back()->with('failed-status', 'Gagal menambahkan monitoring media.'); + } + } + + public function edit($id){ + + $mediaMonitoring = MediaMonitoring::findOrFail(decrypt_id($id)); + + return view('dashboard.media-monitorings.edit', [ + 'title' => 'Ubah Monitoring Media', + 'mediaMonitoring' => $mediaMonitoring + ]); + } + + public function update(MediaMonitoringRequest $request, $id){ + $validatedData = $request->validated(); + + $mediaMonitoring = MediaMonitoring::findOrFail(decrypt_id($id)); + $validatedData['enhancer_id'] = Auth::id(); + $validatedData['code'] = $mediaMonitoring->code; + + if($request->has('image')){ + delete_file('app/public/uploads/media-monitorings/'.$mediaMonitoring->image); + $validatedData['image'] = store_file($validatedData['image'], '/uploads/media-monitorings', 'public')['randomFileName']; + }else{ + $validatedData['image'] = $mediaMonitoring->image; + } + + $updatedMediaMonitoring = $mediaMonitoring->update($validatedData); + + if($updatedMediaMonitoring){ + return redirect()->back()->with('success-status', 'Berhasil mengubah monitoring media.'); + }else{ + return redirect()->back()->with('failed-status', 'Gagal mengubah monitoring media.'); + } + } + + public function show($id){ + + $mediaMonitoring = MediaMonitoring::findOrFail(decrypt_id($id)); + + return view('dashboard.media-monitorings.show', [ + 'title' => 'Detail Monitoring Media', + 'mediaMonitoring' => $mediaMonitoring + ]); + } + + public function destroy($id){ + try { + $mediaMonitoring = MediaMonitoring::findOrFail(decrypt_id($id)); + delete_file('app/public/uploads/media-monitorings/'.$mediaMonitoring->image); + $mediaMonitoring->delete(); + + + return response()->json(['message' => 'Berhasil menghapus monitoring media.']); + } catch (\Exception $e) { + return response()->json(['message' => 'Gagal menghapus monitoring media.'], 500); + } + } + + public function checkLink(Request $request) + { + $linkExists = MediaMonitoring::where('link', $request->link)->exists(); + + return response()->json([ + 'exists' => $linkExists + ]); + } +} diff --git a/app/Http/Requests/MediaMonitoringRequest.php b/app/Http/Requests/MediaMonitoringRequest.php new file mode 100644 index 0000000..d938747 --- /dev/null +++ b/app/Http/Requests/MediaMonitoringRequest.php @@ -0,0 +1,84 @@ +|string> + */ + public function rules(): array + { + $rules = [ + 'media_name' => ['required', 'max:100'], + 'theme' => ['required', 'max:100'], + 'title' => ['required'], + 'link' => ['nullable', 'url'], + 'writter' => ['required'], + 'channel'=> ['required', 'in:website,tiktok,youtube,instagram,facebook,twitter,cetak'], + 'content' => ['required'], + 'influencer' => ['nullable'], + 'keyword' => ['required'], + 'quote' => ['nullable'], + 'release_date' => ['required', 'date'], + ]; + + if($this->isMethod('post')){ + $rules['image'] = ['required', 'image', 'mimes:png,jpg,jpeg', 'max:2048']; + }else if($this->isMethod('put')){ + $rules['image'] = ['nullable', 'image', 'mimes:png,jpg,jpeg', 'max:2048']; + } + + return $rules; + } + + public function messages() +{ + return [ + 'media_name.required' => 'Nama media wajib diisi.', + 'media_name.max' => 'Nama media tidak boleh lebih dari 100 karakter.', + + 'theme.required' => 'Tema wajib diisi.', + 'theme.max' => 'Tema tidak boleh lebih dari 100 karakter.', + + 'title.required' => 'Judul wajib diisi.', + + 'link.url' => 'Link harus dalam format URL yang valid.', + + 'writter.required' => 'Nama penulis wajib diisi.', + + 'channel.required' => 'Channel wajib dipilih.', + 'channel.in' => 'Channel yang dipilih tidak valid.', + + 'content.required' => 'Konten wajib diisi.', + + 'influencer.nullable' => 'Nama influencer boleh dikosongkan.', + + 'keyword.required' => 'Keyword wajib diisi.', + + 'quote.nullable' => 'Quote boleh dikosongkan.', + + 'release_date.required' => 'Tanggal rilis wajib diisi.', + 'release_date.date' => 'Tanggal rilis harus dalam format tanggal yang valid.', + + 'image.required' => 'Gambar wajib diunggah.', + 'image.image' => 'File yang diunggah harus berupa gambar.', + 'image.mimes' => 'Gambar hanya boleh berformat PNG, JPG, atau JPEG.', + 'image.max' => 'Gambar tidak boleh lebih dari 2MB.', + ]; +} + +} diff --git a/app/Models/MediaMonitoring.php b/app/Models/MediaMonitoring.php new file mode 100644 index 0000000..6081747 --- /dev/null +++ b/app/Models/MediaMonitoring.php @@ -0,0 +1,34 @@ +belongsTo(User::class, 'enhancer_id', 'id'); + } + +} diff --git a/database/migrations/2025_02_28_134617_create_media_monitorings_table.php b/database/migrations/2025_02_28_134617_create_media_monitorings_table.php new file mode 100644 index 0000000..9200692 --- /dev/null +++ b/database/migrations/2025_02_28_134617_create_media_monitorings_table.php @@ -0,0 +1,43 @@ +id(); + $table->string('code'); + $table->string('media_name'); + $table->string('theme'); + $table->text('title'); + $table->string('channel'); + $table->string('writter'); + $table->string('link')->nullable(); + $table->string('news_page')->nullable(); + $table->text('quote')->nullable(); + $table->text('content'); + $table->string('influencer')->nullable(); + $table->string('keyword'); + $table->string('image'); + $table->date('release_date'); + $table->unsignedBigInteger('enhancer_id'); + $table->foreign('enhancer_id')->references('id')->on('users'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('media_monitorings'); + } +}; diff --git a/database/seeders/MediaMonitoringSeeder.php b/database/seeders/MediaMonitoringSeeder.php new file mode 100644 index 0000000..b849879 --- /dev/null +++ b/database/seeders/MediaMonitoringSeeder.php @@ -0,0 +1,17 @@ +]/.test(password); // Memeriksa simbol +// // Regex untuk memeriksa kriteria kata sandi +// var hasUpper = /[A-Z]/.test(password); // Memeriksa huruf besar +// var hasLower = /[a-z]/.test(password); // Memeriksa huruf kecil +// var hasNumber = /\d/.test(password); // Memeriksa angka +// var hasSymbol = /[!@#$%^&*(),.?":{}|<>]/.test(password); // Memeriksa simbol - // Cek apakah kata sandi memenuhi semua kriteria - if (hasUpper && hasLower && hasNumber && hasSymbol) { - strengthStatus.textContent = 'Kata sandi valid'; - colorClass = 'valid'; // Jika valid, set warna hijau - } else { - strengthStatus.textContent = 'Kata sandi tidak memenuhi syarat'; - colorClass = 'invalid'; // Jika tidak memenuhi syarat, set warna merah - } +// // Cek apakah kata sandi memenuhi semua kriteria +// if (hasUpper && hasLower && hasNumber && hasSymbol) { +// strengthStatus.textContent = 'Kata sandi valid'; +// colorClass = 'valid'; // Jika valid, set warna hijau +// } else { +// strengthStatus.textContent = 'Kata sandi tidak memenuhi syarat'; +// colorClass = 'invalid'; // Jika tidak memenuhi syarat, set warna merah +// } - // Ubah warna input dan border sesuai dengan status - this.classList.remove("invalid", "valid"); - this.classList.add(colorClass); +// // Ubah warna input dan border sesuai dengan status +// this.classList.remove("invalid", "valid"); +// this.classList.add(colorClass); - // Set warna indikator kekuatan - strengthStatus.className = colorClass; +// // Set warna indikator kekuatan +// strengthStatus.className = colorClass; +// }); + +$(document).ready(function() { + // Setup CSRF token untuk semua AJAX request + $.ajaxSetup({ + headers: { + 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') + } + }); + + let typingTimer; + let delay = 500; + + $('#link').on('keyup', function() { + clearTimeout(typingTimer); + let inputField = $(this); + let linkValue = inputField.val(); + + if (linkValue.length > 0) { + typingTimer = setTimeout(function() { + $.ajax({ + url: '/dashboard/media-monitorings/check-link', // Sesuaikan dengan route yang benar + method: 'POST', + data: { link: linkValue }, // CSRF sudah otomatis ditambahkan + success: function(response) { + console.log('Response:', response); + if (response.exists) { + $('#linkFeedback') + .removeClass('d-none text-success') + .addClass('text-danger') + .text('Link tersebut sudah ada di database!'); + inputField.addClass('is-invalid').removeClass('is-valid'); + } else { + $('#linkFeedback') + .removeClass('d-none text-danger') + .addClass('text-success') + .text('Link tidak ada di database.'); + inputField.addClass('is-valid').removeClass('is-invalid'); + } + }, + error: function(xhr, status, error) { + console.error('AJAX Error:', error); // Debugging + } + }); + }, delay); + } else { + $('#linkFeedback').addClass('d-none'); + inputField.removeClass('is-invalid is-valid'); + } + }); }); + + diff --git a/resources/views/dashboard/media-monitorings/create.blade.php b/resources/views/dashboard/media-monitorings/create.blade.php new file mode 100644 index 0000000..898ec13 --- /dev/null +++ b/resources/views/dashboard/media-monitorings/create.blade.php @@ -0,0 +1,170 @@ +@include('partials.dashboard.head') +@include('partials.dashboard.sidebar', ['page' => 'media_monitorings']) +@include('partials.dashboard.header') + +
+
+
+
+
+
+
+
+
{{$title}}
+
+
+ @csrf +
+
+
+ +
+ +
+ @error('media_name') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('theme') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('title') + {{$message}} + @enderror +
+
+
+
+ +
+ + +
+ @error('link') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('writter') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+ @error('content') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('influencer') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('keyword') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+ @error('release_date') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('image') + {{$message}} + @enderror +
+
+
+
+
+ Kembali + +
+
+
+
+
+
+
+
+
+
+
+ +@include('partials.dashboard.footer', ['rich_editor' => true]) diff --git a/resources/views/dashboard/media-monitorings/edit.blade.php b/resources/views/dashboard/media-monitorings/edit.blade.php new file mode 100644 index 0000000..ed9b14b --- /dev/null +++ b/resources/views/dashboard/media-monitorings/edit.blade.php @@ -0,0 +1,171 @@ +@include('partials.dashboard.head') +@include('partials.dashboard.sidebar', ['page' => 'media_monitorings']) +@include('partials.dashboard.header') + +
+
+
+
+
+
+
+
+
{{$title}}
+
+
+ @csrf + @method('put') +
+
+
+ +
+ +
+ @error('media_name') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('theme') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('title') + {{$message}} + @enderror +
+
+
+
+ +
+ + +
+ @error('link') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('writter') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+ @error('content') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('influencer') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('keyword') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+ @error('release_date') + {{$message}} + @enderror +
+
+
+
+ +
+ +
+ @error('image') + {{$message}} + @enderror +
+
+
+
+
+ Kembali + +
+
+
+
+
+
+
+
+
+
+
+ +@include('partials.dashboard.footer', ['rich_editor' => true]) diff --git a/resources/views/dashboard/media-monitorings/index.blade.php b/resources/views/dashboard/media-monitorings/index.blade.php new file mode 100644 index 0000000..740d4d8 --- /dev/null +++ b/resources/views/dashboard/media-monitorings/index.blade.php @@ -0,0 +1,65 @@ +@include('partials.dashboard.head') +@include('partials.dashboard.sidebar', ['page' => 'media_monitorings']) +@include('partials.dashboard.header') + +
+
+
+
+
+
+
+

{{$title}}

+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + +
NoOlehKodeTanggal InputJudulMediaLink
+
+
+
+
+
+
+
+
+ +@include('partials.dashboard.footer' ,['datatable' => 'media_monitoring']) diff --git a/resources/views/dashboard/media-monitorings/show.blade.php b/resources/views/dashboard/media-monitorings/show.blade.php new file mode 100644 index 0000000..1131284 --- /dev/null +++ b/resources/views/dashboard/media-monitorings/show.blade.php @@ -0,0 +1,144 @@ +@include('partials.dashboard.head') +@include('partials.dashboard.sidebar', ['page' => 'media_monitorings']) +@include('partials.dashboard.header') + +
+
+
+
+
+
+
+
+ +
+
+ {{--
+
Personal Information
+

Basic info, like your name and address, that you use on Nio Platform.

+
--}} +
+
+
+ Nama Media + {{$mediaMonitoring->media_name}} +
+
+
+
+ Tema + {{$mediaMonitoring->theme}} +
+
+
+
+ Judul + {{$mediaMonitoring->title}} +
+
+
+
+ Link + + @if ($mediaMonitoring->link != '' || $mediaMonitoring != null) + {{$mediaMonitoring->link}} + @else + - + @endif + +
+
+
+
+ Penulis + {{$mediaMonitoring->writter}} +
+
+
+
+ Kanal + {{$mediaMonitoring->channel}} +
+
+
+
+ Influencer + {{$mediaMonitoring->influencer}} +
+
+
+
+ Kata Kunci + {{$mediaMonitoring->keyword}} +
+
+
+
+ Tanggal Input + {{idn_date($mediaMonitoring->created_at, 'l, m F Y')}} +
+
+
+
+ Tanggal Rilis + {{idn_date($mediaMonitoring->release_date, 'l, m F Y')}} +
+
+
+
+ {{--
--}} +
+
+ Kutipan +
+
+
+
+ {!!$mediaMonitoring->quote!!} +
+
+
+
+
+
+ Konten +
+
+
+
+ {!!$mediaMonitoring->content!!} +
+
+
+
+
+
+ Gambar +
+
+
+
+ +
+
+
+
+
+ Kembali + Ubah +
+
+
+
+
+
+
+
+
+
+ +@include('partials.dashboard.footer', ['rich_editor' => false]) diff --git a/resources/views/partials/app/datatable.blade.php b/resources/views/partials/app/datatable.blade.php index 4cb51e1..88e2b41 100644 --- a/resources/views/partials/app/datatable.blade.php +++ b/resources/views/partials/app/datatable.blade.php @@ -213,6 +213,33 @@ @endif +@if ($datatable === 'media_monitoring') + +@endif + @if ($datatable === 'user') + @include('partials.app.sweetalert') diff --git a/resources/views/partials/dashboard/sidebar.blade.php b/resources/views/partials/dashboard/sidebar.blade.php index 5414b4c..055c71b 100644 --- a/resources/views/partials/dashboard/sidebar.blade.php +++ b/resources/views/partials/dashboard/sidebar.blade.php @@ -145,7 +145,7 @@
  • - + Monitoring Media diff --git a/routes/web.php b/routes/web.php index 5baff38..431dd97 100644 --- a/routes/web.php +++ b/routes/web.php @@ -7,6 +7,7 @@ use App\Http\Controllers\Dashboard\DatatableController; use App\Http\Controllers\Dashboard\GovernmentAgencyController; use App\Http\Controllers\Dashboard\LocationController; +use App\Http\Controllers\Dashboard\MediaMonitoringController; use App\Http\Controllers\Dashboard\NewsController; use App\Http\Controllers\Dashboard\OverviewController; use App\Http\Controllers\Dashboard\RoleController; @@ -159,6 +160,21 @@ Route::get('/data', [DatatableController::class, 'contentRecap'])->name('data'); }); + Route::prefix('media-monitorings')->name('media.monitoring.')->group(function(){ + Route::controller(MediaMonitoringController::class)->group(function(){ + Route::get('/', 'index')->name('index'); + Route::get('/create', 'create')->name('create'); + Route::post('/', 'store')->name('store'); + Route::post('/check-link', 'checkLink')->name('check.link'); + Route::get('/{id}/show', 'show')->name('show'); + Route::get('/{id}/edit', 'edit')->name('edit'); + Route::put('/{id}', 'update')->name('update'); + Route::delete('/{id}', 'destroy')->name('destroy'); + }); + + Route::get('/data', [DatatableController::class, 'mediaMonitoring'])->name('data'); + }); + Route::prefix('users')->name('users.')->group(function(){ Route::controller(UserController::class)->group(function(){ Route::get('/', 'index')->name('index');