TKK_E3220375/resources/views/admin/announcements/index.blade.php

605 lines
31 KiB
PHP

@extends('layouts.dashboard')
@section('content')
<div class="p-4 sm:p-6">
<!-- Header Section -->
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-6 gap-4">
<div class="flex items-center space-x-3">
<div class="p-3 rounded-xl bg-blue-100/80 shadow-inner">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" />
</svg>
</div>
<div>
<h1 class="text-2xl font-bold text-gray-800">Sistem Pengumuman</h1>
<p class="text-sm text-gray-500">Kelola pengumuman untuk seluruh ruangan</p>
</div>
</div>
<div class="flex items-center space-x-2">
<div id="mqtt-status" class="flex items-center px-3 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
<span class="w-2 h-2 rounded-full bg-gray-400 mr-2"></span>
<span>Memeriksa koneksi...</span>
</div>
</div>
</div>
<!-- Notification System -->
<div id="notification-container">
@if(session('success'))
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-6 rounded-md shadow-sm animate-fade-in">
{{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-6 rounded-md shadow-sm animate-fade-in">
{{ session('error') }}
</div>
@endif
</div>
<!-- Main Content Grid -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 animate-fade-in">
<!-- Announcement Form Card -->
<div class="lg:col-span-2">
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden transition-all duration-300 hover:shadow-md">
<div class="bg-gradient-to-r from-blue-500 to-blue-600 px-6 py-4">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
Buat Pengumuman Baru
</h2>
</div>
<div class="p-6">
<form id="announcement-form">
@csrf
<!-- Announcement Type -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-3">Mode Pengumuman</label>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
<label class="relative cursor-pointer">
<input type="radio" name="type" value="tts" class="peer absolute opacity-0" checked>
<div class="p-4 border-2 border-gray-200 rounded-xl transition-all duration-200 peer-checked:border-blue-500 peer-checked:bg-blue-50 peer-checked:ring-1 peer-checked:ring-blue-200 hover:border-blue-300">
<div class="flex items-center">
<div class="flex-shrink-0 h-5 w-5 rounded-full border-2 border-gray-300 peer-checked:border-blue-500 peer-checked:bg-blue-500 peer-checked:border-4 transition-all duration-200 mr-3"></div>
<div>
<h3 class="font-medium text-gray-800">Text-to-Speech</h3>
<p class="text-sm text-gray-500">Sistem akan membacakan teks otomatis</p>
</div>
</div>
</div>
</label>
<label class="relative cursor-pointer">
<input type="radio" name="type" value="manual" class="peer absolute opacity-0">
<div class="p-4 border-2 border-gray-200 rounded-xl transition-all duration-200 peer-checked:border-blue-500 peer-checked:bg-blue-50 peer-checked:ring-1 peer-checked:ring-blue-200 hover:border-blue-300">
<div class="flex items-center">
<div class="flex-shrink-0 h-5 w-5 rounded-full border-2 border-gray-300 peer-checked:border-blue-500 peer-checked:bg-blue-500 peer-checked:border-4 transition-all duration-200 mr-3"></div>
<div>
<h3 class="font-medium text-gray-800">Mikrofon Manual</h3>
<p class="text-sm text-gray-500">Gunakan mikrofon langsung</p>
</div>
</div>
</div>
</label>
</div>
</div>
<!-- Target Rooms -->
<div class="mb-6">
<div class="flex justify-between items-center mb-3">
<label class="block text-sm font-medium text-gray-700">Ruangan Tujuan</label>
<button type="button" id="select-all" class="text-xs text-blue-600 hover:text-blue-800 font-medium transition-colors duration-200">Pilih Semua</button>
</div>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
@foreach($rooms as $room)
<label class="relative cursor-pointer">
<input type="checkbox" name="rooms[]" value="{{ $room }}" class="peer absolute opacity-0">
<div class="px-3 py-2 border border-gray-200 rounded-lg text-center transition-all duration-150 peer-checked:bg-blue-50 peer-checked:border-blue-300 peer-checked:text-blue-700 peer-checked:font-medium hover:bg-gray-50">
{{ $room }}
</div>
</label>
@endforeach
</div>
</div>
<!-- TTS Content -->
<div id="tts-fields" class="mb-6 transition-all duration-300">
<label class="block text-sm font-medium text-gray-700 mb-2">Isi Pengumuman</label>
<div class="relative">
<textarea name="content" rows="4" class="block w-full px-4 py-3 border border-gray-300 rounded-xl shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 transition duration-150 ease-in-out" placeholder="Ketikkan teks pengumuman..."></textarea>
<div class="absolute bottom-3 right-3 flex items-center text-xs text-gray-500 bg-white px-2 rounded-full transition-opacity duration-200">
<span id="char-count">0</span>/500
</div>
</div>
</div>
<!-- Manual Mic Duration -->
<div id="manual-fields" class="hidden mb-6 transition-all duration-300">
<label class="block text-sm font-medium text-gray-700 mb-2">Durasi (detik)</label>
<div class="flex items-center space-x-2">
<input type="range" name="duration" min="5" max="300" value="60" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
<span id="duration-value" class="text-sm font-medium text-gray-700 w-12 text-center">60</span>
</div>
<p class="mt-1 text-xs text-gray-500">Durasi: 5-300 detik (5 menit)</p>
</div>
<!-- Submit Button -->
<div class="flex justify-end pt-4">
<button type="submit" id="submit-btn" class="px-5 py-2.5 bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl text-sm font-medium text-white hover:from-blue-600 hover:to-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-sm transition-all duration-300 flex items-center justify-center transform hover:scale-105">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
Kirim Pengumuman
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Right Sidebar -->
<div class="space-y-6">
<!-- Audio Routing Control Card -->
<div id="stop-manual-section" class="hidden bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden h-full flex flex-col">
<div class="bg-gradient-to-r from-amber-500 to-orange-500 px-6 py-4">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" clip-rule="evenodd" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2" />
</svg>
Kontrol Routing Audio
</h2>
</div>
<div class="p-6 flex-grow">
<div class="bg-amber-50 border-l-4 border-amber-400 p-4 rounded-lg mb-4 animate-pulse">
<div class="flex">
<div class="flex-shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-amber-500" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<p class="text-sm text-amber-700">
<span class="font-medium">Perhatian!</span> Mikrofon aktif sedang di-routing ke speaker ruangan.
</p>
</div>
</div>
</div>
<div class="flex items-center space-x-3 p-3 bg-gray-50 rounded-lg mb-4">
<div class="flex-shrink-0 p-2 bg-blue-100 rounded-lg text-blue-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" />
</svg>
</div>
<div>
<p class="text-sm font-medium text-gray-800">Status Mikrofon</p>
<p class="text-sm text-gray-500">Sedang aktif dan terhubung</p>
</div>
</div>
<div id="timer-display" class="hidden text-center mb-4">
<div class="inline-flex items-center justify-center">
<div class="relative">
<svg class="w-16 h-16" viewBox="0 0 36 36">
<circle cx="18" cy="18" r="16" fill="none" class="stroke-gray-200" stroke-width="2"></circle>
<circle cx="18" cy="18" r="16" fill="none" class="stroke-blue-500" stroke-width="2" stroke-dasharray="100" stroke-dashoffset="0" id="countdown-circle"></circle>
</svg>
<span id="countdown" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-lg font-bold text-gray-800">60</span>
</div>
</div>
<p class="text-xs text-gray-500 mt-2">Sisa waktu pengumuman</p>
</div>
</div>
<div class="p-6 pt-0">
<button id="stop-routing-btn" class="w-full px-4 py-3 bg-gradient-to-r from-amber-500 to-orange-500 rounded-xl text-sm font-medium text-white hover:from-amber-600 hover:to-orange-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-amber-500 shadow-sm transition-all duration-300 flex items-center justify-center transform hover:scale-105">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" clip-rule="evenodd" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2" />
</svg>
Putuskan Routing Audio
</button>
</div>
</div>
<!-- Active Announcements Card -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden transition-all duration-300 hover:shadow-md">
<div class="bg-gradient-to-r from-green-500 to-green-600 px-6 py-4">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
Pengumuman Aktif
</h2>
</div>
<div class="p-6">
<div id="active-announcements-container">
<p class="text-sm text-gray-500">Memuat pengumuman aktif...</p>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.animate-fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
#countdown-circle {
transition: stroke-dashoffset 1s linear;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).ready(function() {
// Base URL for API endpoints
const baseUrl = '/admin/pengumuman';
// Initialize UI state
function initUI() {
// Set initial state for manual fields
$('input[name="duration"]').val(60);
$('#duration-value').text(60);
// Check MQTT status immediately
updateMqttStatus();
// Check for active announcements
checkActiveAnnouncement();
// Trigger change event to set initial view
$('input[name="type"]').trigger('change');
}
// MQTT Status Indicator
function updateMqttStatus() {
$.ajax({
url: `${baseUrl}/mqtt-status`,
method: 'GET',
beforeSend: function() {
$('#mqtt-status span:first').removeClass('bg-green-500 bg-red-500').addClass('bg-gray-400');
$('#mqtt-status span:last').text('Memeriksa...');
},
success: function(response) {
const statusEl = $('#mqtt-status');
const statusDot = statusEl.find('span:first');
const statusText = statusEl.find('span:last');
statusDot.removeClass('bg-gray-400');
if (response.connected) {
statusDot.addClass('bg-green-500');
statusText.text('Terhubung');
} else {
statusDot.addClass('bg-red-500');
statusText.text('Terputus');
}
},
error: function() {
$('#mqtt-status span:first').removeClass('bg-green-500 bg-red-500').addClass('bg-gray-400');
$('#mqtt-status span:last').text('Gagal memeriksa');
}
});
}
// Update duration value display
$('input[name="duration"]').on('input', function() {
$('#duration-value').text($(this).val());
});
// Character counter
$('textarea[name="content"]').on('input', function() {
const count = $(this).val().length;
$('#char-count').text(count);
$('#char-count').toggleClass('text-red-500', count > 500);
}).trigger('input');
// Toggle fields based on announcement type
$('input[name="type"]').change(function() {
const isManual = $(this).val() === 'manual';
$('#tts-fields').toggleClass('hidden', isManual);
$('#manual-fields').toggleClass('hidden', !isManual);
$('#stop-manual-section').toggleClass('hidden', !isManual);
});
// Select all rooms
$('#select-all').click(function() {
const checkboxes = $('input[name="rooms[]"]');
const allChecked = checkboxes.length === checkboxes.filter(':checked').length;
checkboxes.prop('checked', !allChecked).trigger('change');
$(this).text(allChecked ? 'Pilih Semua' : 'Batalkan Semua');
});
// Form submission
$('#announcement-form').submit(function(e) {
e.preventDefault();
const formData = $(this).serializeArray();
const isManual = $('input[name="type"]:checked').val() === 'manual';
const duration = isManual ? parseInt($('input[name="duration"]').val()) : 0;
const selectedRooms = $('input[name="rooms[]"]:checked').map(function() {
return $(this).closest('label').text().trim();
}).get();
if (selectedRooms.length === 0) {
Swal.fire({
icon: 'error',
title: 'Peringatan',
text: 'Silakan pilih minimal satu ruangan',
confirmButtonColor: '#3b82f6'
});
return;
}
Swal.fire({
title: 'Konfirmasi Pengiriman',
html: `<div class="text-left">
<p>Anda akan mengirim pengumuman <strong>${isManual ? 'manual' : 'TTS'}</strong> ke:</p>
<ul class="list-disc pl-5 mt-2 mb-2 max-h-40 overflow-y-auto">
${selectedRooms.map(room => `<li>${room}</li>`).join('')}
</ul>
${isManual ? `<p>Durasi: <strong>${duration} detik</strong></p>` : ''}
</div>`,
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Ya, Kirim Sekarang',
cancelButtonText: 'Batal',
reverseButtons: true,
customClass: {
confirmButton: 'px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-md',
cancelButton: 'px-4 py-2 bg-gray-200 hover:bg-gray-300 text-gray-800 rounded-md'
}
}).then((result) => {
if (result.isConfirmed) {
const submitBtn = $('#submit-btn');
submitBtn.prop('disabled', true).html(`
<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Mengirim...
`);
$.ajax({
url: `${baseUrl}/send`,
method: 'POST',
data: formData,
success: function(response) {
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: response.message || 'Pengumuman berhasil dikirim',
timer: 2000,
showConfirmButton: false
});
if (isManual) {
startCountdown(duration);
}
// Refresh active announcements
loadActiveAnnouncements();
},
error: function(xhr) {
const errorMsg = xhr.responseJSON?.message || 'Terjadi kesalahan saat mengirim pengumuman';
Swal.fire({
icon: 'error',
title: 'Gagal!',
text: errorMsg,
timer: 2000,
showConfirmButton: false
});
},
complete: function() {
submitBtn.prop('disabled', false).html(`
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
Kirim Pengumuman
`);
}
});
}
});
});
// Stop routing button
$('#stop-routing-btn').click(function(e) {
e.preventDefault();
Swal.fire({
title: 'Konfirmasi',
text: 'Anda yakin ingin memutus routing audio?',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Ya, Putuskan',
cancelButtonText: 'Batal',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
const stopBtn = $('#stop-routing-btn');
stopBtn.prop('disabled', true).html(`
<svg class="animate-spin -ml-1 mr-2 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Memproses...
`);
$.post(`${baseUrl}/stop-manual`, function(response) {
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: response.message || 'Routing audio berhasil diputus',
timer: 2000,
showConfirmButton: false
});
$('#timer-display').hide();
// Refresh active announcements
loadActiveAnnouncements();
}).fail(function(xhr) {
const errorMsg = xhr.responseJSON?.message || 'Gagal memutus routing audio';
Swal.fire({
icon: 'error',
title: 'Gagal!',
text: errorMsg,
timer: 2000,
showConfirmButton: false
});
}).always(function() {
stopBtn.prop('disabled', false).html(`
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" clip-rule="evenodd" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2" />
</svg>
Putuskan Routing Audio
`);
});
}
});
});
// Countdown timer with circular progress
function startCountdown(seconds) {
$('#timer-display').show();
let counter = seconds;
const circle = $('#countdown-circle');
const circumference = 2 * Math.PI * 16;
const countdownElement = $('#countdown');
// Initialize circle
circle.css('stroke-dasharray', circumference);
circle.css('stroke-dashoffset', 0);
const interval = setInterval(() => {
countdownElement.text(counter);
// Update progress circle
const offset = circumference - (counter / seconds) * circumference;
circle.css('stroke-dashoffset', offset);
counter--;
if (counter < 0) {
clearInterval(interval);
$('#timer-display').hide();
}
}, 1000);
}
// Check if there's an active manual announcement
function checkActiveAnnouncement() {
$.get(`${baseUrl}/check-active`, function(response) {
if (response.active && response.type === 'manual') {
$('input[name="type"][value="manual"]').prop('checked', true).trigger('change');
$('input[name="duration"]').val(response.duration);
$('#duration-value').text(response.duration);
startCountdown(response.remaining);
}
});
}
// Load active announcements
function loadActiveAnnouncements() {
$.get(`${baseUrl}/active-announcements`, function(response) {
const container = $('#active-announcements-container');
if (response.length === 0) {
container.html('<p class="text-sm text-gray-500">Tidak ada pengumuman aktif</p>');
return;
}
let html = '<div class="space-y-3">';
response.forEach(announcement => {
html += `
<div class="p-3 border border-gray-200 rounded-lg">
<div class="flex justify-between items-start">
<div>
<h3 class="font-medium text-gray-800">${announcement.room}</h3>
<p class="text-sm text-gray-500">${announcement.type === 'tts' ? 'TTS' : 'Manual'}</p>
</div>
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
Active
</span>
</div>
<div class="mt-2 text-sm text-gray-500">
<p>Mulai: ${new Date(announcement.sent_at).toLocaleString()}</p>
${announcement.type === 'manual' ? `<p>Durasi: ${announcement.duration} detik</p>` : ''}
</div>
<div class="mt-2">
<button class="text-red-600 hover:text-red-900 text-sm font-medium stop-announcement" data-id="${announcement.id}">
Hentikan
</button>
</div>
</div>
`;
});
html += '</div>';
container.html(html);
});
}
// Stop announcement button handler
$(document).on('click', '.stop-announcement', function() {
const announcementId = $(this).data('id');
Swal.fire({
title: 'Konfirmasi',
text: 'Anda yakin ingin menghentikan pengumuman ini?',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Ya, Hentikan',
cancelButtonText: 'Batal',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
$.post(`${baseUrl}/stop-announcement`, {
id: announcementId,
_token: $('meta[name="csrf-token"]').attr('content')
}, function(response) {
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: response.message || 'Pengumuman berhasil dihentikan',
timer: 2000,
showConfirmButton: false
});
// Refresh active announcements
loadActiveAnnouncements();
}).fail(function(xhr) {
const errorMsg = xhr.responseJSON?.message || 'Gagal menghentikan pengumuman';
Swal.fire({
icon: 'error',
title: 'Gagal!',
text: errorMsg,
timer: 2000,
showConfirmButton: false
});
});
}
});
});
// Initialize the UI
initUI();
// Load initial data
loadActiveAnnouncements();
});
</script>
@endsection